/// <summary> /// Writes a ShocoModel as a C# Class /// </summary> /// <param name="model">ShocoModel to generate the class from</param> /// <param name="Filename">Destination for the generated class</param> /// <param name="Name">Name of the C# Class</param> /// <param name="Namespace">Namespace for the C# Class</param> public static void WriteAsCSharpClass(this ShocoModel model, string Filename, string Name, string Namespace) { using (var streamWriter = File.CreateText(Filename)) { WriteAsCSharpClass(model, streamWriter, Name, Namespace); } }
/// <summary> /// Writes a ShocoModel as a C Header /// </summary> /// <param name="model">ShocoModel to generate the header from</param> /// <param name="Filename">Destination for the generated header</param> public static void WriteAsCHeader(this ShocoModel model, string Filename) { using (var stream = new FileStream(Filename, FileMode.Create, FileAccess.Write)) { using (var writer = new StreamWriter(stream, Encoding.ASCII)) { WriteAsCHeader(model, writer); } } }
/// <summary> /// Writes a ShocoModel as a C# Class /// </summary> /// <param name="model">ShocoModel to generate the class from</param> /// <param name="Writer">Destination for the generated class</param> /// <param name="Name">Name of the C# Class</param> /// <param name="Namespace">Namespace for the C# Class</param> public static void WriteAsCSharpClass(this ShocoModel model, TextWriter Writer, string Name, string Namespace) { if (model == null) { throw new ArgumentNullException(nameof(model)); } if (Writer == null) { throw new ArgumentNullException(nameof(Writer)); } if (string.IsNullOrWhiteSpace(Name)) { throw new ArgumentNullException(nameof(Name)); } if (string.IsNullOrWhiteSpace(Namespace)) { Namespace = DefaultCSharpNamespace; } Writer.WriteLine($"namespace {Namespace}"); Writer.WriteLine("{"); if (Namespace != DefaultCSharpNamespace) { Writer.WriteLine($" using {DefaultCSharpNamespace};"); Writer.WriteLine(); } Writer.WriteLine($" public class {Name} : ShocoModel"); Writer.WriteLine(" {"); Writer.WriteLine($" public static {Name} Instance {{ get; }} = new {Name}();"); Writer.WriteLine(); Writer.WriteLine($" private {Name}()"); Writer.WriteLine($" : base(MinimumCharacter: {model.MinimumCharacter},"); Writer.WriteLine($" MaximumCharacter: {model.MaximumCharacter},"); Writer.WriteLine($" MaximumSuccessorLength: {model.MaximumSuccessorLength},"); Writer.WriteLine($" CharactersById: new byte[{model.CharactersById.Length}] {{"); for (int offset = 0; offset < model.CharactersById.Length; offset += 11) { if (offset != 0) { Writer.WriteLine(","); } Writer.Write($" {string.Join(", ", model.CharactersById.Skip(offset).Take(11).Select(EscapeCSharp))}"); } Writer.WriteLine(" },"); var idsByCharacter = model.IdsByCharacter; Writer.Write($" IdsByCharacter: new byte[256] {{"); for (int offset = 0; offset < idsByCharacter.Length; offset += 32) { if (offset != 0) { Writer.Write(","); } Writer.WriteLine(); Writer.Write($" {string.Join(", ", idsByCharacter.Skip(offset).Take(32).Select(FormatAsCSharpByte))}"); } Writer.WriteLine(" },"); var successorIdsByCharacterId = model.SuccessorIdsByCharacterId; Writer.Write($" SuccessorIdsByCharacterId: new byte[{successorIdsByCharacterId.GetLength(0)}, {successorIdsByCharacterId.GetLength(1)}] {{"); for (int offset = 0; offset < successorIdsByCharacterId.GetLength(0); offset++) { if (offset != 0) { Writer.Write(","); } Writer.WriteLine(); Writer.Write($" {{{string.Join(", ", successorIdsByCharacterId.Cast<byte>().Skip(offset * successorIdsByCharacterId.GetLength(1)).Take(successorIdsByCharacterId.GetLength(1)).Select(FormatAsCSharpByte))}}}"); } Writer.WriteLine(" },"); var charactersBySuccessorId = model.CharactersBySuccessorId; Writer.Write($" CharactersBySuccessorId: new byte[{charactersBySuccessorId.GetLength(0)}, {charactersBySuccessorId.GetLength(1)}] {{"); for (int offset = 0; offset < charactersBySuccessorId.GetLength(0); offset++) { if (offset != 0) { Writer.Write(","); } Writer.WriteLine(); Writer.Write($" {{{string.Join(", ", charactersBySuccessorId.Cast<byte>().Skip(offset * charactersBySuccessorId.GetLength(1)).Take(charactersBySuccessorId.GetLength(1)).Select(EscapeCSharp))}}}"); } Writer.WriteLine(" },"); var packs = model.Packs; Writer.Write($" Packs: new ShocoPack[] {{"); for (int index = 0; index < packs.Length; index++) { var pack = packs[index]; if (index != 0) { Writer.Write(","); } Writer.WriteLine(); Writer.Write($" new ShocoPack(0x{pack.Header:X2}, {pack.BytesPacked}, {pack.BytesUnpacked}, new int[] {{ {string.Join(", ", pack.offsets)} }}, new int[] {{ {string.Join(", ", pack.masks)} }})"); } Writer.WriteLine(" })"); Writer.WriteLine($" {{ }}"); Writer.WriteLine(); Writer.WriteLine(" }"); Writer.WriteLine("}"); }
/// <summary> /// Writes a ShocoModel as a C Header /// </summary> /// <param name="model">ShocoModel to generate the header from</param> /// <param name="Writer">Destination for the generated header</param> public static void WriteAsCHeader(this ShocoModel model, TextWriter Writer) { if (model == null) { throw new ArgumentNullException(nameof(model)); } if (Writer == null) { throw new ArgumentNullException(nameof(Writer)); } var chars_count = model.CharactersById.Length; Writer.WriteLine(@"#ifndef _SHOCO_INTERNAL #error This header file is only to be included by 'shoco.c'. #endif #pragma once /* This file was generated by 'generate_compressor_model.py' so don't edit this by hand. Also, do not include this file anywhere. It is internal to 'shoco.c'. Include 'shoco.h' if you want to use shoco in your project. */ "); Writer.WriteLine($"#define MIN_CHR {model.MinimumCharacter}"); Writer.WriteLine($"#define MAX_CHR {model.MaximumCharacter}"); Writer.WriteLine(); Writer.WriteLine($"static const char chrs_by_chr_id[{chars_count}] = {{"); Writer.Write(" "); Writer.WriteLine(string.Join(", ", model.CharactersById.Select(EscapeC))); Writer.WriteLine("};"); Writer.WriteLine(); Writer.WriteLine($"static const int8_t chr_ids_by_chr[256] = {{"); Writer.Write(" "); Writer.WriteLine(string.Join(", ", model.IdsByCharacter.Select(FormatAsCByte))); Writer.WriteLine("};"); Writer.WriteLine(); var successors = model.SuccessorIdsByCharacterId; Writer.WriteLine($"static const int8_t successor_ids_by_chr_id_and_chr_id[{chars_count}][{chars_count}] = {{"); for (int x = 0; x < chars_count; x++) { if (x != 0) { Writer.WriteLine(","); } Writer.Write(" {"); for (int y = 0; y < chars_count; y++) { if (y != 0) { Writer.Write(", "); } Writer.Write(FormatAsCByte(successors[x, y])); } Writer.Write("}"); } Writer.WriteLine(); Writer.WriteLine("};"); Writer.WriteLine(); var characters = model.CharactersBySuccessorId; Writer.WriteLine($"static const int8_t chrs_by_chr_and_successor_id[MAX_CHR - MIN_CHR][{characters.GetLength(1)}] = {{"); for (int x = 0; x < characters.GetLength(0); x++) { if (x != 0) { Writer.WriteLine(","); } Writer.Write(" {"); for (int y = 0; y < characters.GetLength(1); y++) { if (y != 0) { Writer.Write(", "); } Writer.Write(EscapeC(characters[x, y])); } Writer.Write("}"); } Writer.WriteLine(); Writer.WriteLine("};"); Writer.WriteLine(); Writer.WriteLine(); Writer.WriteLine($@"#ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4324) // structure was padded due to __declspec(align()) #endif typedef struct Pack {{ const uint32_t word; const unsigned int bytes_packed; const unsigned int bytes_unpacked; const unsigned int offsets[{model.Packs[0].offsets.Length}]; const int16_t _ALIGNED masks[{model.Packs[0].masks.Length}]; const char header_mask; const char header; }} Pack; #ifdef _MSC_VER #pragma warning(pop) #endif"); Writer.WriteLine(); var packs = model.Packs; Writer.WriteLine($@"#define PACK_COUNT {packs.Length} #define MAX_SUCCESSOR_N {8 - 1}"); Writer.WriteLine(); Writer.WriteLine("static const Pack packs[PACK_COUNT] = {"); for (int i = 0; i < packs.Length; i++) { var pack = packs[i]; if (i != 0) { Writer.WriteLine(","); } Writer.Write($" {{ 0x{pack.Header << 24:x8}, {pack.BytesPacked}, {pack.BytesUnpacked}, {{ {string.Join(", ", pack.offsets)} }}, {{ {string.Join(", ", pack.masks)} }}, 0x{(pack.Header >> 1) | pack.Header:x2}, 0x{pack.Header:x2} }}"); } Writer.WriteLine(); Writer.WriteLine("};"); }
/// <summary> /// Writes a ShocoModel as a C# Class using the default namespace /// </summary> /// <param name="model">ShocoModel to generate the class from</param> /// <param name="Filename">Destination for the generated class</param> /// <param name="Name">Name of the C# Class</param> public static void WriteAsCSharpClass(this ShocoModel model, string Filename, string Name) { WriteAsCSharpClass(model, Filename, Name, Namespace: null); }
/// <summary> /// Writes a ShocoModel as a C# Class using the default namespace /// </summary> /// <param name="model">ShocoModel to generate the class from</param> /// <param name="Writer">Destination for the generated class</param> /// <param name="Name">Name of the C# Class</param> public static void WriteAsCSharpClass(this ShocoModel model, TextWriter Writer, string Name) { WriteAsCSharpClass(model, Writer, Name, Namespace: null); }