public static string GenerateCode(string json) { var discoveredTypes = intrinsicTypes.ToDictionary(type => type.Name, type => type); var schemaDefinitions = JsonConvert.DeserializeObject <SchemaTypeDefinitions>(json); var cppTypes = schemaDefinitions.Types.Select(t => GenerateType(t)); var template = new CodeTemplate(cppTypes); return(template.TransformText()); ICppType GenerateType(SchemaType schemaType) { var topLevelParts = GenerateParts(schemaType); var properties = new List <CppProperty>(); GenerateProperties(topLevelParts); var(finalTopLevelParts, topLevelType) = OptimizePartLayout(topLevelParts); var namedType = new CppTypeInfo( name: schemaType.Name, alignment: Math.Max(topLevelType.Alignment, schemaType.Alignment), bits: topLevelType.Bits); discoveredTypes.Add(namedType.Name, namedType); return(new CppClass(namedType, finalTopLevelParts, properties.ToArray())); void GenerateProperties(ICppPart[] parts, params CppPropertyCondition[] conditions) { foreach (var part in parts) { switch (part) { case CppPropertyPart property: properties.Add(new CppProperty(property.Type, property.Name, conditions)); break; case CppUnionHeaderPart unionHeader: var headerFieldType = new CppTypeInfo("", 0, unionHeader.Bits); break; case CppUnionBodyPart unionBody: foreach (var(unionCase, i) in unionBody.Cases.Select((c, i) => (c, i))) { var caseCondition = new CppPropertyCondition(unionBody.ID, i); GenerateProperties(unionCase.Parts, conditions.Concat(new[] { caseCondition }).ToArray()); } break; } } } (ICppPart[] parts, CppTypeInfo type) OptimizePartLayout(ICppPart[] unoptimizedParts) { var unoptimizedPartsAndTypes = GetPartsAndTypes(unoptimizedParts); return(ArrangeParts(unoptimizedPartsAndTypes)); (ICppPart part, CppTypeInfo type)[] GetPartsAndTypes(ICppPart[] parts) { return(parts.Select <ICppPart, ValueTuple <ICppPart, CppTypeInfo> >(part => { switch (part) { case CppPropertyPart property: return (property, property.Type); case CppUnionHeaderPart unionHeader: return (unionHeader, new CppTypeInfo("", 0, unionHeader.Bits)); case CppUnionBodyPart unionBody: var optimizedCases = new List <CppUnionCase>(); var unionBodySize = 8; var unionBodyAlignment = 1; foreach (var unionCase in unionBody.Cases) { (ICppPart[] caseParts, CppTypeInfo caseType) = OptimizePartLayout(unionCase.Parts); unionBodySize = Math.Max(caseType.Bits, unionBodySize); unionBodyAlignment = Math.Max(caseType.Alignment, unionBodyAlignment); optimizedCases.Add(new CppUnionCase(caseParts)); } var unionBodyType = new CppTypeInfo("", unionBodyAlignment, unionBodySize); return (new CppUnionBodyPart(unionBody.ID, optimizedCases.ToArray()), unionBodyType); } throw new ArgumentNullException(nameof(part)); }).ToArray()); } (ICppPart[] parts, CppTypeInfo type) ArrangeParts((ICppPart part, CppTypeInfo type)[] typesAndParts)
public CppPropertyPart(CppTypeInfo type, string name) { Type = type; Name = name; }
public CppEnum(CppTypeInfo typeInfo, string[] cases) { TypeInfo = typeInfo; Cases = cases; }
public CppClass(CppTypeInfo typeInfo, ICppPart[] parts, CppProperty[] properties) { TypeInfo = typeInfo; Parts = parts; Properties = properties; }
public CppProperty(CppTypeInfo type, string name, params CppPropertyCondition[] conditions) { Type = type; Name = name; Conditions = conditions; }
public CppBitFieldPart(CppTypeInfo type, ICppPart[] parts) { Type = type; Parts = parts; }
private string GetParameterType(CppTypeInfo type) { return(type.Bits <= 64 ? type.Name : $"const {type.Name}&"); }