Exemplo n.º 1
0
        public void FillMajorRecords(
            OverlayStream stream,
            int finalPos,
            int offset,
            RecordTypeConverter?recordTypeConverter,
            RecordTypeFillWrapper fill)
        {
            int?lastParsed = null;

            while (!stream.Complete && stream.Position < finalPos)
            {
                MajorRecordHeader majorMeta = stream.GetMajorRecord();
                var minimumFinalPos         = stream.Position + majorMeta.TotalLength;
                var parsed = fill(
                    stream: stream,
                    finalPos: finalPos,
                    offset: offset,
                    type: majorMeta.RecordType,
                    lastParsed: lastParsed,
                    recordTypeConverter: recordTypeConverter);
                if (parsed.Failed)
                {
                    break;
                }
                if (minimumFinalPos > stream.Position)
                {
                    stream.Position = checked ((int)minimumFinalPos);
                }
                lastParsed = parsed.Value;
            }
        }
Exemplo n.º 2
0
        public void FillMajorRecords(
            OverlayStream stream,
            int finalPos,
            int offset,
            RecordTypeConverter?recordTypeConverter,
            RecordTypeFillWrapper fill)
        {
            int?lastParsed = null;
            Dictionary <RecordType, int>?recordParseCount = null;

            while (!stream.Complete && stream.Position < finalPos)
            {
                MajorRecordHeader majorMeta = stream.GetMajorRecord();
                var minimumFinalPos         = stream.Position + majorMeta.TotalLength;
                var parsed = fill(
                    stream: stream,
                    finalPos: finalPos,
                    offset: offset,
                    recordParseCount: recordParseCount,
                    type: majorMeta.RecordType,
                    lastParsed: lastParsed,
                    recordTypeConverter: recordTypeConverter);
                if (!parsed.KeepParsing)
                {
                    break;
                }
                if (parsed.DuplicateParseMarker != null)
                {
                    if (recordParseCount == null)
                    {
                        recordParseCount = new Dictionary <RecordType, int>();
                    }
                    recordParseCount[parsed.DuplicateParseMarker !.Value] = recordParseCount.GetOrAdd(parsed.DuplicateParseMarker !.Value) + 1;
Exemplo n.º 3
0
        public IReadOnlyList <T> ParseRepeatedTypelessSubrecord <T>(
            OverlayStream stream,
            RecordType trigger,
            SpanRecordFactory <T> factory,
            RecordTypeConverter?recordTypeConverter,
            bool skipHeader)
        {
            var ret = new List <T>();

            while (!stream.Complete)
            {
                var subMeta = stream.GetSubrecord();
                var recType = subMeta.RecordType;
                if (trigger != recType)
                {
                    break;
                }
                var minimumFinalPos = stream.Position + subMeta.TotalLength;
                if (skipHeader)
                {
                    stream.Position += subMeta.HeaderLength;
                }
                ret.Add(factory(stream.ReadMemory(skipHeader ? subMeta.ContentLength : subMeta.TotalLength), _package, recordTypeConverter));
                if (stream.Position < minimumFinalPos)
                {
                    stream.Position = minimumFinalPos;
                }
            }
            return(ret);
        }
Exemplo n.º 4
0
        public static int[] ParseRecordLocationsByCount(
            OverlayStream stream,
            uint count,
            RecordType trigger,
            RecordHeaderConstants constants,
            bool skipHeader)
        {
            List <int> ret         = new List <int>();
            var        startingPos = stream.Position;

            for (uint i = 0; i < count; i++)
            {
                var varMeta = constants.GetVariableMeta(stream);
                var recType = varMeta.RecordType;
                if (trigger == recType)
                {
                    if (skipHeader)
                    {
                        stream.Position += varMeta.HeaderLength;
                        ret.Add(stream.Position - startingPos);
                        stream.Position += (int)varMeta.RecordLength;
                    }
                    else
                    {
                        ret.Add(stream.Position - startingPos);
                        stream.Position += (int)varMeta.TotalLength;
                    }
                }
                else
                {
                    stream.Position += (int)varMeta.TotalLength;
                }
            }
            return(ret.ToArray());
        }
Exemplo n.º 5
0
        public IReadOnlyList <T> ParseRepeatedTypelessSubrecord <T>(
            OverlayStream stream,
            ICollectionGetter <RecordType> trigger,
            StreamTypedFactory <T> factory,
            RecordTypeConverter?recordTypeConverter)
        {
            var ret = new List <T>();

            while (!stream.Complete)
            {
                var subMeta = stream.GetSubrecord();
                var recType = subMeta.RecordType;
                if (!trigger.Contains(recType))
                {
                    break;
                }
                var minimumFinalPos = stream.Position + subMeta.TotalLength;
                ret.Add(factory(stream, recType, _package, recordTypeConverter));
                if (stream.Position < minimumFinalPos)
                {
                    stream.Position = minimumFinalPos;
                }
            }
            return(ret);
        }
Exemplo n.º 6
0
        public static int[] ParseRecordLocations(
            OverlayStream stream,
            ICollectionGetter <RecordType> triggers,
            RecordHeaderConstants constants,
            bool skipHeader,
            RecordTypeConverter?recordTypeConverter = null)
        {
            List <int> ret         = new List <int>();
            var        startingPos = stream.Position;

            while (!stream.Complete)
            {
                var varMeta = constants.GetVariableMeta(stream);
                var recType = recordTypeConverter.ConvertToStandard(varMeta.RecordType);
                if (!triggers.Contains(recType))
                {
                    break;
                }
                if (skipHeader)
                {
                    stream.Position += varMeta.HeaderLength;
                    ret.Add(stream.Position - startingPos);
                    stream.Position += (int)varMeta.RecordLength;
                }
                else
                {
                    ret.Add(stream.Position - startingPos);
                    stream.Position += (int)varMeta.TotalLength;
                }
            }
            return(ret.ToArray());
        }
Exemplo n.º 7
0
        public void FillGroupRecordsForWrapper(
            OverlayStream stream,
            int finalPos,
            int offset,
            RecordTypeConverter?recordTypeConverter,
            RecordTypeFillWrapper fill)
        {
            int?lastParsed = null;

            while (!stream.Complete && stream.Position < finalPos)
            {
                if (!stream.TryGetGroup(out var groupMeta))
                {
                    throw new DataMisalignedException();
                }
                var subStream = new OverlayStream(stream.RemainingMemory.Slice(0, finalPos - stream.Position), stream.MetaData);
                var parsed    = fill(
                    stream: subStream,
                    finalPos: subStream.Length,
                    offset: 0, // unused
                    type: groupMeta.RecordType,
                    lastParsed: lastParsed,
                    recordTypeConverter: recordTypeConverter);
                stream.Position += subStream.Position;
                if (parsed.Failed)
                {
                    break;
                }
                lastParsed = parsed.Value;
            }
        }
Exemplo n.º 8
0
 public IReadOnlyList <T> ParseRepeatedTypelessSubrecord <T>(
     OverlayStream stream,
     RecordType trigger,
     ConverterFactory <T> factory,
     RecordTypeConverter?recordTypeConverter)
 {
     return(ParseRepeatedTypelessSubrecord(
                stream,
                trigger,
                (s, r, p, recConv) => factory(s, p, recConv),
                recordTypeConverter));
 }
Exemplo n.º 9
0
        /// <summary>
        /// Finds locations of a number of records given by count that match a set of record types.
        /// A new location is marked each time a record type that has already been encounterd is seen
        /// </summary>
        /// <param name="stream">Stream to read and progress</param>
        /// <param name="count">Number of expected records</param>
        /// <param name="trigger">Set of record types expected within one record</param>
        /// <param name="constants">Metadata for reference</param>
        /// <param name="skipHeader">Whether to skip the header in the return location values</param>
        /// <returns>Array of located positions relative to the stream's position at the start</returns>
        public static int[] ParseRecordLocationsByCount(
            OverlayStream stream,
            uint count,
            ICollectionGetter <RecordType> trigger,
            RecordHeaderConstants constants,
            bool skipHeader)
        {
            var ret         = new List <int>();
            var set         = new HashSet <RecordType>();
            var startingPos = stream.Position;

            while (!stream.Complete)
            {
                var varMeta = constants.GetVariableMeta(stream);
                var recType = varMeta.RecordType;
                if (trigger.Contains(recType))
                {
                    // If new record type we haven't seen before in our current record, just continue
                    if (set.Add(recType) && ret.Count > 0)
                    {
                        stream.Position += (int)varMeta.TotalLength;
                        continue;
                    }

                    // Otherwise mark as a new record location
                    if (skipHeader)
                    {
                        stream.Position += varMeta.HeaderLength;
                        ret.Add(stream.Position - startingPos);
                        stream.Position += (int)varMeta.RecordLength;
                    }
                    else
                    {
                        ret.Add(stream.Position - startingPos);
                        stream.Position += (int)varMeta.TotalLength;
                    }

                    // Clear set of seen types
                    set.Clear();
                    set.Add(recType);
                }
                else if (ret.Count == count)
                {
                    break;
                }
                else
                {
                    throw new ArgumentException($"Unexpected record encountered: {recType}. Was expecting: {string.Join(", ", trigger)}");
                }
            }
            return(ret.ToArray());
        }
Exemplo n.º 10
0
        public static IReadOnlyList <T> FactoryByCountPerItem <T>(
            OverlayStream stream,
            BinaryOverlayFactoryPackage package,
            int countLength,
            RecordType subrecordType,
            RecordType countType,
            RecordTypeConverter?recordTypeConverter,
            BinaryOverlay.SpanRecordFactory <T> getter,
            bool skipHeader = true)
        {
            var mem           = stream.RemainingMemory;
            var initialHeader = package.MetaData.Constants.SubrecordFrame(mem);
            var recType       = initialHeader.RecordType;

            if (recType == countType)
            {
                var count = countLength switch
                {
                    1 => initialHeader.Content[0],
                    2 => BinaryPrimitives.ReadUInt16LittleEndian(initialHeader.Content),
                    4 => BinaryPrimitives.ReadUInt32LittleEndian(initialHeader.Content),
                    _ => throw new NotImplementedException(),
                };
                stream.Position += initialHeader.TotalLength;
                return(FactoryByArray(
                           mem: stream.RemainingMemory,
                           package: package,
                           recordTypeConverter: recordTypeConverter,
                           getter: getter,
                           locs: BinaryOverlay.ParseRecordLocationsByCount(
                               stream: stream,
                               count: count,
                               trigger: subrecordType,
                               constants: package.MetaData.Constants.SubConstants,
                               skipHeader: false)));
            }
            else
            {
                return(FactoryByArray(
                           mem: stream.RemainingMemory,
                           package: package,
                           recordTypeConverter: recordTypeConverter,
                           getter: getter,
                           locs: BinaryOverlay.ParseRecordLocations(
                               stream: stream,
                               constants: package.MetaData.Constants.SubConstants,
                               trigger: subrecordType,
                               skipHeader: skipHeader,
                               recordTypeConverter: recordTypeConverter)));
            }
        }
Exemplo n.º 11
0
        public static IReadOnlyList <T> FactoryByCount <T>(
            OverlayStream stream,
            BinaryOverlayFactoryPackage package,
            uint count,
            BinaryOverlay.StreamFactory <T> getter)
        {
            var ret = new List <T>(checked ((int)count));

            for (uint i = 0; i < count; i++)
            {
                ret.Add(getter(stream, package));
            }
            return(ret);
        }
Exemplo n.º 12
0
        public static IReadOnlyList <T> FactoryByCount <T>(
            OverlayStream stream,
            BinaryOverlayFactoryPackage package,
            int itemLength,
            int countLength,
            RecordType subrecordType,
            RecordType countType,
            BinaryOverlay.SpanFactory <T> getter)
        {
            var mem           = stream.RemainingMemory;
            var initialHeader = package.MetaData.Constants.SubrecordFrame(mem);
            var recType       = initialHeader.RecordType;

            if (recType == countType)
            {
                var count = countLength switch
                {
                    1 => initialHeader.Content[0],
                    2 => (int)BinaryPrimitives.ReadUInt16LittleEndian(initialHeader.Content),
                    4 => checked ((int)BinaryPrimitives.ReadUInt32LittleEndian(initialHeader.Content)),
                    _ => throw new NotImplementedException(),
                };
                stream.Position += initialHeader.TotalLength;
                if (!stream.TryReadSubrecordFrame(subrecordType, out var contentFrame))
                {
                    if (count == 0)
                    {
                        return(Array.Empty <T>());
                    }
                    throw new ArgumentException($"List with a non zero {initialHeader.RecordType} counter did not follow up with expected type: {subrecordType}");
                }
                return(new BinaryOverlayListByStartIndex <T>(
                           contentFrame.Content,
                           package,
                           getter,
                           itemLength));
            }
            else
            {
                return(FactoryByStartIndex(
                           mem: stream.RemainingMemory,
                           package: package,
                           getter: getter,
                           itemLength: itemLength));
            }
        }
Exemplo n.º 13
0
        public static IReadOnlyList <T>?FactoryByCountNullIfZero <T>(
            OverlayStream stream,
            BinaryOverlayFactoryPackage package,
            int itemLength,
            int countLength,
            RecordType subrecordType,
            RecordType countType,
            BinaryOverlay.SpanFactory <T> getter)
        {
            var mem           = stream.RemainingMemory;
            var initialHeader = package.MetaData.Constants.SubrecordFrame(mem);
            var recType       = initialHeader.RecordType;

            if (recType == countType)
            {
                var count = countLength switch
                {
                    1 => initialHeader.Content[0],
                    2 => (int)BinaryPrimitives.ReadUInt16LittleEndian(initialHeader.Content),
                    4 => checked ((int)BinaryPrimitives.ReadUInt32LittleEndian(initialHeader.Content)),
                    _ => throw new NotImplementedException(),
                };
                stream.Position += initialHeader.TotalLength;
                if (count == 0)
                {
                    return(null);
                }
                var contentFrame = stream.ReadSubrecordFrame(subrecordType);
                return(new BinaryOverlayListByStartIndex <T>(
                           contentFrame.Content,
                           package,
                           getter,
                           itemLength));
            }
            else
            {
                return(FactoryByStartIndex(
                           mem: stream.RemainingMemory,
                           package: package,
                           getter: getter,
                           itemLength: itemLength));
            }
        }
Exemplo n.º 14
0
        public static int[] ParseRecordLocations(
            OverlayStream stream,
            long finalPos,
            RecordType trigger,
            RecordType includeTrigger,
            RecordHeaderConstants constants,
            bool skipHeader)
        {
            List <int> ret         = new List <int>();
            var        startingPos = stream.Position;

            while (!stream.Complete && stream.Position < finalPos)
            {
                var varMeta          = constants.GetVariableMeta(stream);
                var recType          = varMeta.RecordType;
                var isTrigger        = trigger == recType;
                var isIncludeTrigger = includeTrigger == recType;
                if (!isTrigger && !isIncludeTrigger)
                {
                    break;
                }
                if (isTrigger)
                {
                    if (skipHeader)
                    {
                        stream.Position += varMeta.HeaderLength;
                        ret.Add(stream.Position - startingPos);
                        stream.Position += (int)varMeta.RecordLength;
                    }
                    else
                    {
                        ret.Add(stream.Position - startingPos);
                        stream.Position += (int)varMeta.TotalLength;
                    }
                }
                else
                {
                    stream.Position += (int)varMeta.TotalLength;
                }
            }
            return(ret.ToArray());
        }
Exemplo n.º 15
0
 public static IReadOnlyList <T> FactoryByLazyParse <T>(
     ReadOnlyMemorySlice <byte> mem,
     BinaryOverlayFactoryPackage package,
     BinaryOverlay.Factory <T> getter)
 {
     return(new BinaryOverlayLazyList <T>(
                mem,
                package,
                (m, p) =>
     {
         var ret = new List <T>();
         using (var stream = new OverlayStream(m, package))
         {
             while (!stream.Complete)
             {
                 ret.Add(getter(stream, p));
             }
         }
         return ret;
     }));
 }