-JsonReader refactor

This commit is contained in:
James Newton-King
2015-12-26 01:55:36 +13:00
parent 68fa401d70
commit d1451bd4ae
7 changed files with 722 additions and 546 deletions
+57 -10
View File
@@ -305,7 +305,7 @@ third line", jsonTextReader.Value);
ExceptionAssert.Throws<JsonReaderException>(() => jsonTextReader.ReadAsInt32(), "Input string '3.3' is not a valid integer. Path '[1]', line 3, position 5.");
ExceptionAssert.Throws<JsonReaderException>(() => jsonTextReader.ReadAsInt32(), "Error reading integer. Unexpected token: Undefined. Path '[2]', line 4, position 2.");
ExceptionAssert.Throws<JsonReaderException>(() => jsonTextReader.ReadAsInt32(), "Unexpected character encountered while parsing value: ,. Path '[2]', line 4, position 2.");
ExceptionAssert.Throws<JsonReaderException>(() => jsonTextReader.ReadAsInt32(), "Input string '0f' is not a valid integer. Path '[3]', line 5, position 4.");
@@ -2087,7 +2087,16 @@ third line", jsonTextReader.Value);
{
JsonTextReader reader = new JsonTextReader(new StringReader(@"new Date()"));
ExceptionAssert.Throws<JsonReaderException>(() => { reader.ReadAsDecimal(); }, "Error reading decimal. Unexpected token: StartConstructor. Path '', line 1, position 9.");
ExceptionAssert.Throws<JsonReaderException>(() => { reader.ReadAsDecimal(); }, "Unexpected character encountered while parsing value: e. Path '', line 1, position 2.");
}
[Test]
public void ReadAsDecimalBadContent_SecondLine()
{
JsonTextReader reader = new JsonTextReader(new StringReader(@"
new Date()"));
ExceptionAssert.Throws<JsonReaderException>(() => { reader.ReadAsDecimal(); }, "Unexpected character encountered while parsing value: e. Path '', line 2, position 2.");
}
[Test]
@@ -2104,7 +2113,7 @@ third line", jsonTextReader.Value);
{
JsonTextReader reader = new JsonTextReader(new StringReader(@"new Date()"));
ExceptionAssert.Throws<JsonReaderException>(() => { reader.ReadAsDateTimeOffset(); }, "Error reading date. Unexpected token: StartConstructor. Path '', line 1, position 9.");
ExceptionAssert.Throws<JsonReaderException>(() => { reader.ReadAsDateTimeOffset(); }, "Unexpected character encountered while parsing value: e. Path '', line 1, position 2.");
}
#endif
@@ -2892,7 +2901,7 @@ null//comment
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.Comment, reader.TokenType);
Assert.AreEqual("comment*//*hi*/", reader.Value);
Assert.AreEqual(2, reader.LineNumber);
Assert.AreEqual(1, reader.LineNumber);
Assert.IsTrue(reader.Read());
Assert.AreEqual(2, reader.LineNumber);
@@ -2900,7 +2909,7 @@ null//comment
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.Comment, reader.TokenType);
Assert.AreEqual(3, reader.LineNumber);
Assert.AreEqual(2, reader.LineNumber);
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.PropertyName, reader.TokenType);
@@ -2909,7 +2918,7 @@ null//comment
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.Comment, reader.TokenType);
Assert.AreEqual(4, reader.LineNumber);
Assert.AreEqual(3, reader.LineNumber);
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.Boolean, reader.TokenType);
@@ -2919,12 +2928,12 @@ null//comment
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.Comment, reader.TokenType);
Assert.AreEqual("comment after true", reader.Value);
Assert.AreEqual(5, reader.LineNumber);
Assert.AreEqual(4, reader.LineNumber);
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.Comment, reader.TokenType);
Assert.AreEqual("comment after comma", reader.Value);
Assert.AreEqual(6, reader.LineNumber);
Assert.AreEqual(5, reader.LineNumber);
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.PropertyName, reader.TokenType);
@@ -2933,7 +2942,7 @@ null//comment
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.Comment, reader.TokenType);
Assert.AreEqual(7, reader.LineNumber);
Assert.AreEqual(6, reader.LineNumber);
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.StartConstructor, reader.TokenType);
@@ -2949,7 +2958,7 @@ null//comment
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.Comment, reader.TokenType);
Assert.AreEqual(11, reader.LineNumber);
Assert.AreEqual(10, reader.LineNumber);
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.EndConstructor, reader.TokenType);
@@ -3001,6 +3010,44 @@ null//comment
Assert.IsFalse(reader.Read());
}
[Test]
public void ReadNullIntLineNumberAndPosition()
{
string json = @"[
1,
2,
3,
null
]";
JsonTextReader reader = new JsonTextReader(new StreamReader(new SlowStream(json, new UTF8Encoding(false), 1)));
reader.Read();
Assert.AreEqual(1, reader.LineNumber);
reader.ReadAsInt32();
Assert.AreEqual(2, reader.LineNumber);
Assert.AreEqual("[0]", reader.Path);
reader.ReadAsInt32();
Assert.AreEqual(3, reader.LineNumber);
Assert.AreEqual("[1]", reader.Path);
reader.ReadAsInt32();
Assert.AreEqual(4, reader.LineNumber);
Assert.AreEqual("[2]", reader.Path);
reader.ReadAsInt32();
Assert.AreEqual(5, reader.LineNumber);
Assert.AreEqual("[3]", reader.Path);
reader.Read();
Assert.AreEqual(6, reader.LineNumber);
Assert.AreEqual(string.Empty, reader.Path);
Assert.IsFalse(reader.Read());
}
[Test]
public void JustSinglelineComment()
{
@@ -221,8 +221,8 @@ namespace Newtonsoft.Json.Tests.Linq
IJsonLineInfo lineInfo = v;
Assert.AreEqual(true, lineInfo.HasLineInfo());
Assert.AreEqual(3, lineInfo.LineNumber);
Assert.AreEqual(0, lineInfo.LinePosition);
Assert.AreEqual(2, lineInfo.LineNumber);
Assert.AreEqual(5, lineInfo.LinePosition);
}
[Test]
@@ -377,6 +377,10 @@ namespace Newtonsoft.Json.Tests.Serialization
[Test]
public void IncompleteContainers()
{
ExceptionAssert.Throws<JsonSerializationException>(
() => JsonConvert.DeserializeObject<IList<object>>("[1,"),
"Unexpected end when deserializing array. Path '[0]', line 1, position 3.");
ExceptionAssert.Throws<JsonSerializationException>(
() => JsonConvert.DeserializeObject<IList<int>>("[1,"),
"Unexpected end when deserializing array. Path '[0]', line 1, position 3.");
@@ -6960,7 +6964,7 @@ Path '', line 1, position 1.");
}";
JsonConvert.DeserializeObject<TestObjects.MyClass>(json);
}, "Error reading integer. Unexpected token: Boolean. Path 'PreProperty', line 2, position 21.");
}, "Unexpected character encountered while parsing value: t. Path 'PreProperty', line 2, position 17.");
}
[Test]
-67
View File
@@ -174,66 +174,6 @@ namespace Newtonsoft.Json.Bson
return elementName;
}
/// <summary>
/// Reads the next JSON token from the stream as a <see cref="Byte"/>[].
/// </summary>
/// <returns>
/// A <see cref="Byte"/>[] or a null reference if the next JSON token is null. This method will return <c>null</c> at the end of an array.
/// </returns>
public override byte[] ReadAsBytes()
{
return ReadAsBytesInternal();
}
/// <summary>
/// Reads the next JSON token from the stream as a <see cref="Nullable{Decimal}"/>.
/// </summary>
/// <returns>A <see cref="Nullable{Decimal}"/>. This method will return <c>null</c> at the end of an array.</returns>
public override decimal? ReadAsDecimal()
{
return ReadAsDecimalInternal();
}
/// <summary>
/// Reads the next JSON token from the stream as a <see cref="Nullable{Int32}"/>.
/// </summary>
/// <returns>A <see cref="Nullable{Int32}"/>. This method will return <c>null</c> at the end of an array.</returns>
public override int? ReadAsInt32()
{
return ReadAsInt32Internal();
}
/// <summary>
/// Reads the next JSON token from the stream as a <see cref="String"/>.
/// </summary>
/// <returns>A <see cref="String"/>. This method will return <c>null</c> at the end of an array.</returns>
public override string ReadAsString()
{
return ReadAsStringInternal();
}
/// <summary>
/// Reads the next JSON token from the stream as a <see cref="Nullable{DateTime}"/>.
/// </summary>
/// <returns>A <see cref="Nullable{DateTime}"/>. This method will return <c>null</c> at the end of an array.</returns>
public override DateTime? ReadAsDateTime()
{
return ReadAsDateTimeInternal();
}
#if !NET20
/// <summary>
/// Reads the next JSON token from the stream as a <see cref="Nullable{DateTimeOffset}"/>.
/// </summary>
/// <returns>
/// A <see cref="Nullable{DateTimeOffset}"/>. This method will return <c>null</c> at the end of an array.
/// </returns>
public override DateTimeOffset? ReadAsDateTimeOffset()
{
return ReadAsDateTimeOffsetInternal();
}
#endif
/// <summary>
/// Reads the next JSON token from the stream.
/// </summary>
@@ -241,13 +181,6 @@ namespace Newtonsoft.Json.Bson
/// true if the next token was read successfully; false if there are no more tokens to read.
/// </returns>
public override bool Read()
{
_readType = Json.ReadType.Read;
return ReadInternal();
}
internal override bool ReadInternal()
{
try
{
+258 -268
View File
@@ -119,7 +119,6 @@ namespace Newtonsoft.Json
private object _value;
internal char _quoteChar;
internal State _currentState;
internal ReadType _readType;
private JsonPosition _currentPosition;
private CultureInfo _culture;
private DateTimeZoneHandling _dateTimeZoneHandling;
@@ -413,222 +412,9 @@ namespace Newtonsoft.Json
/// Reads the next JSON token from the stream as a <see cref="Nullable{Int32}"/>.
/// </summary>
/// <returns>A <see cref="Nullable{Int32}"/>. This method will return <c>null</c> at the end of an array.</returns>
public abstract int? ReadAsInt32();
/// <summary>
/// Reads the next JSON token from the stream as a <see cref="String"/>.
/// </summary>
/// <returns>A <see cref="String"/>. This method will return <c>null</c> at the end of an array.</returns>
public abstract string ReadAsString();
/// <summary>
/// Reads the next JSON token from the stream as a <see cref="Byte"/>[].
/// </summary>
/// <returns>A <see cref="Byte"/>[] or a null reference if the next JSON token is null. This method will return <c>null</c> at the end of an array.</returns>
public abstract byte[] ReadAsBytes();
/// <summary>
/// Reads the next JSON token from the stream as a <see cref="Nullable{Decimal}"/>.
/// </summary>
/// <returns>A <see cref="Nullable{Decimal}"/>. This method will return <c>null</c> at the end of an array.</returns>
public abstract decimal? ReadAsDecimal();
/// <summary>
/// Reads the next JSON token from the stream as a <see cref="Nullable{DateTime}"/>.
/// </summary>
/// <returns>A <see cref="Nullable{DateTime}"/>. This method will return <c>null</c> at the end of an array.</returns>
public abstract DateTime? ReadAsDateTime();
#if !NET20
/// <summary>
/// Reads the next JSON token from the stream as a <see cref="Nullable{DateTimeOffset}"/>.
/// </summary>
/// <returns>A <see cref="Nullable{DateTimeOffset}"/>. This method will return <c>null</c> at the end of an array.</returns>
public abstract DateTimeOffset? ReadAsDateTimeOffset();
#endif
internal virtual bool ReadInternal()
public virtual int? ReadAsInt32()
{
throw new NotImplementedException();
}
#if !NET20
internal DateTimeOffset? ReadAsDateTimeOffsetInternal()
{
_readType = ReadType.ReadAsDateTimeOffset;
JsonToken t = GetContentTokenInternal();
switch (t)
{
case JsonToken.None:
case JsonToken.Null:
case JsonToken.EndArray:
return null;
case JsonToken.Date:
if (Value is DateTime)
{
SetToken(JsonToken.Date, new DateTimeOffset((DateTime)Value), false);
}
return (DateTimeOffset)Value;
case JsonToken.String:
string s = (string)Value;
if (string.IsNullOrEmpty(s))
{
SetToken(JsonToken.Null);
return null;
}
DateTimeOffset dt;
if (DateTimeUtils.TryParseDateTimeOffset(s, _dateFormatString, Culture, out dt))
{
SetToken(JsonToken.Date, dt, false);
return dt;
}
if (DateTimeOffset.TryParse(s, Culture, DateTimeStyles.RoundtripKind, out dt))
{
SetToken(JsonToken.Date, dt, false);
return dt;
}
throw JsonReaderException.Create(this, "Could not convert string to DateTimeOffset: {0}.".FormatWith(CultureInfo.InvariantCulture, Value));
default:
throw JsonReaderException.Create(this, "Error reading date. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, t));
}
}
#endif
internal byte[] ReadAsBytesInternal()
{
_readType = ReadType.ReadAsBytes;
JsonToken t = GetContentTokenInternal();
if (t == JsonToken.None)
{
return null;
}
if (IsWrappedInTypeObject())
{
byte[] data = ReadAsBytes();
ReadInternal();
SetToken(JsonToken.Bytes, data, false);
return data;
}
switch (t)
{
case JsonToken.String:
{
// attempt to convert possible base 64 or GUID string to bytes
// GUID has to have format 00000000-0000-0000-0000-000000000000
string s = (string)Value;
byte[] data;
Guid g;
if (s.Length == 0)
{
data = new byte[0];
}
else if (ConvertUtils.TryConvertGuid(s, out g))
{
data = g.ToByteArray();
}
else
{
data = Convert.FromBase64String(s);
}
SetToken(JsonToken.Bytes, data, false);
return data;
}
case JsonToken.Null:
case JsonToken.EndArray:
return null;
case JsonToken.Bytes:
if (ValueType == typeof(Guid))
{
byte[] data = ((Guid)Value).ToByteArray();
SetToken(JsonToken.Bytes, data, false);
return data;
}
return (byte[])Value;
case JsonToken.StartArray:
List<byte> buffer = new List<byte>();
while (true)
{
switch (t = GetContentTokenInternal())
{
case JsonToken.None:
throw JsonReaderException.Create(this, "Unexpected end when reading bytes.");
case JsonToken.Integer:
buffer.Add(Convert.ToByte(Value, CultureInfo.InvariantCulture));
break;
case JsonToken.EndArray:
byte[] d = buffer.ToArray();
SetToken(JsonToken.Bytes, d, false);
return d;
default:
throw JsonReaderException.Create(this, "Unexpected token when reading bytes: {0}.".FormatWith(CultureInfo.InvariantCulture, t));
}
}
}
throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, t));
}
internal decimal? ReadAsDecimalInternal()
{
_readType = ReadType.ReadAsDecimal;
JsonToken t = GetContentTokenInternal();
switch (t)
{
case JsonToken.None:
case JsonToken.Null:
case JsonToken.EndArray:
return null;
case JsonToken.Integer:
case JsonToken.Float:
if (!(Value is decimal))
{
SetToken(JsonToken.Float, Convert.ToDecimal(Value, CultureInfo.InvariantCulture), false);
}
return (decimal)Value;
case JsonToken.String:
string s = (string)Value;
if (string.IsNullOrEmpty(s))
{
SetToken(JsonToken.Null);
return null;
}
decimal d;
if (decimal.TryParse(s, NumberStyles.Number, Culture, out d))
{
SetToken(JsonToken.Float, d, false);
return d;
}
else
{
throw JsonReaderException.Create(this, "Could not convert string to decimal: {0}.".FormatWith(CultureInfo.InvariantCulture, Value));
}
}
throw JsonReaderException.Create(this, "Error reading decimal. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, t));
}
internal int? ReadAsInt32Internal()
{
_readType = ReadType.ReadAsInt32;
switch (GetContentTokenInternal())
switch (GetContentToken())
{
case JsonToken.None:
case JsonToken.Null:
@@ -644,31 +430,40 @@ namespace Newtonsoft.Json
return (int)Value;
case JsonToken.String:
string s = (string)Value;
if (string.IsNullOrEmpty(s))
{
SetToken(JsonToken.Null);
return null;
}
int i;
if (int.TryParse(s, NumberStyles.Integer, Culture, out i))
{
SetToken(JsonToken.Integer, i, false);
return i;
}
else
{
throw JsonReaderException.Create(this, "Could not convert string to integer: {0}.".FormatWith(CultureInfo.InvariantCulture, Value));
}
return ReadInt32String(s);
}
throw JsonReaderException.Create(this, "Error reading integer. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType));
}
internal string ReadAsStringInternal()
internal int? ReadInt32String(string s)
{
_readType = ReadType.ReadAsString;
if (string.IsNullOrEmpty(s))
{
SetToken(JsonToken.Null);
return null;
}
JsonToken t = GetContentTokenInternal();
int i;
if (int.TryParse(s, NumberStyles.Integer, Culture, out i))
{
SetToken(JsonToken.Integer, i, false);
return i;
}
else
{
SetToken(JsonToken.String, s, false);
throw JsonReaderException.Create(this, "Could not convert string to integer: {0}.".FormatWith(CultureInfo.InvariantCulture, s));
}
}
/// <summary>
/// Reads the next JSON token from the stream as a <see cref="String"/>.
/// </summary>
/// <returns>A <see cref="String"/>. This method will return <c>null</c> at the end of an array.</returns>
public virtual string ReadAsString()
{
JsonToken t = GetContentToken();
switch (t)
{
@@ -702,11 +497,148 @@ namespace Newtonsoft.Json
throw JsonReaderException.Create(this, "Error reading string. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, t));
}
internal DateTime? ReadAsDateTimeInternal()
/// <summary>
/// Reads the next JSON token from the stream as a <see cref="Byte"/>[].
/// </summary>
/// <returns>A <see cref="Byte"/>[] or a null reference if the next JSON token is null. This method will return <c>null</c> at the end of an array.</returns>
public virtual byte[] ReadAsBytes()
{
_readType = ReadType.ReadAsDateTime;
JsonToken t = GetContentToken();
switch (GetContentTokenInternal())
if (t == JsonToken.None)
{
return null;
}
if (IsWrappedInTypeObject())
{
byte[] data = ReadAsBytes();
Read();
SetToken(JsonToken.Bytes, data, false);
return data;
}
switch (t)
{
case JsonToken.String:
{
// attempt to convert possible base 64 or GUID string to bytes
// GUID has to have format 00000000-0000-0000-0000-000000000000
string s = (string)Value;
byte[] data;
Guid g;
if (s.Length == 0)
{
data = new byte[0];
}
else if (ConvertUtils.TryConvertGuid(s, out g))
{
data = g.ToByteArray();
}
else
{
data = Convert.FromBase64String(s);
}
SetToken(JsonToken.Bytes, data, false);
return data;
}
case JsonToken.Null:
case JsonToken.EndArray:
return null;
case JsonToken.Bytes:
if (ValueType == typeof(Guid))
{
byte[] data = ((Guid)Value).ToByteArray();
SetToken(JsonToken.Bytes, data, false);
return data;
}
return (byte[])Value;
case JsonToken.StartArray:
List<byte> buffer = new List<byte>();
while (true)
{
switch (t = GetContentToken())
{
case JsonToken.None:
throw JsonReaderException.Create(this, "Unexpected end when reading bytes.");
case JsonToken.Integer:
buffer.Add(Convert.ToByte(Value, CultureInfo.InvariantCulture));
break;
case JsonToken.EndArray:
byte[] d = buffer.ToArray();
SetToken(JsonToken.Bytes, d, false);
return d;
default:
throw JsonReaderException.Create(this, "Unexpected token when reading bytes: {0}.".FormatWith(CultureInfo.InvariantCulture, t));
}
}
}
throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, t));
}
/// <summary>
/// Reads the next JSON token from the stream as a <see cref="Nullable{Decimal}"/>.
/// </summary>
/// <returns>A <see cref="Nullable{Decimal}"/>. This method will return <c>null</c> at the end of an array.</returns>
public virtual decimal? ReadAsDecimal()
{
JsonToken t = GetContentToken();
switch (t)
{
case JsonToken.None:
case JsonToken.Null:
case JsonToken.EndArray:
return null;
case JsonToken.Integer:
case JsonToken.Float:
if (!(Value is decimal))
{
SetToken(JsonToken.Float, Convert.ToDecimal(Value, CultureInfo.InvariantCulture), false);
}
return (decimal)Value;
case JsonToken.String:
return ReadDecimalString((string)Value);
}
throw JsonReaderException.Create(this, "Error reading decimal. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, t));
}
internal decimal? ReadDecimalString(string s)
{
if (string.IsNullOrEmpty(s))
{
SetToken(JsonToken.Null);
return null;
}
decimal d;
if (decimal.TryParse(s, NumberStyles.Number, Culture, out d))
{
SetToken(JsonToken.Float, d, false);
return d;
}
else
{
SetToken(JsonToken.String, s, false);
throw JsonReaderException.Create(this, "Could not convert string to decimal: {0}.".FormatWith(CultureInfo.InvariantCulture, s));
}
}
/// <summary>
/// Reads the next JSON token from the stream as a <see cref="Nullable{DateTime}"/>.
/// </summary>
/// <returns>A <see cref="Nullable{DateTime}"/>. This method will return <c>null</c> at the end of an array.</returns>
public virtual DateTime? ReadAsDateTime()
{
switch (GetContentToken())
{
case JsonToken.None:
case JsonToken.Null:
@@ -716,51 +648,109 @@ namespace Newtonsoft.Json
return (DateTime)Value;
case JsonToken.String:
string s = (string)Value;
if (string.IsNullOrEmpty(s))
{
SetToken(JsonToken.Null);
return null;
}
DateTime dt;
if (DateTimeUtils.TryParseDateTime(s, DateTimeZoneHandling, _dateFormatString, Culture, out dt))
{
dt = DateTimeUtils.EnsureDateTime(dt, DateTimeZoneHandling);
SetToken(JsonToken.Date, dt, false);
return dt;
}
if (DateTime.TryParse(s, Culture, DateTimeStyles.RoundtripKind, out dt))
{
dt = DateTimeUtils.EnsureDateTime(dt, DateTimeZoneHandling);
SetToken(JsonToken.Date, dt, false);
return dt;
}
throw JsonReaderException.Create(this, "Could not convert string to DateTime: {0}.".FormatWith(CultureInfo.InvariantCulture, Value));
return ReadDateTimeString(s);
}
throw JsonReaderException.Create(this, "Error reading date. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType));
}
internal DateTime? ReadDateTimeString(string s)
{
if (string.IsNullOrEmpty(s))
{
SetToken(JsonToken.Null);
return null;
}
DateTime dt;
if (DateTimeUtils.TryParseDateTime(s, DateTimeZoneHandling, _dateFormatString, Culture, out dt))
{
dt = DateTimeUtils.EnsureDateTime(dt, DateTimeZoneHandling);
SetToken(JsonToken.Date, dt, false);
return dt;
}
if (DateTime.TryParse(s, Culture, DateTimeStyles.RoundtripKind, out dt))
{
dt = DateTimeUtils.EnsureDateTime(dt, DateTimeZoneHandling);
SetToken(JsonToken.Date, dt, false);
return dt;
}
throw JsonReaderException.Create(this, "Could not convert string to DateTime: {0}.".FormatWith(CultureInfo.InvariantCulture, s));
}
#if !NET20
/// <summary>
/// Reads the next JSON token from the stream as a <see cref="Nullable{DateTimeOffset}"/>.
/// </summary>
/// <returns>A <see cref="Nullable{DateTimeOffset}"/>. This method will return <c>null</c> at the end of an array.</returns>
public virtual DateTimeOffset? ReadAsDateTimeOffset()
{
JsonToken t = GetContentToken();
switch (t)
{
case JsonToken.None:
case JsonToken.Null:
case JsonToken.EndArray:
return null;
case JsonToken.Date:
if (Value is DateTime)
{
SetToken(JsonToken.Date, new DateTimeOffset((DateTime)Value), false);
}
return (DateTimeOffset)Value;
case JsonToken.String:
string s = (string)Value;
return ReadDateTimeOffsetString(s);
default:
throw JsonReaderException.Create(this, "Error reading date. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, t));
}
}
internal DateTimeOffset? ReadDateTimeOffsetString(string s)
{
if (string.IsNullOrEmpty(s))
{
SetToken(JsonToken.Null);
return null;
}
DateTimeOffset dt;
if (DateTimeUtils.TryParseDateTimeOffset(s, _dateFormatString, Culture, out dt))
{
SetToken(JsonToken.Date, dt, false);
return dt;
}
if (DateTimeOffset.TryParse(s, Culture, DateTimeStyles.RoundtripKind, out dt))
{
SetToken(JsonToken.Date, dt, false);
return dt;
}
SetToken(JsonToken.String, s, false);
throw JsonReaderException.Create(this, "Could not convert string to DateTimeOffset: {0}.".FormatWith(CultureInfo.InvariantCulture, s));
}
#endif
private bool IsWrappedInTypeObject()
{
_readType = ReadType.Read;
if (TokenType == JsonToken.StartObject)
{
if (!ReadInternal())
if (!Read())
{
throw JsonReaderException.Create(this, "Unexpected end when reading bytes.");
}
if (Value.ToString() == JsonTypeReflector.TypePropertyName)
{
ReadInternal();
Read();
if (Value != null && Value.ToString().StartsWith("System.Byte[]", StringComparison.Ordinal))
{
ReadInternal();
Read();
if (Value.ToString() == JsonTypeReflector.ValuePropertyName)
{
return true;
@@ -1017,12 +1007,12 @@ namespace Newtonsoft.Json
return true;
}
private JsonToken GetContentTokenInternal()
private JsonToken GetContentToken()
{
JsonToken t;
do
{
if (!ReadInternal())
if (!Read())
{
SetToken(JsonToken.None);
return JsonToken.None;
+397 -130
View File
@@ -120,7 +120,7 @@ namespace Newtonsoft.Json
_lineStartPos = pos;
}
private void ParseString(char quote)
private void ParseString(char quote, ReadType readType)
{
_charPos++;
@@ -128,7 +128,7 @@ namespace Newtonsoft.Json
ReadStringIntoBuffer(quote);
SetPostValueState(true);
if (_readType == ReadType.ReadAsBytes)
if (readType == ReadType.ReadAsBytes)
{
Guid g;
byte[] data;
@@ -147,24 +147,29 @@ namespace Newtonsoft.Json
SetToken(JsonToken.Bytes, data, false);
}
else if (_readType == ReadType.ReadAsString)
else if (readType == ReadType.ReadAsString)
{
string text = _stringReference.ToString();
SetToken(JsonToken.String, text, false);
_quoteChar = quote;
}
else if (readType == ReadType.ReadAsInt32 ||
readType == ReadType.ReadAsDecimal)
{
// caller will convert result
}
else
{
if (_dateParseHandling != DateParseHandling.None)
{
DateParseHandling dateParseHandling;
if (_readType == ReadType.ReadAsDateTime)
if (readType == ReadType.ReadAsDateTime)
{
dateParseHandling = DateParseHandling.DateTime;
}
#if !NET20
else if (_readType == ReadType.ReadAsDateTimeOffset)
else if (readType == ReadType.ReadAsDateTimeOffset)
{
dateParseHandling = DateParseHandling.DateTimeOffset;
}
@@ -205,7 +210,7 @@ namespace Newtonsoft.Json
{
const int charByteCount = 2;
Buffer.BlockCopy(src, srcOffset * charByteCount, dst, dstOffset * charByteCount, count * charByteCount);
Buffer.BlockCopy(src, srcOffset*charByteCount, dst, dstOffset*charByteCount, count*charByteCount);
}
private void ShiftBufferIfNeeded()
@@ -213,7 +218,7 @@ namespace Newtonsoft.Json
// once in the last 10% of the buffer shift the remaining content to the start to avoid
// unnessesarly increasing the buffer size when reading numbers/strings
int length = _chars.Length;
if (length - _charPos <= length * 0.1)
if (length - _charPos <= length*0.1)
{
int count = _charsUsed - _charPos;
if (count > 0)
@@ -246,7 +251,7 @@ namespace Newtonsoft.Json
if (append)
{
// copy to new array either double the size of the current or big enough to fit required content
int newArrayLength = Math.Max(_chars.Length * 2, _charsUsed + charsRequired + 1);
int newArrayLength = Math.Max(_chars.Length*2, _charsUsed + charsRequired + 1);
// increase the size of the buffer
char[] dst = BufferUtils.RentBuffer(_arrayPool, newArrayLength);
@@ -354,84 +359,9 @@ namespace Newtonsoft.Json
/// <returns>
/// true if the next token was read successfully; false if there are no more tokens to read.
/// </returns>
[DebuggerStepThrough]
public override bool Read()
{
_readType = ReadType.Read;
if (!ReadInternal())
{
SetToken(JsonToken.None);
return false;
}
return true;
}
/// <summary>
/// Reads the next JSON token from the stream as a <see cref="Byte"/>[].
/// </summary>
/// <returns>
/// A <see cref="Byte"/>[] or a null reference if the next JSON token is null. This method will return <c>null</c> at the end of an array.
/// </returns>
public override byte[] ReadAsBytes()
{
return ReadAsBytesInternal();
}
/// <summary>
/// Reads the next JSON token from the stream as a <see cref="Nullable{Decimal}"/>.
/// </summary>
/// <returns>A <see cref="Nullable{Decimal}"/>. This method will return <c>null</c> at the end of an array.</returns>
public override decimal? ReadAsDecimal()
{
return ReadAsDecimalInternal();
}
/// <summary>
/// Reads the next JSON token from the stream as a <see cref="Nullable{Int32}"/>.
/// </summary>
/// <returns>A <see cref="Nullable{Int32}"/>. This method will return <c>null</c> at the end of an array.</returns>
public override int? ReadAsInt32()
{
return ReadAsInt32Internal();
}
/// <summary>
/// Reads the next JSON token from the stream as a <see cref="String"/>.
/// </summary>
/// <returns>A <see cref="String"/>. This method will return <c>null</c> at the end of an array.</returns>
public override string ReadAsString()
{
return ReadAsStringInternal();
}
/// <summary>
/// Reads the next JSON token from the stream as a <see cref="Nullable{DateTime}"/>.
/// </summary>
/// <returns>A <see cref="Nullable{DateTime}"/>. This method will return <c>null</c> at the end of an array.</returns>
public override DateTime? ReadAsDateTime()
{
return ReadAsDateTimeInternal();
}
#if !NET20
/// <summary>
/// Reads the next JSON token from the stream as a <see cref="Nullable{DateTimeOffset}"/>.
/// </summary>
/// <returns>A <see cref="DateTimeOffset"/>. This method will return <c>null</c> at the end of an array.</returns>
public override DateTimeOffset? ReadAsDateTimeOffset()
{
return ReadAsDateTimeOffsetInternal();
}
#endif
internal override bool ReadInternal()
{
if (_chars == null)
{
_chars = BufferUtils.RentBuffer(_arrayPool, 1024);
_chars[0] = '\0';
}
EnsureBuffer();
while (true)
{
@@ -461,16 +391,18 @@ namespace Newtonsoft.Json
EatWhitespace(false);
if (_isEndOfFile)
{
SetToken(JsonToken.None);
return false;
}
if (_chars[_charPos] == '/')
{
ParseComment();
ParseComment(true);
return true;
}
throw JsonReaderException.Create(this, "Additional text encountered after finished reading JSON content: {0}.".FormatWith(CultureInfo.InvariantCulture, _chars[_charPos]));
}
SetToken(JsonToken.None);
return false;
default:
throw JsonReaderException.Create(this, "Unexpected state: {0}.".FormatWith(CultureInfo.InvariantCulture, CurrentState));
@@ -478,6 +410,353 @@ namespace Newtonsoft.Json
}
}
/// <summary>
/// Reads the next JSON token from the stream as a <see cref="Nullable{Int32}"/>.
/// </summary>
/// <returns>A <see cref="Nullable{Int32}"/>. This method will return <c>null</c> at the end of an array.</returns>
public override int? ReadAsInt32()
{
return (int?) ReadNumberValue(ReadType.ReadAsInt32);
}
/// <summary>
/// Reads the next JSON token from the stream as a <see cref="Nullable{DateTime}"/>.
/// </summary>
/// <returns>A <see cref="Nullable{DateTime}"/>. This method will return <c>null</c> at the end of an array.</returns>
public override DateTime? ReadAsDateTime()
{
return (DateTime?) ReadStringValue(ReadType.ReadAsDateTime);
}
/// <summary>
/// Reads the next JSON token from the stream as a <see cref="String"/>.
/// </summary>
/// <returns>A <see cref="String"/>. This method will return <c>null</c> at the end of an array.</returns>
public override string ReadAsString()
{
return (string) ReadStringValue(ReadType.ReadAsString);
}
private object ReadStringValue(ReadType readType)
{
EnsureBuffer();
switch (_currentState)
{
case State.Start:
case State.Property:
case State.Array:
case State.ArrayStart:
case State.Constructor:
case State.ConstructorStart:
case State.PostValue:
while (true)
{
char currentChar = _chars[_charPos];
switch (currentChar)
{
case '\0':
if (ReadNullChar())
{
SetToken(JsonToken.None, null, false);
return null;
}
break;
case '"':
case '\'':
ParseString(currentChar, readType);
switch (readType)
{
case ReadType.ReadAsBytes:
return Value;
case ReadType.ReadAsString:
return Value;
case ReadType.ReadAsDateTime:
if (Value is DateTime)
{
return (DateTime) Value;
}
return ReadDateTimeString((string) Value);
#if !NET20
case ReadType.ReadAsDateTimeOffset:
if (Value is DateTimeOffset)
{
return (DateTimeOffset) Value;
}
return ReadDateTimeOffsetString((string) Value);
#endif
default:
throw new ArgumentOutOfRangeException(nameof(readType));
}
case '-':
case '.':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (readType != ReadType.ReadAsString)
{
throw JsonReaderException.Create(this, "Unexpected character encountered while parsing value: {0}.".FormatWith(CultureInfo.InvariantCulture, currentChar));
}
ParseNumber(ReadType.Read);
string s = ((IFormattable) Value).ToString(null, CultureInfo.InvariantCulture);
SetToken(JsonToken.String, s);
return s;
case 'n':
HandleNull();
return null;
case '/':
ParseComment(false);
break;
case ',':
if (_currentState != State.PostValue)
{
SetToken(JsonToken.Undefined);
throw JsonReaderException.Create(this, "Unexpected character encountered while parsing value: {0}.".FormatWith(CultureInfo.InvariantCulture, currentChar));
}
_charPos++;
SetStateBasedOnCurrent();
break;
case '}':
_charPos++;
SetToken(JsonToken.EndObject);
return null;
case ']':
_charPos++;
SetToken(JsonToken.EndArray);
return null;
case StringUtils.CarriageReturn:
ProcessCarriageReturn(false);
break;
case StringUtils.LineFeed:
ProcessLineFeed();
break;
case ' ':
case StringUtils.Tab:
// eat
_charPos++;
break;
default:
if (char.IsWhiteSpace(currentChar))
{
// eat
_charPos++;
break;
}
throw JsonReaderException.Create(this, "Unexpected character encountered while parsing value: {0}.".FormatWith(CultureInfo.InvariantCulture, currentChar));
}
}
case State.Finished:
ReadFinished();
SetToken(JsonToken.None);
return null;
default:
throw JsonReaderException.Create(this, "Unexpected state: {0}.".FormatWith(CultureInfo.InvariantCulture, CurrentState));
}
}
#if !NET20
/// <summary>
/// Reads the next JSON token from the stream as a <see cref="Nullable{DateTimeOffset}"/>.
/// </summary>
/// <returns>A <see cref="Nullable{DateTimeOffset}"/>. This method will return <c>null</c> at the end of an array.</returns>
public override DateTimeOffset? ReadAsDateTimeOffset()
{
return (DateTimeOffset?) ReadStringValue(ReadType.ReadAsDateTimeOffset);
}
#endif
/// <summary>
/// Reads the next JSON token from the stream as a <see cref="Nullable{Decimal}"/>.
/// </summary>
/// <returns>A <see cref="Nullable{Decimal}"/>. This method will return <c>null</c> at the end of an array.</returns>
public override decimal? ReadAsDecimal()
{
return (decimal?) ReadNumberValue(ReadType.ReadAsDecimal);
}
private object ReadNumberValue(ReadType readType)
{
EnsureBuffer();
switch (_currentState)
{
case State.Start:
case State.Property:
case State.Array:
case State.ArrayStart:
case State.Constructor:
case State.ConstructorStart:
case State.PostValue:
while (true)
{
char currentChar = _chars[_charPos];
switch (currentChar)
{
case '\0':
if (ReadNullChar())
{
SetToken(JsonToken.None, null, false);
return null;
}
break;
case '"':
case '\'':
ParseString(currentChar, readType);
switch (readType)
{
case ReadType.ReadAsInt32:
return ReadInt32String(_stringReference.ToString());
case ReadType.ReadAsDecimal:
return ReadDecimalString(_stringReference.ToString());
default:
throw new ArgumentOutOfRangeException(nameof(readType));
}
case 'n':
HandleNull();
return null;
case '-':
case '.':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
ParseNumber(readType);
return Value;
case '/':
ParseComment(false);
break;
case ',':
if (_currentState != State.PostValue)
{
SetToken(JsonToken.Undefined);
throw JsonReaderException.Create(this, "Unexpected character encountered while parsing value: {0}.".FormatWith(CultureInfo.InvariantCulture, currentChar));
}
_charPos++;
SetStateBasedOnCurrent();
break;
case '}':
_charPos++;
SetToken(JsonToken.EndObject);
return null;
case ']':
_charPos++;
SetToken(JsonToken.EndArray);
return null;
case StringUtils.CarriageReturn:
ProcessCarriageReturn(false);
break;
case StringUtils.LineFeed:
ProcessLineFeed();
break;
case ' ':
case StringUtils.Tab:
// eat
_charPos++;
break;
default:
if (char.IsWhiteSpace(currentChar))
{
// eat
_charPos++;
break;
}
throw JsonReaderException.Create(this, "Unexpected character encountered while parsing value: {0}.".FormatWith(CultureInfo.InvariantCulture, currentChar));
}
}
case State.Finished:
ReadFinished();
SetToken(JsonToken.None);
return null;
default:
throw JsonReaderException.Create(this, "Unexpected state: {0}.".FormatWith(CultureInfo.InvariantCulture, CurrentState));
}
}
private void HandleNull()
{
if (EnsureChars(1, true))
{
char next = _chars[_charPos + 1];
if (next == 'u')
{
ParseNull();
return;
}
_charPos += 2;
throw JsonReaderException.Create(this, "Unexpected character encountered while parsing value: {0}.".FormatWith(CultureInfo.InvariantCulture, _chars[_charPos - 1]));
}
throw JsonReaderException.Create(this, "Unexpected end when reading JSON.");
}
private void ReadFinished()
{
if (EnsureChars(0, false))
{
EatWhitespace(false);
if (_isEndOfFile)
{
return;
}
if (_chars[_charPos] == '/')
{
ParseComment(false);
}
else
{
throw JsonReaderException.Create(this, "Additional text encountered after finished reading JSON content: {0}.".FormatWith(CultureInfo.InvariantCulture, _chars[_charPos]));
}
}
}
private bool ReadNullChar()
{
if (_charsUsed == _charPos)
{
if (ReadData(false) == 0)
{
_isEndOfFile = true;
return true;
}
}
else
{
_charPos++;
}
return false;
}
private void EnsureBuffer()
{
if (_chars == null)
{
_chars = BufferUtils.RentBuffer(_arrayPool, 1024);
_chars[0] = '\0';
}
}
private void ReadStringIntoBuffer(char quote)
{
int charPos = _charPos;
@@ -733,12 +1012,7 @@ namespace Newtonsoft.Json
_charPos = charPos;
char currentChar = _chars[_charPos];
if (char.IsWhiteSpace(currentChar)
|| currentChar == ','
|| currentChar == '}'
|| currentChar == ']'
|| currentChar == ')'
|| currentChar == '/')
if (char.IsWhiteSpace(currentChar) || currentChar == ',' || currentChar == '}' || currentChar == ']' || currentChar == ')' || currentChar == '/')
{
return;
}
@@ -789,7 +1063,7 @@ namespace Newtonsoft.Json
SetToken(JsonToken.EndConstructor);
return true;
case '/':
ParseComment();
ParseComment(true);
return true;
case ',':
_charPos++;
@@ -849,7 +1123,7 @@ namespace Newtonsoft.Json
_charPos++;
return true;
case '/':
ParseComment();
ParseComment(true);
return true;
case StringUtils.CarriageReturn:
ProcessCarriageReturn(false);
@@ -1002,7 +1276,7 @@ namespace Newtonsoft.Json
break;
case '"':
case '\'':
ParseString(currentChar);
ParseString(currentChar, ReadType.Read);
return true;
case 't':
ParseTrue();
@@ -1046,11 +1320,11 @@ namespace Newtonsoft.Json
}
else
{
ParseNumber();
ParseNumber(ReadType.Read);
}
return true;
case '/':
ParseComment();
ParseComment(true);
return true;
case 'u':
ParseUndefined();
@@ -1096,7 +1370,7 @@ namespace Newtonsoft.Json
}
if (char.IsNumber(currentChar) || currentChar == '-' || currentChar == '.')
{
ParseNumber();
ParseNumber(ReadType.Read);
return true;
}
@@ -1252,7 +1526,7 @@ namespace Newtonsoft.Json
}
}
private void ParseNumber()
private void ParseNumber(ReadType readType)
{
ShiftBufferIfNeeded();
@@ -1270,12 +1544,9 @@ namespace Newtonsoft.Json
JsonToken numberType;
bool singleDigit = (char.IsDigit(firstChar) && _stringReference.Length == 1);
bool nonBase10 = (firstChar == '0' && _stringReference.Length > 1
&& _stringReference.Chars[_stringReference.StartIndex + 1] != '.'
&& _stringReference.Chars[_stringReference.StartIndex + 1] != 'e'
&& _stringReference.Chars[_stringReference.StartIndex + 1] != 'E');
bool nonBase10 = (firstChar == '0' && _stringReference.Length > 1 && _stringReference.Chars[_stringReference.StartIndex + 1] != '.' && _stringReference.Chars[_stringReference.StartIndex + 1] != 'e' && _stringReference.Chars[_stringReference.StartIndex + 1] != 'E');
if (_readType == ReadType.ReadAsInt32)
if (readType == ReadType.ReadAsInt32)
{
if (singleDigit)
{
@@ -1288,9 +1559,7 @@ namespace Newtonsoft.Json
try
{
int integer = number.StartsWith("0x", StringComparison.OrdinalIgnoreCase)
? Convert.ToInt32(number, 16)
: Convert.ToInt32(number, 8);
int integer = number.StartsWith("0x", StringComparison.OrdinalIgnoreCase) ? Convert.ToInt32(number, 16) : Convert.ToInt32(number, 8);
numberValue = integer;
}
@@ -1319,12 +1588,12 @@ namespace Newtonsoft.Json
numberType = JsonToken.Integer;
}
else if (_readType == ReadType.ReadAsDecimal)
else if (readType == ReadType.ReadAsDecimal)
{
if (singleDigit)
{
// digit char values start at 48
numberValue = (decimal)firstChar - 48;
numberValue = (decimal) firstChar - 48;
}
else if (nonBase10)
{
@@ -1333,9 +1602,7 @@ namespace Newtonsoft.Json
try
{
// decimal.Parse doesn't support parsing hexadecimal values
long integer = number.StartsWith("0x", StringComparison.OrdinalIgnoreCase)
? Convert.ToInt64(number, 16)
: Convert.ToInt64(number, 8);
long integer = number.StartsWith("0x", StringComparison.OrdinalIgnoreCase) ? Convert.ToInt64(number, 16) : Convert.ToInt64(number, 8);
numberValue = Convert.ToDecimal(integer);
}
@@ -1366,7 +1633,7 @@ namespace Newtonsoft.Json
if (singleDigit)
{
// digit char values start at 48
numberValue = (long)firstChar - 48;
numberValue = (long) firstChar - 48;
numberType = JsonToken.Integer;
}
else if (nonBase10)
@@ -1375,9 +1642,7 @@ namespace Newtonsoft.Json
try
{
numberValue = number.StartsWith("0x", StringComparison.OrdinalIgnoreCase)
? Convert.ToInt64(number, 16)
: Convert.ToInt64(number, 8);
numberValue = number.StartsWith("0x", StringComparison.OrdinalIgnoreCase) ? Convert.ToInt64(number, 16) : Convert.ToInt64(number, 8);
}
catch (Exception ex)
{
@@ -1463,7 +1728,7 @@ namespace Newtonsoft.Json
}
#endif
private void ParseComment()
private void ParseComment(bool setToken)
{
// should have already parsed / character before reaching this method
_charPos++;
@@ -1492,9 +1757,7 @@ namespace Newtonsoft.Json
int initialPosition = _charPos;
bool commentFinished = false;
while (!commentFinished)
while (true)
{
switch (_chars[_charPos])
{
@@ -1508,8 +1771,8 @@ namespace Newtonsoft.Json
throw JsonReaderException.Create(this, "Unexpected end while parsing comment.");
}
_stringReference = new StringReference(_chars, initialPosition, _charPos - initialPosition);
commentFinished = true;
EndComment(setToken, initialPosition, _charPos);
return;
}
}
else
@@ -1526,10 +1789,10 @@ namespace Newtonsoft.Json
{
if (_chars[_charPos] == '/')
{
_stringReference = new StringReference(_chars, initialPosition, _charPos - initialPosition - 1);
EndComment(setToken, initialPosition, _charPos - 1);
_charPos++;
commentFinished = true;
return;
}
}
}
@@ -1537,16 +1800,16 @@ namespace Newtonsoft.Json
case StringUtils.CarriageReturn:
if (singlelineComment)
{
_stringReference = new StringReference(_chars, initialPosition, _charPos - initialPosition);
commentFinished = true;
EndComment(setToken, initialPosition, _charPos);
return;
}
ProcessCarriageReturn(true);
break;
case StringUtils.LineFeed:
if (singlelineComment)
{
_stringReference = new StringReference(_chars, initialPosition, _charPos - initialPosition);
commentFinished = true;
EndComment(setToken, initialPosition, _charPos);
return;
}
ProcessLineFeed();
break;
@@ -1555,10 +1818,14 @@ namespace Newtonsoft.Json
break;
}
}
}
SetToken(JsonToken.Comment, _stringReference.ToString());
ClearRecentString();
private void EndComment(bool setToken, int initialPosition, int endPosition)
{
if (setToken)
{
SetToken(JsonToken.Comment, new string(_chars, initialPosition, endPosition - initialPosition));
}
}
private bool MatchValue(string value)
+3 -68
View File
@@ -64,64 +64,12 @@ namespace Newtonsoft.Json.Linq
}
/// <summary>
/// Reads the next JSON token from the stream as a <see cref="Byte"/>[].
/// Reads the next JSON token from the stream.
/// </summary>
/// <returns>
/// A <see cref="Byte"/>[] or a null reference if the next JSON token is null. This method will return <c>null</c> at the end of an array.
/// true if the next token was read successfully; false if there are no more tokens to read.
/// </returns>
public override byte[] ReadAsBytes()
{
return ReadAsBytesInternal();
}
/// <summary>
/// Reads the next JSON token from the stream as a <see cref="Nullable{Decimal}"/>.
/// </summary>
/// <returns>A <see cref="Nullable{Decimal}"/>. This method will return <c>null</c> at the end of an array.</returns>
public override decimal? ReadAsDecimal()
{
return ReadAsDecimalInternal();
}
/// <summary>
/// Reads the next JSON token from the stream as a <see cref="Nullable{Int32}"/>.
/// </summary>
/// <returns>A <see cref="Nullable{Int32}"/>. This method will return <c>null</c> at the end of an array.</returns>
public override int? ReadAsInt32()
{
return ReadAsInt32Internal();
}
/// <summary>
/// Reads the next JSON token from the stream as a <see cref="String"/>.
/// </summary>
/// <returns>A <see cref="String"/>. This method will return <c>null</c> at the end of an array.</returns>
public override string ReadAsString()
{
return ReadAsStringInternal();
}
/// <summary>
/// Reads the next JSON token from the stream as a <see cref="Nullable{DateTime}"/>.
/// </summary>
/// <returns>A <see cref="Nullable{DateTime}"/>. This method will return <c>null</c> at the end of an array.</returns>
public override DateTime? ReadAsDateTime()
{
return ReadAsDateTimeInternal();
}
#if !NET20
/// <summary>
/// Reads the next JSON token from the stream as a <see cref="Nullable{DateTimeOffset}"/>.
/// </summary>
/// <returns>A <see cref="Nullable{DateTimeOffset}"/>. This method will return <c>null</c> at the end of an array.</returns>
public override DateTimeOffset? ReadAsDateTimeOffset()
{
return ReadAsDateTimeOffsetInternal();
}
#endif
internal override bool ReadInternal()
public override bool Read()
{
if (CurrentState != State.Start)
{
@@ -146,19 +94,6 @@ namespace Newtonsoft.Json.Linq
return true;
}
/// <summary>
/// Reads the next JSON token from the stream.
/// </summary>
/// <returns>
/// true if the next token was read successfully; false if there are no more tokens to read.
/// </returns>
public override bool Read()
{
_readType = ReadType.Read;
return ReadInternal();
}
private bool ReadOver(JToken t)
{
if (t == _root)