#@ 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();
}
#>