Skip to content

Instantly share code, notes, and snippets.

@volgar1x
Created April 24, 2013 08:45
Show Gist options
  • Save volgar1x/5450687 to your computer and use it in GitHub Desktop.
Save volgar1x/5450687 to your computer and use it in GitHub Desktop.
<#@ assembly name="System.dll" #>
<#@ import namespace="System" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text.RegularExpressions" #>
<#@ import namespace="DofusProtocolBuilder" #>
<#@ import namespace="DofusProtocolBuilder.Parsing" #>
<#@ import namespace="DofusProtocolBuilder.XmlPatterns" #>
<#+
bool IsInherited(XmlMessage msg)
{
return !string.IsNullOrEmpty(msg.Heritage) && msg.Heritage != "Message";
}
bool IsInherited(XmlType type)
{
return !string.IsNullOrEmpty(type.Heritage) && type.Heritage != "Object";
}
XmlMessage GetSupertype(XmlMessage msg)
{
return Program.Configuration.XmlMessagesProfile.SearchXmlPattern(msg.Heritage);
}
IEnumerable<XmlField> GetAllFields(XmlMessage msg)
{
if (msg == null)
return new XmlField[0];
if (!IsInherited(msg))
return msg.Fields;
var supertype = GetSupertype(msg);
return GetAllFields(supertype).Concat(msg.Fields);
}
XmlField[] GetHierarchyFields(XmlMessage message)
{
if (message.Heritage == string.Empty ||
message.Heritage == "Message")
return new XmlField[0];
var baseMessage = Program.Configuration.XmlMessagesProfile.SearchXmlPattern(message.Heritage);
if (baseMessage == null)
return new XmlField[0];
return GetHierarchyFields(baseMessage).Concat(baseMessage.Fields).ToArray();
}
XmlField[] GetHierarchyFields(XmlType type)
{
if (type.Heritage == string.Empty ||
type.Heritage == "Object")
return new XmlField[0];
var baseType = Program.Configuration.XmlTypesProfile.SearchXmlPattern(type.Heritage);
if (baseType == null)
return new XmlField[0];
return GetHierarchyFields(baseType).Concat(baseType.Fields).ToArray();
}
void WriteIOMethodStatements(IEnumerable<XmlField> fields, bool serializeMethod)
{
bool limitDefined = false;
int? flagsCount = null;
int? lastFlagOffset = null;
foreach(var field in fields)
{
string limit = field.Limit;
string type = field.Type;
string name = field.Name;
bool array = false;
if (type.EndsWith("[]"))
{
array = true;
type = type.Substring(0, type.Length - 2);
if (!serializeMethod) // read
{
WriteLine(string.Format("{0} = mutable.Seq.empty[{1}]", name, GetRealType(type)));
WriteLine("for (i <- 0 to buf.readUShort()) {");
PushIndent(" ");
name += "(i)";
}
else // write
{
WriteLine("buf.writeUShort(" + field.Name + ".length)")
WriteLine("for (entry <- " + field.Name + ") {");
PushIndent(" ");
name = "entry";
}
}
if (serializeMethod &&
(lastFlagOffset.HasValue && flagsCount.HasValue) &&
(lastFlagOffset.Value >= 7 || !type.StartsWith("flag") ))
{
WriteLine("buf.writeByte(flag" + flagsCount + ");");
lastFlagOffset = null;
}
if (type.StartsWith("flag") && Regex.Match(type, @"flag\((\d+)\)").Success)
{
if (!lastFlagOffset.HasValue || lastFlagOffset.Value >= 7)
{
flagsCount = flagsCount.HasValue ? flagsCount + 1 : 1;
if (serializeMethod)
WriteLine("var flag" + flagsCount + " = 0.toShort");
else
WriteLine("var flag" + flagsCount + " = buf.readUByte()");
}
int flagOffset = int.Parse(match.Groups[1].Value);
lastFlagOffset = flagOffset;
if (serializeMethod)
WriteLine(string.Format("flag{0} = BooleanByteWrapper.setFlag(flag{0}, {1}, {2})", flagsCount, flagOffset, name));
else
WriteLine(string.Format("{0} = BooleanByteWrapper.getFlag(flag{1}, {2})", name, flagsCount, flagOffset));
}
else if (type.StartsWith("Types."))
{
if (serializeMethod)
WriteLine(string.Format("{0}.serialize(buf)", name));
else
{
WriteLine(string.Format("{0} = new {1}()", name, type));
WriteLine(string.Format("{0}.deserialize(reader)", name));
}
}
else if (type.StartsWith("instance of"))
{
if (serializeMethod)
{
WriteLine(string.Format("buf.writeShort({0}.typeId);", name));
WriteLine(string.Format("{0}.serialize(buf)", name));
}
else if (Regex.Match(type, @"instance of ([\w\d_\.]+)").Success)
{
string instanceType = match.Groups[1].Value;
WriteLine(string.Format("{0} = network.Types.build(buf.readShort())"));
WriteLine(string.Format("{0}.deserialize(buf)", name));
}
else
Error(string.Format("Type {0} doesn't match 'instance of ([\\w\\d_\\.]+)'", type));
}
else
{
if (serializeMethod)
WriteLine(string.Format("buf.write{0}({1})", GetIOMethodTypeName(type), name));
else
WriteLine(string.Format("{0} = buf.read{1}()", name, GetIOMethodTypeName(type)));
}
if (!string.IsNullOrEmpty(field.Condition))
{
if (!serializeMethod)
{
WriteLine("if (" + field.Condition + ")");
PushIndent(" ");
WriteLine(string.Format("throw new Exception(\"Forbidden value on {0} = \" + {0} + \", " +
"it doesn't respect the following condition : {1}\")", name, field.Condition));
PopIndent();
}
}
if (array)
{
PopIndent();
WriteLine("}");
}
}
if (lastFlagOffset.HasValue)
{
if (serializeMethod)
WriteLine("buf.writeUByte(flag" + flagsCount + ")");
}
}
string Capitalize(string str)
{
return char.ToUpper(str [0]) + str.Substring(1);
}
bool IsArray(string rawType)
{
return Regex.Match(rawType, @"([\.\w\d_]+)\[\]").Success;
}
string GetRealType(string rawType)
{
if (rawType.StartsWith("instance of "))
rawType = rawType.Replace("instance of ", "");
if (rawType.StartsWith("Types."))
rawType = rawType.Replace("Types.", "type.");
if (rawType.EndsWith("[]"))
{
var underlying = GetRealType(rawType.Substring(0, rawType.Length - 2));
return "mutable.Seq[" + underlying + "]";
}
if (rawType.StartsWith("flag"))
return "Boolean";
return GetIOMethodTypeName(rawType);
}
string GetIOMethodTypeName(string rawType)
{
if (rawType.StartsWith("instance of "))
rawType = rawType.Replace("instance of ", "");
if (rawType == "utf")
return "String";
if (rawType == "sbyte")
return "Byte";
if (rawType == "byte")
return "UByte";
char[] letters = rawType.ToCharArray();
letters[0] = char.ToUpper(letters[0]);
if (rawType.StartsWith("u")) letters[1] = char.ToUpper(letters[1]);
return new string(letters);
}
#>
<#@ template language="C#" debug="true" #>
<#@ output extension=".cs" #>
<#@ assembly name="System.dll" #>
<#@ import namespace="System" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="DofusProtocolBuilder.Parsing" #>
<#@ parameter name="Message" type="DofusProtocolBuilder.XmlPatterns.XmlMessage" #>
<#@ parameter name="Profile" type="DofusProtocolBuilder.Profiles.ParsingProfile" #>
<#@ include file="./Helper.tt"#>
// Generated by DofusProtocolBuilder by bouh2 on <#= DateTime.Now #>
// Scala version by Blackrush for github.com/Emudofus/Mambo
package <#= Profile.OutPutNamespace #>.messages
import collection.mutable
import org.mambo.core.io.Buffer
import <#= Profile.OutPutNamespace #>.{Serializable, Deserializer, EmptyMessage, types, enums}
<#
var fields = GetAllFields(Message);
if (fields.Count() <= 0)
{
WriteLine(string.Format("case object {0} extends EmptyMessage({1}) {{", Message.Name, Message.Id));
PushIndent(" ");
WriteLine(string.Format("type Target = {0}.type", Message.Name));
WriteLine("def deserializer = this");
PopIndent();
WriteLine("}");
}
else
{
}
#>
Compilation de la transformation : ; attendu
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment