root / trunk / Libraries / Json40r2 / Source / Src / Newtonsoft.Json / JsonTextReader.cs @ ed0be341
History | View | Annotate | Download (29.7 kB)
1 | d78cbf09 | Panagiotis Kanavos | #region License |
---|---|---|---|
2 | d78cbf09 | Panagiotis Kanavos | // Copyright (c) 2007 James Newton-King |
3 | d78cbf09 | Panagiotis Kanavos | // |
4 | d78cbf09 | Panagiotis Kanavos | // Permission is hereby granted, free of charge, to any person |
5 | d78cbf09 | Panagiotis Kanavos | // obtaining a copy of this software and associated documentation |
6 | d78cbf09 | Panagiotis Kanavos | // files (the "Software"), to deal in the Software without |
7 | d78cbf09 | Panagiotis Kanavos | // restriction, including without limitation the rights to use, |
8 | d78cbf09 | Panagiotis Kanavos | // copy, modify, merge, publish, distribute, sublicense, and/or sell |
9 | d78cbf09 | Panagiotis Kanavos | // copies of the Software, and to permit persons to whom the |
10 | d78cbf09 | Panagiotis Kanavos | // Software is furnished to do so, subject to the following |
11 | d78cbf09 | Panagiotis Kanavos | // conditions: |
12 | d78cbf09 | Panagiotis Kanavos | // |
13 | d78cbf09 | Panagiotis Kanavos | // The above copyright notice and this permission notice shall be |
14 | d78cbf09 | Panagiotis Kanavos | // included in all copies or substantial portions of the Software. |
15 | d78cbf09 | Panagiotis Kanavos | // |
16 | d78cbf09 | Panagiotis Kanavos | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
17 | d78cbf09 | Panagiotis Kanavos | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES |
18 | d78cbf09 | Panagiotis Kanavos | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
19 | d78cbf09 | Panagiotis Kanavos | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
20 | d78cbf09 | Panagiotis Kanavos | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
21 | d78cbf09 | Panagiotis Kanavos | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
22 | d78cbf09 | Panagiotis Kanavos | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
23 | d78cbf09 | Panagiotis Kanavos | // OTHER DEALINGS IN THE SOFTWARE. |
24 | d78cbf09 | Panagiotis Kanavos | #endregion |
25 | d78cbf09 | Panagiotis Kanavos | |
26 | d78cbf09 | Panagiotis Kanavos | using System; |
27 | d78cbf09 | Panagiotis Kanavos | using System.Collections.Generic; |
28 | d78cbf09 | Panagiotis Kanavos | using System.Text; |
29 | d78cbf09 | Panagiotis Kanavos | using System.IO; |
30 | d78cbf09 | Panagiotis Kanavos | using System.Xml; |
31 | d78cbf09 | Panagiotis Kanavos | using System.Globalization; |
32 | d78cbf09 | Panagiotis Kanavos | using Newtonsoft.Json.Utilities; |
33 | d78cbf09 | Panagiotis Kanavos | |
34 | d78cbf09 | Panagiotis Kanavos | namespace Newtonsoft.Json |
35 | d78cbf09 | Panagiotis Kanavos | { |
36 | d78cbf09 | Panagiotis Kanavos | /// <summary> |
37 | d78cbf09 | Panagiotis Kanavos | /// Represents a reader that provides fast, non-cached, forward-only access to serialized Json data. |
38 | d78cbf09 | Panagiotis Kanavos | /// </summary> |
39 | d78cbf09 | Panagiotis Kanavos | public class JsonTextReader : JsonReader, IJsonLineInfo |
40 | d78cbf09 | Panagiotis Kanavos | { |
41 | d78cbf09 | Panagiotis Kanavos | private enum ReadType |
42 | d78cbf09 | Panagiotis Kanavos | { |
43 | d78cbf09 | Panagiotis Kanavos | Read, |
44 | d78cbf09 | Panagiotis Kanavos | ReadAsBytes, |
45 | d78cbf09 | Panagiotis Kanavos | ReadAsDecimal, |
46 | d78cbf09 | Panagiotis Kanavos | #if !NET20 |
47 | d78cbf09 | Panagiotis Kanavos | ReadAsDateTimeOffset |
48 | d78cbf09 | Panagiotis Kanavos | #endif |
49 | d78cbf09 | Panagiotis Kanavos | } |
50 | d78cbf09 | Panagiotis Kanavos | |
51 | d78cbf09 | Panagiotis Kanavos | private readonly TextReader _reader; |
52 | d78cbf09 | Panagiotis Kanavos | private readonly StringBuffer _buffer; |
53 | d78cbf09 | Panagiotis Kanavos | private char? _lastChar; |
54 | d78cbf09 | Panagiotis Kanavos | private int _currentLinePosition; |
55 | d78cbf09 | Panagiotis Kanavos | private int _currentLineNumber; |
56 | d78cbf09 | Panagiotis Kanavos | private bool _end; |
57 | d78cbf09 | Panagiotis Kanavos | private ReadType _readType; |
58 | d78cbf09 | Panagiotis Kanavos | |
59 | d78cbf09 | Panagiotis Kanavos | /// <summary> |
60 | d78cbf09 | Panagiotis Kanavos | /// Initializes a new instance of the <see cref="JsonReader"/> class with the specified <see cref="TextReader"/>. |
61 | d78cbf09 | Panagiotis Kanavos | /// </summary> |
62 | d78cbf09 | Panagiotis Kanavos | /// <param name="reader">The <c>TextReader</c> containing the XML data to read.</param> |
63 | d78cbf09 | Panagiotis Kanavos | public JsonTextReader(TextReader reader) |
64 | d78cbf09 | Panagiotis Kanavos | { |
65 | d78cbf09 | Panagiotis Kanavos | if (reader == null) |
66 | d78cbf09 | Panagiotis Kanavos | throw new ArgumentNullException("reader"); |
67 | d78cbf09 | Panagiotis Kanavos | |
68 | d78cbf09 | Panagiotis Kanavos | _reader = reader; |
69 | d78cbf09 | Panagiotis Kanavos | _buffer = new StringBuffer(4096); |
70 | d78cbf09 | Panagiotis Kanavos | _currentLineNumber = 1; |
71 | d78cbf09 | Panagiotis Kanavos | } |
72 | d78cbf09 | Panagiotis Kanavos | |
73 | d78cbf09 | Panagiotis Kanavos | private void ParseString(char quote) |
74 | d78cbf09 | Panagiotis Kanavos | { |
75 | d78cbf09 | Panagiotis Kanavos | ReadStringIntoBuffer(quote); |
76 | d78cbf09 | Panagiotis Kanavos | |
77 | d78cbf09 | Panagiotis Kanavos | if (_readType == ReadType.ReadAsBytes) |
78 | d78cbf09 | Panagiotis Kanavos | { |
79 | d78cbf09 | Panagiotis Kanavos | byte[] data; |
80 | d78cbf09 | Panagiotis Kanavos | if (_buffer.Position == 0) |
81 | d78cbf09 | Panagiotis Kanavos | { |
82 | d78cbf09 | Panagiotis Kanavos | data = new byte[0]; |
83 | d78cbf09 | Panagiotis Kanavos | } |
84 | d78cbf09 | Panagiotis Kanavos | else |
85 | d78cbf09 | Panagiotis Kanavos | { |
86 | d78cbf09 | Panagiotis Kanavos | data = Convert.FromBase64CharArray(_buffer.GetInternalBuffer(), 0, _buffer.Position); |
87 | d78cbf09 | Panagiotis Kanavos | _buffer.Position = 0; |
88 | d78cbf09 | Panagiotis Kanavos | } |
89 | d78cbf09 | Panagiotis Kanavos | |
90 | d78cbf09 | Panagiotis Kanavos | SetToken(JsonToken.Bytes, data); |
91 | d78cbf09 | Panagiotis Kanavos | } |
92 | d78cbf09 | Panagiotis Kanavos | else |
93 | d78cbf09 | Panagiotis Kanavos | { |
94 | d78cbf09 | Panagiotis Kanavos | string text = _buffer.ToString(); |
95 | d78cbf09 | Panagiotis Kanavos | _buffer.Position = 0; |
96 | d78cbf09 | Panagiotis Kanavos | |
97 | d78cbf09 | Panagiotis Kanavos | if (text.StartsWith("/Date(", StringComparison.Ordinal) && text.EndsWith(")/", StringComparison.Ordinal)) |
98 | d78cbf09 | Panagiotis Kanavos | { |
99 | d78cbf09 | Panagiotis Kanavos | ParseDate(text); |
100 | d78cbf09 | Panagiotis Kanavos | } |
101 | d78cbf09 | Panagiotis Kanavos | else |
102 | d78cbf09 | Panagiotis Kanavos | { |
103 | d78cbf09 | Panagiotis Kanavos | SetToken(JsonToken.String, text); |
104 | d78cbf09 | Panagiotis Kanavos | QuoteChar = quote; |
105 | d78cbf09 | Panagiotis Kanavos | } |
106 | d78cbf09 | Panagiotis Kanavos | } |
107 | d78cbf09 | Panagiotis Kanavos | } |
108 | d78cbf09 | Panagiotis Kanavos | |
109 | d78cbf09 | Panagiotis Kanavos | private void ReadStringIntoBuffer(char quote) |
110 | d78cbf09 | Panagiotis Kanavos | { |
111 | d78cbf09 | Panagiotis Kanavos | while (true) |
112 | d78cbf09 | Panagiotis Kanavos | { |
113 | d78cbf09 | Panagiotis Kanavos | char currentChar = MoveNext(); |
114 | d78cbf09 | Panagiotis Kanavos | |
115 | d78cbf09 | Panagiotis Kanavos | switch (currentChar) |
116 | d78cbf09 | Panagiotis Kanavos | { |
117 | d78cbf09 | Panagiotis Kanavos | case '\0': |
118 | d78cbf09 | Panagiotis Kanavos | if (_end) |
119 | d78cbf09 | Panagiotis Kanavos | throw CreateJsonReaderException("Unterminated string. Expected delimiter: {0}. Line {1}, position {2}.", quote, _currentLineNumber, _currentLinePosition); |
120 | d78cbf09 | Panagiotis Kanavos | |
121 | d78cbf09 | Panagiotis Kanavos | _buffer.Append('\0'); |
122 | d78cbf09 | Panagiotis Kanavos | break; |
123 | d78cbf09 | Panagiotis Kanavos | case '\\': |
124 | d78cbf09 | Panagiotis Kanavos | if ((currentChar = MoveNext()) != '\0' || !_end) |
125 | d78cbf09 | Panagiotis Kanavos | { |
126 | d78cbf09 | Panagiotis Kanavos | switch (currentChar) |
127 | d78cbf09 | Panagiotis Kanavos | { |
128 | d78cbf09 | Panagiotis Kanavos | case 'b': |
129 | d78cbf09 | Panagiotis Kanavos | _buffer.Append('\b'); |
130 | d78cbf09 | Panagiotis Kanavos | break; |
131 | d78cbf09 | Panagiotis Kanavos | case 't': |
132 | d78cbf09 | Panagiotis Kanavos | _buffer.Append('\t'); |
133 | d78cbf09 | Panagiotis Kanavos | break; |
134 | d78cbf09 | Panagiotis Kanavos | case 'n': |
135 | d78cbf09 | Panagiotis Kanavos | _buffer.Append('\n'); |
136 | d78cbf09 | Panagiotis Kanavos | break; |
137 | d78cbf09 | Panagiotis Kanavos | case 'f': |
138 | d78cbf09 | Panagiotis Kanavos | _buffer.Append('\f'); |
139 | d78cbf09 | Panagiotis Kanavos | break; |
140 | d78cbf09 | Panagiotis Kanavos | case 'r': |
141 | d78cbf09 | Panagiotis Kanavos | _buffer.Append('\r'); |
142 | d78cbf09 | Panagiotis Kanavos | break; |
143 | d78cbf09 | Panagiotis Kanavos | case '\\': |
144 | d78cbf09 | Panagiotis Kanavos | _buffer.Append('\\'); |
145 | d78cbf09 | Panagiotis Kanavos | break; |
146 | d78cbf09 | Panagiotis Kanavos | case '"': |
147 | d78cbf09 | Panagiotis Kanavos | case '\'': |
148 | d78cbf09 | Panagiotis Kanavos | case '/': |
149 | d78cbf09 | Panagiotis Kanavos | _buffer.Append(currentChar); |
150 | d78cbf09 | Panagiotis Kanavos | break; |
151 | d78cbf09 | Panagiotis Kanavos | case 'u': |
152 | d78cbf09 | Panagiotis Kanavos | char[] hexValues = new char[4]; |
153 | d78cbf09 | Panagiotis Kanavos | for (int i = 0; i < hexValues.Length; i++) |
154 | d78cbf09 | Panagiotis Kanavos | { |
155 | d78cbf09 | Panagiotis Kanavos | if ((currentChar = MoveNext()) != '\0' || !_end) |
156 | d78cbf09 | Panagiotis Kanavos | hexValues[i] = currentChar; |
157 | d78cbf09 | Panagiotis Kanavos | else |
158 | d78cbf09 | Panagiotis Kanavos | throw CreateJsonReaderException("Unexpected end while parsing unicode character. Line {0}, position {1}.", _currentLineNumber, _currentLinePosition); |
159 | d78cbf09 | Panagiotis Kanavos | } |
160 | d78cbf09 | Panagiotis Kanavos | |
161 | d78cbf09 | Panagiotis Kanavos | char hexChar = Convert.ToChar(int.Parse(new string(hexValues), NumberStyles.HexNumber, NumberFormatInfo.InvariantInfo)); |
162 | d78cbf09 | Panagiotis Kanavos | _buffer.Append(hexChar); |
163 | d78cbf09 | Panagiotis Kanavos | break; |
164 | d78cbf09 | Panagiotis Kanavos | default: |
165 | d78cbf09 | Panagiotis Kanavos | throw CreateJsonReaderException("Bad JSON escape sequence: {0}. Line {1}, position {2}.", @"\" + currentChar, _currentLineNumber, _currentLinePosition); |
166 | d78cbf09 | Panagiotis Kanavos | } |
167 | d78cbf09 | Panagiotis Kanavos | } |
168 | d78cbf09 | Panagiotis Kanavos | else |
169 | d78cbf09 | Panagiotis Kanavos | { |
170 | d78cbf09 | Panagiotis Kanavos | throw CreateJsonReaderException("Unterminated string. Expected delimiter: {0}. Line {1}, position {2}.", quote, _currentLineNumber, _currentLinePosition); |
171 | d78cbf09 | Panagiotis Kanavos | } |
172 | d78cbf09 | Panagiotis Kanavos | break; |
173 | d78cbf09 | Panagiotis Kanavos | case '"': |
174 | d78cbf09 | Panagiotis Kanavos | case '\'': |
175 | d78cbf09 | Panagiotis Kanavos | if (currentChar == quote) |
176 | d78cbf09 | Panagiotis Kanavos | { |
177 | d78cbf09 | Panagiotis Kanavos | return; |
178 | d78cbf09 | Panagiotis Kanavos | } |
179 | d78cbf09 | Panagiotis Kanavos | else |
180 | d78cbf09 | Panagiotis Kanavos | { |
181 | d78cbf09 | Panagiotis Kanavos | _buffer.Append(currentChar); |
182 | d78cbf09 | Panagiotis Kanavos | } |
183 | d78cbf09 | Panagiotis Kanavos | break; |
184 | d78cbf09 | Panagiotis Kanavos | default: |
185 | d78cbf09 | Panagiotis Kanavos | _buffer.Append(currentChar); |
186 | d78cbf09 | Panagiotis Kanavos | break; |
187 | d78cbf09 | Panagiotis Kanavos | } |
188 | d78cbf09 | Panagiotis Kanavos | } |
189 | d78cbf09 | Panagiotis Kanavos | } |
190 | d78cbf09 | Panagiotis Kanavos | |
191 | d78cbf09 | Panagiotis Kanavos | private JsonReaderException CreateJsonReaderException(string format, params object[] args) |
192 | d78cbf09 | Panagiotis Kanavos | { |
193 | d78cbf09 | Panagiotis Kanavos | string message = format.FormatWith(CultureInfo.InvariantCulture, args); |
194 | d78cbf09 | Panagiotis Kanavos | return new JsonReaderException(message, null, _currentLineNumber, _currentLinePosition); |
195 | d78cbf09 | Panagiotis Kanavos | } |
196 | d78cbf09 | Panagiotis Kanavos | |
197 | d78cbf09 | Panagiotis Kanavos | private TimeSpan ReadOffset(string offsetText) |
198 | d78cbf09 | Panagiotis Kanavos | { |
199 | d78cbf09 | Panagiotis Kanavos | bool negative = (offsetText[0] == '-'); |
200 | d78cbf09 | Panagiotis Kanavos | |
201 | d78cbf09 | Panagiotis Kanavos | int hours = int.Parse(offsetText.Substring(1, 2), NumberStyles.Integer, CultureInfo.InvariantCulture); |
202 | d78cbf09 | Panagiotis Kanavos | int minutes = 0; |
203 | d78cbf09 | Panagiotis Kanavos | if (offsetText.Length >= 5) |
204 | d78cbf09 | Panagiotis Kanavos | minutes = int.Parse(offsetText.Substring(3, 2), NumberStyles.Integer, CultureInfo.InvariantCulture); |
205 | d78cbf09 | Panagiotis Kanavos | |
206 | d78cbf09 | Panagiotis Kanavos | TimeSpan offset = TimeSpan.FromHours(hours) + TimeSpan.FromMinutes(minutes); |
207 | d78cbf09 | Panagiotis Kanavos | if (negative) |
208 | d78cbf09 | Panagiotis Kanavos | offset = offset.Negate(); |
209 | d78cbf09 | Panagiotis Kanavos | |
210 | d78cbf09 | Panagiotis Kanavos | return offset; |
211 | d78cbf09 | Panagiotis Kanavos | } |
212 | d78cbf09 | Panagiotis Kanavos | |
213 | d78cbf09 | Panagiotis Kanavos | private void ParseDate(string text) |
214 | d78cbf09 | Panagiotis Kanavos | { |
215 | d78cbf09 | Panagiotis Kanavos | string value = text.Substring(6, text.Length - 8); |
216 | d78cbf09 | Panagiotis Kanavos | DateTimeKind kind = DateTimeKind.Utc; |
217 | d78cbf09 | Panagiotis Kanavos | |
218 | d78cbf09 | Panagiotis Kanavos | int index = value.IndexOf('+', 1); |
219 | d78cbf09 | Panagiotis Kanavos | |
220 | d78cbf09 | Panagiotis Kanavos | if (index == -1) |
221 | d78cbf09 | Panagiotis Kanavos | index = value.IndexOf('-', 1); |
222 | d78cbf09 | Panagiotis Kanavos | |
223 | d78cbf09 | Panagiotis Kanavos | TimeSpan offset = TimeSpan.Zero; |
224 | d78cbf09 | Panagiotis Kanavos | |
225 | d78cbf09 | Panagiotis Kanavos | if (index != -1) |
226 | d78cbf09 | Panagiotis Kanavos | { |
227 | d78cbf09 | Panagiotis Kanavos | kind = DateTimeKind.Local; |
228 | d78cbf09 | Panagiotis Kanavos | offset = ReadOffset(value.Substring(index)); |
229 | d78cbf09 | Panagiotis Kanavos | value = value.Substring(0, index); |
230 | d78cbf09 | Panagiotis Kanavos | } |
231 | d78cbf09 | Panagiotis Kanavos | |
232 | d78cbf09 | Panagiotis Kanavos | long javaScriptTicks = long.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); |
233 | d78cbf09 | Panagiotis Kanavos | |
234 | d78cbf09 | Panagiotis Kanavos | DateTime utcDateTime = JsonConvert.ConvertJavaScriptTicksToDateTime(javaScriptTicks); |
235 | d78cbf09 | Panagiotis Kanavos | |
236 | d78cbf09 | Panagiotis Kanavos | #if !NET20 |
237 | d78cbf09 | Panagiotis Kanavos | if (_readType == ReadType.ReadAsDateTimeOffset) |
238 | d78cbf09 | Panagiotis Kanavos | { |
239 | d78cbf09 | Panagiotis Kanavos | SetToken(JsonToken.Date, new DateTimeOffset(utcDateTime.Add(offset).Ticks, offset)); |
240 | d78cbf09 | Panagiotis Kanavos | } |
241 | d78cbf09 | Panagiotis Kanavos | else |
242 | d78cbf09 | Panagiotis Kanavos | #endif |
243 | d78cbf09 | Panagiotis Kanavos | { |
244 | d78cbf09 | Panagiotis Kanavos | DateTime dateTime; |
245 | d78cbf09 | Panagiotis Kanavos | |
246 | d78cbf09 | Panagiotis Kanavos | switch (kind) |
247 | d78cbf09 | Panagiotis Kanavos | { |
248 | d78cbf09 | Panagiotis Kanavos | case DateTimeKind.Unspecified: |
249 | d78cbf09 | Panagiotis Kanavos | dateTime = DateTime.SpecifyKind(utcDateTime.ToLocalTime(), DateTimeKind.Unspecified); |
250 | d78cbf09 | Panagiotis Kanavos | break; |
251 | d78cbf09 | Panagiotis Kanavos | case DateTimeKind.Local: |
252 | d78cbf09 | Panagiotis Kanavos | dateTime = utcDateTime.ToLocalTime(); |
253 | d78cbf09 | Panagiotis Kanavos | break; |
254 | d78cbf09 | Panagiotis Kanavos | default: |
255 | d78cbf09 | Panagiotis Kanavos | dateTime = utcDateTime; |
256 | d78cbf09 | Panagiotis Kanavos | break; |
257 | d78cbf09 | Panagiotis Kanavos | } |
258 | d78cbf09 | Panagiotis Kanavos | |
259 | d78cbf09 | Panagiotis Kanavos | SetToken(JsonToken.Date, dateTime); |
260 | d78cbf09 | Panagiotis Kanavos | } |
261 | d78cbf09 | Panagiotis Kanavos | } |
262 | d78cbf09 | Panagiotis Kanavos | |
263 | d78cbf09 | Panagiotis Kanavos | private const int LineFeedValue = StringUtils.LineFeed; |
264 | d78cbf09 | Panagiotis Kanavos | private const int CarriageReturnValue = StringUtils.CarriageReturn; |
265 | d78cbf09 | Panagiotis Kanavos | |
266 | d78cbf09 | Panagiotis Kanavos | private char MoveNext() |
267 | d78cbf09 | Panagiotis Kanavos | { |
268 | d78cbf09 | Panagiotis Kanavos | int value = _reader.Read(); |
269 | d78cbf09 | Panagiotis Kanavos | |
270 | d78cbf09 | Panagiotis Kanavos | switch (value) |
271 | d78cbf09 | Panagiotis Kanavos | { |
272 | d78cbf09 | Panagiotis Kanavos | case -1: |
273 | d78cbf09 | Panagiotis Kanavos | _end = true; |
274 | d78cbf09 | Panagiotis Kanavos | return '\0'; |
275 | d78cbf09 | Panagiotis Kanavos | case CarriageReturnValue: |
276 | d78cbf09 | Panagiotis Kanavos | if (_reader.Peek() == LineFeedValue) |
277 | d78cbf09 | Panagiotis Kanavos | _reader.Read(); |
278 | d78cbf09 | Panagiotis Kanavos | |
279 | d78cbf09 | Panagiotis Kanavos | _currentLineNumber++; |
280 | d78cbf09 | Panagiotis Kanavos | _currentLinePosition = 0; |
281 | d78cbf09 | Panagiotis Kanavos | break; |
282 | d78cbf09 | Panagiotis Kanavos | case LineFeedValue: |
283 | d78cbf09 | Panagiotis Kanavos | _currentLineNumber++; |
284 | d78cbf09 | Panagiotis Kanavos | _currentLinePosition = 0; |
285 | d78cbf09 | Panagiotis Kanavos | break; |
286 | d78cbf09 | Panagiotis Kanavos | default: |
287 | d78cbf09 | Panagiotis Kanavos | _currentLinePosition++; |
288 | d78cbf09 | Panagiotis Kanavos | break; |
289 | d78cbf09 | Panagiotis Kanavos | } |
290 | d78cbf09 | Panagiotis Kanavos | |
291 | d78cbf09 | Panagiotis Kanavos | return (char)value; |
292 | d78cbf09 | Panagiotis Kanavos | } |
293 | d78cbf09 | Panagiotis Kanavos | |
294 | d78cbf09 | Panagiotis Kanavos | private bool HasNext() |
295 | d78cbf09 | Panagiotis Kanavos | { |
296 | d78cbf09 | Panagiotis Kanavos | return (_reader.Peek() != -1); |
297 | d78cbf09 | Panagiotis Kanavos | } |
298 | d78cbf09 | Panagiotis Kanavos | |
299 | d78cbf09 | Panagiotis Kanavos | private int PeekNext() |
300 | d78cbf09 | Panagiotis Kanavos | { |
301 | d78cbf09 | Panagiotis Kanavos | return _reader.Peek(); |
302 | d78cbf09 | Panagiotis Kanavos | } |
303 | d78cbf09 | Panagiotis Kanavos | |
304 | d78cbf09 | Panagiotis Kanavos | /// <summary> |
305 | d78cbf09 | Panagiotis Kanavos | /// Reads the next JSON token from the stream. |
306 | d78cbf09 | Panagiotis Kanavos | /// </summary> |
307 | d78cbf09 | Panagiotis Kanavos | /// <returns> |
308 | d78cbf09 | Panagiotis Kanavos | /// true if the next token was read successfully; false if there are no more tokens to read. |
309 | d78cbf09 | Panagiotis Kanavos | /// </returns> |
310 | d78cbf09 | Panagiotis Kanavos | public override bool Read() |
311 | d78cbf09 | Panagiotis Kanavos | { |
312 | d78cbf09 | Panagiotis Kanavos | _readType = ReadType.Read; |
313 | d78cbf09 | Panagiotis Kanavos | return ReadInternal(); |
314 | d78cbf09 | Panagiotis Kanavos | } |
315 | d78cbf09 | Panagiotis Kanavos | |
316 | d78cbf09 | Panagiotis Kanavos | /// <summary> |
317 | d78cbf09 | Panagiotis Kanavos | /// Reads the next JSON token from the stream as a <see cref="T:Byte[]"/>. |
318 | d78cbf09 | Panagiotis Kanavos | /// </summary> |
319 | d78cbf09 | Panagiotis Kanavos | /// <returns> |
320 | d78cbf09 | Panagiotis Kanavos | /// A <see cref="T:Byte[]"/> or a null reference if the next JSON token is null. |
321 | d78cbf09 | Panagiotis Kanavos | /// </returns> |
322 | d78cbf09 | Panagiotis Kanavos | public override byte[] ReadAsBytes() |
323 | d78cbf09 | Panagiotis Kanavos | { |
324 | d78cbf09 | Panagiotis Kanavos | _readType = ReadType.ReadAsBytes; |
325 | d78cbf09 | Panagiotis Kanavos | |
326 | d78cbf09 | Panagiotis Kanavos | do |
327 | d78cbf09 | Panagiotis Kanavos | { |
328 | d78cbf09 | Panagiotis Kanavos | if (!ReadInternal()) |
329 | d78cbf09 | Panagiotis Kanavos | throw CreateJsonReaderException("Unexpected end when reading bytes: Line {0}, position {1}.", _currentLineNumber, _currentLinePosition); |
330 | d78cbf09 | Panagiotis Kanavos | } while (TokenType == JsonToken.Comment); |
331 | d78cbf09 | Panagiotis Kanavos | |
332 | d78cbf09 | Panagiotis Kanavos | if (TokenType == JsonToken.Null) |
333 | d78cbf09 | Panagiotis Kanavos | return null; |
334 | d78cbf09 | Panagiotis Kanavos | if (TokenType == JsonToken.Bytes) |
335 | d78cbf09 | Panagiotis Kanavos | return (byte[]) Value; |
336 | d78cbf09 | Panagiotis Kanavos | |
337 | d78cbf09 | Panagiotis Kanavos | throw CreateJsonReaderException("Unexpected token when reading bytes: {0}. Line {1}, position {2}.", TokenType, _currentLineNumber, _currentLinePosition); |
338 | d78cbf09 | Panagiotis Kanavos | } |
339 | d78cbf09 | Panagiotis Kanavos | |
340 | d78cbf09 | Panagiotis Kanavos | /// <summary> |
341 | d78cbf09 | Panagiotis Kanavos | /// Reads the next JSON token from the stream as a <see cref="Nullable{Decimal}"/>. |
342 | d78cbf09 | Panagiotis Kanavos | /// </summary> |
343 | d78cbf09 | Panagiotis Kanavos | /// <returns>A <see cref="Nullable{Decimal}"/>.</returns> |
344 | d78cbf09 | Panagiotis Kanavos | public override decimal? ReadAsDecimal() |
345 | d78cbf09 | Panagiotis Kanavos | { |
346 | d78cbf09 | Panagiotis Kanavos | _readType = ReadType.ReadAsDecimal; |
347 | d78cbf09 | Panagiotis Kanavos | |
348 | d78cbf09 | Panagiotis Kanavos | do |
349 | d78cbf09 | Panagiotis Kanavos | { |
350 | d78cbf09 | Panagiotis Kanavos | if (!ReadInternal()) |
351 | d78cbf09 | Panagiotis Kanavos | throw CreateJsonReaderException("Unexpected end when reading decimal: Line {0}, position {1}.", _currentLineNumber, _currentLinePosition); |
352 | d78cbf09 | Panagiotis Kanavos | } while (TokenType == JsonToken.Comment); |
353 | d78cbf09 | Panagiotis Kanavos | |
354 | d78cbf09 | Panagiotis Kanavos | if (TokenType == JsonToken.Null) |
355 | d78cbf09 | Panagiotis Kanavos | return null; |
356 | d78cbf09 | Panagiotis Kanavos | if (TokenType == JsonToken.Float) |
357 | d78cbf09 | Panagiotis Kanavos | return (decimal?)Value; |
358 | d78cbf09 | Panagiotis Kanavos | |
359 | d78cbf09 | Panagiotis Kanavos | decimal d; |
360 | d78cbf09 | Panagiotis Kanavos | if (TokenType == JsonToken.String && decimal.TryParse((string)Value, NumberStyles.Number, CultureInfo.InvariantCulture, out d)) |
361 | d78cbf09 | Panagiotis Kanavos | { |
362 | d78cbf09 | Panagiotis Kanavos | SetToken(JsonToken.Float, d); |
363 | d78cbf09 | Panagiotis Kanavos | return d; |
364 | d78cbf09 | Panagiotis Kanavos | } |
365 | d78cbf09 | Panagiotis Kanavos | |
366 | d78cbf09 | Panagiotis Kanavos | throw CreateJsonReaderException("Unexpected token when reading decimal: {0}. Line {1}, position {2}.", TokenType, _currentLineNumber, _currentLinePosition); |
367 | d78cbf09 | Panagiotis Kanavos | } |
368 | d78cbf09 | Panagiotis Kanavos | |
369 | d78cbf09 | Panagiotis Kanavos | #if !NET20 |
370 | d78cbf09 | Panagiotis Kanavos | /// <summary> |
371 | d78cbf09 | Panagiotis Kanavos | /// Reads the next JSON token from the stream as a <see cref="Nullable{DateTimeOffset}"/>. |
372 | d78cbf09 | Panagiotis Kanavos | /// </summary> |
373 | d78cbf09 | Panagiotis Kanavos | /// <returns>A <see cref="DateTimeOffset"/>.</returns> |
374 | d78cbf09 | Panagiotis Kanavos | public override DateTimeOffset? ReadAsDateTimeOffset() |
375 | d78cbf09 | Panagiotis Kanavos | { |
376 | d78cbf09 | Panagiotis Kanavos | _readType = ReadType.ReadAsDateTimeOffset; |
377 | d78cbf09 | Panagiotis Kanavos | |
378 | d78cbf09 | Panagiotis Kanavos | do |
379 | d78cbf09 | Panagiotis Kanavos | { |
380 | d78cbf09 | Panagiotis Kanavos | if (!ReadInternal()) |
381 | d78cbf09 | Panagiotis Kanavos | throw CreateJsonReaderException("Unexpected end when reading date: Line {0}, position {1}.", _currentLineNumber, _currentLinePosition); |
382 | d78cbf09 | Panagiotis Kanavos | } while (TokenType == JsonToken.Comment); |
383 | d78cbf09 | Panagiotis Kanavos | |
384 | d78cbf09 | Panagiotis Kanavos | if (TokenType == JsonToken.Null) |
385 | d78cbf09 | Panagiotis Kanavos | return null; |
386 | d78cbf09 | Panagiotis Kanavos | if (TokenType == JsonToken.Date) |
387 | d78cbf09 | Panagiotis Kanavos | return (DateTimeOffset)Value; |
388 | d78cbf09 | Panagiotis Kanavos | |
389 | d78cbf09 | Panagiotis Kanavos | throw CreateJsonReaderException("Unexpected token when reading date: {0}. Line {1}, position {2}.", TokenType, _currentLineNumber, _currentLinePosition); |
390 | d78cbf09 | Panagiotis Kanavos | } |
391 | d78cbf09 | Panagiotis Kanavos | #endif |
392 | d78cbf09 | Panagiotis Kanavos | |
393 | d78cbf09 | Panagiotis Kanavos | private bool ReadInternal() |
394 | d78cbf09 | Panagiotis Kanavos | { |
395 | d78cbf09 | Panagiotis Kanavos | while (true) |
396 | d78cbf09 | Panagiotis Kanavos | { |
397 | d78cbf09 | Panagiotis Kanavos | char currentChar; |
398 | d78cbf09 | Panagiotis Kanavos | if (_lastChar != null) |
399 | d78cbf09 | Panagiotis Kanavos | { |
400 | d78cbf09 | Panagiotis Kanavos | currentChar = _lastChar.Value; |
401 | d78cbf09 | Panagiotis Kanavos | _lastChar = null; |
402 | d78cbf09 | Panagiotis Kanavos | } |
403 | d78cbf09 | Panagiotis Kanavos | else |
404 | d78cbf09 | Panagiotis Kanavos | { |
405 | d78cbf09 | Panagiotis Kanavos | currentChar = MoveNext(); |
406 | d78cbf09 | Panagiotis Kanavos | } |
407 | d78cbf09 | Panagiotis Kanavos | |
408 | d78cbf09 | Panagiotis Kanavos | if (currentChar == '\0' && _end) |
409 | d78cbf09 | Panagiotis Kanavos | return false; |
410 | d78cbf09 | Panagiotis Kanavos | |
411 | d78cbf09 | Panagiotis Kanavos | switch (CurrentState) |
412 | d78cbf09 | Panagiotis Kanavos | { |
413 | d78cbf09 | Panagiotis Kanavos | case State.Start: |
414 | d78cbf09 | Panagiotis Kanavos | case State.Property: |
415 | d78cbf09 | Panagiotis Kanavos | case State.Array: |
416 | d78cbf09 | Panagiotis Kanavos | case State.ArrayStart: |
417 | d78cbf09 | Panagiotis Kanavos | case State.Constructor: |
418 | d78cbf09 | Panagiotis Kanavos | case State.ConstructorStart: |
419 | d78cbf09 | Panagiotis Kanavos | return ParseValue(currentChar); |
420 | d78cbf09 | Panagiotis Kanavos | case State.Complete: |
421 | d78cbf09 | Panagiotis Kanavos | break; |
422 | d78cbf09 | Panagiotis Kanavos | case State.Object: |
423 | d78cbf09 | Panagiotis Kanavos | case State.ObjectStart: |
424 | d78cbf09 | Panagiotis Kanavos | return ParseObject(currentChar); |
425 | d78cbf09 | Panagiotis Kanavos | case State.PostValue: |
426 | d78cbf09 | Panagiotis Kanavos | // returns true if it hits |
427 | d78cbf09 | Panagiotis Kanavos | // end of object or array |
428 | d78cbf09 | Panagiotis Kanavos | if (ParsePostValue(currentChar)) |
429 | d78cbf09 | Panagiotis Kanavos | return true; |
430 | d78cbf09 | Panagiotis Kanavos | break; |
431 | d78cbf09 | Panagiotis Kanavos | case State.Closed: |
432 | d78cbf09 | Panagiotis Kanavos | break; |
433 | d78cbf09 | Panagiotis Kanavos | case State.Error: |
434 | d78cbf09 | Panagiotis Kanavos | break; |
435 | d78cbf09 | Panagiotis Kanavos | default: |
436 | d78cbf09 | Panagiotis Kanavos | throw CreateJsonReaderException("Unexpected state: {0}. Line {1}, position {2}.", CurrentState, _currentLineNumber, _currentLinePosition); |
437 | d78cbf09 | Panagiotis Kanavos | } |
438 | d78cbf09 | Panagiotis Kanavos | } |
439 | d78cbf09 | Panagiotis Kanavos | } |
440 | d78cbf09 | Panagiotis Kanavos | |
441 | d78cbf09 | Panagiotis Kanavos | private bool ParsePostValue(char currentChar) |
442 | d78cbf09 | Panagiotis Kanavos | { |
443 | d78cbf09 | Panagiotis Kanavos | do |
444 | d78cbf09 | Panagiotis Kanavos | { |
445 | d78cbf09 | Panagiotis Kanavos | switch (currentChar) |
446 | d78cbf09 | Panagiotis Kanavos | { |
447 | d78cbf09 | Panagiotis Kanavos | case '}': |
448 | d78cbf09 | Panagiotis Kanavos | SetToken(JsonToken.EndObject); |
449 | d78cbf09 | Panagiotis Kanavos | return true; |
450 | d78cbf09 | Panagiotis Kanavos | case ']': |
451 | d78cbf09 | Panagiotis Kanavos | SetToken(JsonToken.EndArray); |
452 | d78cbf09 | Panagiotis Kanavos | return true; |
453 | d78cbf09 | Panagiotis Kanavos | case ')': |
454 | d78cbf09 | Panagiotis Kanavos | SetToken(JsonToken.EndConstructor); |
455 | d78cbf09 | Panagiotis Kanavos | return true; |
456 | d78cbf09 | Panagiotis Kanavos | case '/': |
457 | d78cbf09 | Panagiotis Kanavos | ParseComment(); |
458 | d78cbf09 | Panagiotis Kanavos | return true; |
459 | d78cbf09 | Panagiotis Kanavos | case ',': |
460 | d78cbf09 | Panagiotis Kanavos | // finished parsing |
461 | d78cbf09 | Panagiotis Kanavos | SetStateBasedOnCurrent(); |
462 | d78cbf09 | Panagiotis Kanavos | return false; |
463 | d78cbf09 | Panagiotis Kanavos | case ' ': |
464 | d78cbf09 | Panagiotis Kanavos | case StringUtils.Tab: |
465 | d78cbf09 | Panagiotis Kanavos | case StringUtils.LineFeed: |
466 | d78cbf09 | Panagiotis Kanavos | case StringUtils.CarriageReturn: |
467 | d78cbf09 | Panagiotis Kanavos | // eat |
468 | d78cbf09 | Panagiotis Kanavos | break; |
469 | d78cbf09 | Panagiotis Kanavos | default: |
470 | d78cbf09 | Panagiotis Kanavos | if (char.IsWhiteSpace(currentChar)) |
471 | d78cbf09 | Panagiotis Kanavos | { |
472 | d78cbf09 | Panagiotis Kanavos | // eat |
473 | d78cbf09 | Panagiotis Kanavos | } |
474 | d78cbf09 | Panagiotis Kanavos | else |
475 | d78cbf09 | Panagiotis Kanavos | { |
476 | d78cbf09 | Panagiotis Kanavos | throw CreateJsonReaderException("After parsing a value an unexpected character was encountered: {0}. Line {1}, position {2}.", currentChar, _currentLineNumber, _currentLinePosition); |
477 | d78cbf09 | Panagiotis Kanavos | } |
478 | d78cbf09 | Panagiotis Kanavos | break; |
479 | d78cbf09 | Panagiotis Kanavos | } |
480 | d78cbf09 | Panagiotis Kanavos | } while ((currentChar = MoveNext()) != '\0' || !_end); |
481 | d78cbf09 | Panagiotis Kanavos | |
482 | d78cbf09 | Panagiotis Kanavos | return false; |
483 | d78cbf09 | Panagiotis Kanavos | } |
484 | d78cbf09 | Panagiotis Kanavos | |
485 | d78cbf09 | Panagiotis Kanavos | private bool ParseObject(char currentChar) |
486 | d78cbf09 | Panagiotis Kanavos | { |
487 | d78cbf09 | Panagiotis Kanavos | do |
488 | d78cbf09 | Panagiotis Kanavos | { |
489 | d78cbf09 | Panagiotis Kanavos | switch (currentChar) |
490 | d78cbf09 | Panagiotis Kanavos | { |
491 | d78cbf09 | Panagiotis Kanavos | case '}': |
492 | d78cbf09 | Panagiotis Kanavos | SetToken(JsonToken.EndObject); |
493 | d78cbf09 | Panagiotis Kanavos | return true; |
494 | d78cbf09 | Panagiotis Kanavos | case '/': |
495 | d78cbf09 | Panagiotis Kanavos | ParseComment(); |
496 | d78cbf09 | Panagiotis Kanavos | return true; |
497 | d78cbf09 | Panagiotis Kanavos | case ' ': |
498 | d78cbf09 | Panagiotis Kanavos | case StringUtils.Tab: |
499 | d78cbf09 | Panagiotis Kanavos | case StringUtils.LineFeed: |
500 | d78cbf09 | Panagiotis Kanavos | case StringUtils.CarriageReturn: |
501 | d78cbf09 | Panagiotis Kanavos | // eat |
502 | d78cbf09 | Panagiotis Kanavos | break; |
503 | d78cbf09 | Panagiotis Kanavos | default: |
504 | d78cbf09 | Panagiotis Kanavos | if (char.IsWhiteSpace(currentChar)) |
505 | d78cbf09 | Panagiotis Kanavos | { |
506 | d78cbf09 | Panagiotis Kanavos | // eat |
507 | d78cbf09 | Panagiotis Kanavos | } |
508 | d78cbf09 | Panagiotis Kanavos | else |
509 | d78cbf09 | Panagiotis Kanavos | { |
510 | d78cbf09 | Panagiotis Kanavos | return ParseProperty(currentChar); |
511 | d78cbf09 | Panagiotis Kanavos | } |
512 | d78cbf09 | Panagiotis Kanavos | break; |
513 | d78cbf09 | Panagiotis Kanavos | } |
514 | d78cbf09 | Panagiotis Kanavos | } while ((currentChar = MoveNext()) != '\0' || !_end); |
515 | d78cbf09 | Panagiotis Kanavos | |
516 | d78cbf09 | Panagiotis Kanavos | return false; |
517 | d78cbf09 | Panagiotis Kanavos | } |
518 | d78cbf09 | Panagiotis Kanavos | |
519 | d78cbf09 | Panagiotis Kanavos | private bool ParseProperty(char firstChar) |
520 | d78cbf09 | Panagiotis Kanavos | { |
521 | d78cbf09 | Panagiotis Kanavos | char currentChar = firstChar; |
522 | d78cbf09 | Panagiotis Kanavos | char quoteChar; |
523 | d78cbf09 | Panagiotis Kanavos | |
524 | d78cbf09 | Panagiotis Kanavos | if (ValidIdentifierChar(currentChar)) |
525 | d78cbf09 | Panagiotis Kanavos | { |
526 | d78cbf09 | Panagiotis Kanavos | quoteChar = '\0'; |
527 | d78cbf09 | Panagiotis Kanavos | currentChar = ParseUnquotedProperty(currentChar); |
528 | d78cbf09 | Panagiotis Kanavos | } |
529 | d78cbf09 | Panagiotis Kanavos | else if (currentChar == '"' || currentChar == '\'') |
530 | d78cbf09 | Panagiotis Kanavos | { |
531 | d78cbf09 | Panagiotis Kanavos | quoteChar = currentChar; |
532 | d78cbf09 | Panagiotis Kanavos | ReadStringIntoBuffer(quoteChar); |
533 | d78cbf09 | Panagiotis Kanavos | currentChar = MoveNext(); |
534 | d78cbf09 | Panagiotis Kanavos | } |
535 | d78cbf09 | Panagiotis Kanavos | else |
536 | d78cbf09 | Panagiotis Kanavos | { |
537 | d78cbf09 | Panagiotis Kanavos | throw CreateJsonReaderException("Invalid property identifier character: {0}. Line {1}, position {2}.", currentChar, _currentLineNumber, _currentLinePosition); |
538 | d78cbf09 | Panagiotis Kanavos | } |
539 | d78cbf09 | Panagiotis Kanavos | |
540 | d78cbf09 | Panagiotis Kanavos | if (currentChar != ':') |
541 | d78cbf09 | Panagiotis Kanavos | { |
542 | d78cbf09 | Panagiotis Kanavos | currentChar = MoveNext(); |
543 | d78cbf09 | Panagiotis Kanavos | |
544 | d78cbf09 | Panagiotis Kanavos | // finished property. skip any whitespace and move to colon |
545 | d78cbf09 | Panagiotis Kanavos | EatWhitespace(currentChar, false, out currentChar); |
546 | d78cbf09 | Panagiotis Kanavos | |
547 | d78cbf09 | Panagiotis Kanavos | if (currentChar != ':') |
548 | d78cbf09 | Panagiotis Kanavos | throw CreateJsonReaderException("Invalid character after parsing property name. Expected ':' but got: {0}. Line {1}, position {2}.", currentChar, _currentLineNumber, _currentLinePosition); |
549 | d78cbf09 | Panagiotis Kanavos | } |
550 | d78cbf09 | Panagiotis Kanavos | |
551 | d78cbf09 | Panagiotis Kanavos | SetToken(JsonToken.PropertyName, _buffer.ToString()); |
552 | d78cbf09 | Panagiotis Kanavos | QuoteChar = quoteChar; |
553 | d78cbf09 | Panagiotis Kanavos | _buffer.Position = 0; |
554 | d78cbf09 | Panagiotis Kanavos | |
555 | d78cbf09 | Panagiotis Kanavos | return true; |
556 | d78cbf09 | Panagiotis Kanavos | } |
557 | d78cbf09 | Panagiotis Kanavos | |
558 | d78cbf09 | Panagiotis Kanavos | private bool ValidIdentifierChar(char value) |
559 | d78cbf09 | Panagiotis Kanavos | { |
560 | d78cbf09 | Panagiotis Kanavos | return (char.IsLetterOrDigit(value) || value == '_' || value == '$'); |
561 | d78cbf09 | Panagiotis Kanavos | } |
562 | d78cbf09 | Panagiotis Kanavos | |
563 | d78cbf09 | Panagiotis Kanavos | private char ParseUnquotedProperty(char firstChar) |
564 | d78cbf09 | Panagiotis Kanavos | { |
565 | d78cbf09 | Panagiotis Kanavos | // parse unquoted property name until whitespace or colon |
566 | d78cbf09 | Panagiotis Kanavos | _buffer.Append(firstChar); |
567 | d78cbf09 | Panagiotis Kanavos | |
568 | d78cbf09 | Panagiotis Kanavos | char currentChar; |
569 | d78cbf09 | Panagiotis Kanavos | |
570 | d78cbf09 | Panagiotis Kanavos | while ((currentChar = MoveNext()) != '\0' || !_end) |
571 | d78cbf09 | Panagiotis Kanavos | { |
572 | d78cbf09 | Panagiotis Kanavos | if (char.IsWhiteSpace(currentChar) || currentChar == ':') |
573 | d78cbf09 | Panagiotis Kanavos | { |
574 | d78cbf09 | Panagiotis Kanavos | return currentChar; |
575 | d78cbf09 | Panagiotis Kanavos | } |
576 | d78cbf09 | Panagiotis Kanavos | else if (ValidIdentifierChar(currentChar)) |
577 | d78cbf09 | Panagiotis Kanavos | { |
578 | d78cbf09 | Panagiotis Kanavos | _buffer.Append(currentChar); |
579 | d78cbf09 | Panagiotis Kanavos | } |
580 | d78cbf09 | Panagiotis Kanavos | else |
581 | d78cbf09 | Panagiotis Kanavos | { |
582 | d78cbf09 | Panagiotis Kanavos | throw CreateJsonReaderException("Invalid JavaScript property identifier character: {0}. Line {1}, position {2}.", currentChar, _currentLineNumber, _currentLinePosition); |
583 | d78cbf09 | Panagiotis Kanavos | } |
584 | d78cbf09 | Panagiotis Kanavos | } |
585 | d78cbf09 | Panagiotis Kanavos | |
586 | d78cbf09 | Panagiotis Kanavos | throw CreateJsonReaderException("Unexpected end when parsing unquoted property name. Line {0}, position {1}.", _currentLineNumber, _currentLinePosition); |
587 | d78cbf09 | Panagiotis Kanavos | } |
588 | d78cbf09 | Panagiotis Kanavos | |
589 | d78cbf09 | Panagiotis Kanavos | private bool ParseValue(char currentChar) |
590 | d78cbf09 | Panagiotis Kanavos | { |
591 | d78cbf09 | Panagiotis Kanavos | do |
592 | d78cbf09 | Panagiotis Kanavos | { |
593 | d78cbf09 | Panagiotis Kanavos | switch (currentChar) |
594 | d78cbf09 | Panagiotis Kanavos | { |
595 | d78cbf09 | Panagiotis Kanavos | case '"': |
596 | d78cbf09 | Panagiotis Kanavos | case '\'': |
597 | d78cbf09 | Panagiotis Kanavos | ParseString(currentChar); |
598 | d78cbf09 | Panagiotis Kanavos | return true; |
599 | d78cbf09 | Panagiotis Kanavos | case 't': |
600 | d78cbf09 | Panagiotis Kanavos | ParseTrue(); |
601 | d78cbf09 | Panagiotis Kanavos | return true; |
602 | d78cbf09 | Panagiotis Kanavos | case 'f': |
603 | d78cbf09 | Panagiotis Kanavos | ParseFalse(); |
604 | d78cbf09 | Panagiotis Kanavos | return true; |
605 | d78cbf09 | Panagiotis Kanavos | case 'n': |
606 | d78cbf09 | Panagiotis Kanavos | if (HasNext()) |
607 | d78cbf09 | Panagiotis Kanavos | { |
608 | d78cbf09 | Panagiotis Kanavos | char next = (char)PeekNext(); |
609 | d78cbf09 | Panagiotis Kanavos | |
610 | d78cbf09 | Panagiotis Kanavos | if (next == 'u') |
611 | d78cbf09 | Panagiotis Kanavos | ParseNull(); |
612 | d78cbf09 | Panagiotis Kanavos | else if (next == 'e') |
613 | d78cbf09 | Panagiotis Kanavos | ParseConstructor(); |
614 | d78cbf09 | Panagiotis Kanavos | else |
615 | d78cbf09 | Panagiotis Kanavos | throw CreateJsonReaderException("Unexpected character encountered while parsing value: {0}. Line {1}, position {2}.", currentChar, _currentLineNumber, _currentLinePosition); |
616 | d78cbf09 | Panagiotis Kanavos | } |
617 | d78cbf09 | Panagiotis Kanavos | else |
618 | d78cbf09 | Panagiotis Kanavos | { |
619 | d78cbf09 | Panagiotis Kanavos | throw CreateJsonReaderException("Unexpected end. Line {0}, position {1}.", _currentLineNumber, _currentLinePosition); |
620 | d78cbf09 | Panagiotis Kanavos | } |
621 | d78cbf09 | Panagiotis Kanavos | return true; |
622 | d78cbf09 | Panagiotis Kanavos | case 'N': |
623 | d78cbf09 | Panagiotis Kanavos | ParseNumberNaN(); |
624 | d78cbf09 | Panagiotis Kanavos | return true; |
625 | d78cbf09 | Panagiotis Kanavos | case 'I': |
626 | d78cbf09 | Panagiotis Kanavos | ParseNumberPositiveInfinity(); |
627 | d78cbf09 | Panagiotis Kanavos | return true; |
628 | d78cbf09 | Panagiotis Kanavos | case '-': |
629 | d78cbf09 | Panagiotis Kanavos | if (PeekNext() == 'I') |
630 | d78cbf09 | Panagiotis Kanavos | ParseNumberNegativeInfinity(); |
631 | d78cbf09 | Panagiotis Kanavos | else |
632 | d78cbf09 | Panagiotis Kanavos | ParseNumber(currentChar); |
633 | d78cbf09 | Panagiotis Kanavos | return true; |
634 | d78cbf09 | Panagiotis Kanavos | case '/': |
635 | d78cbf09 | Panagiotis Kanavos | ParseComment(); |
636 | d78cbf09 | Panagiotis Kanavos | return true; |
637 | d78cbf09 | Panagiotis Kanavos | case 'u': |
638 | d78cbf09 | Panagiotis Kanavos | ParseUndefined(); |
639 | d78cbf09 | Panagiotis Kanavos | return true; |
640 | d78cbf09 | Panagiotis Kanavos | case '{': |
641 | d78cbf09 | Panagiotis Kanavos | SetToken(JsonToken.StartObject); |
642 | d78cbf09 | Panagiotis Kanavos | return true; |
643 | d78cbf09 | Panagiotis Kanavos | case '[': |
644 | d78cbf09 | Panagiotis Kanavos | SetToken(JsonToken.StartArray); |
645 | d78cbf09 | Panagiotis Kanavos | return true; |
646 | d78cbf09 | Panagiotis Kanavos | case '}': |
647 | d78cbf09 | Panagiotis Kanavos | SetToken(JsonToken.EndObject); |
648 | d78cbf09 | Panagiotis Kanavos | return true; |
649 | d78cbf09 | Panagiotis Kanavos | case ']': |
650 | d78cbf09 | Panagiotis Kanavos | SetToken(JsonToken.EndArray); |
651 | d78cbf09 | Panagiotis Kanavos | return true; |
652 | d78cbf09 | Panagiotis Kanavos | case ',': |
653 | d78cbf09 | Panagiotis Kanavos | SetToken(JsonToken.Undefined); |
654 | d78cbf09 | Panagiotis Kanavos | return true; |
655 | d78cbf09 | Panagiotis Kanavos | case ')': |
656 | d78cbf09 | Panagiotis Kanavos | SetToken(JsonToken.EndConstructor); |
657 | d78cbf09 | Panagiotis Kanavos | return true; |
658 | d78cbf09 | Panagiotis Kanavos | case ' ': |
659 | d78cbf09 | Panagiotis Kanavos | case StringUtils.Tab: |
660 | d78cbf09 | Panagiotis Kanavos | case StringUtils.LineFeed: |
661 | d78cbf09 | Panagiotis Kanavos | case StringUtils.CarriageReturn: |
662 | d78cbf09 | Panagiotis Kanavos | // eat |
663 | d78cbf09 | Panagiotis Kanavos | break; |
664 | d78cbf09 | Panagiotis Kanavos | default: |
665 | d78cbf09 | Panagiotis Kanavos | if (char.IsWhiteSpace(currentChar)) |
666 | d78cbf09 | Panagiotis Kanavos | { |
667 | d78cbf09 | Panagiotis Kanavos | // eat |
668 | d78cbf09 | Panagiotis Kanavos | } |
669 | d78cbf09 | Panagiotis Kanavos | else if (char.IsNumber(currentChar) || currentChar == '-' || currentChar == '.') |
670 | d78cbf09 | Panagiotis Kanavos | { |
671 | d78cbf09 | Panagiotis Kanavos | ParseNumber(currentChar); |
672 | d78cbf09 | Panagiotis Kanavos | return true; |
673 | d78cbf09 | Panagiotis Kanavos | } |
674 | d78cbf09 | Panagiotis Kanavos | else |
675 | d78cbf09 | Panagiotis Kanavos | { |
676 | d78cbf09 | Panagiotis Kanavos | throw CreateJsonReaderException("Unexpected character encountered while parsing value: {0}. Line {1}, position {2}.", currentChar, _currentLineNumber, _currentLinePosition); |
677 | d78cbf09 | Panagiotis Kanavos | } |
678 | d78cbf09 | Panagiotis Kanavos | break; |
679 | d78cbf09 | Panagiotis Kanavos | } |
680 | d78cbf09 | Panagiotis Kanavos | } while ((currentChar = MoveNext()) != '\0' || !_end); |
681 | d78cbf09 | Panagiotis Kanavos | |
682 | d78cbf09 | Panagiotis Kanavos | return false; |
683 | d78cbf09 | Panagiotis Kanavos | } |
684 | d78cbf09 | Panagiotis Kanavos | |
685 | d78cbf09 | Panagiotis Kanavos | private bool EatWhitespace(char initialChar, bool oneOrMore, out char finalChar) |
686 | d78cbf09 | Panagiotis Kanavos | { |
687 | d78cbf09 | Panagiotis Kanavos | bool whitespace = false; |
688 | d78cbf09 | Panagiotis Kanavos | char currentChar = initialChar; |
689 | d78cbf09 | Panagiotis Kanavos | while (currentChar == ' ' || char.IsWhiteSpace(currentChar)) |
690 | d78cbf09 | Panagiotis Kanavos | { |
691 | d78cbf09 | Panagiotis Kanavos | whitespace = true; |
692 | d78cbf09 | Panagiotis Kanavos | currentChar = MoveNext(); |
693 | d78cbf09 | Panagiotis Kanavos | } |
694 | d78cbf09 | Panagiotis Kanavos | |
695 | d78cbf09 | Panagiotis Kanavos | finalChar = currentChar; |
696 | d78cbf09 | Panagiotis Kanavos | |
697 | d78cbf09 | Panagiotis Kanavos | return (!oneOrMore || whitespace); |
698 | d78cbf09 | Panagiotis Kanavos | } |
699 | d78cbf09 | Panagiotis Kanavos | |
700 | d78cbf09 | Panagiotis Kanavos | private void ParseConstructor() |
701 | d78cbf09 | Panagiotis Kanavos | { |
702 | d78cbf09 | Panagiotis Kanavos | if (MatchValue('n', "new", true)) |
703 | d78cbf09 | Panagiotis Kanavos | { |
704 | d78cbf09 | Panagiotis Kanavos | char currentChar = MoveNext(); |
705 | d78cbf09 | Panagiotis Kanavos | |
706 | d78cbf09 | Panagiotis Kanavos | if (EatWhitespace(currentChar, true, out currentChar)) |
707 | d78cbf09 | Panagiotis Kanavos | { |
708 | d78cbf09 | Panagiotis Kanavos | while (char.IsLetter(currentChar)) |
709 | d78cbf09 | Panagiotis Kanavos | { |
710 | d78cbf09 | Panagiotis Kanavos | _buffer.Append(currentChar); |
711 | d78cbf09 | Panagiotis Kanavos | currentChar = MoveNext(); |
712 | d78cbf09 | Panagiotis Kanavos | } |
713 | d78cbf09 | Panagiotis Kanavos | |
714 | d78cbf09 | Panagiotis Kanavos | EatWhitespace(currentChar, false, out currentChar); |
715 | d78cbf09 | Panagiotis Kanavos | |
716 | d78cbf09 | Panagiotis Kanavos | if (currentChar != '(') |
717 | d78cbf09 | Panagiotis Kanavos | throw CreateJsonReaderException("Unexpected character while parsing constructor: {0}. Line {1}, position {2}.", currentChar, _currentLineNumber, _currentLinePosition); |
718 | d78cbf09 | Panagiotis Kanavos | |
719 | d78cbf09 | Panagiotis Kanavos | string constructorName = _buffer.ToString(); |
720 | d78cbf09 | Panagiotis Kanavos | _buffer.Position = 0; |
721 | d78cbf09 | Panagiotis Kanavos | |
722 | d78cbf09 | Panagiotis Kanavos | SetToken(JsonToken.StartConstructor, constructorName); |
723 | d78cbf09 | Panagiotis Kanavos | } |
724 | d78cbf09 | Panagiotis Kanavos | } |
725 | d78cbf09 | Panagiotis Kanavos | } |
726 | d78cbf09 | Panagiotis Kanavos | |
727 | d78cbf09 | Panagiotis Kanavos | private void ParseNumber(char firstChar) |
728 | d78cbf09 | Panagiotis Kanavos | { |
729 | d78cbf09 | Panagiotis Kanavos | char currentChar = firstChar; |
730 | d78cbf09 | Panagiotis Kanavos | |
731 | d78cbf09 | Panagiotis Kanavos | // parse until seperator character or end |
732 | d78cbf09 | Panagiotis Kanavos | bool end = false; |
733 | d78cbf09 | Panagiotis Kanavos | do |
734 | d78cbf09 | Panagiotis Kanavos | { |
735 | d78cbf09 | Panagiotis Kanavos | if (IsSeperator(currentChar)) |
736 | d78cbf09 | Panagiotis Kanavos | { |
737 | d78cbf09 | Panagiotis Kanavos | end = true; |
738 | d78cbf09 | Panagiotis Kanavos | _lastChar = currentChar; |
739 | d78cbf09 | Panagiotis Kanavos | } |
740 | d78cbf09 | Panagiotis Kanavos | else |
741 | d78cbf09 | Panagiotis Kanavos | { |
742 | d78cbf09 | Panagiotis Kanavos | _buffer.Append(currentChar); |
743 | d78cbf09 | Panagiotis Kanavos | } |
744 | d78cbf09 | Panagiotis Kanavos | |
745 | d78cbf09 | Panagiotis Kanavos | } while (!end && ((currentChar = MoveNext()) != '\0' || !_end)); |
746 | d78cbf09 | Panagiotis Kanavos | |
747 | d78cbf09 | Panagiotis Kanavos | string number = _buffer.ToString(); |
748 | d78cbf09 | Panagiotis Kanavos | object numberValue; |
749 | d78cbf09 | Panagiotis Kanavos | JsonToken numberType; |
750 | d78cbf09 | Panagiotis Kanavos | |
751 | d78cbf09 | Panagiotis Kanavos | bool nonBase10 = (firstChar == '0' && !number.StartsWith("0.", StringComparison.OrdinalIgnoreCase)); |
752 | d78cbf09 | Panagiotis Kanavos | |
753 | d78cbf09 | Panagiotis Kanavos | if (_readType == ReadType.ReadAsDecimal) |
754 | d78cbf09 | Panagiotis Kanavos | { |
755 | d78cbf09 | Panagiotis Kanavos | if (nonBase10) |
756 | d78cbf09 | Panagiotis Kanavos | { |
757 | d78cbf09 | Panagiotis Kanavos | // decimal.Parse doesn't support parsing hexadecimal values |
758 | d78cbf09 | Panagiotis Kanavos | long integer = number.StartsWith("0x", StringComparison.OrdinalIgnoreCase) |
759 | d78cbf09 | Panagiotis Kanavos | ? Convert.ToInt64(number, 16) |
760 | d78cbf09 | Panagiotis Kanavos | : Convert.ToInt64(number, 8); |
761 | d78cbf09 | Panagiotis Kanavos | |
762 | d78cbf09 | Panagiotis Kanavos | numberValue = Convert.ToDecimal(integer); |
763 | d78cbf09 | Panagiotis Kanavos | } |
764 | d78cbf09 | Panagiotis Kanavos | else |
765 | d78cbf09 | Panagiotis Kanavos | { |
766 | d78cbf09 | Panagiotis Kanavos | numberValue = decimal.Parse(number, NumberStyles.Number | NumberStyles.AllowExponent, CultureInfo.InvariantCulture); |
767 | d78cbf09 | Panagiotis Kanavos | } |
768 | d78cbf09 | Panagiotis Kanavos | |
769 | d78cbf09 | Panagiotis Kanavos | numberType = JsonToken.Float; |
770 | d78cbf09 | Panagiotis Kanavos | } |
771 | d78cbf09 | Panagiotis Kanavos | else |
772 | d78cbf09 | Panagiotis Kanavos | { |
773 | d78cbf09 | Panagiotis Kanavos | if (nonBase10) |
774 | d78cbf09 | Panagiotis Kanavos | { |
775 | d78cbf09 | Panagiotis Kanavos | numberValue = number.StartsWith("0x", StringComparison.OrdinalIgnoreCase) |
776 | d78cbf09 | Panagiotis Kanavos | ? Convert.ToInt64(number, 16) |
777 | d78cbf09 | Panagiotis Kanavos | : Convert.ToInt64(number, 8); |
778 | d78cbf09 | Panagiotis Kanavos | numberType = JsonToken.Integer; |
779 | d78cbf09 | Panagiotis Kanavos | } |
780 | d78cbf09 | Panagiotis Kanavos | else if (number.IndexOf(".", StringComparison.OrdinalIgnoreCase) != -1 || number.IndexOf("e", StringComparison.OrdinalIgnoreCase) != -1) |
781 | d78cbf09 | Panagiotis Kanavos | { |
782 | d78cbf09 | Panagiotis Kanavos | numberValue = Convert.ToDouble(number, CultureInfo.InvariantCulture); |
783 | d78cbf09 | Panagiotis Kanavos | numberType = JsonToken.Float; |
784 | d78cbf09 | Panagiotis Kanavos | } |
785 | d78cbf09 | Panagiotis Kanavos | else |
786 | d78cbf09 | Panagiotis Kanavos | { |
787 | d78cbf09 | Panagiotis Kanavos | try |
788 | d78cbf09 | Panagiotis Kanavos | { |
789 | d78cbf09 | Panagiotis Kanavos | numberValue = Convert.ToInt64(number, CultureInfo.InvariantCulture); |
790 | d78cbf09 | Panagiotis Kanavos | } |
791 | d78cbf09 | Panagiotis Kanavos | catch (OverflowException ex) |
792 | d78cbf09 | Panagiotis Kanavos | { |
793 | d78cbf09 | Panagiotis Kanavos | throw new JsonReaderException("JSON integer {0} is too large or small for an Int64.".FormatWith(CultureInfo.InvariantCulture, number), ex); |
794 | d78cbf09 | Panagiotis Kanavos | } |
795 | d78cbf09 | Panagiotis Kanavos | |
796 | d78cbf09 | Panagiotis Kanavos | numberType = JsonToken.Integer; |
797 | d78cbf09 | Panagiotis Kanavos | } |
798 | d78cbf09 | Panagiotis Kanavos | } |
799 | d78cbf09 | Panagiotis Kanavos | |
800 | d78cbf09 | Panagiotis Kanavos | _buffer.Position = 0; |
801 | d78cbf09 | Panagiotis Kanavos | |
802 | d78cbf09 | Panagiotis Kanavos | SetToken(numberType, numberValue); |
803 | d78cbf09 | Panagiotis Kanavos | } |
804 | d78cbf09 | Panagiotis Kanavos | |
805 | d78cbf09 | Panagiotis Kanavos | private void ParseComment() |
806 | d78cbf09 | Panagiotis Kanavos | { |
807 | d78cbf09 | Panagiotis Kanavos | // should have already parsed / character before reaching this method |
808 | d78cbf09 | Panagiotis Kanavos | |
809 | d78cbf09 | Panagiotis Kanavos | char currentChar = MoveNext(); |
810 | d78cbf09 | Panagiotis Kanavos | |
811 | d78cbf09 | Panagiotis Kanavos | if (currentChar == '*') |
812 | d78cbf09 | Panagiotis Kanavos | { |
813 | d78cbf09 | Panagiotis Kanavos | while ((currentChar = MoveNext()) != '\0' || !_end) |
814 | d78cbf09 | Panagiotis Kanavos | { |
815 | d78cbf09 | Panagiotis Kanavos | if (currentChar == '*') |
816 | d78cbf09 | Panagiotis Kanavos | { |
817 | d78cbf09 | Panagiotis Kanavos | if ((currentChar = MoveNext()) != '\0' || !_end) |
818 | d78cbf09 | Panagiotis Kanavos | { |
819 | d78cbf09 | Panagiotis Kanavos | if (currentChar == '/') |
820 | d78cbf09 | Panagiotis Kanavos | { |
821 | d78cbf09 | Panagiotis Kanavos | break; |
822 | d78cbf09 | Panagiotis Kanavos | } |
823 | d78cbf09 | Panagiotis Kanavos | else |
824 | d78cbf09 | Panagiotis Kanavos | { |
825 | d78cbf09 | Panagiotis Kanavos | _buffer.Append('*'); |
826 | d78cbf09 | Panagiotis Kanavos | _buffer.Append(currentChar); |
827 | d78cbf09 | Panagiotis Kanavos | } |
828 | d78cbf09 | Panagiotis Kanavos | } |
829 | d78cbf09 | Panagiotis Kanavos | } |
830 | d78cbf09 | Panagiotis Kanavos | else |
831 | d78cbf09 | Panagiotis Kanavos | { |
832 | d78cbf09 | Panagiotis Kanavos | _buffer.Append(currentChar); |
833 | d78cbf09 | Panagiotis Kanavos | } |
834 | d78cbf09 | Panagiotis Kanavos | } |
835 | d78cbf09 | Panagiotis Kanavos | } |
836 | d78cbf09 | Panagiotis Kanavos | else |
837 | d78cbf09 | Panagiotis Kanavos | { |
838 | d78cbf09 | Panagiotis Kanavos | throw CreateJsonReaderException("Error parsing comment. Expected: *. Line {0}, position {1}.", _currentLineNumber, _currentLinePosition); |
839 | d78cbf09 | Panagiotis Kanavos | } |
840 | d78cbf09 | Panagiotis Kanavos | |
841 | d78cbf09 | Panagiotis Kanavos | SetToken(JsonToken.Comment, _buffer.ToString()); |
842 | d78cbf09 | Panagiotis Kanavos | |
843 | d78cbf09 | Panagiotis Kanavos | _buffer.Position = 0; |
844 | d78cbf09 | Panagiotis Kanavos | } |
845 | d78cbf09 | Panagiotis Kanavos | |
846 | d78cbf09 | Panagiotis Kanavos | private bool MatchValue(char firstChar, string value) |
847 | d78cbf09 | Panagiotis Kanavos | { |
848 | d78cbf09 | Panagiotis Kanavos | char currentChar = firstChar; |
849 | d78cbf09 | Panagiotis Kanavos | |
850 | d78cbf09 | Panagiotis Kanavos | int i = 0; |
851 | d78cbf09 | Panagiotis Kanavos | do |
852 | d78cbf09 | Panagiotis Kanavos | { |
853 | d78cbf09 | Panagiotis Kanavos | if (currentChar != value[i]) |
854 | d78cbf09 | Panagiotis Kanavos | { |
855 | d78cbf09 | Panagiotis Kanavos | break; |
856 | d78cbf09 | Panagiotis Kanavos | } |
857 | d78cbf09 | Panagiotis Kanavos | i++; |
858 | d78cbf09 | Panagiotis Kanavos | } |
859 | d78cbf09 | Panagiotis Kanavos | while (i < value.Length && ((currentChar = MoveNext()) != '\0' || !_end)); |
860 | d78cbf09 | Panagiotis Kanavos | |
861 | d78cbf09 | Panagiotis Kanavos | return (i == value.Length); |
862 | d78cbf09 | Panagiotis Kanavos | } |
863 | d78cbf09 | Panagiotis Kanavos | |
864 | d78cbf09 | Panagiotis Kanavos | private bool MatchValue(char firstChar, string value, bool noTrailingNonSeperatorCharacters) |
865 | d78cbf09 | Panagiotis Kanavos | { |
866 | d78cbf09 | Panagiotis Kanavos | // will match value and then move to the next character, checking that it is a seperator character |
867 | d78cbf09 | Panagiotis Kanavos | bool match = MatchValue(firstChar, value); |
868 | d78cbf09 | Panagiotis Kanavos | |
869 | d78cbf09 | Panagiotis Kanavos | if (!noTrailingNonSeperatorCharacters) |
870 | d78cbf09 | Panagiotis Kanavos | { |
871 | d78cbf09 | Panagiotis Kanavos | return match; |
872 | d78cbf09 | Panagiotis Kanavos | } |
873 | d78cbf09 | Panagiotis Kanavos | else |
874 | d78cbf09 | Panagiotis Kanavos | { |
875 | d78cbf09 | Panagiotis Kanavos | int c = PeekNext(); |
876 | d78cbf09 | Panagiotis Kanavos | char next = (c != -1) ? (char) c : '\0'; |
877 | d78cbf09 | Panagiotis Kanavos | bool matchAndNoTrainingNonSeperatorCharacters = (match && (next == '\0' || IsSeperator(next))); |
878 | d78cbf09 | Panagiotis Kanavos | |
879 | d78cbf09 | Panagiotis Kanavos | return matchAndNoTrainingNonSeperatorCharacters; |
880 | d78cbf09 | Panagiotis Kanavos | } |
881 | d78cbf09 | Panagiotis Kanavos | } |
882 | d78cbf09 | Panagiotis Kanavos | |
883 | d78cbf09 | Panagiotis Kanavos | private bool IsSeperator(char c) |
884 | d78cbf09 | Panagiotis Kanavos | { |
885 | d78cbf09 | Panagiotis Kanavos | switch (c) |
886 | d78cbf09 | Panagiotis Kanavos | { |
887 | d78cbf09 | Panagiotis Kanavos | case '}': |
888 | d78cbf09 | Panagiotis Kanavos | case ']': |
889 | d78cbf09 | Panagiotis Kanavos | case ',': |
890 | d78cbf09 | Panagiotis Kanavos | return true; |
891 | d78cbf09 | Panagiotis Kanavos | case '/': |
892 | d78cbf09 | Panagiotis Kanavos | // check next character to see if start of a comment |
893 | d78cbf09 | Panagiotis Kanavos | return (HasNext() && PeekNext() == '*'); |
894 | d78cbf09 | Panagiotis Kanavos | case ')': |
895 | d78cbf09 | Panagiotis Kanavos | if (CurrentState == State.Constructor || CurrentState == State.ConstructorStart) |
896 | d78cbf09 | Panagiotis Kanavos | return true; |
897 | d78cbf09 | Panagiotis Kanavos | break; |
898 | d78cbf09 | Panagiotis Kanavos | case ' ': |
899 | d78cbf09 | Panagiotis Kanavos | case StringUtils.Tab: |
900 | d78cbf09 | Panagiotis Kanavos | case StringUtils.LineFeed: |
901 | d78cbf09 | Panagiotis Kanavos | case StringUtils.CarriageReturn: |
902 | d78cbf09 | Panagiotis Kanavos | return true; |
903 | d78cbf09 | Panagiotis Kanavos | default: |
904 | d78cbf09 | Panagiotis Kanavos | if (char.IsWhiteSpace(c)) |
905 | d78cbf09 | Panagiotis Kanavos | return true; |
906 | d78cbf09 | Panagiotis Kanavos | break; |
907 | d78cbf09 | Panagiotis Kanavos | } |
908 | d78cbf09 | Panagiotis Kanavos | |
909 | d78cbf09 | Panagiotis Kanavos | return false; |
910 | d78cbf09 | Panagiotis Kanavos | } |
911 | d78cbf09 | Panagiotis Kanavos | |
912 | d78cbf09 | Panagiotis Kanavos | private void ParseTrue() |
913 | d78cbf09 | Panagiotis Kanavos | { |
914 | d78cbf09 | Panagiotis Kanavos | // check characters equal 'true' |
915 | d78cbf09 | Panagiotis Kanavos | // and that it is followed by either a seperator character |
916 | d78cbf09 | Panagiotis Kanavos | // or the text ends |
917 | d78cbf09 | Panagiotis Kanavos | if (MatchValue('t', JsonConvert.True, true)) |
918 | d78cbf09 | Panagiotis Kanavos | { |
919 | d78cbf09 | Panagiotis Kanavos | SetToken(JsonToken.Boolean, true); |
920 | d78cbf09 | Panagiotis Kanavos | } |
921 | d78cbf09 | Panagiotis Kanavos | else |
922 | d78cbf09 | Panagiotis Kanavos | { |
923 | d78cbf09 | Panagiotis Kanavos | throw CreateJsonReaderException("Error parsing boolean value. Line {0}, position {1}.", _currentLineNumber, _currentLinePosition); |
924 | d78cbf09 | Panagiotis Kanavos | } |
925 | d78cbf09 | Panagiotis Kanavos | } |
926 | d78cbf09 | Panagiotis Kanavos | |
927 | d78cbf09 | Panagiotis Kanavos | private void ParseNull() |
928 | d78cbf09 | Panagiotis Kanavos | { |
929 | d78cbf09 | Panagiotis Kanavos | if (MatchValue('n', JsonConvert.Null, true)) |
930 | d78cbf09 | Panagiotis Kanavos | { |
931 | d78cbf09 | Panagiotis Kanavos | SetToken(JsonToken.Null); |
932 | d78cbf09 | Panagiotis Kanavos | } |
933 | d78cbf09 | Panagiotis Kanavos | else |
934 | d78cbf09 | Panagiotis Kanavos | { |
935 | d78cbf09 | Panagiotis Kanavos | throw CreateJsonReaderException("Error parsing null value. Line {0}, position {1}.", _currentLineNumber, _currentLinePosition); |
936 | d78cbf09 | Panagiotis Kanavos | } |
937 | d78cbf09 | Panagiotis Kanavos | } |
938 | d78cbf09 | Panagiotis Kanavos | |
939 | d78cbf09 | Panagiotis Kanavos | private void ParseUndefined() |
940 | d78cbf09 | Panagiotis Kanavos | { |
941 | d78cbf09 | Panagiotis Kanavos | if (MatchValue('u', JsonConvert.Undefined, true)) |
942 | d78cbf09 | Panagiotis Kanavos | { |
943 | d78cbf09 | Panagiotis Kanavos | SetToken(JsonToken.Undefined); |
944 | d78cbf09 | Panagiotis Kanavos | } |
945 | d78cbf09 | Panagiotis Kanavos | else |
946 | d78cbf09 | Panagiotis Kanavos | { |
947 | d78cbf09 | Panagiotis Kanavos | throw CreateJsonReaderException("Error parsing undefined value. Line {0}, position {1}.", _currentLineNumber, _currentLinePosition); |
948 | d78cbf09 | Panagiotis Kanavos | } |
949 | d78cbf09 | Panagiotis Kanavos | } |
950 | d78cbf09 | Panagiotis Kanavos | |
951 | d78cbf09 | Panagiotis Kanavos | private void ParseFalse() |
952 | d78cbf09 | Panagiotis Kanavos | { |
953 | d78cbf09 | Panagiotis Kanavos | if (MatchValue('f', JsonConvert.False, true)) |
954 | d78cbf09 | Panagiotis Kanavos | { |
955 | d78cbf09 | Panagiotis Kanavos | SetToken(JsonToken.Boolean, false); |
956 | d78cbf09 | Panagiotis Kanavos | } |
957 | d78cbf09 | Panagiotis Kanavos | else |
958 | d78cbf09 | Panagiotis Kanavos | { |
959 | d78cbf09 | Panagiotis Kanavos | throw CreateJsonReaderException("Error parsing boolean value. Line {0}, position {1}.", _currentLineNumber, _currentLinePosition); |
960 | d78cbf09 | Panagiotis Kanavos | } |
961 | d78cbf09 | Panagiotis Kanavos | } |
962 | d78cbf09 | Panagiotis Kanavos | |
963 | d78cbf09 | Panagiotis Kanavos | private void ParseNumberNegativeInfinity() |
964 | d78cbf09 | Panagiotis Kanavos | { |
965 | d78cbf09 | Panagiotis Kanavos | if (MatchValue('-', JsonConvert.NegativeInfinity, true)) |
966 | d78cbf09 | Panagiotis Kanavos | { |
967 | d78cbf09 | Panagiotis Kanavos | SetToken(JsonToken.Float, double.NegativeInfinity); |
968 | d78cbf09 | Panagiotis Kanavos | } |
969 | d78cbf09 | Panagiotis Kanavos | else |
970 | d78cbf09 | Panagiotis Kanavos | { |
971 | d78cbf09 | Panagiotis Kanavos | throw CreateJsonReaderException("Error parsing negative infinity value. Line {0}, position {1}.", _currentLineNumber, _currentLinePosition); |
972 | d78cbf09 | Panagiotis Kanavos | } |
973 | d78cbf09 | Panagiotis Kanavos | } |
974 | d78cbf09 | Panagiotis Kanavos | |
975 | d78cbf09 | Panagiotis Kanavos | private void ParseNumberPositiveInfinity() |
976 | d78cbf09 | Panagiotis Kanavos | { |
977 | d78cbf09 | Panagiotis Kanavos | if (MatchValue('I', JsonConvert.PositiveInfinity, true)) |
978 | d78cbf09 | Panagiotis Kanavos | { |
979 | d78cbf09 | Panagiotis Kanavos | SetToken(JsonToken.Float, double.PositiveInfinity); |
980 | d78cbf09 | Panagiotis Kanavos | } |
981 | d78cbf09 | Panagiotis Kanavos | else |
982 | d78cbf09 | Panagiotis Kanavos | { |
983 | d78cbf09 | Panagiotis Kanavos | throw CreateJsonReaderException("Error parsing positive infinity value. Line {0}, position {1}.", _currentLineNumber, _currentLinePosition); |
984 | d78cbf09 | Panagiotis Kanavos | } |
985 | d78cbf09 | Panagiotis Kanavos | } |
986 | d78cbf09 | Panagiotis Kanavos | |
987 | d78cbf09 | Panagiotis Kanavos | private void ParseNumberNaN() |
988 | d78cbf09 | Panagiotis Kanavos | { |
989 | d78cbf09 | Panagiotis Kanavos | if (MatchValue('N', JsonConvert.NaN, true)) |
990 | d78cbf09 | Panagiotis Kanavos | { |
991 | d78cbf09 | Panagiotis Kanavos | SetToken(JsonToken.Float, double.NaN); |
992 | d78cbf09 | Panagiotis Kanavos | } |
993 | d78cbf09 | Panagiotis Kanavos | else |
994 | d78cbf09 | Panagiotis Kanavos | { |
995 | d78cbf09 | Panagiotis Kanavos | throw CreateJsonReaderException("Error parsing NaN value. Line {0}, position {1}.", _currentLineNumber, _currentLinePosition); |
996 | d78cbf09 | Panagiotis Kanavos | } |
997 | d78cbf09 | Panagiotis Kanavos | } |
998 | d78cbf09 | Panagiotis Kanavos | |
999 | d78cbf09 | Panagiotis Kanavos | /// <summary> |
1000 | d78cbf09 | Panagiotis Kanavos | /// Changes the state to closed. |
1001 | d78cbf09 | Panagiotis Kanavos | /// </summary> |
1002 | d78cbf09 | Panagiotis Kanavos | public override void Close() |
1003 | d78cbf09 | Panagiotis Kanavos | { |
1004 | d78cbf09 | Panagiotis Kanavos | base.Close(); |
1005 | d78cbf09 | Panagiotis Kanavos | |
1006 | d78cbf09 | Panagiotis Kanavos | if (CloseInput && _reader != null) |
1007 | d78cbf09 | Panagiotis Kanavos | _reader.Close(); |
1008 | d78cbf09 | Panagiotis Kanavos | |
1009 | d78cbf09 | Panagiotis Kanavos | if (_buffer != null) |
1010 | d78cbf09 | Panagiotis Kanavos | _buffer.Clear(); |
1011 | d78cbf09 | Panagiotis Kanavos | } |
1012 | d78cbf09 | Panagiotis Kanavos | |
1013 | d78cbf09 | Panagiotis Kanavos | /// <summary> |
1014 | d78cbf09 | Panagiotis Kanavos | /// Gets a value indicating whether the class can return line information. |
1015 | d78cbf09 | Panagiotis Kanavos | /// </summary> |
1016 | d78cbf09 | Panagiotis Kanavos | /// <returns> |
1017 | d78cbf09 | Panagiotis Kanavos | /// <c>true</c> if LineNumber and LinePosition can be provided; otherwise, <c>false</c>. |
1018 | d78cbf09 | Panagiotis Kanavos | /// </returns> |
1019 | d78cbf09 | Panagiotis Kanavos | public bool HasLineInfo() |
1020 | d78cbf09 | Panagiotis Kanavos | { |
1021 | d78cbf09 | Panagiotis Kanavos | return true; |
1022 | d78cbf09 | Panagiotis Kanavos | } |
1023 | d78cbf09 | Panagiotis Kanavos | |
1024 | d78cbf09 | Panagiotis Kanavos | /// <summary> |
1025 | d78cbf09 | Panagiotis Kanavos | /// Gets the current line number. |
1026 | d78cbf09 | Panagiotis Kanavos | /// </summary> |
1027 | d78cbf09 | Panagiotis Kanavos | /// <value> |
1028 | d78cbf09 | Panagiotis Kanavos | /// The current line number or 0 if no line information is available (for example, HasLineInfo returns false). |
1029 | d78cbf09 | Panagiotis Kanavos | /// </value> |
1030 | d78cbf09 | Panagiotis Kanavos | public int LineNumber |
1031 | d78cbf09 | Panagiotis Kanavos | { |
1032 | d78cbf09 | Panagiotis Kanavos | get |
1033 | d78cbf09 | Panagiotis Kanavos | { |
1034 | d78cbf09 | Panagiotis Kanavos | if (CurrentState == State.Start) |
1035 | d78cbf09 | Panagiotis Kanavos | return 0; |
1036 | d78cbf09 | Panagiotis Kanavos | |
1037 | d78cbf09 | Panagiotis Kanavos | return _currentLineNumber; |
1038 | d78cbf09 | Panagiotis Kanavos | } |
1039 | d78cbf09 | Panagiotis Kanavos | } |
1040 | d78cbf09 | Panagiotis Kanavos | |
1041 | d78cbf09 | Panagiotis Kanavos | /// <summary> |
1042 | d78cbf09 | Panagiotis Kanavos | /// Gets the current line position. |
1043 | d78cbf09 | Panagiotis Kanavos | /// </summary> |
1044 | d78cbf09 | Panagiotis Kanavos | /// <value> |
1045 | d78cbf09 | Panagiotis Kanavos | /// The current line position or 0 if no line information is available (for example, HasLineInfo returns false). |
1046 | d78cbf09 | Panagiotis Kanavos | /// </value> |
1047 | d78cbf09 | Panagiotis Kanavos | public int LinePosition |
1048 | d78cbf09 | Panagiotis Kanavos | { |
1049 | d78cbf09 | Panagiotis Kanavos | get { return _currentLinePosition; } |
1050 | d78cbf09 | Panagiotis Kanavos | } |
1051 | d78cbf09 | Panagiotis Kanavos | } |
1052 | d78cbf09 | Panagiotis Kanavos | } |