示例#1
0
        public void StringValue_Update_SourceIsChangedProperly()
        {
            TrackedStringManager source = new TrackedStringManager("test 123");
            TrackedString        number = source.Track(5, 3);

            Assert.AreEqual("123", number.StringValue);
            number.StringValue = "456";

            Assert.AreEqual("test 456", source.Text);
        }
示例#2
0
        public static void AssertIsValid(this TrackedStringManager mgr)
        {
            int last = -1;

            foreach (TrackedString ts in mgr)
            {
                //Assert.IsTrue(ts.OffsetInSource >= last, "Offset was less last! Source is out of order.");
                last = ts.OffsetInSource;

                string stringValueAfterOffsetChange = mgr.Text.Substring(ts.OffsetInSource, ts.StringValue.Length);
                Assert.AreEqual(ts.StringValue, stringValueAfterOffsetChange);
            }
        }
示例#3
0
            public TrackedString CreateTS(TrackedStringManager tracker)
            {
                string target      = tracker.Text.SubstringWithIndices(this.StartIndex, this.EndIndex);
                int    startOffset = 0;

                // If it's unquoted text, then we need to trim
                if (!this.IsInsideQuotes)
                {
                    target = JsonHelper.TrimUnquotedValue(target, out startOffset);
                }

                return(tracker.Track(this.StartIndex + startOffset, target.Length));
            }
示例#4
0
文件: JsonValue.cs 项目: ajbadaj/AJut
 /// <summary>
 /// Base class constructor
 /// </summary>
 internal JsonValue(TrackedStringManager source) : base(source)
 {
     // Track value types manually with our source. This is done because values aren't parsed,
     //  they're created in documents or arrays and so don't have a chance to know if they need
     //  to be tracked or not (done at the end of parse in document and array).
     //
     // If we are in placeholder mode, then we are *not* adding it yet as we don't know the whole
     //  range of the json value until we're done building our placeholders, but we need to allocate
     //  it in order to process it.
     if (this.IsValue && !this.Source.IsInPlaceholderMode)
     {
         this.Source.Track(this);
     }
 }
示例#5
0
        private static Json RunParse(TrackedStringManager tracker, ParserRules rules)
        {
            Json output = new Json(tracker);

            try
            {
                if (tracker.Text == null)
                {
                    output.AddError("Null source text provided!");
                    tracker.HasChanges = false;
                    return(output);
                }

                JsonTextIndexer indexer = new JsonTextIndexer(tracker.Text, rules);
                // TODO: Handle case where root is document without braces( ie "item : value, item2 : value2")

                int indexOfFirstOpenBracket = indexer.NextAny(0, '{', '[');

                // ============ No Brackets ===========
                if (indexOfFirstOpenBracket == -1)
                {
                    output.Data        = new JsonValue(output.TextTracking, 0, indexer.NextAny(0, '}', ']'), false);
                    tracker.HasChanges = false;
                    return(output);
                }

                // ============ Has Brackets ===========
                char nextBracket = output.TextTracking.Text[indexOfFirstOpenBracket];
                if (nextBracket == '{')
                {
                    output.Data        = new JsonDocument(indexer, output.TextTracking, indexOfFirstOpenBracket, out int endIndex);
                    tracker.HasChanges = false;
                    return(output);
                }
                else // if(nextBracket == '[')
                {
                    output.Data        = new JsonArray(indexer, output.TextTracking, indexOfFirstOpenBracket, out int endIndex);
                    tracker.HasChanges = false;
                    return(output);
                }
            }
            catch (Exception exc)
            {
                output.AddError(exc.ToString());
            }

            return(output);
        }
示例#6
0
        // ===================[ Construction & Parsing ]===========================
        /// <summary>
        /// Constructor for parsing
        /// </summary>
        internal JsonArray(JsonTextIndexer indexer, TrackedStringManager source, int startIndex, out int endIndex) : base(source)
        {
            endIndex = -1;

            int  nextEval   = indexer.NextAny(startIndex + 1);
            int  lastStart  = startIndex + 1;
            int  quoteStart = -1;
            bool lastWasUseful;

            while (nextEval != -1)
            {
                lastWasUseful = true;
                switch (source.Text[nextEval])
                {
                case ']':
                    if (quoteStart != -1)
                    {
                        break;
                    }

                    // There can be an unquoted array item inbetween the last comma'd item and the end
                    //  bracket. To make sure we handle that case, but don't add empty elements, we're
                    //  going to check it's an empty string before we add it.
                    //
                    // While empty keys and values will be supported (keys as long as they are unique)
                    //  they must be quoted so we can tell when the item is supposed to end.
                    if (lastStart != nextEval)
                    {
                        this.Add(new JsonValue(source, lastStart, nextEval - 1, false));
                    }

                    endIndex = nextEval;
                    break;

                case '[':
                {
                    int endOfArr;
                    this.Add(new JsonArray(indexer, source, nextEval, out endOfArr));
                    if (endOfArr == -1)
                    {
                        throw new FormatException($"Invalid json format provided, issue starts with array that begins at text index {nextEval}");
                    }

                    int peekAheadInd = indexer.NextAny(endOfArr + 1);
                    if (peekAheadInd != -1 && source.Text[peekAheadInd] == ',')
                    {
                        nextEval = peekAheadInd;
                    }
                    else
                    {
                        nextEval = endOfArr;
                    }
                }
                break;

                case '{':
                {
                    if (quoteStart != -1)
                    {
                        break;
                    }

                    int endOfDoc;
                    this.Add(new JsonDocument(indexer, source, nextEval, out endOfDoc));
                    if (endOfDoc == -1)
                    {
                        throw new FormatException($"Invalid json format provided, issue starts with document that begins at text index {nextEval}");
                    }

                    int peekAheadInd = indexer.NextAny(endOfDoc + 1);
                    if (peekAheadInd != -1 && source.Text[peekAheadInd] == ',')
                    {
                        nextEval = peekAheadInd;
                    }
                    else
                    {
                        nextEval = endOfDoc;
                    }
                }
                break;

                case ',':
                    if (quoteStart != -1)
                    {
                        break;
                    }

                    // We're safe to assume we can add this here because commas after docs are covered above
                    this.Add(new JsonValue(source, lastStart, nextEval - 1, false));
                    break;

                case '\"':
                    if (quoteStart != -1)
                    {
                        this.Add(new JsonValue(source, quoteStart, nextEval - 1, true));
                        quoteStart = -1;

                        int peekAheadInd = indexer.NextAny(nextEval + 1);
                        if (peekAheadInd != -1 && source.Text[peekAheadInd] == ',')
                        {
                            nextEval = peekAheadInd;
                        }
                    }
                    else
                    {
                        quoteStart = nextEval + 1;
                    }
                    break;

                default:
                    lastWasUseful = false;
                    break;
                }

                if (endIndex != -1)
                {
                    break;
                }

                if (lastWasUseful)
                {
                    lastStart = nextEval + 1;
                }
                nextEval = indexer.NextAny(nextEval + 1);
            }

            this.ResetStringValue(startIndex, endIndex);
            this.Source.Track(this);
        }
示例#7
0
 /// <summary>
 /// Constructor for building
 /// </summary>
 internal JsonArray(TrackedStringManager source, int startIndex) : base(source)
 {
     this.OffsetInSource = startIndex;
 }
示例#8
0
 /// <summary>
 /// Parses the text from the passed in <see cref="TrackedStringManager"/>, and returns a non-<c>null</c> <see cref="Json"/> instance.
 /// </summary>
 /// <param name="jsonText">Some json text.</param>
 /// <param name="rules">Parser rules</param>
 /// <returns>A non-<c>null</c> <see cref="Json"/> instance</returns>
 public static Json ParseText(TrackedStringManager source, ParserRules rules = null)
 {
     return(RunParse(source, rules));
 }
示例#9
0
文件: Json.cs 项目: ajbadaj/AJut
 internal Json(TrackedStringManager tracker)
 {
     this.TextTracking = tracker;
 }
示例#10
0
        // =========================[ Constructor & Parsing ]===============================
        /// <summary>
        /// Constructor for parsing
        /// </summary>
        internal JsonDocument(JsonTextIndexer textIndexer, TrackedStringManager source, int startIndex, out int endIndex) : base(source)
        {
            endIndex = -1;

            int nextEval = textIndexer.NextAny(startIndex + 1);

            JsonHelper.IndexTrackingHelper keyIndexTracker = new JsonHelper.IndexTrackingHelper();
            int  lastStart        = startIndex + 1;
            int  insideQuoteStart = -1;
            bool lastWasUseful;

            while (nextEval != -1)
            {
                lastWasUseful = true;
                switch (source.Text[nextEval])
                {
                case '}':
                    if (insideQuoteStart != -1)
                    {
                        break;
                    }

                    if (keyIndexTracker)
                    {
                        this.Add(keyIndexTracker.CreateTS(source), new JsonValue(source, lastStart, nextEval - 1, false));
                    }
                    endIndex = nextEval;
                    break;

                case '{':
                {
                    if (insideQuoteStart != -1)
                    {
                        break;
                    }

                    int endOfDoc;

                    if (!keyIndexTracker)
                    {
                        throw new FormatException("Can't read json format - error found around  offset: " + nextEval.ToString());
                    }

                    this.Add(keyIndexTracker.CreateTS(source),
                             new JsonDocument(textIndexer, source, nextEval, out endOfDoc));
                    if (endOfDoc == -1)
                    {
                        throw new FormatException($"Invalid json format provided, issue starts with document that begins at text index {nextEval}");
                    }

                    nextEval = endOfDoc;
                    keyIndexTracker.Reset();
                }
                break;

                case '[':
                {
                    if (insideQuoteStart != -1)
                    {
                        break;
                    }

                    if (!keyIndexTracker)
                    {
                        throw new FormatException("Can't read json format - attempted to add empty string key");
                    }

                    this.Add(keyIndexTracker.CreateTS(source),
                             new JsonArray(textIndexer, source, nextEval, out int endOfArr));
                    if (endOfArr == -1)
                    {
                        throw new FormatException($"Invalid json format provided, issue starts with array that begins at text index {nextEval}");
                    }

                    nextEval = endOfArr;
                    keyIndexTracker.Reset();
                }
                break;

                case ':':
                    if (insideQuoteStart != -1)
                    {
                        break;
                    }

                    keyIndexTracker.StartIndex = lastStart;
                    keyIndexTracker.EndIndex   = nextEval - 1;
                    break;

                case '\"':
                    // Start quote
                    if (insideQuoteStart == -1)
                    {
                        insideQuoteStart = nextEval + 1;
                    }
                    // End quote
                    else
                    {
                        // Peek ahead so we can decide if it's a key or a value
                        // If the next thing is a colon, then it's a key, otherwise it's a value
                        int peekAheadInd = textIndexer.NextAny(nextEval + 1);
                        if (peekAheadInd != -1 && source.Text[peekAheadInd] == ':')
                        {
                            keyIndexTracker.StartIndex     = insideQuoteStart;
                            keyIndexTracker.EndIndex       = nextEval - 1; // One before the quote that was just found
                            keyIndexTracker.IsInsideQuotes = true;
                            nextEval = peekAheadInd;
                        }
                        else
                        {
                            if (!keyIndexTracker)
                            {
                                string quote = source.Text.Substring(insideQuoteStart, nextEval - 1);
                                throw new FormatException("Json parsing failed due to incorrect string formatting around string: " + quote);
                            }

                            this.Add(keyIndexTracker.CreateTS(source), new JsonValue(source, insideQuoteStart, nextEval - 1, true));
                            keyIndexTracker.Reset();
                        }

                        insideQuoteStart = -1;
                    }

                    break;

                case ',':
                    if (insideQuoteStart != -1)
                    {
                        break;
                    }

                    if (keyIndexTracker)
                    {
                        var endValue = new JsonValue(source, lastStart, nextEval - 1, false);
                        if (endValue.StringValue.Length != 0)
                        {
                            this.Add(keyIndexTracker.CreateTS(source), endValue);
                            keyIndexTracker.Reset();
                        }
                    }
                    break;

                default:
                    lastWasUseful = false;
                    break;
                }

                if (endIndex != -1)
                {
                    break;
                }

                if (lastWasUseful)
                {
                    lastStart = nextEval + 1;
                }
                nextEval = textIndexer.NextAny(nextEval + 1);
            }

            if (nextEval == -1)
            {
                throw new FormatException("Json was improperly formatted");
            }

            this.ResetStringValue(startIndex, endIndex);
            this.Source.Track(this);
        }
示例#11
0
文件: JsonValue.cs 项目: ajbadaj/AJut
 /// <summary>
 /// Constructor (for building)
 /// </summary>
 internal JsonValue(TrackedStringManager source, int start, string value) : this(source)
 {
     this.SetValueInternal(value);
     this.OffsetInSource = start;
 }
示例#12
0
文件: JsonValue.cs 项目: ajbadaj/AJut
 /// <summary>
 /// Constructor (for parsing)
 /// </summary>
 internal JsonValue(TrackedStringManager source, int start, int end, bool isInsideQuote) : this(source)
 {
     this.ResetStringValue(start, end, isInsideQuote);
 }