2016-08-03 10:59:49 +00:00
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------
namespace System.Runtime.Serialization.Json
{
using System.Globalization ;
using System.IO ;
2016-11-10 13:04:39 +00:00
#if ! MONO
2016-08-03 10:59:49 +00:00
using System.ServiceModel ;
2016-11-10 13:04:39 +00:00
#endif
2016-08-03 10:59:49 +00:00
using System.Text ;
using System.Runtime.Serialization ;
using System.Collections.Generic ;
using System.Xml ;
class XmlJsonReader : XmlBaseReader , IXmlJsonReaderInitializer
{
const int MaxTextChunk = 2048 ;
static byte [ ] charType = new byte [ 256 ]
{
CharType . None , // 0 (.)
CharType . None , // 1 (.)
CharType . None , // 2 (.)
CharType . None , // 3 (.)
CharType . None , // 4 (.)
CharType . None , // 5 (.)
CharType . None , // 6 (.)
CharType . None , // 7 (.)
CharType . None , // 8 (.)
CharType . None , // 9 (.)
CharType . None , // A (.)
CharType . None , // B (.)
CharType . None , // C (.)
CharType . None , // D (.)
CharType . None , // E (.)
CharType . None , // F (.)
CharType . None , // 10 (.)
CharType . None , // 11 (.)
CharType . None , // 12 (.)
CharType . None , // 13 (.)
CharType . None , // 14 (.)
CharType . None , // 15 (.)
CharType . None , // 16 (.)
CharType . None , // 17 (.)
CharType . None , // 18 (.)
CharType . None , // 19 (.)
CharType . None , // 1A (.)
CharType . None , // 1B (.)
CharType . None , // 1C (.)
CharType . None , // 1D (.)
CharType . None , // 1E (.)
CharType . None , // 1F (.)
CharType . None , // 20 ( )
CharType . None , // 21 (!)
CharType . None , // 22 (")
CharType . None , // 23 (#)
CharType . None , // 24 ($)
CharType . None , // 25 (%)
CharType . None , // 26 (&)
CharType . None , // 27 (')
CharType . None , // 28 (()
CharType . None , // 29 ())
CharType . None , // 2A (*)
CharType . None , // 2B (+)
CharType . None , // 2C (,)
CharType . None | CharType . Name , // 2D (-)
CharType . None | CharType . Name , // 2E (.)
CharType . None , // 2F (/)
CharType . None | CharType . Name , // 30 (0)
CharType . None | CharType . Name , // 31 (1)
CharType . None | CharType . Name , // 32 (2)
CharType . None | CharType . Name , // 33 (3)
CharType . None | CharType . Name , // 34 (4)
CharType . None | CharType . Name , // 35 (5)
CharType . None | CharType . Name , // 36 (6)
CharType . None | CharType . Name , // 37 (7)
CharType . None | CharType . Name , // 38 (8)
CharType . None | CharType . Name , // 39 (9)
CharType . None , // 3A (:)
CharType . None , // 3B (;)
CharType . None , // 3C (<)
CharType . None , // 3D (=)
CharType . None , // 3E (>)
CharType . None , // 3F (?)
CharType . None , // 40 (@)
CharType . None | CharType . FirstName | CharType . Name , // 41 (A)
CharType . None | CharType . FirstName | CharType . Name , // 42 (B)
CharType . None | CharType . FirstName | CharType . Name , // 43 (C)
CharType . None | CharType . FirstName | CharType . Name , // 44 (D)
CharType . None | CharType . FirstName | CharType . Name , // 45 (E)
CharType . None | CharType . FirstName | CharType . Name , // 46 (F)
CharType . None | CharType . FirstName | CharType . Name , // 47 (G)
CharType . None | CharType . FirstName | CharType . Name , // 48 (H)
CharType . None | CharType . FirstName | CharType . Name , // 49 (I)
CharType . None | CharType . FirstName | CharType . Name , // 4A (J)
CharType . None | CharType . FirstName | CharType . Name , // 4B (K)
CharType . None | CharType . FirstName | CharType . Name , // 4C (L)
CharType . None | CharType . FirstName | CharType . Name , // 4D (M)
CharType . None | CharType . FirstName | CharType . Name , // 4E (N)
CharType . None | CharType . FirstName | CharType . Name , // 4F (O)
CharType . None | CharType . FirstName | CharType . Name , // 50 (P)
CharType . None | CharType . FirstName | CharType . Name , // 51 (Q)
CharType . None | CharType . FirstName | CharType . Name , // 52 (R)
CharType . None | CharType . FirstName | CharType . Name , // 53 (S)
CharType . None | CharType . FirstName | CharType . Name , // 54 (T)
CharType . None | CharType . FirstName | CharType . Name , // 55 (U)
CharType . None | CharType . FirstName | CharType . Name , // 56 (V)
CharType . None | CharType . FirstName | CharType . Name , // 57 (W)
CharType . None | CharType . FirstName | CharType . Name , // 58 (X)
CharType . None | CharType . FirstName | CharType . Name , // 59 (Y)
CharType . None | CharType . FirstName | CharType . Name , // 5A (Z)
CharType . None , // 5B ([)
CharType . None , // 5C (\)
CharType . None , // 5D (])
CharType . None , // 5E (^)
CharType . None | CharType . FirstName | CharType . Name , // 5F (_)
CharType . None , // 60 (`)
CharType . None | CharType . FirstName | CharType . Name , // 61 (a)
CharType . None | CharType . FirstName | CharType . Name , // 62 (b)
CharType . None | CharType . FirstName | CharType . Name , // 63 (c)
CharType . None | CharType . FirstName | CharType . Name , // 64 (d)
CharType . None | CharType . FirstName | CharType . Name , // 65 (e)
CharType . None | CharType . FirstName | CharType . Name , // 66 (f)
CharType . None | CharType . FirstName | CharType . Name , // 67 (g)
CharType . None | CharType . FirstName | CharType . Name , // 68 (h)
CharType . None | CharType . FirstName | CharType . Name , // 69 (i)
CharType . None | CharType . FirstName | CharType . Name , // 6A (j)
CharType . None | CharType . FirstName | CharType . Name , // 6B (k)
CharType . None | CharType . FirstName | CharType . Name , // 6C (l)
CharType . None | CharType . FirstName | CharType . Name , // 6D (m)
CharType . None | CharType . FirstName | CharType . Name , // 6E (n)
CharType . None | CharType . FirstName | CharType . Name , // 6F (o)
CharType . None | CharType . FirstName | CharType . Name , // 70 (p)
CharType . None | CharType . FirstName | CharType . Name , // 71 (q)
CharType . None | CharType . FirstName | CharType . Name , // 72 (r)
CharType . None | CharType . FirstName | CharType . Name , // 73 (s)
CharType . None | CharType . FirstName | CharType . Name , // 74 (t)
CharType . None | CharType . FirstName | CharType . Name , // 75 (u)
CharType . None | CharType . FirstName | CharType . Name , // 76 (v)
CharType . None | CharType . FirstName | CharType . Name , // 77 (w)
CharType . None | CharType . FirstName | CharType . Name , // 78 (x)
CharType . None | CharType . FirstName | CharType . Name , // 79 (y)
CharType . None | CharType . FirstName | CharType . Name , // 7A (z)
CharType . None , // 7B ({)
CharType . None , // 7C (|)
CharType . None , // 7D (})
CharType . None , // 7E (~)
CharType . None , // 7F (.)
CharType . None | CharType . FirstName | CharType . Name , // 80 (.)
CharType . None | CharType . FirstName | CharType . Name , // 81 (.)
CharType . None | CharType . FirstName | CharType . Name , // 82 (.)
CharType . None | CharType . FirstName | CharType . Name , // 83 (.)
CharType . None | CharType . FirstName | CharType . Name , // 84 (.)
CharType . None | CharType . FirstName | CharType . Name , // 85 (.)
CharType . None | CharType . FirstName | CharType . Name , // 86 (.)
CharType . None | CharType . FirstName | CharType . Name , // 87 (.)
CharType . None | CharType . FirstName | CharType . Name , // 88 (.)
CharType . None | CharType . FirstName | CharType . Name , // 89 (.)
CharType . None | CharType . FirstName | CharType . Name , // 8A (.)
CharType . None | CharType . FirstName | CharType . Name , // 8B (.)
CharType . None | CharType . FirstName | CharType . Name , // 8C (.)
CharType . None | CharType . FirstName | CharType . Name , // 8D (.)
CharType . None | CharType . FirstName | CharType . Name , // 8E (.)
CharType . None | CharType . FirstName | CharType . Name , // 8F (.)
CharType . None | CharType . FirstName | CharType . Name , // 90 (.)
CharType . None | CharType . FirstName | CharType . Name , // 91 (.)
CharType . None | CharType . FirstName | CharType . Name , // 92 (.)
CharType . None | CharType . FirstName | CharType . Name , // 93 (.)
CharType . None | CharType . FirstName | CharType . Name , // 94 (.)
CharType . None | CharType . FirstName | CharType . Name , // 95 (.)
CharType . None | CharType . FirstName | CharType . Name , // 96 (.)
CharType . None | CharType . FirstName | CharType . Name , // 97 (.)
CharType . None | CharType . FirstName | CharType . Name , // 98 (.)
CharType . None | CharType . FirstName | CharType . Name , // 99 (.)
CharType . None | CharType . FirstName | CharType . Name , // 9A (.)
CharType . None | CharType . FirstName | CharType . Name , // 9B (.)
CharType . None | CharType . FirstName | CharType . Name , // 9C (.)
CharType . None | CharType . FirstName | CharType . Name , // 9D (.)
CharType . None | CharType . FirstName | CharType . Name , // 9E (.)
CharType . None | CharType . FirstName | CharType . Name , // 9F (.)
CharType . None | CharType . FirstName | CharType . Name , // A0 (<28> )
CharType . None | CharType . FirstName | CharType . Name , // A1 (<28> )
CharType . None | CharType . FirstName | CharType . Name , // A2 (<28> )
CharType . None | CharType . FirstName | CharType . Name , // A3 (<28> )
CharType . None | CharType . FirstName | CharType . Name , // A4 ( )
CharType . None | CharType . FirstName | CharType . Name , // A5 (<28> )
CharType . None | CharType . FirstName | CharType . Name , // A6 (<28> )
CharType . None | CharType . FirstName | CharType . Name , // A7 ( )
CharType . None | CharType . FirstName | CharType . Name , // A8 (")
CharType . None | CharType . FirstName | CharType . Name , // A9 (c)
CharType . None | CharType . FirstName | CharType . Name , // AA (<28> )
CharType . None | CharType . FirstName | CharType . Name , // AB (<28> )
CharType . None | CharType . FirstName | CharType . Name , // AC (<28> )
CharType . None | CharType . FirstName | CharType . Name , // AD (-)
CharType . None | CharType . FirstName | CharType . Name , // AE (r)
CharType . None | CharType . FirstName | CharType . Name , // AF (_)
CharType . None | CharType . FirstName | CharType . Name , // B0 (<28> )
CharType . None | CharType . FirstName | CharType . Name , // B1 (<28> )
CharType . None | CharType . FirstName | CharType . Name , // B2 (<28> )
CharType . None | CharType . FirstName | CharType . Name , // B3 (3)
CharType . None | CharType . FirstName | CharType . Name , // B4 (')
CharType . None | CharType . FirstName | CharType . Name , // B5 (<28> )
CharType . None | CharType . FirstName | CharType . Name , // B6 ( )
CharType . None | CharType . FirstName | CharType . Name , // B7 (<28> )
CharType . None | CharType . FirstName | CharType . Name , // B8 (,)
CharType . None | CharType . FirstName | CharType . Name , // B9 (1)
CharType . None | CharType . FirstName | CharType . Name , // BA (<28> )
CharType . None | CharType . FirstName | CharType . Name , // BB (<28> )
CharType . None | CharType . FirstName | CharType . Name , // BC (<28> )
CharType . None | CharType . FirstName | CharType . Name , // BD (<28> )
CharType . None | CharType . FirstName | CharType . Name , // BE (_)
CharType . None | CharType . FirstName | CharType . Name , // BF (<28> )
CharType . None | CharType . FirstName | CharType . Name , // C0 (A)
CharType . None | CharType . FirstName | CharType . Name , // C1 (A)
CharType . None | CharType . FirstName | CharType . Name , // C2 (A)
CharType . None | CharType . FirstName | CharType . Name , // C3 (A)
CharType . None | CharType . FirstName | CharType . Name , // C4 (<28> )
CharType . None | CharType . FirstName | CharType . Name , // C5 (<28> )
CharType . None | CharType . FirstName | CharType . Name , // C6 (<28> )
CharType . None | CharType . FirstName | CharType . Name , // C7 (<28> )
CharType . None | CharType . FirstName | CharType . Name , // C8 (E)
CharType . None | CharType . FirstName | CharType . Name , // C9 (<28> )
CharType . None | CharType . FirstName | CharType . Name , // CA (E)
CharType . None | CharType . FirstName | CharType . Name , // CB (E)
CharType . None | CharType . FirstName | CharType . Name , // CC (I)
CharType . None | CharType . FirstName | CharType . Name , // CD (I)
CharType . None | CharType . FirstName | CharType . Name , // CE (I)
CharType . None | CharType . FirstName | CharType . Name , // CF (I)
CharType . None | CharType . FirstName | CharType . Name , // D0 (D)
CharType . None | CharType . FirstName | CharType . Name , // D1 (<28> )
CharType . None | CharType . FirstName | CharType . Name , // D2 (O)
CharType . None | CharType . FirstName | CharType . Name , // D3 (O)
CharType . None | CharType . FirstName | CharType . Name , // D4 (O)
CharType . None | CharType . FirstName | CharType . Name , // D5 (O)
CharType . None | CharType . FirstName | CharType . Name , // D6 (<28> )
CharType . None | CharType . FirstName | CharType . Name , // D7 (x)
CharType . None | CharType . FirstName | CharType . Name , // D8 (O)
CharType . None | CharType . FirstName | CharType . Name , // D9 (U)
CharType . None | CharType . FirstName | CharType . Name , // DA (U)
CharType . None | CharType . FirstName | CharType . Name , // DB (U)
CharType . None | CharType . FirstName | CharType . Name , // DC (<28> )
CharType . None | CharType . FirstName | CharType . Name , // DD (Y)
CharType . None | CharType . FirstName | CharType . Name , // DE (_)
CharType . None | CharType . FirstName | CharType . Name , // DF (<28> )
CharType . None | CharType . FirstName | CharType . Name , // E0 (<28> )
CharType . None | CharType . FirstName | CharType . Name , // E1 (<28> )
CharType . None | CharType . FirstName | CharType . Name , // E2 (<28> )
CharType . None | CharType . FirstName | CharType . Name , // E3 (a)
CharType . None | CharType . FirstName | CharType . Name , // E4 (<28> )
CharType . None | CharType . FirstName | CharType . Name , // E5 (<28> )
CharType . None | CharType . FirstName | CharType . Name , // E6 (<28> )
CharType . None | CharType . FirstName | CharType . Name , // E7 (<28> )
CharType . None | CharType . FirstName | CharType . Name , // E8 (<28> )
CharType . None | CharType . FirstName | CharType . Name , // E9 (<28> )
CharType . None | CharType . FirstName | CharType . Name , // EA (<28> )
CharType . None | CharType . FirstName | CharType . Name , // EB (<28> )
CharType . None | CharType . FirstName | CharType . Name , // EC (<28> )
CharType . None | CharType . FirstName | CharType . Name , // ED (<28> )
CharType . None | CharType . FirstName | CharType . Name , // EE (<28> )
CharType . None | CharType . FirstName | CharType . Name , // EF (<28> )
CharType . None | CharType . FirstName | CharType . Name , // F0 (d)
CharType . None | CharType . FirstName | CharType . Name , // F1 (<28> )
CharType . None | CharType . FirstName | CharType . Name , // F2 (<28> )
CharType . None | CharType . FirstName | CharType . Name , // F3 (<28> )
CharType . None | CharType . FirstName | CharType . Name , // F4 (<28> )
CharType . None | CharType . FirstName | CharType . Name , // F5 (o)
CharType . None | CharType . FirstName | CharType . Name , // F6 (<28> )
CharType . None | CharType . FirstName | CharType . Name , // F7 (<28> )
CharType . None | CharType . FirstName | CharType . Name , // F8 (o)
CharType . None | CharType . FirstName | CharType . Name , // F9 (<28> )
CharType . None | CharType . FirstName | CharType . Name , // FA (<28> )
CharType . None | CharType . FirstName | CharType . Name , // FB (<28> )
CharType . None | CharType . FirstName | CharType . Name , // FC (<28> )
CharType . None | CharType . FirstName | CharType . Name , // FD (y)
CharType . None | CharType . FirstName | CharType . Name , // FE (_)
CharType . None | CharType . FirstName | CharType . Name , // FF (<28> )
} ;
bool buffered ;
byte [ ] charactersToSkipOnNextRead ;
JsonComplexTextMode complexTextMode = JsonComplexTextMode . None ;
bool expectingFirstElementInNonPrimitiveChild ;
int maxBytesPerRead ;
OnXmlDictionaryReaderClose onReaderClose ;
bool readServerTypeElement = false ;
int scopeDepth = 0 ;
JsonNodeType [ ] scopes ;
enum JsonComplexTextMode
{
QuotedText ,
NumericalText ,
None
} ;
public override bool CanCanonicalize
{
get
{
return false ;
}
}
public override string Value
{
get
{
if ( IsAttributeValue & & ! this . IsLocalName ( JsonGlobals . typeString ) )
{
return UnescapeJsonString ( base . Value ) ;
}
return base . Value ;
}
}
bool IsAttributeValue
{
get
{
return ( this . Node . NodeType = = XmlNodeType . Attribute | | this . Node is XmlAttributeTextNode ) ;
}
}
bool IsReadingCollection
{
get
{
return ( ( scopeDepth > 0 ) & & ( scopes [ scopeDepth ] = = JsonNodeType . Collection ) ) ;
}
}
bool IsReadingComplexText
{
get
{
return ( ( ! this . Node . IsAtomicValue ) & &
( this . Node . NodeType = = XmlNodeType . Text ) ) ;
}
}
public override void Close ( )
{
base . Close ( ) ;
OnXmlDictionaryReaderClose onClose = this . onReaderClose ;
this . onReaderClose = null ;
ResetState ( ) ;
if ( onClose ! = null )
{
try
{
onClose ( this ) ;
}
catch ( Exception e )
{
if ( Fx . IsFatal ( e ) )
{
throw ;
}
throw DiagnosticUtility . ExceptionUtility . ThrowHelperCallback ( e ) ;
}
}
}
public override void EndCanonicalization ( )
{
throw DiagnosticUtility . ExceptionUtility . ThrowHelperError ( new NotSupportedException ( ) ) ;
}
public override string GetAttribute ( int index )
{
return UnescapeJsonString ( base . GetAttribute ( index ) ) ;
}
public override string GetAttribute ( string localName , string namespaceUri )
{
if ( localName ! = JsonGlobals . typeString )
{
return UnescapeJsonString ( base . GetAttribute ( localName , namespaceUri ) ) ;
}
return base . GetAttribute ( localName , namespaceUri ) ;
}
public override string GetAttribute ( string name )
{
if ( name ! = JsonGlobals . typeString )
{
return UnescapeJsonString ( base . GetAttribute ( name ) ) ;
}
return base . GetAttribute ( name ) ;
}
public override string GetAttribute ( XmlDictionaryString localName , XmlDictionaryString namespaceUri )
{
if ( XmlDictionaryString . GetString ( localName ) ! = JsonGlobals . typeString )
{
return UnescapeJsonString ( base . GetAttribute ( localName , namespaceUri ) ) ;
}
return base . GetAttribute ( localName , namespaceUri ) ;
}
public override bool Read ( )
{
if ( this . Node . CanMoveToElement )
{
// If we're positioned on an attribute or attribute text on an empty element, we need to move back
// to the element in order to get the correct setting of ExitScope
MoveToElement ( ) ;
}
if ( this . Node . ReadState = = ReadState . Closed )
{
return false ;
}
if ( this . Node . ExitScope )
{
ExitScope ( ) ;
}
if ( ! buffered )
{
BufferReader . SetWindow ( ElementNode . BufferOffset , this . maxBytesPerRead ) ;
}
byte ch ;
// Skip whitespace before checking EOF
// Complex text check necessary because whitespace could be part of really long
// quoted text that's read using multiple Read() calls.
// This also ensures that we deal with the whitespace-only input case properly by not
// floating a root element at all.
if ( ! IsReadingComplexText )
{
SkipWhitespaceInBufferReader ( ) ;
if ( TryGetByte ( out ch ) )
{
if ( charactersToSkipOnNextRead [ 0 ] = = ch | | charactersToSkipOnNextRead [ 1 ] = = ch )
{
BufferReader . SkipByte ( ) ;
charactersToSkipOnNextRead [ 0 ] = 0 ;
charactersToSkipOnNextRead [ 1 ] = 0 ;
}
}
SkipWhitespaceInBufferReader ( ) ;
if ( TryGetByte ( out ch ) )
{
if ( ch = = JsonGlobals . EndCollectionByte & & IsReadingCollection )
{
BufferReader . SkipByte ( ) ;
SkipWhitespaceInBufferReader ( ) ;
ExitJsonScope ( ) ;
}
}
if ( BufferReader . EndOfFile )
{
if ( scopeDepth > 0 )
{
MoveToEndElement ( ) ;
return true ;
}
else
{
MoveToEndOfFile ( ) ;
return false ;
}
}
}
ch = BufferReader . GetByte ( ) ;
if ( scopeDepth = = 0 )
{
ReadNonExistentElementName ( StringHandleConstStringType . Root ) ;
}
else if ( IsReadingComplexText )
{
switch ( complexTextMode )
{
case JsonComplexTextMode . NumericalText :
ReadNumericalText ( ) ;
break ;
case JsonComplexTextMode . QuotedText :
if ( ch = = ( byte ) '\\' )
{
ReadEscapedCharacter ( true ) ; // moveToText
}
else
{
ReadQuotedText ( true ) ; // moveToText
}
break ;
case JsonComplexTextMode . None :
XmlExceptionHelper . ThrowXmlException ( this ,
new XmlException ( SR . GetString ( SR . JsonEncounteredUnexpectedCharacter , ( char ) ch ) ) ) ;
break ;
}
}
else if ( IsReadingCollection )
{
ReadNonExistentElementName ( StringHandleConstStringType . Item ) ;
}
else if ( ch = = JsonGlobals . EndCollectionByte )
{
BufferReader . SkipByte ( ) ;
MoveToEndElement ( ) ;
ExitJsonScope ( ) ;
}
else if ( ch = = JsonGlobals . ObjectByte )
{
BufferReader . SkipByte ( ) ;
SkipWhitespaceInBufferReader ( ) ;
ch = ( byte ) BufferReader . GetByte ( ) ;
if ( ch = = JsonGlobals . EndObjectByte )
{
BufferReader . SkipByte ( ) ;
SkipWhitespaceInBufferReader ( ) ;
if ( TryGetByte ( out ch ) )
{
if ( ch = = JsonGlobals . MemberSeparatorByte )
{
BufferReader . SkipByte ( ) ;
}
}
else
{
charactersToSkipOnNextRead [ 0 ] = JsonGlobals . MemberSeparatorByte ;
}
MoveToEndElement ( ) ;
}
else
{
EnterJsonScope ( JsonNodeType . Object ) ;
ParseStartElement ( ) ;
}
}
else if ( ch = = JsonGlobals . EndObjectByte )
{
BufferReader . SkipByte ( ) ;
if ( expectingFirstElementInNonPrimitiveChild )
{
SkipWhitespaceInBufferReader ( ) ;
ch = BufferReader . GetByte ( ) ;
if ( ( ch = = JsonGlobals . MemberSeparatorByte ) | |
( ch = = JsonGlobals . EndObjectByte ) )
{
BufferReader . SkipByte ( ) ;
}
else
{
XmlExceptionHelper . ThrowXmlException ( this ,
new XmlException ( SR . GetString ( SR . JsonEncounteredUnexpectedCharacter ,
( char ) ch ) ) ) ;
}
expectingFirstElementInNonPrimitiveChild = false ;
}
MoveToEndElement ( ) ;
}
else if ( ch = = JsonGlobals . MemberSeparatorByte )
{
BufferReader . SkipByte ( ) ;
MoveToEndElement ( ) ;
}
else if ( ch = = JsonGlobals . QuoteByte )
{
if ( readServerTypeElement )
{
readServerTypeElement = false ;
EnterJsonScope ( JsonNodeType . Object ) ;
ParseStartElement ( ) ;
}
else if ( this . Node . NodeType = = XmlNodeType . Element )
{
if ( expectingFirstElementInNonPrimitiveChild )
{
EnterJsonScope ( JsonNodeType . Object ) ;
ParseStartElement ( ) ;
}
else
{
BufferReader . SkipByte ( ) ;
ReadQuotedText ( true ) ; // moveToText
}
}
else if ( this . Node . NodeType = = XmlNodeType . EndElement )
{
EnterJsonScope ( JsonNodeType . Element ) ;
ParseStartElement ( ) ;
}
else
{
XmlExceptionHelper . ThrowXmlException ( this ,
new XmlException ( SR . GetString ( SR . JsonEncounteredUnexpectedCharacter ,
JsonGlobals . QuoteChar ) ) ) ;
}
}
else if ( ch = = ( byte ) 'f' )
{
int offset ;
byte [ ] buffer = BufferReader . GetBuffer ( 5 , out offset ) ;
if ( buffer [ offset + 1 ] ! = ( byte ) 'a' | |
buffer [ offset + 2 ] ! = ( byte ) 'l' | |
buffer [ offset + 3 ] ! = ( byte ) 's' | |
buffer [ offset + 4 ] ! = ( byte ) 'e' )
{
XmlExceptionHelper . ThrowTokenExpected ( this , "false" , Encoding . UTF8 . GetString ( buffer , offset , 5 ) ) ;
}
BufferReader . Advance ( 5 ) ;
if ( TryGetByte ( out ch ) )
{
if ( ! IsWhitespace ( ch ) & & ch ! = JsonGlobals . MemberSeparatorByte & & ch ! = JsonGlobals . EndObjectChar & & ch ! = JsonGlobals . EndCollectionByte )
{
XmlExceptionHelper . ThrowTokenExpected ( this , "false" , Encoding . UTF8 . GetString ( buffer , offset , 4 ) + ( char ) ch ) ;
}
}
MoveToAtomicText ( ) . Value . SetValue ( ValueHandleType . UTF8 , offset , 5 ) ;
}
else if ( ch = = ( byte ) 't' )
{
int offset ;
byte [ ] buffer = BufferReader . GetBuffer ( 4 , out offset ) ;
if ( buffer [ offset + 1 ] ! = ( byte ) 'r' | |
buffer [ offset + 2 ] ! = ( byte ) 'u' | |
buffer [ offset + 3 ] ! = ( byte ) 'e' )
{
XmlExceptionHelper . ThrowTokenExpected ( this , "true" , Encoding . UTF8 . GetString ( buffer , offset , 4 ) ) ;
}
BufferReader . Advance ( 4 ) ;
if ( TryGetByte ( out ch ) )
{
if ( ! IsWhitespace ( ch ) & & ch ! = JsonGlobals . MemberSeparatorByte & & ch ! = JsonGlobals . EndObjectChar & & ch ! = JsonGlobals . EndCollectionByte )
{
XmlExceptionHelper . ThrowTokenExpected ( this , "true" , Encoding . UTF8 . GetString ( buffer , offset , 4 ) + ( char ) ch ) ;
}
}
MoveToAtomicText ( ) . Value . SetValue ( ValueHandleType . UTF8 , offset , 4 ) ;
}
else if ( ch = = ( byte ) 'n' )
{
int offset ;
byte [ ] buffer = BufferReader . GetBuffer ( 4 , out offset ) ;
if ( buffer [ offset + 1 ] ! = ( byte ) 'u' | |
buffer [ offset + 2 ] ! = ( byte ) 'l' | |
buffer [ offset + 3 ] ! = ( byte ) 'l' )
{
XmlExceptionHelper . ThrowTokenExpected ( this , "null" , Encoding . UTF8 . GetString ( buffer , offset , 4 ) ) ;
}
BufferReader . Advance ( 4 ) ;
SkipWhitespaceInBufferReader ( ) ;
if ( TryGetByte ( out ch ) )
{
if ( ch = = JsonGlobals . MemberSeparatorByte | | ch = = JsonGlobals . EndObjectChar )
{
BufferReader . SkipByte ( ) ;
}
else if ( ch ! = JsonGlobals . EndCollectionByte )
{
XmlExceptionHelper . ThrowTokenExpected ( this , "null" , Encoding . UTF8 . GetString ( buffer , offset , 4 ) + ( char ) ch ) ;
}
}
else
{
charactersToSkipOnNextRead [ 0 ] = JsonGlobals . MemberSeparatorByte ;
charactersToSkipOnNextRead [ 1 ] = JsonGlobals . EndObjectByte ;
}
MoveToEndElement ( ) ;
}
else if ( ( ch = = ( byte ) '-' ) | |
( ( ( byte ) '0' < = ch ) & & ( ch < = ( byte ) '9' ) ) | |
( ch = = ( byte ) 'I' ) | |
( ch = = ( byte ) 'N' ) )
{
ReadNumericalText ( ) ;
}
else
{
XmlExceptionHelper . ThrowXmlException ( this ,
new XmlException ( SR . GetString ( SR . JsonEncounteredUnexpectedCharacter , ( char ) ch ) ) ) ;
}
return true ;
}
public override decimal ReadContentAsDecimal ( )
{
string value = ReadContentAsString ( ) ;
try
{
return decimal . Parse ( value , NumberStyles . Float , NumberFormatInfo . InvariantInfo ) ;
}
catch ( ArgumentException exception )
{
throw DiagnosticUtility . ExceptionUtility . ThrowHelperError ( XmlExceptionHelper . CreateConversionException ( value , "decimal" , exception ) ) ;
}
catch ( FormatException exception )
{
throw DiagnosticUtility . ExceptionUtility . ThrowHelperError ( XmlExceptionHelper . CreateConversionException ( value , "decimal" , exception ) ) ;
}
catch ( OverflowException exception )
{
throw DiagnosticUtility . ExceptionUtility . ThrowHelperError ( XmlExceptionHelper . CreateConversionException ( value , "decimal" , exception ) ) ;
}
}
public override int ReadContentAsInt ( )
{
return ParseInt ( ReadContentAsString ( ) , NumberStyles . Float ) ;
}
public override long ReadContentAsLong ( )
{
string value = ReadContentAsString ( ) ;
try
{
return long . Parse ( value , NumberStyles . Float , NumberFormatInfo . InvariantInfo ) ;
}
catch ( ArgumentException exception )
{
throw DiagnosticUtility . ExceptionUtility . ThrowHelperError ( XmlExceptionHelper . CreateConversionException ( value , "Int64" , exception ) ) ;
}
catch ( FormatException exception )
{
throw DiagnosticUtility . ExceptionUtility . ThrowHelperError ( XmlExceptionHelper . CreateConversionException ( value , "Int64" , exception ) ) ;
}
catch ( OverflowException exception )
{
throw DiagnosticUtility . ExceptionUtility . ThrowHelperError ( XmlExceptionHelper . CreateConversionException ( value , "Int64" , exception ) ) ;
}
}
public override int ReadValueAsBase64 ( byte [ ] buffer , int offset , int count )
{
if ( IsAttributeValue )
{
if ( buffer = = null )
{
throw DiagnosticUtility . ExceptionUtility . ThrowHelperError ( new ArgumentNullException ( "buffer" ) ) ;
}
if ( offset < 0 )
{
throw DiagnosticUtility . ExceptionUtility . ThrowHelperError ( new ArgumentOutOfRangeException ( "offset" , System . Runtime . Serialization . SR . GetString ( System . Runtime . Serialization . SR . ValueMustBeNonNegative ) ) ) ;
}
if ( offset > buffer . Length )
{
throw DiagnosticUtility . ExceptionUtility . ThrowHelperError ( new ArgumentOutOfRangeException ( "offset" , System . Runtime . Serialization . SR . GetString ( System . Runtime . Serialization . SR . OffsetExceedsBufferSize , buffer . Length ) ) ) ;
}
if ( count < 0 )
{
throw DiagnosticUtility . ExceptionUtility . ThrowHelperError ( new ArgumentOutOfRangeException ( "count" , System . Runtime . Serialization . SR . GetString ( System . Runtime . Serialization . SR . ValueMustBeNonNegative ) ) ) ;
}
if ( count > buffer . Length - offset )
{
throw DiagnosticUtility . ExceptionUtility . ThrowHelperError ( new ArgumentOutOfRangeException ( "count" , System . Runtime . Serialization . SR . GetString ( System . Runtime . Serialization . SR . SizeExceedsRemainingBufferSpace , buffer . Length - offset ) ) ) ;
}
return 0 ;
}
return base . ReadValueAsBase64 ( buffer , offset , count ) ;
}
public override int ReadValueChunk ( char [ ] chars , int offset , int count )
{
if ( IsAttributeValue )
{
if ( chars = = null )
{
throw DiagnosticUtility . ExceptionUtility . ThrowHelperError ( new ArgumentNullException ( "chars" ) ) ;
}
if ( offset < 0 )
{
throw DiagnosticUtility . ExceptionUtility . ThrowHelperError ( new ArgumentOutOfRangeException ( "offset" , System . Runtime . Serialization . SR . GetString ( System . Runtime . Serialization . SR . ValueMustBeNonNegative ) ) ) ;
}
if ( offset > chars . Length )
{
throw DiagnosticUtility . ExceptionUtility . ThrowHelperError ( new ArgumentOutOfRangeException ( "offset" , System . Runtime . Serialization . SR . GetString ( System . Runtime . Serialization . SR . OffsetExceedsBufferSize , chars . Length ) ) ) ;
}
if ( count < 0 )
{
throw DiagnosticUtility . ExceptionUtility . ThrowHelperError ( new ArgumentOutOfRangeException ( "count" , System . Runtime . Serialization . SR . GetString ( System . Runtime . Serialization . SR . ValueMustBeNonNegative ) ) ) ;
}
if ( count > chars . Length - offset )
{
throw DiagnosticUtility . ExceptionUtility . ThrowHelperError ( new ArgumentOutOfRangeException ( "count" , System . Runtime . Serialization . SR . GetString ( System . Runtime . Serialization . SR . SizeExceedsRemainingBufferSpace , chars . Length - offset ) ) ) ;
}
int actual ;
string value = UnescapeJsonString ( this . Node . ValueAsString ) ;
actual = Math . Min ( count , value . Length ) ;
if ( actual > 0 )
{
value . CopyTo ( 0 , chars , offset , actual ) ;
if ( this . Node . QNameType = = QNameType . Xmlns )
{
this . Node . Namespace . Uri . SetValue ( 0 , 0 ) ;
}
else
{
this . Node . Value . SetValue ( ValueHandleType . UTF8 , 0 , 0 ) ;
}
}
return actual ;
}
return base . ReadValueChunk ( chars , offset , count ) ;
}
public void SetInput ( byte [ ] buffer , int offset , int count , Encoding encoding , XmlDictionaryReaderQuotas quotas ,
OnXmlDictionaryReaderClose onClose )
{
if ( buffer = = null )
{
throw DiagnosticUtility . ExceptionUtility . ThrowHelperArgumentNull ( "buffer" ) ;
}
if ( offset < 0 )
{
throw DiagnosticUtility . ExceptionUtility . ThrowHelperError (
new ArgumentOutOfRangeException ( "offset" , SR . GetString ( SR . ValueMustBeNonNegative ) ) ) ;
}
if ( offset > buffer . Length )
{
throw DiagnosticUtility . ExceptionUtility . ThrowHelperError (
new ArgumentOutOfRangeException ( "offset" ,
SR . GetString ( SR . JsonOffsetExceedsBufferSize , buffer . Length ) ) ) ;
}
if ( count < 0 )
{
throw DiagnosticUtility . ExceptionUtility . ThrowHelperError (
new ArgumentOutOfRangeException ( "count" , SR . GetString ( SR . ValueMustBeNonNegative ) ) ) ;
}
if ( count > buffer . Length - offset )
{
throw DiagnosticUtility . ExceptionUtility . ThrowHelperError (
new ArgumentOutOfRangeException ( "count" ,
SR . GetString ( SR . JsonSizeExceedsRemainingBufferSpace ,
buffer . Length - offset ) ) ) ;
}
MoveToInitial ( quotas , onClose ) ;
ArraySegment < byte > seg = JsonEncodingStreamWrapper . ProcessBuffer ( buffer , offset , count , encoding ) ;
BufferReader . SetBuffer ( seg . Array , seg . Offset , seg . Count , null , null ) ;
this . buffered = true ;
ResetState ( ) ;
}
public void SetInput ( Stream stream , Encoding encoding , XmlDictionaryReaderQuotas quotas ,
OnXmlDictionaryReaderClose onClose )
{
if ( stream = = null )
{
throw DiagnosticUtility . ExceptionUtility . ThrowHelperArgumentNull ( "stream" ) ;
}
MoveToInitial ( quotas , onClose ) ;
stream = new JsonEncodingStreamWrapper ( stream , encoding , true ) ;
BufferReader . SetBuffer ( stream , null , null ) ;
this . buffered = false ;
ResetState ( ) ;
}
public override void StartCanonicalization ( Stream stream , bool includeComments , string [ ] inclusivePrefixes )
{
throw DiagnosticUtility . ExceptionUtility . ThrowHelperError ( new NotSupportedException ( ) ) ;
}
internal static void CheckArray ( Array array , int offset , int count )
{
if ( array = = null )
{
throw DiagnosticUtility . ExceptionUtility . ThrowHelperError ( new ArgumentNullException ( "array" ) ) ;
}
if ( offset < 0 )
{
throw DiagnosticUtility . ExceptionUtility . ThrowHelperError ( new ArgumentOutOfRangeException ( "offset" , SR . GetString ( SR . ValueMustBeNonNegative ) ) ) ;
}
if ( offset > array . Length )
{
throw DiagnosticUtility . ExceptionUtility . ThrowHelperError ( new ArgumentOutOfRangeException ( "offset" , SR . GetString ( SR . OffsetExceedsBufferSize , array . Length ) ) ) ;
}
if ( count < 0 )
{
throw DiagnosticUtility . ExceptionUtility . ThrowHelperError ( new ArgumentOutOfRangeException ( "count" , SR . GetString ( SR . ValueMustBeNonNegative ) ) ) ;
}
if ( count > array . Length - offset )
{
throw DiagnosticUtility . ExceptionUtility . ThrowHelperError ( new ArgumentOutOfRangeException ( "count" , SR . GetString ( SR . SizeExceedsRemainingBufferSpace , array . Length - offset ) ) ) ;
}
}
protected override XmlSigningNodeWriter CreateSigningNodeWriter ( )
{
throw DiagnosticUtility . ExceptionUtility . ThrowHelperError ( new NotSupportedException ( SR . GetString ( SR . JsonMethodNotSupported , "CreateSigningNodeWriter" ) ) ) ;
}
static int BreakText ( byte [ ] buffer , int offset , int length )
{
// See if we might be breaking a utf8 sequence
if ( length > 0 & & ( buffer [ offset + length - 1 ] & 0x80 ) = = 0x80 )
{
// Find the lead char of the utf8 sequence (0x11xxxxxx)
int originalLength = length ;
do
{
length - - ;
} while ( length > 0 & & ( buffer [ offset + length ] & 0xC0 ) ! = 0xC0 ) ;
// Couldn't find the lead char
if ( length = = 0 )
{
return originalLength ; // Invalid utf8 sequence - can't break
}
// Count how many bytes follow the lead char
byte b = ( byte ) ( buffer [ offset + length ] < < 2 ) ;
int byteCount = 2 ;
while ( ( b & 0x80 ) = = 0x80 )
{
b = ( byte ) ( b < < 1 ) ;
byteCount + + ;
// There shouldn't be more than 3 bytes following the lead char
if ( byteCount > 4 )
{
return originalLength ; // Invalid utf8 sequence - can't break
}
}
if ( length + byteCount = = originalLength )
{
return originalLength ; // sequence fits exactly
}
if ( length = = 0 )
{
return originalLength ; // Quota too small to read a char
}
}
return length ;
}
static int ComputeNumericalTextLength ( byte [ ] buffer , int offset , int offsetMax )
{
int beginOffset = offset ;
while ( offset < offsetMax )
{
byte ch = buffer [ offset ] ;
if ( ch = = JsonGlobals . MemberSeparatorByte | | ch = = JsonGlobals . EndObjectByte | | ch = = JsonGlobals . EndCollectionByte
| | IsWhitespace ( ch ) )
{
break ;
}
offset + + ;
}
return offset - beginOffset ;
}
static int ComputeQuotedTextLengthUntilEndQuote ( byte [ ] buffer , int offset , int offsetMax , out bool escaped )
{
// Assumes that for quoted text "someText", the first " has been consumed.
// For original text "someText", buffer passed in is someText".
// This method returns return 8 for someText" (s, o, m, e, T, e, x, t).
int beginOffset = offset ;
escaped = false ;
while ( offset < offsetMax )
{
byte ch = buffer [ offset ] ;
if ( ch < 0x20 )
{
throw DiagnosticUtility . ExceptionUtility . ThrowHelperError ( new FormatException ( SR . GetString ( SR . InvalidCharacterEncountered , ( char ) ch ) ) ) ;
}
else if ( ch = = ( byte ) '\\' | | ch = = 0xEF )
{
escaped = true ;
break ;
}
else if ( ch = = JsonGlobals . QuoteByte )
{
break ;
}
offset + + ;
}
return offset - beginOffset ;
}
// From JSON spec:
// ws = *(
// %x20 / ; Space
// %x09 / ; Horizontal tab
// %x0A / ; Line feed or New line
// %x0D ; Carriage return
// )
static bool IsWhitespace ( byte ch )
{
return ( ( ch = = 0x20 ) | | ( ch = = 0x09 ) | | ( ch = = 0x0A ) | | ( ch = = 0x0D ) ) ;
}
static char ParseChar ( string value , NumberStyles style )
{
int intValue = ParseInt ( value , style ) ;
try
{
return Convert . ToChar ( intValue ) ;
}
catch ( OverflowException exception )
{
throw DiagnosticUtility . ExceptionUtility . ThrowHelperError ( XmlExceptionHelper . CreateConversionException ( value , "char" , exception ) ) ;
}
}
static int ParseInt ( string value , NumberStyles style )
{
try
{
return int . Parse ( value , style , NumberFormatInfo . InvariantInfo ) ;
}
catch ( ArgumentException exception )
{
throw DiagnosticUtility . ExceptionUtility . ThrowHelperError ( XmlExceptionHelper . CreateConversionException ( value , "Int32" , exception ) ) ;
}
catch ( FormatException exception )
{
throw DiagnosticUtility . ExceptionUtility . ThrowHelperError ( XmlExceptionHelper . CreateConversionException ( value , "Int32" , exception ) ) ;
}
catch ( OverflowException exception )
{
throw DiagnosticUtility . ExceptionUtility . ThrowHelperError ( XmlExceptionHelper . CreateConversionException ( value , "Int32" , exception ) ) ;
}
}
void BufferElement ( )
{
int elementOffset = BufferReader . Offset ;
const int byteCount = 128 ;
bool done = false ;
byte quoteChar = 0 ;
while ( ! done )
{
int offset ;
int offsetMax ;
byte [ ] buffer = BufferReader . GetBuffer ( byteCount , out offset , out offsetMax ) ;
if ( offset + byteCount ! = offsetMax )
{
break ;
}
for ( int i = offset ; i < offsetMax & & ! done ; i + + )
{
byte b = buffer [ i ] ;
if ( b = = '\\' )
{
i + + ;
if ( i > = offsetMax )
{
break ;
}
}
else if ( quoteChar = = 0 )
{
if ( b = = ( byte ) '\'' | | b = = JsonGlobals . QuoteByte )
{
quoteChar = b ;
}
if ( b = = JsonGlobals . NameValueSeparatorByte )
{
done = true ;
}
}
else
{
if ( b = = quoteChar )
{
quoteChar = 0 ;
}
}
}
BufferReader . Advance ( byteCount ) ;
}
BufferReader . Offset = elementOffset ;
}
void EnterJsonScope ( JsonNodeType currentNodeType )
{
scopeDepth + + ;
if ( scopes = = null )
{
scopes = new JsonNodeType [ 4 ] ;
}
else if ( scopes . Length = = scopeDepth )
{
JsonNodeType [ ] newScopes = new JsonNodeType [ scopeDepth * 2 ] ;
Array . Copy ( scopes , newScopes , scopeDepth ) ;
scopes = newScopes ;
}
scopes [ scopeDepth ] = currentNodeType ;
}
JsonNodeType ExitJsonScope ( )
{
JsonNodeType nodeTypeToReturn = scopes [ scopeDepth ] ;
scopes [ scopeDepth ] = JsonNodeType . None ;
scopeDepth - - ;
return nodeTypeToReturn ;
}
new void MoveToEndElement ( )
{
ExitJsonScope ( ) ;
base . MoveToEndElement ( ) ;
}
void MoveToInitial ( XmlDictionaryReaderQuotas quotas , OnXmlDictionaryReaderClose onClose )
{
MoveToInitial ( quotas ) ;
this . maxBytesPerRead = quotas . MaxBytesPerRead ;
this . onReaderClose = onClose ;
}
void ParseAndSetLocalName ( )
{
XmlElementNode elementNode = EnterScope ( ) ;
elementNode . NameOffset = BufferReader . Offset ;
do
{
if ( BufferReader . GetByte ( ) = = '\\' )
{
ReadEscapedCharacter ( false ) ; // moveToText
}
else
{
ReadQuotedText ( false ) ; // moveToText
}
} while ( complexTextMode = = JsonComplexTextMode . QuotedText ) ;
int actualOffset = BufferReader . Offset - 1 ; // -1 to ignore " at end of local name
elementNode . LocalName . SetValue ( elementNode . NameOffset , actualOffset - elementNode . NameOffset ) ;
elementNode . NameLength = actualOffset - elementNode . NameOffset ;
elementNode . Namespace . Uri . SetValue ( elementNode . NameOffset , 0 ) ;
elementNode . Prefix . SetValue ( PrefixHandleType . Empty ) ;
elementNode . IsEmptyElement = false ;
elementNode . ExitScope = false ;
elementNode . BufferOffset = actualOffset ;
int currentCharacter = ( int ) BufferReader . GetByte ( elementNode . NameOffset ) ;
if ( ( charType [ currentCharacter ] & CharType . FirstName ) = = 0 )
{
SetJsonNameWithMapping ( elementNode ) ;
}
else
{
for ( int i = 0 , offset = elementNode . NameOffset ; i < elementNode . NameLength ; i + + , offset + + )
{
currentCharacter = ( int ) BufferReader . GetByte ( offset ) ;
if ( ( charType [ currentCharacter ] & CharType . Name ) = = 0 | | currentCharacter > = 0x80 )
{
SetJsonNameWithMapping ( elementNode ) ;
break ;
}
}
}
}
void ParseStartElement ( )
{
if ( ! buffered )
{
BufferElement ( ) ;
}
expectingFirstElementInNonPrimitiveChild = false ;
byte ch = BufferReader . GetByte ( ) ;
if ( ch = = JsonGlobals . QuoteByte )
{
BufferReader . SkipByte ( ) ;
ParseAndSetLocalName ( ) ;
SkipWhitespaceInBufferReader ( ) ;
SkipExpectedByteInBufferReader ( JsonGlobals . NameValueSeparatorByte ) ;
SkipWhitespaceInBufferReader ( ) ;
if ( BufferReader . GetByte ( ) = = JsonGlobals . ObjectByte )
{
BufferReader . SkipByte ( ) ;
expectingFirstElementInNonPrimitiveChild = true ;
}
ReadAttributes ( ) ;
}
else
{
// " and } are the only two valid characters that may follow a {
XmlExceptionHelper . ThrowTokenExpected ( this , "\"" , ( char ) ch ) ;
}
}
void ReadAttributes ( )
{
XmlAttributeNode attribute = AddAttribute ( ) ;
attribute . LocalName . SetConstantValue ( StringHandleConstStringType . Type ) ;
attribute . Namespace . Uri . SetValue ( 0 , 0 ) ;
attribute . Prefix . SetValue ( PrefixHandleType . Empty ) ;
SkipWhitespaceInBufferReader ( ) ;
byte nextByte = BufferReader . GetByte ( ) ;
switch ( nextByte )
{
case JsonGlobals . QuoteByte :
if ( ! expectingFirstElementInNonPrimitiveChild )
{
attribute . Value . SetConstantValue ( ValueHandleConstStringType . String ) ;
}
else
{
attribute . Value . SetConstantValue ( ValueHandleConstStringType . Object ) ;
ReadServerTypeAttribute ( true ) ;
}
break ;
case ( byte ) 'n' :
attribute . Value . SetConstantValue ( ValueHandleConstStringType . Null ) ;
break ;
case ( byte ) 't' :
case ( byte ) 'f' :
attribute . Value . SetConstantValue ( ValueHandleConstStringType . Boolean ) ;
break ;
case JsonGlobals . ObjectByte :
attribute . Value . SetConstantValue ( ValueHandleConstStringType . Object ) ;
ReadServerTypeAttribute ( false ) ;
break ;
case JsonGlobals . EndObjectByte :
if ( expectingFirstElementInNonPrimitiveChild )
{
attribute . Value . SetConstantValue ( ValueHandleConstStringType . Object ) ;
}
else
{
XmlExceptionHelper . ThrowXmlException ( this ,
new XmlException ( SR . GetString ( SR . JsonEncounteredUnexpectedCharacter , ( char ) nextByte ) ) ) ;
}
break ;
case JsonGlobals . CollectionByte :
attribute . Value . SetConstantValue ( ValueHandleConstStringType . Array ) ;
BufferReader . SkipByte ( ) ;
EnterJsonScope ( JsonNodeType . Collection ) ;
break ;
default :
if ( nextByte = = '-' | |
( nextByte < = '9' & & nextByte > = '0' ) | |
nextByte = = 'N' | |
nextByte = = 'I' )
{
attribute . Value . SetConstantValue ( ValueHandleConstStringType . Number ) ;
}
else
{
XmlExceptionHelper . ThrowXmlException ( this ,
new XmlException ( SR . GetString ( SR . JsonEncounteredUnexpectedCharacter , ( char ) nextByte ) ) ) ;
}
break ;
}
}
void ReadEscapedCharacter ( bool moveToText )
{
BufferReader . SkipByte ( ) ;
char ch = ( char ) BufferReader . GetByte ( ) ;
if ( ch = = 'u' )
{
BufferReader . SkipByte ( ) ;
int offset ;
byte [ ] buffer = BufferReader . GetBuffer ( 5 , out offset ) ;
string bufferAsString = Encoding . UTF8 . GetString ( buffer , offset , 4 ) ;
BufferReader . Advance ( 4 ) ;
int charValue = ParseChar ( bufferAsString , NumberStyles . HexNumber ) ;
if ( Char . IsHighSurrogate ( ( char ) charValue ) )
{
byte nextByte = BufferReader . GetByte ( ) ;
if ( nextByte = = ( byte ) '\\' )
{
BufferReader . SkipByte ( ) ;
SkipExpectedByteInBufferReader ( ( byte ) 'u' ) ;
buffer = BufferReader . GetBuffer ( 5 , out offset ) ;
bufferAsString = Encoding . UTF8 . GetString ( buffer , offset , 4 ) ;
BufferReader . Advance ( 4 ) ;
char lowChar = ParseChar ( bufferAsString , NumberStyles . HexNumber ) ;
if ( ! Char . IsLowSurrogate ( lowChar ) )
{
XmlExceptionHelper . ThrowXmlException ( this ,
new XmlException ( System . Runtime . Serialization . SR . GetString ( System . Runtime . Serialization . SR . XmlInvalidLowSurrogate , bufferAsString ) ) ) ;
}
charValue = new SurrogateChar ( lowChar , ( char ) charValue ) . Char ;
}
}
if ( buffer [ offset + 4 ] = = JsonGlobals . QuoteByte )
{
BufferReader . SkipByte ( ) ;
if ( moveToText )
{
MoveToAtomicText ( ) . Value . SetCharValue ( charValue ) ;
}
complexTextMode = JsonComplexTextMode . None ;
}
else
{
if ( moveToText )
{
MoveToComplexText ( ) . Value . SetCharValue ( charValue ) ;
}
complexTextMode = JsonComplexTextMode . QuotedText ;
}
}
else
{
switch ( ch )
{
case 'b' :
ch = '\b' ;
break ;
case 'f' :
ch = '\f' ;
break ;
case 'n' :
ch = '\n' ;
break ;
case 'r' :
ch = '\r' ;
break ;
case 't' :
ch = '\t' ;
break ;
case '\"' :
case '\\' :
case '/' :
// Do nothing. These are the actual unescaped values.
break ;
default :
XmlExceptionHelper . ThrowXmlException ( this ,
new XmlException ( SR . GetString ( SR . JsonEncounteredUnexpectedCharacter , ( char ) ch ) ) ) ;
break ;
}
BufferReader . SkipByte ( ) ;
if ( BufferReader . GetByte ( ) = = JsonGlobals . QuoteByte )
{
BufferReader . SkipByte ( ) ;
if ( moveToText )
{
MoveToAtomicText ( ) . Value . SetCharValue ( ch ) ;
}
complexTextMode = JsonComplexTextMode . None ;
}
else
{
if ( moveToText )
{
MoveToComplexText ( ) . Value . SetCharValue ( ch ) ;
}
complexTextMode = JsonComplexTextMode . QuotedText ;
}
}
}
void ReadNonExistentElementName ( StringHandleConstStringType elementName )
{
EnterJsonScope ( JsonNodeType . Object ) ;
XmlElementNode elementNode = EnterScope ( ) ;
elementNode . LocalName . SetConstantValue ( elementName ) ;
elementNode . Namespace . Uri . SetValue ( elementNode . NameOffset , 0 ) ;
elementNode . Prefix . SetValue ( PrefixHandleType . Empty ) ;
elementNode . BufferOffset = BufferReader . Offset ;
elementNode . IsEmptyElement = false ;
elementNode . ExitScope = false ;
ReadAttributes ( ) ;
}
int ReadNonFFFE ( )
{
int off ;
byte [ ] buff = BufferReader . GetBuffer ( 3 , out off ) ;
if ( buff [ off + 1 ] = = 0xBF & & ( buff [ off + 2 ] = = 0xBE | | buff [ off + 2 ] = = 0xBF ) )
{
XmlExceptionHelper . ThrowXmlException ( this , new XmlException ( SR . GetString ( SR . JsonInvalidFFFE ) ) ) ;
}
return 3 ;
}
void ReadNumericalText ( )
{
byte [ ] buffer ;
int offset ;
int offsetMax ;
int length ;
if ( buffered )
{
buffer = BufferReader . GetBuffer ( out offset , out offsetMax ) ;
length = ComputeNumericalTextLength ( buffer , offset , offsetMax ) ;
}
else
{
buffer = BufferReader . GetBuffer ( MaxTextChunk , out offset , out offsetMax ) ;
length = ComputeNumericalTextLength ( buffer , offset , offsetMax ) ;
length = BreakText ( buffer , offset , length ) ;
}
BufferReader . Advance ( length ) ;
if ( offset < = offsetMax - length )
{
MoveToAtomicText ( ) . Value . SetValue ( ValueHandleType . UTF8 , offset , length ) ;
complexTextMode = JsonComplexTextMode . None ;
}
else
{
MoveToComplexText ( ) . Value . SetValue ( ValueHandleType . UTF8 , offset , length ) ;
complexTextMode = JsonComplexTextMode . NumericalText ;
}
}
void ReadQuotedText ( bool moveToText )
{
byte [ ] buffer ;
int offset ;
int offsetMax ;
int length ;
bool escaped ;
bool endReached ;
if ( buffered )
{
buffer = BufferReader . GetBuffer ( out offset , out offsetMax ) ;
length = ComputeQuotedTextLengthUntilEndQuote ( buffer , offset , offsetMax , out escaped ) ;
endReached = offset < offsetMax - length ;
}
else
{
buffer = BufferReader . GetBuffer ( MaxTextChunk , out offset , out offsetMax ) ;
length = ComputeQuotedTextLengthUntilEndQuote ( buffer , offset , offsetMax , out escaped ) ;
endReached = offset < offsetMax - length ;
length = BreakText ( buffer , offset , length ) ;
}
if ( escaped & & BufferReader . GetByte ( ) = = 0xEF )
{
offset = BufferReader . Offset ;
length = ReadNonFFFE ( ) ;
}
BufferReader . Advance ( length ) ;
if ( ! escaped & & endReached )
{
if ( moveToText )
{
MoveToAtomicText ( ) . Value . SetValue ( ValueHandleType . UTF8 , offset , length ) ;
}
SkipExpectedByteInBufferReader ( JsonGlobals . QuoteByte ) ;
complexTextMode = JsonComplexTextMode . None ;
}
else
{
if ( ( length = = 0 ) & & escaped )
{
ReadEscapedCharacter ( moveToText ) ;
}
else
{
if ( moveToText )
{
MoveToComplexText ( ) . Value . SetValue ( ValueHandleType . UTF8 , offset , length ) ;
}
complexTextMode = JsonComplexTextMode . QuotedText ;
}
}
}
void ReadServerTypeAttribute ( bool consumedObjectChar )
{
if ( ! consumedObjectChar )
{
SkipExpectedByteInBufferReader ( JsonGlobals . ObjectByte ) ;
SkipWhitespaceInBufferReader ( ) ;
// we only allow " or } after {
byte ch = BufferReader . GetByte ( ) ;
if ( ch ! = JsonGlobals . QuoteByte & & ch ! = JsonGlobals . EndObjectByte )
{
XmlExceptionHelper . ThrowTokenExpected ( this , "\"" , ( char ) ch ) ;
}
}
else
{
SkipWhitespaceInBufferReader ( ) ;
}
int offset ;
int offsetMax ;
byte [ ] buffer = BufferReader . GetBuffer ( 8 , out offset , out offsetMax ) ;
if ( offset + 8 < = offsetMax )
{
if ( buffer [ offset + 0 ] = = ( byte ) '\"' & &
buffer [ offset + 1 ] = = ( byte ) '_' & &
buffer [ offset + 2 ] = = ( byte ) '_' & &
buffer [ offset + 3 ] = = ( byte ) 't' & &
buffer [ offset + 4 ] = = ( byte ) 'y' & &
buffer [ offset + 5 ] = = ( byte ) 'p' & &
buffer [ offset + 6 ] = = ( byte ) 'e' & &
buffer [ offset + 7 ] = = ( byte ) '\"' )
{
XmlAttributeNode attribute = AddAttribute ( ) ;
attribute . LocalName . SetValue ( offset + 1 , 6 ) ;
attribute . Namespace . Uri . SetValue ( 0 , 0 ) ;
attribute . Prefix . SetValue ( PrefixHandleType . Empty ) ;
BufferReader . Advance ( 8 ) ;
if ( ! buffered )
{
BufferElement ( ) ;
}
SkipWhitespaceInBufferReader ( ) ;
SkipExpectedByteInBufferReader ( JsonGlobals . NameValueSeparatorByte ) ;
SkipWhitespaceInBufferReader ( ) ;
SkipExpectedByteInBufferReader ( JsonGlobals . QuoteByte ) ;
buffer = BufferReader . GetBuffer ( out offset , out offsetMax ) ;
do
{
if ( BufferReader . GetByte ( ) = = '\\' )
{
ReadEscapedCharacter ( false ) ; // moveToText
}
else
{
ReadQuotedText ( false ) ; // moveToText
}
} while ( complexTextMode = = JsonComplexTextMode . QuotedText ) ;
attribute . Value . SetValue ( ValueHandleType . UTF8 , offset , BufferReader . Offset - 1 - offset ) ;
SkipWhitespaceInBufferReader ( ) ;
if ( BufferReader . GetByte ( ) = = JsonGlobals . MemberSeparatorByte )
{
BufferReader . SkipByte ( ) ;
readServerTypeElement = true ;
}
}
}
if ( BufferReader . GetByte ( ) = = JsonGlobals . EndObjectByte )
{
BufferReader . SkipByte ( ) ;
readServerTypeElement = false ;
expectingFirstElementInNonPrimitiveChild = false ;
}
else
{
readServerTypeElement = true ;
}
}
void ResetState ( )
{
complexTextMode = JsonComplexTextMode . None ;
expectingFirstElementInNonPrimitiveChild = false ;
charactersToSkipOnNextRead = new byte [ 2 ] ;
scopeDepth = 0 ;
if ( ( scopes ! = null ) & & ( scopes . Length > JsonGlobals . maxScopeSize ) )
{
scopes = null ;
}
}
void SetJsonNameWithMapping ( XmlElementNode elementNode )
{
Namespace ns = AddNamespace ( ) ;
ns . Prefix . SetValue ( PrefixHandleType . A ) ;
ns . Uri . SetConstantValue ( StringHandleConstStringType . Item ) ;
AddXmlnsAttribute ( ns ) ;
XmlAttributeNode attribute = AddAttribute ( ) ;
attribute . LocalName . SetConstantValue ( StringHandleConstStringType . Item ) ;
attribute . Namespace . Uri . SetValue ( 0 , 0 ) ;
attribute . Prefix . SetValue ( PrefixHandleType . Empty ) ;
attribute . Value . SetValue ( ValueHandleType . UTF8 , elementNode . NameOffset , elementNode . NameLength ) ;
elementNode . NameLength = 0 ;
elementNode . Prefix . SetValue ( PrefixHandleType . A ) ;
elementNode . LocalName . SetConstantValue ( StringHandleConstStringType . Item ) ;
elementNode . Namespace = ns ;
}
void SkipExpectedByteInBufferReader ( byte characterToSkip )
{
if ( BufferReader . GetByte ( ) ! = characterToSkip )
{
XmlExceptionHelper . ThrowTokenExpected ( this , ( ( char ) characterToSkip ) . ToString ( ) , ( char ) BufferReader . GetByte ( ) ) ;
}
BufferReader . SkipByte ( ) ;
}
void SkipWhitespaceInBufferReader ( )
{
byte ch ;
while ( TryGetByte ( out ch ) & & IsWhitespace ( ch ) )
{
BufferReader . SkipByte ( ) ;
}
}
bool TryGetByte ( out byte ch )
{
int offset , offsetMax ;
byte [ ] buffer = BufferReader . GetBuffer ( 1 , out offset , out offsetMax ) ;
if ( offset < offsetMax )
{
ch = buffer [ offset ] ;
return true ;
}
else
{
ch = ( byte ) '\0' ;
return false ;
}
}
string UnescapeJsonString ( string val )
{
if ( val = = null )
{
return null ;
}
StringBuilder sb = null ;
int startIndex = 0 , count = 0 ;
for ( int i = 0 ; i < val . Length ; i + + )
{
if ( val [ i ] = = '\\' )
{
i + + ;
if ( sb = = null )
{
sb = new StringBuilder ( ) ;
}
sb . Append ( val , startIndex , count ) ;
Fx . Assert ( i < val . Length , "Found that an '\' was the last character in a string. ReadServerTypeAttriute validates that the escape sequence is valid when it calls ReadQuotedText and ReadEscapedCharacter" ) ;
if ( i > = val . Length )
{
XmlExceptionHelper . ThrowXmlException ( this , new XmlException ( SR . GetString ( SR . JsonEncounteredUnexpectedCharacter , val [ i ] ) ) ) ;
}
switch ( val [ i ] )
{
case '"' :
case '\'' :
case '/' :
case '\\' :
sb . Append ( val [ i ] ) ;
break ;
case 'b' :
sb . Append ( '\b' ) ;
break ;
case 'f' :
sb . Append ( '\f' ) ;
break ;
case 'n' :
sb . Append ( '\n' ) ;
break ;
case 'r' :
sb . Append ( '\r' ) ;
break ;
case 't' :
sb . Append ( '\t' ) ;
break ;
case 'u' :
if ( ( i + 3 ) > = val . Length )
{
XmlExceptionHelper . ThrowXmlException ( this ,
new XmlException ( SR . GetString ( SR . JsonEncounteredUnexpectedCharacter , val [ i ] ) ) ) ;
}
sb . Append ( ParseChar ( val . Substring ( i + 1 , 4 ) , NumberStyles . HexNumber ) ) ;
i + = 4 ;
break ;
}
startIndex = i + 1 ;
count = 0 ;
}
else
{
count + + ;
}
}
if ( sb = = null )
{
return val ;
}
if ( count > 0 )
{
sb . Append ( val , startIndex , count ) ;
}
return sb . ToString ( ) ;
}
static class CharType
{
public const byte FirstName = 0x01 ;
public const byte Name = 0x02 ;
public const byte None = 0x00 ;
}
}
}