<#@ template debug="false" hostspecific="true" language="C#" #> <#@ output extension=".cs" encoding="utf-8" #> <#@ Assembly Name="System.Core.dll" #> <#@ Assembly Name="System.Xml.dll" #> <#@ Assembly Name="System.Xml.Linq.dll" #> <#@ import namespace="System" #> <#@ import namespace="System.IO" #> <#@ import namespace="System.Diagnostics" #> <#@ import namespace="System.Reflection" #> <#@ import namespace="System.Linq" #> <#@ import namespace="System.Collections" #> <#@ import namespace="System.Collections.Generic" #> <#@ import namespace="System.Xml.Linq" #> <#@ import namespace="System.Text" #> <# string XmlFile = "../ebml.xml"; string MatroskaXmlFile = "../ebml_matroska.xml"; XNamespace ns = "urn:ietf:rfc:8794"; #> using System; using System.Collections.Generic; using System.CodeDom.Compiler; using Matroska.Attributes; //-------------------------------------------------------------------------------------------------------- // // This C# code class was auto-generated at <#= DateTime.Now #>. // Changes to this file may cause incorrect behavior and will be lost if the code is regenerated. // // Based on "https://github.com/ietf-wg-cellar/matroska-specification/blob/master/ebml_matroska.xml". // //-------------------------------------------------------------------------------------------------------- namespace Matroska.Models; <# var isList = new List { { "AttachedFile" }, { "Block" }, { "BlockAdditional" }, { "BlockGroup" }, { "BlockVirtual" }, { "Cluster" }, { "ContentCompression" }, { "ContentEncoding" }, { "CuePoint" }, { "CueReference" }, { "CuetrackPosition" }, { "EncryptedBlock" }, { "SignatureElementList" }, { "SignatureSlot" }, { "SignedElement" }, { "SimpleBlock" }, { "SimpleTag" }, { "Tag" }, { "Target" }, { "TrackEntry" } }; var elementsEbml = XElement.Load(Path.Combine(Path.GetDirectoryName(this.Host.TemplateFile), XmlFile)).Elements() .Select(e => new Element { Name = e.Attribute("name").Value.Replace("CRC-32", "CRC32"), UseNameInsteadOfBinary = UseNameInsteadOfBinary(e.Attribute("name").Value), IsList = isList.Contains(e.Attribute("name").Value), Path = e.Attribute("path").Value, Level = e.Attribute("path").Value.Count(c => c == '\\'), Id = e.Attribute("id").Value, ElementType = e.Attribute("type").Value, Required = (e.Attribute("minOccurs") != null ? int.Parse(e.Attribute("minOccurs").Value) : 0) > 0, Documentation = e.Element(ns + "documentation") != null ? e.Element(ns + "documentation").Value : "" }); var matroskaElementsToSkip = new [] { "EBMLMaxIDLength", "EBMLMaxSizeLength" }; var elementsMatroska = XElement.Load(Path.Combine(Path.GetDirectoryName(this.Host.TemplateFile), MatroskaXmlFile)).Elements() .Select(e => new Element { Name = e.Attribute("name").Value, UseNameInsteadOfBinary = UseNameInsteadOfBinary(e.Attribute("name").Value), IsList = isList.Contains(e.Attribute("name").Value), Path = e.Attribute("path").Value, Level = e.Attribute("path").Value.Count(c => c == '\\'), Id = e.Attribute("id").Value, ElementType = e.Attribute("type").Value, Required = (e.Attribute("minOccurs") != null ? int.Parse(e.Attribute("minOccurs").Value) : 0) > 0, Documentation = e.Element(ns + "documentation") != null ? e.Element(ns + "documentation").Value : "" }) .Where(e => !matroskaElementsToSkip.Contains(e.Name)).ToArray(); var elements = elementsEbml.Union(elementsMatroska).OrderBy(e => e.Path).ToList(); var ebml = elements.FirstOrDefault(e => e.Name == "EBML"); Loop(elements, ebml, ""); var segment = elements.FirstOrDefault(e => e.Name == "Segment"); Loop(elements, segment, ""); var skip = new List { "Block", "SimpleBlock", "SimpleTag" }; foreach (var master in elements.Where(e => e.ElementType == "master" && !skip.Contains(e.Name)).OrderBy(e => e.Path)) { string className = master.Name; if (className == "Tag") { className = "TagItem"; } if (className == "ContentEncoding") { className = "ContentEncodingItem"; } #> [GeneratedCode("MatroskaModels.tt", "1.0.0.0")] public sealed class <#=className#> : BaseModel { <# var subs = master.SubElements.OrderBy(e => e.Path); foreach (var sub in subs) { string field = sub.Name; if (sub.Name == "Tag") { sub.Name = "TagItem"; } if (sub.Name == "ContentEncoding") { sub.Name = "ContentEncodingItem"; } string a; if (sub.IsList && field != "SignedElement") { a = string.Format(new string(' ', 4) + "[MatroskaElementDescriptor(MatroskaSpecification.{0}, typeof({1}))]", field, sub.Name); } else { a = string.Format(new string(' ', 4) + "[MatroskaElementDescriptor(MatroskaSpecification.{0})]", field); } WriteLine(a); WriteLine(new string(' ', 4) + GetProperty(sub)); if (sub != subs.Last()) { WriteLine(""); } } #> } <# } #> <#+ public bool UseNameInsteadOfBinary(string elementName) { return elementName.Contains("Block") && elementName != "BlockAddIDExtraData"; } public void Loop(List all, Element current, string parentPath) { current.SubElements = all.Where(e => e.Path.StartsWith(parentPath + "\\" + current.Name) && e.Level == current.Level + 1).ToList(); foreach (var sub in current.SubElements) { Loop(all, sub, current.Path); } } public string GetProperty(Element property) { string propertyType; switch (property.ElementType) { case "utf-8": propertyType = "string"; break; case "string": propertyType = "string"; break; case "binary": propertyType = property.UseNameInsteadOfBinary ? property.Name : "byte[]"; break; case "date": propertyType = "DateTime"; break; case "float": propertyType = "double"; break; case "uinteger": propertyType = "ulong"; break; case "integer": propertyType = "long"; break; case "master": propertyType = property.Name; break; default: propertyType = "???"; break; } string x; if (property.IsList) { x = string.Format("List<{0}>", propertyType) + (!property.Required ? "?" : ""); } else { x = propertyType + (!property.Required || property.ElementType == "binary" ? "?" : ""); } string name = property.Name; if (property.IsList) { if (property.Name.EndsWith("y")) { name = property.Name.Replace("y", "ies"); } else { name = name + "s"; } } string fixRequired = ""; if (property.Required && !propertyType.Contains("long") && !propertyType.Contains("double")) { fixRequired = " = null!;"; } return "public " + x + " " + name + " { get; set; }" + fixRequired; } public class Element { public string Name; public bool UseNameInsteadOfBinary; public bool IsList; public string Path; public string Id; public string ElementType; public bool Required; public string Documentation; public int Level; public List SubElements = new List(); } #>