void write_header(grammar.StructType value, SymbolTable symbolTable, TextWriter writer) { var full_name = value.FullName(); var typeName = GetCTypeName(full_name); var indent = string.Empty; foreach (var member in value.members()) { var memberName = member.definition.Name(); memberName = GetCTypeName(memberName)?.Trim(); var memberType = GetStorageType(member.definition, symbolTable); memberType = GetCTypeName(memberType); writer.WriteLine(); writer.WriteLine($"{indent}int {typeName?.Trim()}__{memberName}_get(struct {typeName}*object, {memberType}*value_out);"); writer.WriteLine($"{indent}int {typeName?.Trim()}__{memberName}_set(struct {typeName}*object, {memberType}*value_new);"); } }
public bool WriteType(grammar.StructType value, SymbolTable symbolTable, TextWriter writer) { var fullName = value.FullName(); var typeName = GetCTypeName(fullName); int index = fullName.LastIndexOf('.'); grammar.NamespaceType namespaceType = null; var indent = string.Empty; if (value.Parent(out var parent)) { namespaceType = parent as grammar.NamespaceType; var namespaceHeader = namespaceType.FullName(); var headerFileName = GetCTypeName(namespaceHeader); writer.WriteLine($"#include \"{headerFileName.TrimEnd()}.h\""); writer.WriteLine(); lock (_syncpoint) { if (!_headers.ContainsKey(namespaceHeader)) { _headers.Add(namespaceHeader, new TypeList()); } _headers[namespaceHeader].Add(value); } } writer.WriteLine($"{indent}struct {typeName?.Trim()}"); writer.WriteLine($"{indent}{{"); indent = new string(' ', 4); var members = value.members(); foreach (var member in members) { var memberName = member.definition.Name(); memberName = GetCTypeName(memberName); var memberType = GetStorageType(member.definition, symbolTable); memberType = GetCTypeName(memberType); writer.WriteLine($"{indent}int _{memberName?.Trim()}_exists;"); writer.WriteLine($"{indent}unsigned long _{memberName?.Trim()}_oridinal;"); switch (member.definition.Kind()) { default: { writer.WriteLine($"{indent}{memberType}_{memberName?.Trim()}_value;"); } break; } writer.WriteLine(); } indent = string.Empty; writer.WriteLine($"{indent}}};"); writer.WriteLine(); writer.WriteLine($"{indent}int {typeName?.Trim()}__initialize(struct {typeName}*object)"); writer.WriteLine($"{indent}{{"); indent = new string(' ', 4); writer.WriteLine($"{indent}// Zero the struct (default state) but retain all ordinal data."); writer.WriteLine($"{indent}memset(object, 0, sizeof({typeName?.Trim()}));"); writer.WriteLine(); foreach (var member in members) { var memberName = member.definition.Name(); memberName = GetCTypeName(memberName); writer.WriteLine($"{indent}object->_{memberName?.Trim()}_oridinal = {member.ordinal};"); } writer.WriteLine($"{indent}return 0;"); indent = string.Empty; writer.WriteLine($"{indent}}};"); writer.WriteLine(); writer.WriteLine($"{indent}int {typeName?.Trim()}__deserialize(struct {typeName}*object, FILE *stream)"); writer.WriteLine($"{indent}{{"); indent = new string(' ', 4); writer.WriteLine($"{indent}// code goes here"); writer.WriteLine($"{indent}return 0;"); indent = string.Empty; writer.WriteLine($"{indent}}};"); writer.WriteLine(); writer.WriteLine($"{indent}int {typeName?.Trim()}__serialize(struct {typeName}*object, FILE *stream)"); writer.WriteLine($"{indent}{{"); indent = new string(' ', 4); writer.WriteLine($"{indent}// code goes here"); writer.WriteLine($"{indent}return 0;"); indent = string.Empty; writer.WriteLine($"{indent}}};"); writer.WriteLine(); foreach (var member in members) { var memberName = member.definition.Name(); memberName = GetCTypeName(memberName)?.Trim(); var memberType = GetStorageType(member.definition, symbolTable); memberType = GetCTypeName(memberType); writer.WriteLine($"{indent}int {typeName?.Trim()}__{memberName}_get(struct {typeName}*object, {memberType}*value_out)"); writer.WriteLine($"{indent}{{"); indent = new string(' ', 4); writer.WriteLine($"{indent}if (!object->_{memberName}_exists)"); writer.WriteLine($"{new string(' ', 12)}return -1;"); writer.WriteLine(); writer.WriteLine($"{indent}*value_out = object->_{memberName}_value;"); writer.WriteLine($"{indent}return 0;"); indent = string.Empty; writer.WriteLine($"{indent}}}"); writer.WriteLine(); writer.WriteLine($"{indent}int {typeName?.Trim()}__{memberName}_set(struct {typeName}*object, {memberType}*value_new)"); writer.WriteLine($"{indent}{{"); indent = new string(' ', 4); writer.WriteLine($"{indent}object->_{memberName}_value = *value_new;"); writer.WriteLine($"{indent}object->_{memberName}_exists = 1;"); writer.WriteLine($"{indent}return 0;"); indent = string.Empty; writer.WriteLine($"{indent}}}"); writer.WriteLine(); } return(true); }
public bool WriteType(grammar.StructType structType, SymbolTable symbolTable, TextWriter writer) { var full_name = structType.FullName(); grammar.NamespaceType namespace_type = null; string indent = string.Empty; var members = System.Linq.Enumerable.OrderBy(structType.members(), x => x.definition.Name()); if (structType.Parent(out var parent)) { namespace_type = parent as grammar.NamespaceType; writer.WriteLine($"namespace {namespace_type.FullName()}"); writer.WriteLine("{"); indent = new string(' ', 4); } writer.WriteLine($"{indent}partial class {structType.Name()} : WireType.IWireType"); writer.WriteLine($"{indent}{{"); indent = new string(' ', 8); writer.WriteLine($"{indent}public {structType.Name()}()"); writer.WriteLine($"{indent}{{ }}"); writer.WriteLine(); foreach (var member in members) { var storage_type = GetTypeString(member.definition, symbolTable, false); writer.WriteLine($"{indent}private WireType.StructMember<{storage_type}> _{member.definition.Name()} = new WireType.StructMember<{storage_type}>({member.ordinal});"); } writer.WriteLine(); foreach (var member in members) { var export_type = GetTypeString(member.definition, symbolTable, true); var actual_type = GetTypeString(member.definition, symbolTable, false); var member_kind = member.definition.Kind(); // public void definition(kind value) { _exists = true; _value = value; } writer.WriteLine($"{indent}public void {member.definition.Name()}({export_type} value)"); writer.WriteLine($"{indent}{{"); indent = new string(' ', 12); switch (member_kind) { case grammar.MemberKind.blobList: { writer.WriteLine($"{indent}if (value is null)"); writer.WriteLine($"{indent}{{"); indent = new string(' ', 16); writer.WriteLine($"{indent}_{member.definition.Name()}.Value = null;"); writer.WriteLine($"{indent}return;"); indent = new string(' ', 12); writer.WriteLine($"{indent}}}"); writer.WriteLine(); writer.WriteLine($"{indent}_{member.definition.Name()}.Value = (value.Count == 0)"); indent = new string(' ', 16); writer.WriteLine($"{indent}? System.Array.Empty<byte[]>()"); writer.WriteLine($"{indent}: System.Linq.Enumerable.ToArray(value);"); indent = new string(' ', 12); } break; case grammar.MemberKind.blobType: { writer.WriteLine($"{indent}if (value is null)"); writer.WriteLine($"{indent}{{"); indent = new string(' ', 16); writer.WriteLine($"{indent}_{member.definition.Name()}.Value = null;"); writer.WriteLine($"{indent}return;"); indent = new string(' ', 12); writer.WriteLine($"{indent}}}"); writer.WriteLine(); writer.WriteLine($"{indent}_{member.definition.Name()}.Value = (value.Length == 0)"); indent = new string(' ', 16); writer.WriteLine($"{indent}? System.Array.Empty<byte>()"); writer.WriteLine($"{indent}: value;"); indent = new string(' ', 12); } break; case grammar.MemberKind.enumList: case grammar.MemberKind.f32List: case grammar.MemberKind.f64List: case grammar.MemberKind.i32List: case grammar.MemberKind.i64List: case grammar.MemberKind.structList: case grammar.MemberKind.u32List: case grammar.MemberKind.u64List: { writer.WriteLine($"{indent}if (value is null || value.Count == 0)"); writer.WriteLine($"{indent}{{"); indent = new string(' ', 16); writer.WriteLine($"{indent}_{member.definition.Name()}.Value = System.Array.Empty<{actual_type.Substring(0, actual_type.Length - 2)}>();"); writer.WriteLine($"{indent}return;"); indent = new string(' ', 12); writer.WriteLine($"{indent}}}"); writer.WriteLine(); writer.WriteLine($"{indent}// Public export is a read-only list, whereas an array was recorded."); writer.WriteLine($"{indent}_{member.definition.Name()}.Value = System.Linq.Enumerable.ToArray(value);"); } break; case grammar.MemberKind.stringType: { writer.WriteLine($"{indent}if (value is null)"); writer.WriteLine($"{indent}{{"); indent = new string(' ', 16); writer.WriteLine($"{indent}_{member.definition.Name()}.Value = null;"); writer.WriteLine($"{indent}return;"); indent = new string(' ', 12); writer.WriteLine($"{indent}}}"); writer.WriteLine(); writer.WriteLine($"{indent}// NetFx System.String are UTF-16 encoded, whereas UTF-8 values were recorded."); writer.WriteLine($"{indent}_{member.definition.Name()}.Value = System.Text.Encoding.UTF8.GetBytes(value);"); } break; case grammar.MemberKind.stringList: { writer.WriteLine($"{indent}if (value is null)"); writer.WriteLine($"{indent}{{"); indent = new string(' ', 16); writer.WriteLine($"{indent}_{member.definition.Name()}.Value = null;"); writer.WriteLine($"{indent}return;"); indent = new string(' ', 12); writer.WriteLine($"{indent}}}"); writer.WriteLine(); writer.WriteLine($"{indent}if (value.Count == 0)"); writer.WriteLine($"{indent}{{"); indent = new string(' ', 16); writer.WriteLine($"{indent}_{member.definition.Name()}.Value = System.Array.Empty<byte[]>();"); indent = new string(' ', 12); writer.WriteLine($"{indent}}}"); writer.WriteLine($"{indent}else"); writer.WriteLine($"{indent}{{"); indent = new string(' ', 16); writer.WriteLine($"{indent}var values = new byte[value.Count][];"); writer.WriteLine(); writer.WriteLine($"{indent}// NetFx System.String are UTF-16 encoded, whereas UTF-8 values were recorded."); writer.WriteLine($"{indent}for (int i = 0; i < value.Count; i += 1)"); writer.WriteLine($"{indent}{{"); indent = new string(' ', 20); writer.WriteLine($"{indent}values[i] = (value[i] is null || value[i].Length == 0)"); indent = new string(' ', 24); writer.WriteLine($"{indent}? System.Array.Empty<byte>()"); writer.WriteLine($"{indent}: System.Text.Encoding.UTF8.GetBytes(value[i]);"); indent = new string(' ', 16); writer.WriteLine($"{indent}}}"); writer.WriteLine(); writer.WriteLine($"{indent}_{member.definition.Name()}.Value = values;"); indent = new string(' ', 12); writer.WriteLine($"{indent}}}"); } break; case grammar.MemberKind.timespanType: { writer.WriteLine($"{indent}// NetFx System.TimeSpan has 100-nanosecond granularity, whereas nanosecond values were recorded."); writer.WriteLine($"{indent}_{member.definition.Name()}.Value = value.Ticks * 100L;"); } break; case grammar.MemberKind.timestampType: { writer.WriteLine($"{indent}// NetFx System.DateTime has 100-nanosecond granularity, whereas millisecond values were recorded."); writer.WriteLine($"{indent}_{member.definition.Name()}.Value = value.Ticks / 10000L;"); } break; default: { writer.WriteLine($"{indent}_{member.definition.Name()}.Value = value;"); } break; } indent = new string(' ', 8); writer.WriteLine($"{indent}}}"); writer.WriteLine(); // public bool definition(out kind value) { if (!_exits) { value = default(kind); return false; } value = _value; return true; } writer.WriteLine($"{indent}public bool {member.definition.Name()}(out {export_type} value)"); writer.WriteLine($"{indent}{{"); indent = new string(' ', 12); writer.WriteLine($"{indent}if (!_{member.definition.Name()}.Exists)"); writer.WriteLine($"{indent}{{"); indent = new string(' ', 16); writer.WriteLine($"{indent}value = default({export_type});"); writer.WriteLine($"{indent}return false;"); indent = new string(' ', 12); writer.WriteLine($"{indent}}}"); writer.WriteLine(); switch (member.definition.Kind()) { case grammar.MemberKind.stringType: { writer.WriteLine($"{indent}// NetFx System.String are UTF-16 encoded, whereas UTF-8 values were recorded."); writer.WriteLine($"{indent}value = System.Text.Encoding.UTF8.GetString(_{member.definition.Name()}.Value);"); } break; case grammar.MemberKind.stringList: { writer.WriteLine($"{indent}var values = new System.Collections.Generic.List<string>(_{member.definition.Name()}.Value.Length);"); writer.WriteLine(); writer.WriteLine($"{indent}// NetFx System.String are UTF-16 encoded, whereas UTF-8 values were recorded."); writer.WriteLine($"{indent}foreach (byte[] bytes in _{member.definition.Name()}.Value)"); writer.WriteLine($"{indent}{{"); indent = new string(' ', 16); writer.WriteLine($"{indent}string strval = bytes.Length == 0"); indent = new string(' ', 20); writer.WriteLine($"{indent}? string.Empty"); writer.WriteLine($"{indent}: System.Text.Encoding.UTF8.GetString(bytes);"); writer.WriteLine(); indent = new string(' ', 16); writer.WriteLine($"{indent}values.Add(strval);"); indent = new string(' ', 12); writer.WriteLine($"{indent}}}"); writer.WriteLine(); writer.WriteLine($"{indent}value = values;"); } break; case grammar.MemberKind.timespanType: { writer.WriteLine($"{indent}// NetFx System.TimeSpan has 100-nanosecond granularity, whereas nanosecond values were recorded."); writer.WriteLine($"{indent}value = new System.TimeSpan(_{member.definition.Name()}.Value / 100L);"); } break; case grammar.MemberKind.timestampType: { writer.WriteLine($"{indent}// NetFx System.DateTime has 100-nanosecond granularity, whereas millisecond values were recorded."); writer.WriteLine($"{indent}value = new System.DateTime(10000L * _{member.definition.Name()}.Value);"); } break; default: { writer.WriteLine($"{indent}value = _{member.definition.Name()}.Value;"); } break; } writer.WriteLine($"{indent}return true;"); indent = new string(' ', 8); writer.WriteLine($"{indent}}}"); writer.WriteLine(); } writer.WriteLine($"{indent}public unsafe bool ReadFrom(WireType.WireTypeReader reader)"); writer.WriteLine($"{indent}{{"); indent = new string(' ', 12); writer.WriteLine($"{indent}if (reader is null)"); writer.WriteLine($"{new string(' ', 16)}throw new System.ArgumentNullException(nameof(reader));"); writer.WriteLine(); writer.WriteLine($"{indent}long size = reader.Current.Size;"); writer.WriteLine($"{indent}long alreadyRead = reader.TotalRead;"); writer.WriteLine(); writer.WriteLine($"{indent}while (reader.TotalRead - alreadyRead < size)"); writer.WriteLine($"{indent}{{"); indent = new string(' ', 16); writer.WriteLine($"{indent}if (!reader.Read(out WireType.TypeHeader header))"); writer.WriteLine($"{new string(' ', 20)}return false;"); writer.WriteLine(); writer.WriteLine($"{indent}switch (header.Ordinal)"); writer.WriteLine($"{indent}{{"); indent = new string(' ', 20); members = System.Linq.Enumerable.OrderBy(members, x => x.ordinal); foreach (var member in members) { var member_kind = member.definition.Kind(); var type_kind = GetTypeKind(member_kind); var storage_type = GetStorageTypeName(member.definition, symbolTable); writer.WriteLine($"{indent}case {member.ordinal}: // {member.definition.Name()}"); writer.WriteLine($"{indent}{{"); indent = new string(' ', 24); writer.WriteLine($"{indent}if (header.Kind != WireType.TypeKind.{type_kind})"); writer.WriteLine($"{indent}{{"); indent = new string(' ', 28); writer.WriteLine($"{indent}reader.Skip();"); indent = new string(' ', 24); writer.WriteLine($"{indent}}}"); writer.WriteLine(); switch (member_kind) { case grammar.MemberKind.blobList: case grammar.MemberKind.stringList: { writer.WriteLine($"{indent}if (reader.Read(out byte[][] values))"); writer.WriteLine($"{indent}{{"); indent = new string(' ', 28); writer.WriteLine($"{indent}_{member.definition.Name()}.Value = values;"); indent = new string(' ', 24); writer.WriteLine($"{indent}}}"); } break; case grammar.MemberKind.blobType: case grammar.MemberKind.stringType: { writer.WriteLine($"{indent}if (reader.Read(out byte[] value))"); writer.WriteLine($"{indent}{{"); indent = new string(' ', 28); writer.WriteLine($"{indent}_{member.definition.Name()}.Value = value;"); indent = new string(' ', 24); writer.WriteLine($"{indent}}}"); } break; case grammar.MemberKind.enumList: { writer.WriteLine($"{indent}if (reader.Read(out int[] temp))"); writer.WriteLine($"{indent}{{"); indent = new string(' ', 28); writer.WriteLine($"{indent}var values = new {storage_type}[temp.Length];"); writer.WriteLine(); writer.WriteLine($"{indent}System.Buffer.BlockCopy(temp, 0, values, 0, temp.Length * sizeof(int));"); writer.WriteLine(); writer.WriteLine($"{indent}_{member.definition.Name()}.Value = values;"); indent = new string(' ', 24); writer.WriteLine($"{indent}}}"); } break; case grammar.MemberKind.enumType: { writer.WriteLine($"{indent}if (reader.Read(out int value))"); writer.WriteLine($"{indent}{{"); indent = new string(' ', 28); writer.WriteLine($"{indent}_{member.definition.Name()}.Value = ({storage_type})value;"); indent = new string(' ', 24); writer.WriteLine($"{indent}}}"); } break; case grammar.MemberKind.f32List: case grammar.MemberKind.f64List: case grammar.MemberKind.i32List: case grammar.MemberKind.i64List: case grammar.MemberKind.timespanList: case grammar.MemberKind.timestampList: case grammar.MemberKind.u32List: case grammar.MemberKind.u64List: { writer.WriteLine($"{indent}if (reader.Read(out {storage_type}[] values))"); writer.WriteLine($"{indent}{{"); indent = new string(' ', 28); writer.WriteLine($"{indent}_{member.definition.Name()}.Value = values;"); indent = new string(' ', 24); writer.WriteLine($"{indent}}}"); } break; case grammar.MemberKind.f64Type: case grammar.MemberKind.f32Type: case grammar.MemberKind.i32Type: case grammar.MemberKind.i64Type: case grammar.MemberKind.timespanType: case grammar.MemberKind.timestampType: case grammar.MemberKind.u32Type: case grammar.MemberKind.u64Type: { writer.WriteLine($"{indent}if (reader.Read(out {storage_type} value))"); writer.WriteLine($"{indent}{{"); indent = new string(' ', 28); writer.WriteLine($"{indent}_{member.definition.Name()}.Value = value;"); indent = new string(' ', 24); writer.WriteLine($"{indent}}}"); } break; case grammar.MemberKind.structList: { writer.WriteLine($"{indent}if (reader.Read(out {storage_type}[] values))"); writer.WriteLine($"{indent}{{"); indent = new string(' ', 28); writer.WriteLine($"{indent}_{member.definition.Name()}.Value = values;"); indent = new string(' ', 24); writer.WriteLine($"{indent}}}"); } break; case grammar.MemberKind.structType: { writer.WriteLine($"{indent}if (reader.Read(out {storage_type} value))"); writer.WriteLine($"{indent}{{"); indent = new string(' ', 28); writer.WriteLine($"{indent}_{member.definition.Name()}.Value = value;"); indent = new string(' ', 24); writer.WriteLine($"{indent}}}"); } break; } indent = new string(' ', 20); writer.WriteLine($"{indent}}}"); writer.WriteLine($"{indent}break;"); writer.WriteLine(); } indent = new string(' ', 16); writer.WriteLine($"{indent}}}"); indent = new string(' ', 12); writer.WriteLine($"{indent}}}"); writer.WriteLine(); writer.WriteLine($"{indent}return true;"); indent = new string(' ', 8); writer.WriteLine($"{indent}}}"); writer.WriteLine(); writer.WriteLine($"{indent}public unsafe void WriteTo(WireType.WireTypeWriter writer)"); writer.WriteLine($"{indent}{{"); indent = new string(' ', 12); foreach (var member in members) { var member_kind = member.definition.Kind(); var type_kind = GetTypeKind(member_kind); var storage_type = GetStorageTypeName(member.definition, symbolTable); writer.WriteLine($"{indent}if (_{member.definition.Name()}.Exists)"); writer.WriteLine($"{indent}{{"); indent = new string(' ', 16); switch (member_kind) { case grammar.MemberKind.blobList: case grammar.MemberKind.blobType: case grammar.MemberKind.f32List: case grammar.MemberKind.f32Type: case grammar.MemberKind.f64List: case grammar.MemberKind.f64Type: case grammar.MemberKind.i32List: case grammar.MemberKind.i32Type: case grammar.MemberKind.i64List: case grammar.MemberKind.i64Type: case grammar.MemberKind.stringList: case grammar.MemberKind.stringType: case grammar.MemberKind.structList: case grammar.MemberKind.structType: case grammar.MemberKind.timespanList: case grammar.MemberKind.timespanType: case grammar.MemberKind.timestampList: case grammar.MemberKind.timestampType: case grammar.MemberKind.u32List: case grammar.MemberKind.u32Type: case grammar.MemberKind.u64List: case grammar.MemberKind.u64Type: { writer.WriteLine($"{indent}writer.Write(_{member.definition.Name()}.Ordinal, _{member.definition.Name()}.Value);"); } break; case grammar.MemberKind.enumList: { writer.WriteLine($"{indent}var values = new int[_{member.definition.Name()}.Value.Length];"); writer.WriteLine(); writer.WriteLine($"{indent}System.Buffer.BlockCopy(_{member.definition.Name()}.Value, 0, values, 0, values.Length * sizeof(int));"); writer.WriteLine(); writer.WriteLine($"{indent}writer.Write(_{member.definition.Name()}.Ordinal, values);"); } break; case grammar.MemberKind.enumType: { writer.WriteLine($"{indent}int value = (int)_{member.definition.Name()}.Value;"); writer.WriteLine($"{indent}writer.Write(_{member.definition.Name()}.Ordinal, value);"); } break; } indent = new string(' ', 12); writer.WriteLine($"{indent}}}"); writer.WriteLine(); } indent = new string(' ', 8); writer.WriteLine($"{indent}}}"); indent = new string(' ', 4); writer.WriteLine($"{indent}}}"); indent = string.Empty; if (namespace_type != null) { writer.WriteLine("}"); } return(true); }