Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- namespace ConsoleApp2
- {
- class Program
- {
- struct CPVSCompressor
- {
- public static byte[] Decompress(byte[] data, int start, int end)
- {
- byte[] result = new byte[512];
- for (int input = start, output = 0; input < end;)
- {
- byte size = data[input++];
- if (size >= 128) // Copy
- {
- size -= 127;
- for (int j = 0; j < size; ++j)
- result[output++] = data[input++];
- }
- else // Fill
- {
- byte value = data[input++];
- for (int j = 0; j < size; ++j)
- result[output++] = value;
- }
- }
- return result;
- }
- public static int GetFillLength(byte[] data, int index)
- {
- var result = Array.FindIndex(data, index + 1, x => x != data[index]);
- if (result < 0)
- {
- result = data.Length;
- }
- result -= index;
- return result;
- }
- public static (int, int) GetNextFill(byte[] data, int index)
- {
- int length = 0;
- while (index < data.Length)
- {
- length = GetFillLength(data, index);
- if (length >= 3)
- {
- break;
- }
- index += length;
- }
- return (index, length);
- }
- public static void WriteCopy(BinaryWriter writer, byte[] data, int index, int length)
- {
- const int MAX_COPY = 128;
- for (int i = 0; i < length; i += MAX_COPY)
- {
- var block_length = Math.Min(length - i, MAX_COPY);
- writer.Write((byte) (block_length + 127));
- writer.Write(data, index + i, block_length);
- }
- }
- public static void WriteFill(BinaryWriter writer, byte value, int length)
- {
- const int MAX_FILL = 127;
- for (int i = 0; i < length; i += MAX_FILL)
- {
- var block_length = Math.Min(length - i, MAX_FILL);
- writer.Write((byte) block_length);
- writer.Write(value);
- }
- }
- public static byte[] Compress(byte[] data)
- {
- var result = new MemoryStream();
- var writer = new BinaryWriter(result);
- for (int i = 0; i < data.Length;)
- {
- var (fill_start, fill_length) = GetNextFill(data, i);
- var copy_length = fill_start - i;
- if (copy_length > 0)
- {
- WriteCopy(writer, data, i, copy_length);
- }
- if (fill_length > 0)
- {
- var value = data[fill_start];
- // And remaining data is zeroed
- if ((value != 0) || ((fill_start + fill_length) < data.Length))
- {
- WriteFill(writer, data[fill_start], fill_length);
- }
- }
- i = fill_start + fill_length;
- }
- return result.ToArray();
- }
- public static bool[] ExpandCPVSData(byte[] data)
- {
- var results = new bool[data.Length * 4];
- for (int i = 0; i < results.Length; ++i)
- {
- results[i] = ((data[i / 4] >> ((i % 4) * 2)) & 0x3) != 0;
- }
- return results;
- }
- }
- struct CPVS
- {
- static readonly uint PVS0_MAGIC = 0x30535650; /*PVS0*/
- public readonly byte[][] Values;
- public CPVS(BinaryReader reader)
- {
- if (reader.ReadUInt32() != PVS0_MAGIC)
- {
- throw new Exception("Invalid Magic");
- }
- var indices = new int[reader.ReadUInt32()];
- indices[0] = 0;
- for (int i = 1; i < indices.Length; ++i)
- {
- indices[i] = reader.ReadInt32();
- }
- var data = reader.ReadBytes((int)(reader.BaseStream.Length - reader.BaseStream.Position));
- Values = Enumerable.Range(0, indices.Length - 1).Select(x => CPVSCompressor.Decompress(data, indices[x], indices[x + 1])).ToArray();
- }
- public void Save(BinaryWriter writer)
- {
- writer.Write(PVS0_MAGIC);
- var compresed = Values.Select(x => CPVSCompressor.Compress(x)).ToArray();
- writer.Write(compresed.Length + 1);
- for (int i = 0, offset = 0; i < compresed.Length; ++i)
- {
- offset += compresed[i].Length;
- writer.Write(offset);
- }
- foreach (var value in compresed)
- {
- writer.Write(value);
- }
- }
- }
- static CPVS ReadCPVS(string filename)
- {
- using (var fs = File.OpenRead(filename))
- {
- var reader = new BinaryReader(fs);
- return new CPVS(reader);
- }
- }
- static void WriteCPVS(CPVS cpvs, string filename)
- {
- using (var fs = File.OpenWrite(filename))
- {
- var writer = new BinaryWriter(fs);
- cpvs.Save(writer);
- }
- }
- static string ByteArrayToHex(byte[] data)
- {
- return String.Join(String.Empty, Array.ConvertAll(data, x => x.ToString("X2")));
- }
- static void Main(string[] args)
- {
- string original_name = "london.cpvs";
- string copy_name = "london_copy.cpvs";
- var original = ReadCPVS(original_name);
- WriteCPVS(original, copy_name);
- var copy = ReadCPVS(copy_name);
- if (original.Values.Length != copy.Values.Length)
- {
- Console.WriteLine("Failed Length");
- }
- for (int i = 0; i < original.Values.Length; ++i)
- {
- if (!Enumerable.SequenceEqual(original.Values[i], copy.Values[i]))
- {
- Console.WriteLine("{0} Different", i);
- }
- }
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement