Build() public method

public Build ( string text ) : void
text string
return void
Ejemplo n.º 1
0
        public void Serialize(Stream output)
        {
            const uint headerSize = 32;

            output.WriteUInt32(0x42424947);
            output.WriteUInt32(Version);

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

            var maxValueLength = 0;
            var blob           = new StringBuilder();

            foreach (var file in 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 Encoder();

            huffmanEncoder.Build(blob.ToString());

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

            uint stringTableSize;

            using (var data = new MemoryStream())
            {
                data.Position = 4;
                data.WriteInt32(keys.Count);

                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.WriteUInt16((ushort)key.Length);
                    //data.WriteString(key, Encoding.UTF8);
                    data.WriteStringUTF8(key);
                    offsets.Add(new KeyValuePair <uint, uint>(key.HashCrc32(), offset));
                }

                data.Position = 8;

                foreach (var kv in offsets)
                {
                    data.WriteUInt32(kv.Key);
                    data.WriteUInt32(kv.Value - 8);
                }

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

                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.WriteUInt16((ushort)pairs.Length);
                foreach (var pair in pairs)
                {
                    data.WriteInt32(pair.Left);
                    data.WriteInt32(pair.Right);
                }

                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 + (Files.Count * 6);

                var files = new List <KeyValuePair <ushort, int> >();

                foreach (var file in 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.WriteUInt16((ushort)value.Value.Count);
                            valueDataOffset += 2;

                            foreach (var item in value.Value)
                            {
                                switch (item.Type)
                                {
                                case -1:
                                {
                                    continue;
                                }

                                case 1:
                                {
                                    index.WriteInt32((1 << 29) | bitOffset);

                                    break;
                                }

                                case 0:
                                case 2:
                                case 3:
                                case 4:
                                {
                                    var type = item.Type;

                                    if (OverrideCompileValueTypes >= 0)
                                    {
                                        type = OverrideCompileValueTypes;
                                    }

                                    index.WriteInt32((type << 29) | bitOffset);
                                    bitOffset += huffmanEncoder.Encode((item.Value ?? "") + '\0', bits, bitOffset);

                                    break;
                                }
                                }

                                valueDataOffset += 4;
                            }
                        }

                        index.Position = fileDataOffset + sectionDataOffset;

                        index.WriteUInt16((ushort)values.Count);
                        sectionDataOffset += 2;

                        foreach (var value in values)
                        {
                            index.WriteUInt16(value.Key);
                            index.WriteInt32(value.Value);

                            sectionDataOffset += 6;
                        }

                        sectionDataOffset += valueDataOffset;
                    }

                    index.Position = fileDataOffset;

                    index.WriteUInt16((ushort)sections.Count);
                    fileDataOffset += 2;

                    foreach (var section in sections)
                    {
                        index.WriteUInt16(section.Key);
                        index.WriteInt32(section.Value);

                        fileDataOffset += 6;
                    }

                    fileDataOffset += sectionDataOffset;
                }

                index.Position = 0;

                index.WriteUInt16((ushort)files.Count);

                foreach (var file in files)
                {
                    index.WriteUInt16(file.Key);
                    index.WriteInt32(file.Value);
                }

                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.WriteInt32(bits.Length);

            var bytes = new byte[(bits.Length - 1) / 8 + 1];

            bits.CopyTo(bytes, 0);
            output.Write(bytes);

            output.Seek(8, SeekOrigin.Begin);
            output.WriteInt32(maxKeyLength);
            output.WriteInt32(maxValueLength);
            output.WriteUInt32(stringTableSize);
            output.WriteUInt32(huffmanSize);
            output.WriteUInt32(indexSize);
            output.WriteInt32(bytes.Length);

            output.Seek(0, SeekOrigin.Begin);
            output.WriteUInt32(0x666D726D);
        }
Ejemplo n.º 2
0
		public void Serialize(Stream output)
		{
			var endian = ByteOrder;

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

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

			var maxValueLength = 0;
			var blob = new StringBuilder();

			foreach (var file in 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 Encoder();
			huffmanEncoder.Build(blob.ToString());

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

			uint stringTableSize;

			using (var data = new MemoryStream())
			{
				data.Position = 4;
				data.WriteInt32(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.WriteUInt16((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.WriteUInt32(kv.Key, endian);
					data.WriteUInt32(kv.Value - 8, endian);
				}

				data.Position = 0;
				data.WriteUInt32((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.WriteUInt16((ushort) pairs.Length, endian);
				foreach (var pair in pairs)
				{
					data.WriteInt32(pair.Left, endian);
					data.WriteInt32(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 + (Files.Count * 6);

				var files = new List<KeyValuePair<ushort, int>>();

				foreach (var file in 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.WriteUInt16((ushort) value.Value.Count, endian);
							valueDataOffset += 2;

							foreach (var item in value.Value)
							{
								switch (item.Type)
								{
									case -1:
									{
										continue;
									}
									case 1:
									{
										index.WriteInt32((1 << 29) | bitOffset, endian);

										break;
									}
									case 0:
									case 2:
									case 3:
									case 4:
									{
										var type = item.Type;

										if (OverrideCompileValueTypes >= 0)
										{
											type = OverrideCompileValueTypes;
										}

										index.WriteInt32((type << 29) | bitOffset, endian);
										bitOffset += huffmanEncoder.Encode((item.Value ?? "") + '\0', bits, bitOffset);

										break;
									}
								}

								valueDataOffset += 4;
							}
						}

						index.Position = fileDataOffset + sectionDataOffset;

						index.WriteUInt16((ushort) values.Count, endian);
						sectionDataOffset += 2;

						foreach (var value in values)
						{
							index.WriteUInt16(value.Key, endian);
							index.WriteInt32(value.Value, endian);

							sectionDataOffset += 6;
						}

						sectionDataOffset += valueDataOffset;
					}

					index.Position = fileDataOffset;

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

					foreach (var section in sections)
					{
						index.WriteUInt16(section.Key, endian);
						index.WriteInt32(section.Value, endian);

						fileDataOffset += 6;
					}

					fileDataOffset += sectionDataOffset;
				}

				index.Position = 0;

				index.WriteUInt16((ushort) files.Count, endian);

				foreach (var file in files)
				{
					index.WriteUInt16(file.Key, endian);
					index.WriteInt32(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.WriteInt32(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.WriteInt32(maxKeyLength, endian);
			output.WriteInt32(maxValueLength, endian);
			output.WriteUInt32(stringTableSize, endian);
			output.WriteUInt32(huffmanSize, endian);
			output.WriteUInt32(indexSize, endian);
			output.WriteInt32(bytes.Length, endian);

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