2
// Copyright (c) 2007 James Newton-King
4
// Permission is hereby granted, free of charge, to any person
5
// obtaining a copy of this software and associated documentation
6
// files (the "Software"), to deal in the Software without
7
// restriction, including without limitation the rights to use,
8
// copy, modify, merge, publish, distribute, sublicense, and/or sell
9
// copies of the Software, and to permit persons to whom the
10
// Software is furnished to do so, subject to the following
13
// The above copyright notice and this permission notice shall be
14
// included in all copies or substantial portions of the Software.
16
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23
// OTHER DEALINGS IN THE SOFTWARE.
27
using System.Collections.Generic;
28
using System.Globalization;
29
using Newtonsoft.Json.Utilities;
31
namespace Newtonsoft.Json.Linq
35
private readonly string _expression;
36
public List<object> Parts { get; private set; }
38
private int _currentIndex;
40
public JPath(string expression)
42
ValidationUtils.ArgumentNotNull(expression, "expression");
43
_expression = expression;
44
Parts = new List<object>();
49
private void ParseMain()
51
int currentPartStartIndex = _currentIndex;
52
bool followingIndexer = false;
54
while (_currentIndex < _expression.Length)
56
char currentChar = _expression[_currentIndex];
62
if (_currentIndex > currentPartStartIndex)
64
string member = _expression.Substring(currentPartStartIndex, _currentIndex - currentPartStartIndex);
68
ParseIndexer(currentChar);
69
currentPartStartIndex = _currentIndex + 1;
70
followingIndexer = true;
74
throw new JsonException("Unexpected character while parsing path: " + currentChar);
76
if (_currentIndex > currentPartStartIndex)
78
string member = _expression.Substring(currentPartStartIndex, _currentIndex - currentPartStartIndex);
81
currentPartStartIndex = _currentIndex + 1;
82
followingIndexer = false;
86
throw new JsonException("Unexpected character following indexer: " + currentChar);
93
if (_currentIndex > currentPartStartIndex)
95
string member = _expression.Substring(currentPartStartIndex, _currentIndex - currentPartStartIndex);
100
private void ParseIndexer(char indexerOpenChar)
104
char indexerCloseChar = (indexerOpenChar == '[') ? ']' : ')';
105
int indexerStart = _currentIndex;
106
int indexerLength = 0;
107
bool indexerClosed = false;
109
while (_currentIndex < _expression.Length)
111
char currentCharacter = _expression[_currentIndex];
112
if (char.IsDigit(currentCharacter))
116
else if (currentCharacter == indexerCloseChar)
118
indexerClosed = true;
123
throw new JsonException("Unexpected character while parsing path indexer: " + currentCharacter);
130
throw new JsonException("Path ended with open indexer. Expected " + indexerCloseChar);
132
if (indexerLength == 0)
133
throw new JsonException("Empty path indexer.");
135
string indexer = _expression.Substring(indexerStart, indexerLength);
136
Parts.Add(Convert.ToInt32(indexer, CultureInfo.InvariantCulture));
139
internal JToken Evaluate(JToken root, bool errorWhenNoMatch)
141
JToken current = root;
143
foreach (object part in Parts)
145
string propertyName = part as string;
146
if (propertyName != null)
148
JObject o = current as JObject;
151
current = o[propertyName];
153
if (current == null && errorWhenNoMatch)
154
throw new JsonException("Property '{0}' does not exist on JObject.".FormatWith(CultureInfo.InvariantCulture, propertyName));
158
if (errorWhenNoMatch)
159
throw new JsonException("Property '{0}' not valid on {1}.".FormatWith(CultureInfo.InvariantCulture, propertyName, current.GetType().Name));
166
int index = (int) part;
168
JArray a = current as JArray;
169
JConstructor c = current as JConstructor;
173
if (a.Count <= index)
175
if (errorWhenNoMatch)
176
throw new IndexOutOfRangeException("Index {0} outside the bounds of JArray.".FormatWith(CultureInfo.InvariantCulture, index));
185
if (c.Count <= index)
187
if (errorWhenNoMatch)
188
throw new IndexOutOfRangeException("Index {0} outside the bounds of JConstructor.".FormatWith(CultureInfo.InvariantCulture, index));
197
if (errorWhenNoMatch)
198
throw new JsonException("Index {0} not valid on {1}.".FormatWith(CultureInfo.InvariantCulture, index, current.GetType().Name));
b'\\ No newline at end of file'