コード例 #1
0
        public static bool TrySearch(IDataModel data, ModelDelta changeToken, string originalFormat, out ArrayRun self, Func <IFormattedRun, bool> runFilter = null)
        {
            self = null;
            var format = originalFormat;
            var allowPointersToEntries = format.StartsWith(AnchorStart.ToString());

            if (allowPointersToEntries)
            {
                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);
            var elementContent = ParseSegments(segments, data);

            if (elementContent.Count == 0)
            {
                return(false);
            }
            var elementLength = elementContent.Sum(e => e.Length);

            using (ModelCacheScope.CreateScope(data)) {
                if (string.IsNullOrEmpty(length))
                {
                    var bestAddress = StandardSearch(data, elementContent, elementLength, out int bestLength, runFilter);
                    if (bestAddress == Pointer.NULL)
                    {
                        return(false);
                    }
                    self = new ArrayRun(data, originalFormat + bestLength, string.Empty, bestAddress, bestLength, elementContent, data.GetNextRun(bestAddress).PointerSources, null);
                }
                else
                {
                    var bestAddress = KnownLengthSearch(data, elementContent, elementLength, length, out int bestLength, runFilter);
                    if (bestAddress == Pointer.NULL)
                    {
                        return(false);
                    }
                    var lengthFromAnchor = int.TryParse(length, out var _) ? string.Empty : length;
                    self = new ArrayRun(data, originalFormat, lengthFromAnchor, bestAddress, bestLength, elementContent, data.GetNextRun(bestAddress).PointerSources, null);
                }
            }

            if (allowPointersToEntries)
            {
                self = self.AddSourcesPointingWithinArray(changeToken);
            }
            return(true);
        }
コード例 #2
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.GetNextRun(Start);
                while (nextRun is NoInfoRun && nextRun.Start < owner.Count)
                {
                    nextRun = owner.GetNextRun(nextRun.Start + 1);
                }
                var byteLength   = 0;
                var elementCount = 0;
                while (Start + byteLength + ElementLength <= nextRun.Start && DataMatchesElementFormat(owner, Start + byteLength, ElementContent, flags, nextRun))
                {
                    byteLength += ElementLength;
                    elementCount++;
                }
                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.
            }
            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;
        }