public override Task GenerateInRegistration(ObjectGeneration obj, FileGeneration fg) { var objData = obj.GetObjectData(); GenerateConverterMember(fg, obj.BaseClass, objData.BaseRecordTypeConverter, "Base"); foreach (var field in obj.IterateFields(expandSets: SetMarkerType.ExpandSets.FalseAndInclude, nonIntegrated: true)) { LoquiType loquiType = field as LoquiType; if (loquiType == null) { switch (field) { case WrapperType wrapper: loquiType = wrapper.SubTypeGeneration as LoquiType; if (loquiType != null) { break; } continue; default: continue; } } var fieldData = loquiType.GetFieldData(); GenerateConverterMember(fg, loquiType.TargetObjectGeneration, fieldData.RecordTypeConverter, field.Name); } return(base.GenerateInRegistration(obj, fg)); }
public bool NeedsHeaderProcessing(LoquiType loquiGen) { if (!loquiGen.Singleton && loquiGen.TargetObjectGeneration != null && loquiGen.GetFieldData().HasTrigger && !loquiGen.TargetObjectGeneration.Abstract && loquiGen.TargetObjectGeneration.GetObjectData().TriggeringSource == null) { return(true); } return(false); }
public static async Task AddAsSubLoquiType(this LoquiType loqui, IEnumerable <ObjectGeneration> objGens) { var data = loqui.GetFieldData(); foreach (var subObj in objGens) { var subRecs = await subObj.TryGetTriggeringRecordTypes(); if (subRecs.Failed) { continue; } foreach (var subRec in subRecs.Value) { data.SubLoquiTypes.TryCreateValue(subRec).Add(subObj); } } }
public override async Task GenerateWrapperRecordTypeParse( FileGeneration fg, ObjectGeneration objGen, TypeGeneration typeGen, Accessor locationAccessor, Accessor packageAccessor, Accessor converterAccessor) { LoquiType loqui = typeGen as LoquiType; var data = loqui.GetFieldData(); switch (data.BinaryOverlayFallback) { case BinaryGenerationType.Normal: break; case BinaryGenerationType.NoGeneration: return; case BinaryGenerationType.Custom: using (var args = new ArgsWrapper(fg, $"{typeGen.Name}CustomParse")) { args.Add("stream"); args.Add("finalPos"); args.Add("offset"); } return; default: throw new NotImplementedException(); } string accessor; if (loqui.Singleton || !loqui.Nullable) { accessor = $"_{typeGen.Name}"; } else { accessor = typeGen.Name; } if (data.MarkerType.HasValue) { fg.AppendLine($"stream.Position += {packageAccessor}.{nameof(BinaryOverlayFactoryPackage.MetaData)}.{nameof(ParsingBundle.Constants)}.SubConstants.HeaderLength; // Skip marker"); } if (!loqui.TargetObjectGeneration.IsTypelessStruct() && (loqui.GetFieldData()?.HasTrigger ?? false)) { fg.AppendLine($"_{typeGen.Name}Location = new {GetLocationObjectString(objGen)}({locationAccessor}, finalPos);"); var severalSubTypes = data.GenerationTypes .Select(i => i.Value) .WhereCastable <TypeGeneration, LoquiType>() .Where(loqui => !loqui?.TargetObjectGeneration?.Abstract ?? true) .CountGreaterThan(1); if (severalSubTypes) { fg.AppendLine($"_{typeGen.Name}Type = type;"); } } else { if (NeedsHeaderProcessing(loqui)) { fg.AppendLine($"stream.Position += _package.{nameof(BinaryOverlayFactoryPackage.MetaData)}.{nameof(ParsingBundle.Constants)}.SubConstants.HeaderLength;"); } using (var args = new ArgsWrapper(fg, $"this.{accessor} = {this.Module.BinaryOverlayClassName(loqui)}.{loqui.TargetObjectGeneration.Name}Factory")) { args.Add($"stream: stream"); args.Add($"package: {packageAccessor}"); if (loqui.TargetObjectGeneration.IsVariableLengthStruct()) { args.AddPassArg($"finalPos"); } args.Add($"recordTypeConverter: {converterAccessor}"); } } }
public override async Task GenerateWrapperFields( FileGeneration fg, ObjectGeneration objGen, TypeGeneration typeGen, Accessor dataAccessor, int?currentPosition, string passedLengthAccessor, DataType dataType) { LoquiType loqui = typeGen as LoquiType; var data = typeGen.GetFieldData(); switch (data.BinaryOverlayFallback) { case BinaryGenerationType.Normal: break; case BinaryGenerationType.NoGeneration: return; case BinaryGenerationType.Custom: await this.Module.CustomLogic.GenerateForCustomFlagWrapperFields( fg, objGen, typeGen, dataAccessor, currentPosition, passedLengthAccessor, dataType); return; default: throw new NotImplementedException(); } string DataAccessor(Accessor accessor, string positionStr, string lenStr) { if (objGen.GetObjectType() == ObjectType.Mod) { return($"{nameof(BinaryOverlay)}.{nameof(BinaryOverlay.LockExtractMemory)}({accessor}, {positionStr}, {lenStr})"); } else { return($"{accessor}.Slice({positionStr})"); } } string recConverter = $"default({nameof(RecordTypeConverter)})"; if (loqui.GetFieldData()?.RecordTypeConverter != null && loqui.GetFieldData().RecordTypeConverter.FromConversions.Count > 0) { recConverter = $"{objGen.RegistrationName}.{loqui.Name}Converter"; } var isRequiredRecord = !loqui.Nullable && data.HasTrigger; if (dataType == null) { if (loqui.GetFieldData()?.HasTrigger ?? false) { if (loqui.TargetObjectGeneration.IsTypelessStruct()) { if (loqui.Singleton || isRequiredRecord) { fg.AppendLine($"private {loqui.Interface(getter: true, internalInterface: true)}? _{typeGen.Name};"); } else if (loqui.Nullable) { fg.AppendLine($"public {loqui.Interface(getter: true, internalInterface: true)}? {typeGen.Name} {{ get; private set; }}"); } } else { var severalSubTypes = data.GenerationTypes .Select(i => i.Value) .WhereCastable <TypeGeneration, LoquiType>() .Where(loqui => !loqui?.TargetObjectGeneration?.Abstract ?? true) .CountGreaterThan(1); if (severalSubTypes) { fg.AppendLine($"private {nameof(RecordType)} _{typeGen.Name}Type;"); } fg.AppendLine($"private {GetLocationObjectString(objGen)}? _{typeGen.Name}Location;"); using (new LineWrapper(fg)) { if (loqui.IsNullable) { fg.Append($"public "); } else { fg.Append($"private "); } fg.Append($"{loqui.Interface(getter: true, internalInterface: true)}{(typeGen.CanBeNullable(getter: true) ? "?" : null)} "); if (!loqui.IsNullable || isRequiredRecord) { fg.Append("_"); } fg.Append($"{typeGen.Name}"); if (!severalSubTypes) { fg.Append($" => _{typeGen.Name}Location.HasValue ? "); fg.Append($"{this.Module.BinaryOverlayClassName(loqui)}.{loqui.TargetObjectGeneration.Name}Factory(new {nameof(OverlayStream)}({DataAccessor(dataAccessor, $"_{typeGen.Name}Location!.Value.Min", $"_{typeGen.Name}Location!.Value.Max")}, _package), _package"); if (!recConverter.StartsWith("default(")) { fg.Append($", {recConverter}"); } fg.Append($") "); fg.Append($": default;"); } } if (severalSubTypes) { using (new BraceWrapper(fg)) { fg.AppendLine("get"); using (new BraceWrapper(fg)) { fg.AppendLine($"if (!_{typeGen.Name}Location.HasValue) return default;"); fg.AppendLine($"switch (_{typeGen.Name}Type.TypeInt)"); using (new BraceWrapper(fg)) { foreach (var gen in data.GenerationTypes) { if (!(gen.Value is LoquiType subLoq)) { continue; } if (subLoq?.TargetObjectGeneration?.Abstract ?? false) { continue; } foreach (var trigger in gen.Key) { fg.AppendLine($"case 0x{trigger.TypeInt.ToString("X")}: // {trigger.Type}"); } using (new DepthWrapper(fg)) using (new LineWrapper(fg)) { fg.Append($"return {this.Module.BinaryOverlayClassName(subLoq)}.{subLoq.TargetObjectGeneration.Name}Factory(new {nameof(OverlayStream)}({DataAccessor(dataAccessor, $"_{subLoq.Name}Location!.Value.Min", $"_{subLoq.Name}Location!.Value.Max")}, _package), _package"); if (!loqui.Singleton) { fg.Append($", {recConverter}"); } fg.Append($");"); } } fg.AppendLine("default:"); using (new DepthWrapper(fg)) { fg.AppendLine("throw new ArgumentException();"); } } } } } } } else { if (!loqui.Singleton) { fg.AppendLine($"public {loqui.Interface(getter: true, internalInterface: true)} {typeGen.Name} => {this.Module.BinaryOverlayClassName(loqui)}.{loqui.TargetObjectGeneration.Name}Factory(new {nameof(OverlayStream)}({dataAccessor}.Slice({passedLengthAccessor ?? "0x0"}), _package), _package, {recConverter});"); } else { fg.AppendLine($"private {loqui.Interface(getter: true, internalInterface: true)} _{typeGen.Name} {{ get; private set; }}"); } } } else { isRequiredRecord = true; DataBinaryTranslationGeneration.GenerateWrapperExtraMembers(fg, dataType, objGen, typeGen, passedLengthAccessor); fg.AppendLine($"private {loqui.Interface(getter: true, internalInterface: true)}? _{typeGen.Name} => _{typeGen.Name}_IsSet ? {this.Module.BinaryOverlayClassName(loqui)}.{loqui.TargetObjectGeneration.Name}Factory(new {nameof(OverlayStream)}({DataAccessor(dataAccessor, $"_{typeGen.Name}Location", null)}, _package), _package) : default;"); } if (loqui.Singleton || isRequiredRecord) { fg.AppendLine($"public {loqui.Interface(getter: true, internalInterface: true)} {typeGen.Name} => _{typeGen.Name} ?? new {loqui.DirectTypeName}({(loqui.ThisConstruction ? "this" : null)});"); } }
public override Task GenerateInRegistration(ObjectGeneration obj, FileGeneration fg) { var objData = obj.GetObjectData(); GenerateConverterMember(fg, obj.BaseClass, objData.BaseRecordTypeConverter, "Base"); foreach (var field in obj.IterateFields(expandSets: SetMarkerType.ExpandSets.FalseAndInclude, nonIntegrated: true)) { LoquiType loquiType = field as LoquiType; if (loquiType == null) { switch (field) { case WrapperType wrapper: loquiType = wrapper.SubTypeGeneration as LoquiType; if (loquiType != null) { break; } continue; default: continue; } } var fieldData = loquiType.GetFieldData(); GenerateConverterMember(fg, loquiType.TargetObjectGeneration, fieldData.RecordTypeConverter, field.Name); } if (objData.GameReleaseConverters != null) { foreach (var kv in objData.GameReleaseConverters) { GenerateConverterMember(fg, obj, kv.Value, kv.Key.ToString()); } using (var args = new FunctionWrapper(fg, $"public static {nameof(RecordTypeConverter)}? Get")) { args.Add($"{nameof(GameRelease)} release"); } using (new BraceWrapper(fg)) { fg.AppendLine($"return release switch"); using (new BraceWrapper(fg) { AppendSemicolon = true }) { using (var comma = new CommaWrapper(fg)) { foreach (var kv in objData.GameReleaseConverters) { comma.Add($"{nameof(GameRelease)}.{kv.Key} => {kv.Key}Converter"); } comma.Add($"_ => default({nameof(RecordTypeConverter)})"); } } } } if (objData.VersionConverters != null) { foreach (var kv in objData.VersionConverters) { GenerateConverterMember(fg, obj, kv.Value, $"Version{kv.Key}"); } using (var args = new FunctionWrapper(fg, $"public static {nameof(RecordTypeConverter)}? Get")) { args.Add($"int? version"); } using (new BraceWrapper(fg)) { bool first = true; fg.AppendLine($"if (version == null) return default({nameof(RecordTypeConverter)});"); foreach (var kv in objData.VersionConverters.OrderBy(kv => kv.Key)) { fg.AppendLine($"{(first ? null : "else ")}if (version.Value >= {kv.Key})"); using (new BraceWrapper(fg)) { fg.AppendLine($"return Version{kv.Key}Converter;"); } first = false; } fg.AppendLine($"return default({nameof(RecordTypeConverter)});"); } } return(base.GenerateInRegistration(obj, fg)); }