mirror of
https://github.com/SteamAutoCracks/DepotDownloaderMod.git
synced 2026-02-14 05:40:57 +01:00
451 lines
18 KiB
C#
451 lines
18 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
|
|
namespace SteamLanguageParser
|
|
{
|
|
class ObjCImplementationGen : ObjCGenBase
|
|
{
|
|
public override void EmitNamespace(StringBuilder sb, bool end, string nspace)
|
|
{
|
|
if (!end)
|
|
{
|
|
sb.AppendLine("#import \"SteamLanguageInternal.h\"");
|
|
sb.AppendLine("#import \"_SKMsgUtil.h\"");
|
|
sb.AppendLine("#import <CRBoilerplate/CRBoilerplate.h>");
|
|
sb.AppendLine();
|
|
}
|
|
}
|
|
|
|
public string GetUpperName(string name)
|
|
{
|
|
return name.Substring(0, 1).ToUpper() + name.Remove(0, 1);
|
|
}
|
|
|
|
protected override void EmitEnumNode(EnumNode enode, StringBuilder sb, int level)
|
|
{
|
|
// Do nothing. Enums are already defined in the @interface generator.
|
|
}
|
|
|
|
protected override void EmitClassNode(ClassNode cnode, StringBuilder sb, int level)
|
|
{
|
|
EmitClassDef(cnode, sb, level, false);
|
|
|
|
EmitClassIdentity(cnode, sb, level + 1);
|
|
|
|
int baseSize = EmitClassProperties(cnode, sb, level + 1);
|
|
EmitClassConstructor(cnode, sb, level + 1);
|
|
EmitClassDestructor(cnode, sb, level + 1);
|
|
|
|
EmitClassSerializer(cnode, sb, level + 1, baseSize);
|
|
EmitClassDeserializer(cnode, sb, level + 1, baseSize);
|
|
|
|
EmitClassDef(cnode, sb, level, true);
|
|
}
|
|
|
|
private void EmitClassDef(ClassNode cnode, StringBuilder sb, int level, bool end)
|
|
{
|
|
string padding = new String('\t', level);
|
|
|
|
if (end)
|
|
{
|
|
sb.AppendLine(padding + "@end");
|
|
sb.AppendLine();
|
|
return;
|
|
}
|
|
|
|
|
|
if (cnode.Name.Contains("Hdr"))
|
|
{
|
|
sb.AppendLine(padding + "//[StructLayout( LayoutKind.Sequential )]");
|
|
}
|
|
|
|
sb.AppendLine(padding + "@implementation _SK" + cnode.Name);
|
|
sb.AppendLine();
|
|
}
|
|
|
|
private void EmitClassIdentity(ClassNode cnode, StringBuilder sb, int level)
|
|
{
|
|
string padding = new String('\t', level);
|
|
|
|
if (cnode.Ident != null)
|
|
{
|
|
if (cnode.Name.Contains("MsgGC"))
|
|
{
|
|
sb.AppendLine(padding + "- (EGCMsg) eMsg");
|
|
sb.AppendLine(padding + "{");
|
|
sb.AppendLine(padding + "\treturn " + EmitType(cnode.Ident) + ";");
|
|
sb.AppendLine(padding + "}");
|
|
sb.AppendLine();
|
|
}
|
|
else
|
|
{
|
|
sb.AppendLine(padding + "- (EMsg) eMsg");
|
|
sb.AppendLine(padding + "{");
|
|
sb.AppendLine(padding + "\treturn " + EmitType(cnode.Ident) + ";");
|
|
sb.AppendLine(padding + "}");
|
|
sb.AppendLine();
|
|
}
|
|
}
|
|
else if (cnode.Name.Contains("Hdr"))
|
|
{
|
|
if (cnode.Name.Contains("MsgGC"))
|
|
{
|
|
if (cnode.childNodes.Find(node => node.Name == "msg") != null)
|
|
{
|
|
sb.AppendLine(padding + "- (void) setEMsg:(EGCMsg)_msg");
|
|
sb.AppendLine(padding + "{");
|
|
sb.AppendLine(padding + "\tself.msg = _msg;");
|
|
sb.AppendLine(padding + "}");
|
|
sb.AppendLine();
|
|
}
|
|
else
|
|
{
|
|
// this is required for a gc header which doesn't have an emsg
|
|
sb.AppendLine(padding + "- (void) setEMsg:(EGCMsg)msg { }");
|
|
sb.AppendLine();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sb.AppendLine(padding + "- (void) setEMsg:(EMsg)_msg");
|
|
sb.AppendLine(padding + "{");
|
|
sb.AppendLine(padding + "\tself.msg = _msg;");
|
|
sb.AppendLine(padding + "}");
|
|
sb.AppendLine();
|
|
}
|
|
}
|
|
}
|
|
|
|
private int EmitClassProperties(ClassNode cnode, StringBuilder sb, int level)
|
|
{
|
|
string padding = new String('\t', level);
|
|
int baseClassSize = 0;
|
|
|
|
foreach (PropNode prop in cnode.childNodes)
|
|
{
|
|
string typestr = EmitType(prop.Type);
|
|
string propName = GetPropertyName(prop.Name);
|
|
|
|
if (prop.Flags != null && prop.Flags == "const")
|
|
{
|
|
sb.AppendLine(padding + "+ (" + typestr + ") " + GetUpperName(propName));
|
|
sb.AppendLine(padding + "{");
|
|
sb.AppendLine(padding + "\t return " + EmitType(prop.Default) + ";");
|
|
sb.AppendLine(padding + "}");
|
|
continue;
|
|
}
|
|
|
|
int size = CodeGenerator.GetTypeSize(prop);
|
|
baseClassSize += size;
|
|
|
|
sb.AppendLine(padding + "// Static size: " + size);
|
|
|
|
if (prop.Flags != null && prop.Flags == "steamidmarshal" && typestr == "ulong")
|
|
{
|
|
sb.AppendLine(padding + string.Format("private {0} {1};", typestr, prop.Name));
|
|
sb.AppendLine(padding + "public SteamID " + propName + " { get { return new SteamID( " + prop.Name + " ); } set { " + prop.Name + " = value.ConvertToUint64(); } }");
|
|
}
|
|
else if (prop.Flags != null && prop.Flags == "boolmarshal" && typestr == "byte")
|
|
{
|
|
sb.AppendLine(padding + string.Format("private {0} {1};", typestr, prop.Name));
|
|
sb.AppendLine(padding + "public bool " + propName + " { get { return ( " + prop.Name + " == 1 ); } set { " + prop.Name + " = ( byte )( value ? 1 : 0 ); } }");
|
|
}
|
|
else if (prop.Flags != null && prop.Flags == "gameidmarshal" && typestr == "ulong")
|
|
{
|
|
sb.AppendLine(padding + string.Format("private {0} {1};", typestr, prop.Name));
|
|
sb.AppendLine(padding + "public GameID " + propName + " { get { return new GameID( " + prop.Name + " ); } set { " + prop.Name + " = value.ToUint64(); } }");
|
|
}
|
|
else
|
|
{
|
|
int temp;
|
|
if (!String.IsNullOrEmpty(prop.FlagsOpt) && Int32.TryParse(prop.FlagsOpt, out temp))
|
|
{
|
|
typestr += "[]";
|
|
}
|
|
|
|
sb.AppendLine(padding + "@synthesize " + propName + ";");
|
|
}
|
|
}
|
|
|
|
sb.AppendLine();
|
|
|
|
return baseClassSize;
|
|
}
|
|
|
|
private void EmitClassConstructor(ClassNode cnode, StringBuilder sb, int level)
|
|
{
|
|
string padding = new String('\t', level);
|
|
|
|
sb.AppendLine(padding + "- (id) init");
|
|
sb.AppendLine(padding + "{");
|
|
sb.AppendLine(padding + "\tself = [super init];");
|
|
sb.AppendLine(padding + "\tif (self) {");
|
|
|
|
if (cnode.Parent != null)
|
|
{
|
|
sb.AppendLine(padding + "\t\tself.header = new " + EmitType(cnode.Parent) + "();");
|
|
sb.AppendLine(padding + "\t\t[self.header setMsg:[self eMsg]];");
|
|
}
|
|
|
|
foreach (PropNode prop in cnode.childNodes)
|
|
{
|
|
Symbol defsym = prop.Default;
|
|
string defflags = prop.Flags;
|
|
|
|
string symname = GetUpperName(prop.Name);
|
|
string ctor = EmitType(defsym);
|
|
|
|
if (defflags != null && defflags == "proto")
|
|
{
|
|
ctor = "nil";
|
|
}
|
|
else if (defsym == null)
|
|
{
|
|
if (!String.IsNullOrEmpty(prop.FlagsOpt))
|
|
{
|
|
ctor = "nil";
|
|
}
|
|
else if (prop.Type as StrongSymbol != null && ((StrongSymbol)prop.Type).Class.Name.StartsWith("E"))
|
|
{
|
|
ctor = "(" + ((StrongSymbol)prop.Type).Class.Name + ") 0";
|
|
}
|
|
else
|
|
{
|
|
ctor = "0";
|
|
}
|
|
}
|
|
if (defflags != null && (defflags == "steamidmarshal" || defflags == "gameidmarshal" || defflags == "boolmarshal"))
|
|
{
|
|
symname = prop.Name;
|
|
}
|
|
else if (defflags != null && defflags == "const")
|
|
{
|
|
continue;
|
|
}
|
|
|
|
sb.AppendLine(padding + "\t\tself." + GetPropertyName(symname) + " = " + ctor + ";");
|
|
}
|
|
|
|
sb.AppendLine(padding + "\t}");
|
|
sb.AppendLine(padding + "\treturn self;");
|
|
sb.AppendLine(padding + "}");
|
|
}
|
|
|
|
private void EmitClassDestructor(ClassNode cnode, StringBuilder sb, int level)
|
|
{
|
|
string padding = new String('\t', level);
|
|
|
|
sb.AppendLine(padding + "- (void) dealloc");
|
|
sb.AppendLine(padding + "{");
|
|
|
|
foreach (PropNode prop in cnode.childNodes)
|
|
{
|
|
Symbol defsym = prop.Default;
|
|
string defflags = prop.Flags;
|
|
|
|
string symname = GetUpperName(prop.Name);
|
|
string ctor = EmitType(defsym);
|
|
|
|
if (defflags != null && defflags == "proto")
|
|
{
|
|
//sb.AppendLine(padding + "\tdelete " + GetPropertyName(symname) + ";");
|
|
}
|
|
}
|
|
|
|
sb.AppendLine(padding + "}");
|
|
}
|
|
|
|
private void EmitClassSerializer(ClassNode cnode, StringBuilder sb, int level, int baseSize)
|
|
{
|
|
string padding = new String('\t', level);
|
|
|
|
sb.AppendLine();
|
|
sb.AppendLine(padding + "- (void) serialize:(NSMutableData *)_data");
|
|
sb.AppendLine(padding + "{");
|
|
sb.AppendLine();
|
|
|
|
if (cnode.Parent != null)
|
|
{
|
|
sb.AppendLine(padding + "\t[self.header serialize:data];");
|
|
sb.AppendLine();
|
|
}
|
|
|
|
foreach (PropNode prop in cnode.childNodes)
|
|
{
|
|
string typestr = EmitType(prop.Type);
|
|
int size = CodeGenerator.GetTypeSize(prop);
|
|
|
|
if (size == 0)
|
|
{
|
|
if (prop.Flags != null && prop.Flags == "proto")
|
|
{
|
|
//sb.AppendLine(padding + "\t[_data appendProtobuf:" + GetPropertyName(prop.Name) + "];");
|
|
}
|
|
else
|
|
{
|
|
sb.AppendLine(padding + "\tMemoryStream ms" + GetUpperName(prop.Name) + " = " + GetUpperName(prop.Name) + ".serialize();");
|
|
}
|
|
}
|
|
}
|
|
|
|
if (cnode.Parent != null)
|
|
{
|
|
sb.AppendLine(padding + "\tmsHeader.CopyTo( msBuffer );");
|
|
}
|
|
|
|
// next emit writers
|
|
foreach (PropNode prop in cnode.childNodes)
|
|
{
|
|
string typecast = "";
|
|
string propName = GetUpperName(prop.Name);
|
|
|
|
if (prop.Type is StrongSymbol && ((StrongSymbol)prop.Type).Class is EnumNode)
|
|
{
|
|
EnumNode enode = ((StrongSymbol)prop.Type).Class as EnumNode;
|
|
|
|
if (enode.Type is WeakSymbol)
|
|
typecast = "(" + ((WeakSymbol)enode.Type).Identifier + ")";
|
|
else
|
|
typecast = "(int)";
|
|
}
|
|
|
|
if (prop.Flags != null)
|
|
{
|
|
if (prop.Flags == "steamidmarshal" || prop.Flags == "gameidmarshal" || prop.Flags == "boolmarshal")
|
|
{
|
|
propName = prop.Name;
|
|
}
|
|
else if (prop.Flags == "proto")
|
|
{
|
|
sb.AppendLine(padding + "\t[_data appendData:[" + GetPropertyName(propName) + " data]];");
|
|
continue;
|
|
}
|
|
else if (prop.Flags == "const")
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (prop.Flags == "protomask")
|
|
{
|
|
if (prop.Default is StrongSymbol && (prop.Default as StrongSymbol).Class.Name == "EGCMsg")
|
|
propName = "[_SKMsgUtil makeGCMsg:" + GetPropertyName(propName) + " isProtobuf:YES]";
|
|
else
|
|
propName = "[_SKMsgUtil makeMsg:" + GetPropertyName(propName) + " isProtobuf:YES]";
|
|
}
|
|
|
|
int size = CodeGenerator.GetTypeSize(prop);
|
|
string typestr = CodeGenerator.GetTypeOfSize(size, SupportsUnsignedTypes());
|
|
|
|
if (!String.IsNullOrEmpty(prop.FlagsOpt))
|
|
{
|
|
sb.AppendLine(padding + "\t[_data appendData:" + GetPropertyName(propName) + "];");
|
|
}
|
|
else
|
|
{
|
|
sb.AppendLine(padding + "\t[_data cr_append" + readerTypeMap[typestr] + ":" + GetPropertyName(propName) + "];");
|
|
}
|
|
|
|
//sb.AppendLine(padding + "\tbw.Write( " + typecast + propName + " );");
|
|
}
|
|
|
|
sb.AppendLine();
|
|
|
|
//sb.AppendLine();
|
|
//sb.AppendLine(padding + "\tmsBuffer.Seek( 0, SeekOrigin.Begin );");
|
|
sb.AppendLine(padding + "}");
|
|
}
|
|
|
|
private void EmitClassSize(ClassNode cnode, StringBuilder sb, int level)
|
|
{
|
|
}
|
|
|
|
private void EmitClassDeserializer(ClassNode cnode, StringBuilder sb, int level, int baseSize)
|
|
{
|
|
string padding = new String('\t', level);
|
|
|
|
sb.AppendLine();
|
|
sb.AppendLine(padding + "- (void) deserializeWithReader:(CRDataReader *)reader");
|
|
sb.AppendLine(padding + "{");
|
|
|
|
if (cnode.Parent != null)
|
|
{
|
|
sb.AppendLine(padding + "[self.header deserialize:reader]");
|
|
}
|
|
|
|
foreach (PropNode prop in cnode.childNodes)
|
|
{
|
|
string typestr = EmitType(prop.Type);
|
|
int size = CodeGenerator.GetTypeSize(prop);
|
|
|
|
string defflags = prop.Flags;
|
|
string symname = GetUpperName(prop.Name);
|
|
|
|
if (defflags != null && (defflags == "steamidmarshal" || defflags == "gameidmarshal" || defflags == "boolmarshal"))
|
|
{
|
|
symname = prop.Name;
|
|
}
|
|
else if (defflags != null && defflags == "const")
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (size == 0)
|
|
{
|
|
if (prop.Flags != null && prop.Flags == "proto")
|
|
{
|
|
if (prop.FlagsOpt != null)
|
|
{
|
|
sb.AppendLine(padding + "\tNSData * " + GetPropertyName(prop.Name) + "Data = [reader readDataOfLength:" + prop.FlagsOpt + "];");
|
|
sb.AppendLine(padding + "\tself." + GetPropertyName(prop.Name) + " = [" + GetLastPartNameFromDottedType(EmitType(prop.Type)).Trim(' ', '*') + " parseFromData:" + GetPropertyName(prop.Name) + "Data];");
|
|
}
|
|
else
|
|
{
|
|
sb.AppendLine(padding + "\tNSData * " + GetPropertyName(prop.Name) + "Data = [reader remainingData];");
|
|
sb.AppendLine(padding + "\t" + GetPropertyName(prop.Name) + " [" + GetLastPartNameFromDottedType(EmitType(prop.Type)).Trim(' ', '*') + " parseFromData:" + GetPropertyName(prop.Name) + "Data];");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sb.AppendLine(padding + "\t" + GetUpperName(prop.Name) + ".Deserialize( stream );");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
string typecast = "";
|
|
if (!readerTypeMap.ContainsKey(typestr))
|
|
{
|
|
typecast = "(" + typestr + ")";
|
|
typestr = CodeGenerator.GetTypeOfSize(size, SupportsUnsignedTypes());
|
|
}
|
|
|
|
string call;
|
|
if (!String.IsNullOrEmpty(prop.FlagsOpt))
|
|
{
|
|
call = "[reader readDataOfLength:" + prop.FlagsOpt + "]";
|
|
}
|
|
else
|
|
{
|
|
call = "[reader read" + readerTypeMap[typestr] + "]";
|
|
}
|
|
|
|
if (prop.Flags == "protomask")
|
|
{
|
|
if (prop.Default is StrongSymbol && (prop.Default as StrongSymbol).Class.Name == "EGCMsg")
|
|
call = "[_SKMsgUtil getGCMsg:(uint32_t)" + call + "]";
|
|
else
|
|
call = "[_SKMsgUtil getMsg:(uint32_t)" + call + "]";
|
|
}
|
|
|
|
sb.AppendLine(padding + "\tself." + GetPropertyName(symname) + " = " + typecast + call + ";");
|
|
}
|
|
}
|
|
|
|
|
|
sb.AppendLine(padding + "}");
|
|
}
|
|
}
|
|
}
|