public static string Decode(Pair[] tree, BitArray data, int offset, int maxLength) { var sb = new StringBuilder(); var start = tree.Length - 1; while (true) { int 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(); }
public void Deserialize(Stream input) { var magic = input.ReadValueU32(Endian.Little); if (magic != 0x666D726D && // fmrm magic.Swap() != 0x666D726D) { throw new FormatException(); } var endian = magic == 0x666D726D ? Endian.Little : Endian.Big; var version = input.ReadValueU32(endian); if (version != 1) { throw new FormatException(); } this.Version = version; /*var maxKeyLength =*/ input.ReadValueS32(endian); var maxValueLength = input.ReadValueS32(endian); var stringTableSize = input.ReadValueU32(endian); var huffmanSize = input.ReadValueU32(endian); var indexSize = input.ReadValueU32(endian); var dataSize = input.ReadValueU32(endian); var strings = new List <KeyValuePair <uint, string> >(); using (var data = input.ReadToMemoryStream(stringTableSize)) { var localStringTableSize = data.ReadValueU32(endian); if (localStringTableSize != stringTableSize) { throw new FormatException(); } var count = data.ReadValueU32(endian); var offsets = new List <KeyValuePair <uint, uint> >(); for (uint i = 0; i < count; i++) { var hash = data.ReadValueU32(endian); var offset = data.ReadValueU32(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.ReadValueU16(endian); var text = data.ReadString(length, Encoding.UTF8); if (text.HashCrc32() != hash) { throw new InvalidOperationException(); } strings.Add(new KeyValuePair <uint, string>(hash, text)); } } Huffman.Pair[] huffmanTree; using (var data = input.ReadToMemoryStream(huffmanSize)) { var count = data.ReadValueU16(endian); huffmanTree = new Huffman.Pair[count]; for (ushort i = 0; i < count; i++) { var left = data.ReadValueS32(endian); var right = data.ReadValueS32(endian); huffmanTree[i] = new Huffman.Pair(left, right); } } using (var index = input.ReadToMemoryStream(indexSize)) { var totalBits = input.ReadValueS32(endian); var data = input.ReadBytes(dataSize); var bitArray = new BitArray(data) { Length = totalBits }; var files = new List <KeyValuePair <string, uint> >(); var fileCount = index.ReadValueU16(endian); for (ushort i = 0; i < fileCount; i++) { var nameIndex = index.ReadValueU16(endian); var name = strings[nameIndex].Value; var offset = index.ReadValueU32(endian); files.Add(new KeyValuePair <string, uint>(name, offset)); } foreach (var fileInfo in files.OrderBy(f => f.Key)) { var file = new Coalesced.File() { Name = fileInfo.Key }; index.Seek(fileInfo.Value, SeekOrigin.Begin); var sectionCount = index.ReadValueU16(endian); var sections = new List <KeyValuePair <string, uint> >(); for (ushort i = 0; i < sectionCount; i++) { var nameIndex = index.ReadValueU16(endian); var name = strings[nameIndex].Value; var offset = index.ReadValueU32(endian); sections.Add(new KeyValuePair <string, uint>(name, offset)); } foreach (var sectionInfo in sections.OrderBy(s => s.Key)) { var section = new Dictionary <string, List <string> >(); index.Seek(fileInfo.Value + sectionInfo.Value, SeekOrigin.Begin); var valueCount = index.ReadValueU16(endian); var values = new List <KeyValuePair <string, uint> >(); for (ushort i = 0; i < valueCount; i++) { var nameIndex = index.ReadValueU16(endian); var name = strings[nameIndex].Value; var offset = index.ReadValueU32(endian); values.Add(new KeyValuePair <string, uint>(name, offset)); } foreach (var valueInfo in values.OrderBy(v => v.Key)) { var value = new List <string>(); index.Seek(fileInfo.Value + sectionInfo.Value + valueInfo.Value, SeekOrigin.Begin); var itemCount = index.ReadValueU16(endian); for (ushort i = 0; i < itemCount; i++) { var offset = index.ReadValueS32(endian); var type = (offset & 0xE0000000) >> 29; if (type == 1) { value.Add(null); } else if (type == 2) { offset &= 0x1FFFFFFF; var text = Huffman.Decoder.Decode( huffmanTree, bitArray, offset, maxValueLength); value.Add(text); } /*else if (type == 0 || type == 3) * { * offset &= 0x1FFFFFFF; * var text = Huffman.Decoder.Decode( * huffmanTree, bitArray, offset, maxValueLength); * value.Add("<<wtf" + type.ToString() + ">>" + text); * }*/ else { throw new NotImplementedException(); } } section.Add(valueInfo.Key, value); } file.Sections.Add(sectionInfo.Key, section); } this.Files.Add(file); } } this.Endian = endian; }
public Pair[] GetPairs() { var pairs = new List<Pair>(); var mapping = new Dictionary<Node, Pair>(); var queue = new Queue<Node>(); queue.Enqueue(this._Root); var root = new Pair(); mapping.Add(this._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(); }
public void Deserialize(Stream input) { var magic = input.ReadValueU32(Endian.Little); if (magic != 0x666D726D && // fmrm magic.Swap() != 0x666D726D) { throw new FormatException(); } var endian = magic == 0x666D726D ? Endian.Little : Endian.Big; var version = input.ReadValueU32(endian); if (version != 1) { throw new FormatException(); } this.Version = version; /*var maxKeyLength =*/ input.ReadValueS32(endian); var maxValueLength = input.ReadValueS32(endian); var stringTableSize = input.ReadValueU32(endian); var huffmanSize = input.ReadValueU32(endian); var indexSize = input.ReadValueU32(endian); var dataSize = input.ReadValueU32(endian); var strings = new List<KeyValuePair<uint, string>>(); using (var data = input.ReadToMemoryStream(stringTableSize)) { var localStringTableSize = data.ReadValueU32(endian); if (localStringTableSize != stringTableSize) { throw new FormatException(); } var count = data.ReadValueU32(endian); var offsets = new List<KeyValuePair<uint, uint>>(); for (uint i = 0; i < count; i++) { var hash = data.ReadValueU32(endian); var offset = data.ReadValueU32(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.ReadValueU16(endian); var text = data.ReadString(length, Encoding.UTF8); if (text.HashCrc32() != hash) { throw new InvalidOperationException(); } strings.Add(new KeyValuePair<uint, string>(hash, text)); } } Huffman.Pair[] huffmanTree; using (var data = input.ReadToMemoryStream(huffmanSize)) { var count = data.ReadValueU16(endian); huffmanTree = new Huffman.Pair[count]; for (ushort i = 0; i < count; i++) { var left = data.ReadValueS32(endian); var right = data.ReadValueS32(endian); huffmanTree[i] = new Huffman.Pair(left, right); } } using (var index = input.ReadToMemoryStream(indexSize)) { var totalBits = input.ReadValueS32(endian); var data = input.ReadBytes(dataSize); var bitArray = new BitArray(data) { Length = totalBits }; var files = new List<KeyValuePair<string, uint>>(); var fileCount = index.ReadValueU16(endian); for (ushort i = 0; i < fileCount; i++) { var nameIndex = index.ReadValueU16(endian); var name = strings[nameIndex].Value; var offset = index.ReadValueU32(endian); files.Add(new KeyValuePair<string, uint>(name, offset)); } foreach (var fileInfo in files.OrderBy(f => f.Key)) { var file = new Coalesced.File() { Name = fileInfo.Key }; index.Seek(fileInfo.Value, SeekOrigin.Begin); var sectionCount = index.ReadValueU16(endian); var sections = new List<KeyValuePair<string, uint>>(); for (ushort i = 0; i < sectionCount; i++) { var nameIndex = index.ReadValueU16(endian); var name = strings[nameIndex].Value; var offset = index.ReadValueU32(endian); sections.Add(new KeyValuePair<string, uint>(name, offset)); } foreach (var sectionInfo in sections.OrderBy(s => s.Key)) { var section = new Dictionary<string, List<Coalesced.Entry>>(); index.Seek(fileInfo.Value + sectionInfo.Value, SeekOrigin.Begin); var valueCount = index.ReadValueU16(endian); var values = new List<KeyValuePair<string, uint>>(); for (ushort i = 0; i < valueCount; i++) { var nameIndex = index.ReadValueU16(endian); var name = strings[nameIndex].Value; var offset = index.ReadValueU32(endian); values.Add(new KeyValuePair<string, uint>(name, offset)); } foreach (var valueInfo in values.OrderBy(v => v.Key)) { var value = new List<Coalesced.Entry>(); index.Seek(fileInfo.Value + sectionInfo.Value + valueInfo.Value, SeekOrigin.Begin); var itemCount = index.ReadValueU16(endian); for (ushort i = 0; i < itemCount; i++) { var offset = index.ReadValueS32(endian); var type = (offset & 0xE0000000) >> 29; if (type == 1) { value.Add(new Coalesced.Entry(1, null)); } else if (type == 0 || type == 2 || type == 3 || type == 4) { offset &= 0x1FFFFFFF; var text = Huffman.Decoder.Decode( huffmanTree, bitArray, offset, maxValueLength); value.Add(new Coalesced.Entry(2, text)); } else { throw new NotImplementedException(); } } section.Add(valueInfo.Key, value); } file.Sections.Add(sectionInfo.Key, section); } this.Files.Add(file); } } this.Endian = endian; }