public override IDataFormat CreateDataFormat(IDataModel data, int index)
        {
            var destinationAddress = data.ReadPointer(Start);
            var anchor             = data.GetAnchorFromAddress(Start, destinationAddress);
            var pointer            = new Pointer(Start, index - Start, destinationAddress, anchor);

            return(pointer);
        }
        public override IDataFormat CreateDataFormat(IDataModel data, int index)
        {
            var offsets        = ConvertByteOffsetToArrayOffset(index);
            var currentSegment = ElementContent[offsets.SegmentIndex];

            if (currentSegment.Type == ElementContentType.PCS)
            {
                if (currentCachedStartIndex != offsets.SegmentStart || currentCachedIndex > offsets.SegmentOffset)
                {
                    currentCachedStartIndex = offsets.SegmentStart;
                    currentCachedIndex      = offsets.SegmentOffset;
                    cachedCurrentString     = PCSString.Convert(data, offsets.SegmentStart, currentSegment.Length);
                }

                return(PCSRun.CreatePCSFormat(data, offsets.SegmentStart, index, cachedCurrentString));
            }

            var position = index - offsets.SegmentStart;

            if (currentSegment.Type == ElementContentType.Integer)
            {
                if (currentSegment is ArrayRunEnumSegment enumSegment)
                {
                    var value = enumSegment.ToText(data, index);
                    return(new IntegerEnum(offsets.SegmentStart, position, value, currentSegment.Length));
                }
                else
                {
                    var value = ArrayRunElementSegment.ToInteger(data, offsets.SegmentStart, currentSegment.Length);
                    return(new Integer(offsets.SegmentStart, position, value, currentSegment.Length));
                }
            }

            if (currentSegment.Type == ElementContentType.Pointer)
            {
                var destination     = data.ReadPointer(offsets.SegmentStart);
                var destinationName = data.GetAnchorFromAddress(offsets.SegmentStart, destination);
                return(new Pointer(offsets.SegmentStart, position, destination, destinationName));
            }

            if (currentSegment.Type == ElementContentType.BitArray)
            {
                return(new BitArray(offsets.SegmentStart, position, currentSegment.Length));
            }

            throw new NotImplementedException();
        }
Beispiel #3
0
        private ArrayRun(IDataModel data, string format, int start, IReadOnlyList <int> pointerSources) : base(start, pointerSources)
        {
            owner        = data;
            FormatString = format;
            SupportsPointersToElements = format.StartsWith(AnchorStart.ToString());
            if (SupportsPointersToElements)
            {
                format = format.Substring(1);
            }
            var closeArray = format.LastIndexOf(ArrayEnd.ToString());

            if (!format.StartsWith(ArrayStart.ToString()) || closeArray == -1)
            {
                throw new ArrayRunParseException($"Array Content must be wrapped in {ArrayStart}{ArrayEnd}.");
            }
            var segments = format.Substring(1, closeArray - 1);
            var length   = format.Substring(closeArray + 1);

            ElementContent = ParseSegments(segments, data);
            if (ElementContent.Count == 0)
            {
                throw new ArrayRunParseException("Array Content must not be empty.");
            }
            ElementLength = ElementContent.Sum(e => e.Length);

            FormatMatchFlags flags = default;

            if (ElementContent.Count == 1)
            {
                flags |= FormatMatchFlags.IsSingleSegment;
            }

            if (length.Length == 0)
            {
                var nextRun = owner.GetNextAnchor(Start + ElementLength);
                for (; true; nextRun = owner.GetNextAnchor(nextRun.Start + nextRun.Length))
                {
                    if (nextRun.Start > owner.Count)
                    {
                        break;
                    }
                    var anchorName = owner.GetAnchorFromAddress(-1, nextRun.Start);
                    if (string.IsNullOrEmpty(anchorName))
                    {
                        continue;
                    }
                    if ((nextRun.Start - Start) % ElementLength != 0)
                    {
                        break;
                    }
                }
                var byteLength   = 0;
                var elementCount = 0;
                while (Start + byteLength + ElementLength <= nextRun.Start && DataMatchesElementFormat(owner, Start + byteLength, ElementContent, flags, nextRun))
                {
                    byteLength += ElementLength;
                    elementCount++;
                    if (elementCount == 100)
                    {
                        flags |= FormatMatchFlags.AllowJunkAfterText;
                    }
                }
                LengthFromAnchor = string.Empty;
                ElementCount     = Math.Max(1, elementCount); // if the user said there's a format here, then there is, even if the format it wrong.
                FormatString    += ElementCount;
            }
            else if (int.TryParse(length, out int result))
            {
                // fixed length is easy
                LengthFromAnchor = string.Empty;
                ElementCount     = Math.Max(1, result);
            }
            else
            {
                LengthFromAnchor = length;
                ElementCount     = Math.Max(1, ParseLengthFromAnchor());
            }

            Length = ElementLength * ElementCount;
        }