/// <summary> /// Iterates a MajorRecordFrame's subrecords and locates the first occurance of the desired type /// </summary> /// <param name="majorFrame">Frame to read from</param> /// <param name="type">Type to search for</param> /// <param name="header">SubrecordHeader if found</param> /// <param name="loc">Location of the subrecord, relative to the parent record's RecordType data</param> /// <returns>True if matching subrecord is found</returns> public static bool TryLocateSubrecord(this MajorRecordFrame majorFrame, RecordType type, int offset, out SubrecordHeader header, out int loc) { var find = PluginUtilityTranslation.FindFirstSubrecord(majorFrame.Content.Slice(offset - majorFrame.HeaderLength), majorFrame.Meta, type, navigateToContent: false); if (find == null) { header = default; loc = default; return(false); } header = new SubrecordHeader(majorFrame.Meta, majorFrame.Content.Slice(find.Value + offset - majorFrame.HeaderLength)); loc = find.Value + offset; return(true); }
internal static IEnumerable <SubrecordPinFrame> EnumerateSubrecords(ReadOnlyMemorySlice <byte> span, GameConstants meta, int loc, ICollection <RecordType> lengthOverflowTypes) { while (loc < span.Length) { var subFrame = new SubrecordPinFrame(meta, span.Slice(loc), loc); if (lengthOverflowTypes.Contains(subFrame.RecordType)) { // Length overflow record var nextLen = subFrame.AsUInt32(); loc += subFrame.TotalLength; var nextSpan = span.Slice(loc, checked ((int)(nextLen + meta.SubConstants.HeaderLength))); var subHeader = new SubrecordHeader(meta, nextSpan); yield return(SubrecordPinFrame.FactoryNoTrim(subHeader, nextSpan, loc)); loc += checked ((int)(subHeader.HeaderLength + nextLen)); continue; } yield return(subFrame); loc += subFrame.TotalLength; } }
/// <summary> /// Enumerates locations of the contained subrecords, while considering some specified RecordTypes as special length overflow subrecords.<br/> /// These length overflow subrecords will be skipped, and simply used to parse the next subrecord properly.<br /> /// Locations are relative to the RecordType of the MajorRecordFrame. /// </summary> /// <param name="majorFrame">MajorRecordFrame to iterate</param> /// <param name="lengthOverflowTypes">Collection of known RecordTypes that signify a length overflow subrecord</param> public static IEnumerable <SubrecordPinFrame> EnumerateSubrecords(this MajorRecordFrame majorFrame, ICollection <RecordType> lengthOverflowTypes) { int loc = majorFrame.HeaderLength; while (loc < majorFrame.HeaderAndContentData.Length) { var subFrame = new SubrecordPinFrame(majorFrame.Meta, majorFrame.HeaderAndContentData.Slice(loc), loc); if (lengthOverflowTypes.Contains(subFrame.RecordType)) { // Length overflow record var nextLen = subFrame.AsUInt32(); loc += subFrame.TotalLength; var span = majorFrame.HeaderAndContentData.Slice(loc, checked ((int)(nextLen + majorFrame.Meta.SubConstants.HeaderLength))); var subHeader = new SubrecordHeader(majorFrame.Meta, span); yield return(SubrecordPinFrame.FactoryNoTrim(subHeader, span, loc)); continue; } yield return(subFrame); loc += subFrame.TotalLength; } }
/// <summary> /// Iterates a MajorRecordFrame's contents and locates the first occurance of the desired type /// </summary> /// <param name="majorFrame">Frame to read from</param> /// <param name="type">Type to search for</param> /// <param name="header">SubrecordHeader if found</param> /// <returns>True if matching subrecord is found</returns> public static bool TryLocateSubrecord(this MajorRecordFrame majorFrame, RecordType type, out SubrecordHeader header) { return(majorFrame.TryLocateSubrecord(type, header: out header, loc: out var _)); }
public static BodyTemplate ParseBodt(ushort version, IMutagenReadStream frame, SubrecordHeader subrecordHeader) { var len = subrecordHeader.ContentLength; if (version == 44 && len <= 8) { throw SubrecordException.Create("BODT can not be parsed on versions == 44 if length is <= 8", RecordTypes.BODT); } var item = new BodyTemplate(); item.FirstPersonFlags = EnumBinaryTranslation <BipedObjectFlag, IMutagenReadStream, MutagenWriter> .Instance.Parse( reader : frame, length : 4); if (len == 8) { if (version < 22) { item.Flags = EnumBinaryTranslation <BodyTemplate.Flag, IMutagenReadStream, MutagenWriter> .Instance.Parse( reader : frame, length : 4); } else { item.ArmorType = EnumBinaryTranslation <ArmorType, IMutagenReadStream, MutagenWriter> .Instance.Parse( reader : frame, length : 4); } } else { item.Flags = EnumBinaryTranslation <BodyTemplate.Flag, IMutagenReadStream, MutagenWriter> .Instance.Parse( reader : frame, length : 4); item.ArmorType = EnumBinaryTranslation <ArmorType, IMutagenReadStream, MutagenWriter> .Instance.Parse( reader : frame, length : 4); } return(item); }