Gibbed.MassEffect3.FileFormats.CoalescedFile.Serialize C# (CSharp) Method

Serialize() public method

public Serialize ( Stream output ) : void
output Stream
return void
        public void Serialize(Stream output)
        {
            var endian = this.Endian;

            const uint headerSize = 32;
            output.WriteValueU32(0x42424947, endian);
            output.WriteValueU32(this.Version, endian);

            var keys = new List<string>() {""};

            int maxValueLength = 0;
            var blob = new StringBuilder();
            foreach (var file in this.Files)
            {
                keys.Add(file.Name);
                foreach (var section in file.Sections)
                {
                    keys.Add(section.Key);
                    foreach (var value in section.Value)
                    {
                        keys.Add(value.Key);
                        foreach (var item in value.Value)
                        {
                            if (item.Value != null)
                            {
                                blob.Append(item.Value + '\0');
                                maxValueLength = Math.Max(maxValueLength, item.Value.Length);
                            }
                        }
                    }
                }
            }

            var huffmanEncoder = new Huffman.Encoder();
            huffmanEncoder.Build(blob.ToString());

            keys = keys.Distinct().OrderBy(k => k.HashCrc32()).ToList();
            int maxKeyLength = keys.Max(k => k.Length);

            uint stringTableSize;
            using (var data = new MemoryStream())
            {
                data.Position = 4;
                data.WriteValueS32(keys.Count, endian);

                data.Position = 4 + 4 + (8 * keys.Count);
                var offsets = new List<KeyValuePair<uint, uint>>();
                foreach (var key in keys)
                {
                    var offset = (uint)data.Position;
                    data.WriteValueU16((ushort)key.Length, endian);
                    data.WriteString(key, Encoding.UTF8);
                    offsets.Add(new KeyValuePair<uint, uint>(key.HashCrc32(), offset));
                }

                data.Position = 8;
                foreach (var kv in offsets)
                {
                    data.WriteValueU32(kv.Key, endian);
                    data.WriteValueU32(kv.Value - 8, endian);
                }

                data.Position = 0;
                data.WriteValueU32((uint)data.Length, endian);

                data.Position = 0;
                stringTableSize = (uint)data.Length;

                output.Seek(headerSize, SeekOrigin.Begin);
                output.WriteFromStream(data, data.Length);
            }

            uint huffmanSize;
            using (var data = new MemoryStream())
            {
                var pairs = huffmanEncoder.GetPairs();
                data.WriteValueU16((ushort)pairs.Length, endian);
                foreach (var pair in pairs)
                {
                    data.WriteValueS32(pair.Left, endian);
                    data.WriteValueS32(pair.Right, endian);
                }

                data.Position = 0;
                huffmanSize = (uint)data.Length;

                output.Seek(headerSize + stringTableSize, SeekOrigin.Begin);
                output.WriteFromStream(data, data.Length);
            }

            var bits = new BitArray(huffmanEncoder.TotalBits);
            var bitOffset = 0;

            uint indexSize;
            using (var index = new MemoryStream())
            {
                var fileDataOffset = 2 + (this.Files.Count * 6);

                var files = new List<KeyValuePair<ushort, int>>();
                foreach (var file in this.Files.OrderBy(f => keys.IndexOf(f.Name)))
                {
                    files.Add(new KeyValuePair<ushort, int>(
                        (ushort)keys.IndexOf(file.Name), fileDataOffset));

                    var sectionDataOffset = 2 + (file.Sections.Count * 6);

                    var sections = new List<KeyValuePair<ushort, int>>();
                    foreach (var section in file.Sections.OrderBy(s => keys.IndexOf(s.Key)))
                    {
                        sections.Add(new KeyValuePair<ushort, int>(
                            (ushort)keys.IndexOf(section.Key), sectionDataOffset));

                        var valueDataOffset = 2 + (section.Value.Count * 6);

                        var values = new List<KeyValuePair<ushort, int>>();
                        foreach (var value in section.Value.OrderBy(v => keys.IndexOf(v.Key)))
                        {
                            index.Position = fileDataOffset + sectionDataOffset + valueDataOffset;

                            values.Add(new KeyValuePair<ushort, int>(
                                (ushort)keys.IndexOf(value.Key), valueDataOffset));

                            index.WriteValueU16((ushort)value.Value.Count, endian);
                            valueDataOffset += 2;

                            foreach (var item in value.Value)
                            {
                                if (item.Type == 1)
                                {
                                    index.WriteValueS32((1 << 29) | bitOffset, endian);
                                }
                                else if (item.Type == 0 || item.Type == 2 || item.Type == 3 || item.Type == 4)
                                {
                                    index.WriteValueS32((item.Type << 29) | bitOffset, endian);
                                    bitOffset += huffmanEncoder.Encode((item.Value ?? "") + '\0', bits, bitOffset);
                                }
                                valueDataOffset += 4;
                            }
                        }

                        index.Position = fileDataOffset + sectionDataOffset;
                        
                        index.WriteValueU16((ushort)values.Count, endian);
                        sectionDataOffset += 2;

                        foreach (var value in values)
                        {
                            index.WriteValueU16(value.Key, endian);
                            index.WriteValueS32(value.Value, endian);
                            sectionDataOffset += 6;
                        }

                        sectionDataOffset += valueDataOffset;
                    }

                    index.Position = fileDataOffset;

                    index.WriteValueU16((ushort)sections.Count, endian);
                    fileDataOffset += 2;

                    foreach (var section in sections)
                    {
                        index.WriteValueU16(section.Key, endian);
                        index.WriteValueS32(section.Value, endian);
                        fileDataOffset += 6;
                    }

                    fileDataOffset += sectionDataOffset;
                }

                index.Position = 0;

                index.WriteValueU16((ushort)files.Count, endian);
                foreach (var file in files)
                {
                    index.WriteValueU16(file.Key, endian);
                    index.WriteValueS32(file.Value, endian);
                }

                index.Position = 0;
                indexSize = (uint)index.Length;

                output.Seek(headerSize + stringTableSize + huffmanSize, SeekOrigin.Begin);
                output.WriteFromStream(index, index.Length);
            }

            output.Seek(headerSize + stringTableSize + huffmanSize + indexSize, SeekOrigin.Begin);
            output.WriteValueS32(bits.Length, endian);
            var bytes = new byte[(bits.Length - 1) / 8 + 1];
            bits.CopyTo(bytes, 0);
            output.WriteBytes(bytes);

            output.Seek(8, SeekOrigin.Begin);
            output.WriteValueS32(maxKeyLength, endian);
            output.WriteValueS32(maxValueLength, endian);
            output.WriteValueU32(stringTableSize, endian);
            output.WriteValueU32(huffmanSize, endian);
            output.WriteValueU32(indexSize, endian);
            output.WriteValueS32(bytes.Length, endian);

            output.Seek(0, SeekOrigin.Begin);
            output.WriteValueU32(0x666D726D, endian);
        }

Usage Example

示例#1
0
        public static void Main(string[] args)
        {
            //var serializer = new DataContractSerializer(typeof(TType));

            var mode = Mode.Unknown;
            var showHelp = false;

            var options = new OptionSet()
            {
                {
                    "b|json2bin",
                    "convert json to bin",
                    v => mode = v != null ? Mode.ToBin : mode
                },
                {
                    "j|bin2json",
                    "convert bin to json",
                    v => mode = v != null ? Mode.ToJson : mode
                },
                {
                    "h|help",
                    "show this message and exit", 
                    v => showHelp = v != null
                },
            };

            List<string> extras;

            try
            {
                extras = options.Parse(args);
            }
            catch (OptionException e)
            {
                Console.Write("{0}: ", GetExecutableName());
                Console.WriteLine(e.Message);
                Console.WriteLine("Try `{0} --help' for more information.", GetExecutableName());
                return;
            }

            // try to figure out what they want to do
            if (mode == Mode.Unknown &&
                extras.Count >= 1)
            {
                var testPath = extras[0];

                if (Directory.Exists(testPath) == true)
                {
                    mode = Mode.ToBin;
                }
                else if (File.Exists(testPath) == true)
                {
                    mode = Mode.ToJson;
                }
            }

            if (extras.Count < 1 || extras.Count > 2 ||
                showHelp == true || mode == Mode.Unknown)
            {
                Console.WriteLine("Usage: {0} [OPTIONS]+ -j input_bin [output_dir]", GetExecutableName());
                Console.WriteLine("       {0} [OPTIONS]+ -b input_dir [output_bin]", GetExecutableName());
                Console.WriteLine();
                Console.WriteLine("Options:");
                options.WriteOptionDescriptions(Console.Out);
                return;
            }

            if (mode == Mode.ToJson)
            {
                var inputPath = extras[0];
                var outputPath = extras.Count > 1 ? extras[1] : Path.ChangeExtension(inputPath, null);

                using (var input = File.OpenRead(inputPath))
                {
                    var coal = new CoalescedFile();
                    coal.Deserialize(input);

                    var padding = coal.Files.Count.ToString(CultureInfo.InvariantCulture).Length;

                    var setup = new Setup
                    {
                        Endian = coal.Endian,
                        Version = coal.Version,
                    };

                    var counter = 0;
                    foreach (var file in coal.Files)//.OrderBy(f => f.Name))
                    {
                        var iniPath = string.Format("{1}_{0}",
                            Path.GetFileNameWithoutExtension(file.Name),
                            counter.ToString(CultureInfo.InvariantCulture).PadLeft(padding, '0'));
                        iniPath = Path.Combine(outputPath, Path.ChangeExtension(iniPath, ".json"));
                        counter++;

                        setup.Files.Add(Path.GetFileName(iniPath));

                        Directory.CreateDirectory(Path.GetDirectoryName(iniPath));
                        using (var output = File.Create(iniPath))
                        {
                            var writer = new StreamWriter(output);
                            writer.Write(JsonConvert.SerializeObject(
                                new FileWrapper()
                                {
                                    Name = file.Name,
                                    Sections = file.Sections,
                                }, Formatting.Indented));
                            writer.Flush();
                        }
                    }

                    Directory.CreateDirectory(outputPath);
                    using (var output = File.Create(Path.Combine(outputPath, "@coalesced.json")))
                    {
                        var writer = new StreamWriter(output);
                        writer.Write(JsonConvert.SerializeObject(
                            setup, Formatting.Indented));
                        writer.Flush();
                    }
                }
            }
            else
            {
                var inputPath = extras[0];
                var outputPath = extras.Count > 1 ? extras[1] : Path.ChangeExtension(inputPath, ".bin");

                Setup setup;

                var setupPath = Path.Combine(inputPath, "@coalesced.json");
                using (var input = File.OpenRead(setupPath))
                {
                    var reader = new StreamReader(input);
                    var text = reader.ReadToEnd();

                    try
                    {
                        setup = JsonConvert.DeserializeObject<Setup>(text);
                    }
                    catch (JsonReaderException e)
                    {
                        Console.WriteLine("There was an error parsing '{0}':", setupPath);
                        Console.WriteLine("  {0}", e.Message);
                        return;
                    }
                }

                var coal = new CoalescedFile
                {
                    Endian = setup.Endian,
                    Version = setup.Version,
                };

                foreach (var iniName in setup.Files)
                {
                    string iniPath = Path.IsPathRooted(iniName) == false ?
                        Path.Combine(inputPath, iniName) : iniName;

                    using (var input = File.OpenRead(iniPath))
                    {
                        var reader = new StreamReader(input);
                        var text = reader.ReadToEnd();

                        FileWrapper file;
                        try
                        {
                            file = JsonConvert.DeserializeObject<FileWrapper>(text);
                        }
                        catch (JsonReaderException e)
                        {
                            Console.WriteLine("There was an error parsing '{0}':", iniPath);
                            Console.WriteLine("  {0}", e.Message);
                            return;
                        }

                        coal.Files.Add(new Coalesced.File()
                            {
                                Name = file.Name,
                                Sections = file.Sections,
                            });
                    }
                }

                using (var output = File.Create(outputPath))
                {
                    coal.Serialize(output);
                }
            }
        }
All Usage Examples Of Gibbed.MassEffect3.FileFormats.CoalescedFile::Serialize