1 //------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //------------------------------------------------------------
4 
5 namespace System.Runtime.Serialization.Json
6 {
7     using System.Globalization;
8     using System.IO;
9 #if !MONO
10     using System.ServiceModel;
11 #endif
12     using System.Text;
13     using System.Runtime.Serialization;
14     using System.Collections.Generic;
15     using System.Xml;
16 
17     class XmlJsonReader : XmlBaseReader, IXmlJsonReaderInitializer
18     {
19         const int MaxTextChunk = 2048;
20 
21         static byte[] charType = new byte[256]
22             {
23                 CharType.None, //   0 (.)
24                 CharType.None, //   1 (.)
25                 CharType.None, //   2 (.)
26                 CharType.None, //   3 (.)
27                 CharType.None, //   4 (.)
28                 CharType.None, //   5 (.)
29                 CharType.None, //   6 (.)
30                 CharType.None, //   7 (.)
31                 CharType.None, //   8 (.)
32                 CharType.None, //   9 (.)
33                 CharType.None, //   A (.)
34                 CharType.None, //   B (.)
35                 CharType.None, //   C (.)
36                 CharType.None, //   D (.)
37                 CharType.None, //   E (.)
38                 CharType.None, //   F (.)
39                 CharType.None, //  10 (.)
40                 CharType.None, //  11 (.)
41                 CharType.None, //  12 (.)
42                 CharType.None, //  13 (.)
43                 CharType.None, //  14 (.)
44                 CharType.None, //  15 (.)
45                 CharType.None, //  16 (.)
46                 CharType.None, //  17 (.)
47                 CharType.None, //  18 (.)
48                 CharType.None, //  19 (.)
49                 CharType.None, //  1A (.)
50                 CharType.None, //  1B (.)
51                 CharType.None, //  1C (.)
52                 CharType.None, //  1D (.)
53                 CharType.None, //  1E (.)
54                 CharType.None, //  1F (.)
55                 CharType.None, //  20 ( )
56                 CharType.None, //  21 (!)
57                 CharType.None, //  22 (")
58                 CharType.None, //  23 (#)
59                 CharType.None, //  24 ($)
60                 CharType.None, //  25 (%)
61                 CharType.None, //  26 (&)
62                 CharType.None, //  27 (')
63                 CharType.None, //  28 (()
64                 CharType.None, //  29 ())
65                 CharType.None, //  2A (*)
66                 CharType.None, //  2B (+)
67                 CharType.None, //  2C (,)
68                 CharType.None | CharType.Name, //  2D (-)
69                 CharType.None | CharType.Name, //  2E (.)
70                 CharType.None, //  2F (/)
71                 CharType.None | CharType.Name, //  30 (0)
72                 CharType.None | CharType.Name, //  31 (1)
73                 CharType.None | CharType.Name, //  32 (2)
74                 CharType.None | CharType.Name, //  33 (3)
75                 CharType.None | CharType.Name, //  34 (4)
76                 CharType.None | CharType.Name, //  35 (5)
77                 CharType.None | CharType.Name, //  36 (6)
78                 CharType.None | CharType.Name, //  37 (7)
79                 CharType.None | CharType.Name, //  38 (8)
80                 CharType.None | CharType.Name, //  39 (9)
81                 CharType.None, //  3A (:)
82                 CharType.None, //  3B (;)
83                 CharType.None, //  3C (<)
84                 CharType.None, //  3D (=)
85                 CharType.None, //  3E (>)
86                 CharType.None, //  3F (?)
87                 CharType.None, //  40 (@)
88                 CharType.None | CharType.FirstName | CharType.Name, //  41 (A)
89                 CharType.None | CharType.FirstName | CharType.Name, //  42 (B)
90                 CharType.None | CharType.FirstName | CharType.Name, //  43 (C)
91                 CharType.None | CharType.FirstName | CharType.Name, //  44 (D)
92                 CharType.None | CharType.FirstName | CharType.Name, //  45 (E)
93                 CharType.None | CharType.FirstName | CharType.Name, //  46 (F)
94                 CharType.None | CharType.FirstName | CharType.Name, //  47 (G)
95                 CharType.None | CharType.FirstName | CharType.Name, //  48 (H)
96                 CharType.None | CharType.FirstName | CharType.Name, //  49 (I)
97                 CharType.None | CharType.FirstName | CharType.Name, //  4A (J)
98                 CharType.None | CharType.FirstName | CharType.Name, //  4B (K)
99                 CharType.None | CharType.FirstName | CharType.Name, //  4C (L)
100                 CharType.None | CharType.FirstName | CharType.Name, //  4D (M)
101                 CharType.None | CharType.FirstName | CharType.Name, //  4E (N)
102                 CharType.None | CharType.FirstName | CharType.Name, //  4F (O)
103                 CharType.None | CharType.FirstName | CharType.Name, //  50 (P)
104                 CharType.None | CharType.FirstName | CharType.Name, //  51 (Q)
105                 CharType.None | CharType.FirstName | CharType.Name, //  52 (R)
106                 CharType.None | CharType.FirstName | CharType.Name, //  53 (S)
107                 CharType.None | CharType.FirstName | CharType.Name, //  54 (T)
108                 CharType.None | CharType.FirstName | CharType.Name, //  55 (U)
109                 CharType.None | CharType.FirstName | CharType.Name, //  56 (V)
110                 CharType.None | CharType.FirstName | CharType.Name, //  57 (W)
111                 CharType.None | CharType.FirstName | CharType.Name, //  58 (X)
112                 CharType.None | CharType.FirstName | CharType.Name, //  59 (Y)
113                 CharType.None | CharType.FirstName | CharType.Name, //  5A (Z)
114                 CharType.None, //  5B ([)
115                 CharType.None, //  5C (\)
116                 CharType.None, //  5D (])
117                 CharType.None, //  5E (^)
118                 CharType.None | CharType.FirstName | CharType.Name, //  5F (_)
119                 CharType.None, //  60 (`)
120                 CharType.None | CharType.FirstName | CharType.Name, //  61 (a)
121                 CharType.None | CharType.FirstName | CharType.Name, //  62 (b)
122                 CharType.None | CharType.FirstName | CharType.Name, //  63 (c)
123                 CharType.None | CharType.FirstName | CharType.Name, //  64 (d)
124                 CharType.None | CharType.FirstName | CharType.Name, //  65 (e)
125                 CharType.None | CharType.FirstName | CharType.Name, //  66 (f)
126                 CharType.None | CharType.FirstName | CharType.Name, //  67 (g)
127                 CharType.None | CharType.FirstName | CharType.Name, //  68 (h)
128                 CharType.None | CharType.FirstName | CharType.Name, //  69 (i)
129                 CharType.None | CharType.FirstName | CharType.Name, //  6A (j)
130                 CharType.None | CharType.FirstName | CharType.Name, //  6B (k)
131                 CharType.None | CharType.FirstName | CharType.Name, //  6C (l)
132                 CharType.None | CharType.FirstName | CharType.Name, //  6D (m)
133                 CharType.None | CharType.FirstName | CharType.Name, //  6E (n)
134                 CharType.None | CharType.FirstName | CharType.Name, //  6F (o)
135                 CharType.None | CharType.FirstName | CharType.Name, //  70 (p)
136                 CharType.None | CharType.FirstName | CharType.Name, //  71 (q)
137                 CharType.None | CharType.FirstName | CharType.Name, //  72 (r)
138                 CharType.None | CharType.FirstName | CharType.Name, //  73 (s)
139                 CharType.None | CharType.FirstName | CharType.Name, //  74 (t)
140                 CharType.None | CharType.FirstName | CharType.Name, //  75 (u)
141                 CharType.None | CharType.FirstName | CharType.Name, //  76 (v)
142                 CharType.None | CharType.FirstName | CharType.Name, //  77 (w)
143                 CharType.None | CharType.FirstName | CharType.Name, //  78 (x)
144                 CharType.None | CharType.FirstName | CharType.Name, //  79 (y)
145                 CharType.None | CharType.FirstName | CharType.Name, //  7A (z)
146                 CharType.None, //  7B ({)
147                 CharType.None, //  7C (|)
148                 CharType.None, //  7D (})
149                 CharType.None, //  7E (~)
150                 CharType.None, //  7F (.)
151                 CharType.None | CharType.FirstName | CharType.Name, //  80 (.)
152                 CharType.None | CharType.FirstName | CharType.Name, //  81 (.)
153                 CharType.None | CharType.FirstName | CharType.Name, //  82 (.)
154                 CharType.None | CharType.FirstName | CharType.Name, //  83 (.)
155                 CharType.None | CharType.FirstName | CharType.Name, //  84 (.)
156                 CharType.None | CharType.FirstName | CharType.Name, //  85 (.)
157                 CharType.None | CharType.FirstName | CharType.Name, //  86 (.)
158                 CharType.None | CharType.FirstName | CharType.Name, //  87 (.)
159                 CharType.None | CharType.FirstName | CharType.Name, //  88 (.)
160                 CharType.None | CharType.FirstName | CharType.Name, //  89 (.)
161                 CharType.None | CharType.FirstName | CharType.Name, //  8A (.)
162                 CharType.None | CharType.FirstName | CharType.Name, //  8B (.)
163                 CharType.None | CharType.FirstName | CharType.Name, //  8C (.)
164                 CharType.None | CharType.FirstName | CharType.Name, //  8D (.)
165                 CharType.None | CharType.FirstName | CharType.Name, //  8E (.)
166                 CharType.None | CharType.FirstName | CharType.Name, //  8F (.)
167                 CharType.None | CharType.FirstName | CharType.Name, //  90 (.)
168                 CharType.None | CharType.FirstName | CharType.Name, //  91 (.)
169                 CharType.None | CharType.FirstName | CharType.Name, //  92 (.)
170                 CharType.None | CharType.FirstName | CharType.Name, //  93 (.)
171                 CharType.None | CharType.FirstName | CharType.Name, //  94 (.)
172                 CharType.None | CharType.FirstName | CharType.Name, //  95 (.)
173                 CharType.None | CharType.FirstName | CharType.Name, //  96 (.)
174                 CharType.None | CharType.FirstName | CharType.Name, //  97 (.)
175                 CharType.None | CharType.FirstName | CharType.Name, //  98 (.)
176                 CharType.None | CharType.FirstName | CharType.Name, //  99 (.)
177                 CharType.None | CharType.FirstName | CharType.Name, //  9A (.)
178                 CharType.None | CharType.FirstName | CharType.Name, //  9B (.)
179                 CharType.None | CharType.FirstName | CharType.Name, //  9C (.)
180                 CharType.None | CharType.FirstName | CharType.Name, //  9D (.)
181                 CharType.None | CharType.FirstName | CharType.Name, //  9E (.)
182                 CharType.None | CharType.FirstName | CharType.Name, //  9F (.)
183                 CharType.None | CharType.FirstName | CharType.Name, //  A0 (�)
184                 CharType.None | CharType.FirstName | CharType.Name, //  A1 (�)
185                 CharType.None | CharType.FirstName | CharType.Name, //  A2 (�)
186                 CharType.None | CharType.FirstName | CharType.Name, //  A3 (�)
187                 CharType.None | CharType.FirstName | CharType.Name, //  A4 ()
188                 CharType.None | CharType.FirstName | CharType.Name, //  A5 (�)
189                 CharType.None | CharType.FirstName | CharType.Name, //  A6 (�)
190                 CharType.None | CharType.FirstName | CharType.Name, //  A7 ()
191                 CharType.None | CharType.FirstName | CharType.Name, //  A8 (")
192                 CharType.None | CharType.FirstName | CharType.Name, //  A9 (c)
193                 CharType.None | CharType.FirstName | CharType.Name, //  AA (�)
194                 CharType.None | CharType.FirstName | CharType.Name, //  AB (�)
195                 CharType.None | CharType.FirstName | CharType.Name, //  AC (�)
196                 CharType.None | CharType.FirstName | CharType.Name, //  AD (-)
197                 CharType.None | CharType.FirstName | CharType.Name, //  AE (r)
198                 CharType.None | CharType.FirstName | CharType.Name, //  AF (_)
199                 CharType.None | CharType.FirstName | CharType.Name, //  B0 (�)
200                 CharType.None | CharType.FirstName | CharType.Name, //  B1 (�)
201                 CharType.None | CharType.FirstName | CharType.Name, //  B2 (�)
202                 CharType.None | CharType.FirstName | CharType.Name, //  B3 (3)
203                 CharType.None | CharType.FirstName | CharType.Name, //  B4 (')
204                 CharType.None | CharType.FirstName | CharType.Name, //  B5 (�)
205                 CharType.None | CharType.FirstName | CharType.Name, //  B6 ()
206                 CharType.None | CharType.FirstName | CharType.Name, //  B7 (�)
207                 CharType.None | CharType.FirstName | CharType.Name, //  B8 (,)
208                 CharType.None | CharType.FirstName | CharType.Name, //  B9 (1)
209                 CharType.None | CharType.FirstName | CharType.Name, //  BA (�)
210                 CharType.None | CharType.FirstName | CharType.Name, //  BB (�)
211                 CharType.None | CharType.FirstName | CharType.Name, //  BC (�)
212                 CharType.None | CharType.FirstName | CharType.Name, //  BD (�)
213                 CharType.None | CharType.FirstName | CharType.Name, //  BE (_)
214                 CharType.None | CharType.FirstName | CharType.Name, //  BF (�)
215                 CharType.None | CharType.FirstName | CharType.Name, //  C0 (A)
216                 CharType.None | CharType.FirstName | CharType.Name, //  C1 (A)
217                 CharType.None | CharType.FirstName | CharType.Name, //  C2 (A)
218                 CharType.None | CharType.FirstName | CharType.Name, //  C3 (A)
219                 CharType.None | CharType.FirstName | CharType.Name, //  C4 (�)
220                 CharType.None | CharType.FirstName | CharType.Name, //  C5 (�)
221                 CharType.None | CharType.FirstName | CharType.Name, //  C6 (�)
222                 CharType.None | CharType.FirstName | CharType.Name, //  C7 (�)
223                 CharType.None | CharType.FirstName | CharType.Name, //  C8 (E)
224                 CharType.None | CharType.FirstName | CharType.Name, //  C9 (�)
225                 CharType.None | CharType.FirstName | CharType.Name, //  CA (E)
226                 CharType.None | CharType.FirstName | CharType.Name, //  CB (E)
227                 CharType.None | CharType.FirstName | CharType.Name, //  CC (I)
228                 CharType.None | CharType.FirstName | CharType.Name, //  CD (I)
229                 CharType.None | CharType.FirstName | CharType.Name, //  CE (I)
230                 CharType.None | CharType.FirstName | CharType.Name, //  CF (I)
231                 CharType.None | CharType.FirstName | CharType.Name, //  D0 (D)
232                 CharType.None | CharType.FirstName | CharType.Name, //  D1 (�)
233                 CharType.None | CharType.FirstName | CharType.Name, //  D2 (O)
234                 CharType.None | CharType.FirstName | CharType.Name, //  D3 (O)
235                 CharType.None | CharType.FirstName | CharType.Name, //  D4 (O)
236                 CharType.None | CharType.FirstName | CharType.Name, //  D5 (O)
237                 CharType.None | CharType.FirstName | CharType.Name, //  D6 (�)
238                 CharType.None | CharType.FirstName | CharType.Name, //  D7 (x)
239                 CharType.None | CharType.FirstName | CharType.Name, //  D8 (O)
240                 CharType.None | CharType.FirstName | CharType.Name, //  D9 (U)
241                 CharType.None | CharType.FirstName | CharType.Name, //  DA (U)
242                 CharType.None | CharType.FirstName | CharType.Name, //  DB (U)
243                 CharType.None | CharType.FirstName | CharType.Name, //  DC (�)
244                 CharType.None | CharType.FirstName | CharType.Name, //  DD (Y)
245                 CharType.None | CharType.FirstName | CharType.Name, //  DE (_)
246                 CharType.None | CharType.FirstName | CharType.Name, //  DF (�)
247                 CharType.None | CharType.FirstName | CharType.Name, //  E0 (�)
248                 CharType.None | CharType.FirstName | CharType.Name, //  E1 (�)
249                 CharType.None | CharType.FirstName | CharType.Name, //  E2 (�)
250                 CharType.None | CharType.FirstName | CharType.Name, //  E3 (a)
251                 CharType.None | CharType.FirstName | CharType.Name, //  E4 (�)
252                 CharType.None | CharType.FirstName | CharType.Name, //  E5 (�)
253                 CharType.None | CharType.FirstName | CharType.Name, //  E6 (�)
254                 CharType.None | CharType.FirstName | CharType.Name, //  E7 (�)
255                 CharType.None | CharType.FirstName | CharType.Name, //  E8 (�)
256                 CharType.None | CharType.FirstName | CharType.Name, //  E9 (�)
257                 CharType.None | CharType.FirstName | CharType.Name, //  EA (�)
258                 CharType.None | CharType.FirstName | CharType.Name, //  EB (�)
259                 CharType.None | CharType.FirstName | CharType.Name, //  EC (�)
260                 CharType.None | CharType.FirstName | CharType.Name, //  ED (�)
261                 CharType.None | CharType.FirstName | CharType.Name, //  EE (�)
262                 CharType.None | CharType.FirstName | CharType.Name, //  EF (�)
263                 CharType.None | CharType.FirstName | CharType.Name, //  F0 (d)
264                 CharType.None | CharType.FirstName | CharType.Name, //  F1 (�)
265                 CharType.None | CharType.FirstName | CharType.Name, //  F2 (�)
266                 CharType.None | CharType.FirstName | CharType.Name, //  F3 (�)
267                 CharType.None | CharType.FirstName | CharType.Name, //  F4 (�)
268                 CharType.None | CharType.FirstName | CharType.Name, //  F5 (o)
269                 CharType.None | CharType.FirstName | CharType.Name, //  F6 (�)
270                 CharType.None | CharType.FirstName | CharType.Name, //  F7 (�)
271                 CharType.None | CharType.FirstName | CharType.Name, //  F8 (o)
272                 CharType.None | CharType.FirstName | CharType.Name, //  F9 (�)
273                 CharType.None | CharType.FirstName | CharType.Name, //  FA (�)
274                 CharType.None | CharType.FirstName | CharType.Name, //  FB (�)
275                 CharType.None | CharType.FirstName | CharType.Name, //  FC (�)
276                 CharType.None | CharType.FirstName | CharType.Name, //  FD (y)
277                 CharType.None | CharType.FirstName | CharType.Name, //  FE (_)
278                 CharType.None | CharType.FirstName | CharType.Name, //  FF (�)
279             };
280         bool buffered;
281         byte[] charactersToSkipOnNextRead;
282         JsonComplexTextMode complexTextMode = JsonComplexTextMode.None;
283         bool expectingFirstElementInNonPrimitiveChild;
284         int maxBytesPerRead;
285         OnXmlDictionaryReaderClose onReaderClose;
286         bool readServerTypeElement = false;
287         int scopeDepth = 0;
288         JsonNodeType[] scopes;
289 
290         enum JsonComplexTextMode
291         {
292             QuotedText,
293             NumericalText,
294             None
295         };
296 
297         public override bool CanCanonicalize
298         {
299             get
300             {
301                 return false;
302             }
303         }
304 
305         public override string Value
306         {
307             get
308             {
309                 if (IsAttributeValue && !this.IsLocalName(JsonGlobals.typeString))
310                 {
311                     return UnescapeJsonString(base.Value);
312                 }
313                 return base.Value;
314             }
315         }
316 
317         bool IsAttributeValue
318         {
319             get
320             {
321                 return (this.Node.NodeType == XmlNodeType.Attribute || this.Node is XmlAttributeTextNode);
322             }
323         }
324 
325         bool IsReadingCollection
326         {
327             get
328             {
329                 return ((scopeDepth > 0) && (scopes[scopeDepth] == JsonNodeType.Collection));
330             }
331         }
332 
333         bool IsReadingComplexText
334         {
335             get
336             {
337                 return ((!this.Node.IsAtomicValue) &&
338                     (this.Node.NodeType == XmlNodeType.Text));
339 
340             }
341         }
342 
Close()343         public override void Close()
344         {
345             base.Close();
346             OnXmlDictionaryReaderClose onClose = this.onReaderClose;
347             this.onReaderClose = null;
348             ResetState();
349             if (onClose != null)
350             {
351                 try
352                 {
353                     onClose(this);
354                 }
355                 catch (Exception e)
356                 {
357                     if (Fx.IsFatal(e))
358                     {
359                         throw;
360                     }
361 
362                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperCallback(e);
363                 }
364             }
365         }
366 
EndCanonicalization()367         public override void EndCanonicalization()
368         {
369             throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
370         }
371 
GetAttribute(int index)372         public override string GetAttribute(int index)
373         {
374             return UnescapeJsonString(base.GetAttribute(index));
375         }
376 
GetAttribute(string localName, string namespaceUri)377         public override string GetAttribute(string localName, string namespaceUri)
378         {
379             if (localName != JsonGlobals.typeString)
380             {
381                 return UnescapeJsonString(base.GetAttribute(localName, namespaceUri));
382             }
383             return base.GetAttribute(localName, namespaceUri);
384         }
GetAttribute(string name)385         public override string GetAttribute(string name)
386         {
387             if (name != JsonGlobals.typeString)
388             {
389                 return UnescapeJsonString(base.GetAttribute(name));
390             }
391             return base.GetAttribute(name);
392         }
393 
GetAttribute(XmlDictionaryString localName, XmlDictionaryString namespaceUri)394         public override string GetAttribute(XmlDictionaryString localName, XmlDictionaryString namespaceUri)
395         {
396             if (XmlDictionaryString.GetString(localName) != JsonGlobals.typeString)
397             {
398                 return UnescapeJsonString(base.GetAttribute(localName, namespaceUri));
399             }
400             return base.GetAttribute(localName, namespaceUri);
401         }
402 
Read()403         public override bool Read()
404         {
405             if (this.Node.CanMoveToElement)
406             {
407                 // If we're positioned on an attribute or attribute text on an empty element, we need to move back
408                 // to the element in order to get the correct setting of ExitScope
409                 MoveToElement();
410             }
411 
412             if (this.Node.ReadState == ReadState.Closed)
413             {
414                 return false;
415             }
416             if (this.Node.ExitScope)
417             {
418                 ExitScope();
419             }
420             if (!buffered)
421             {
422                 BufferReader.SetWindow(ElementNode.BufferOffset, this.maxBytesPerRead);
423             }
424 
425             byte ch;
426 
427             // Skip whitespace before checking EOF
428             // Complex text check necessary because whitespace could be part of really long
429             //    quoted text that's read using multiple Read() calls.
430             // This also ensures that we deal with the whitespace-only input case properly by not
431             //    floating a root element at all.
432             if (!IsReadingComplexText)
433             {
434                 SkipWhitespaceInBufferReader();
435 
436                 if (TryGetByte(out ch))
437                 {
438                     if (charactersToSkipOnNextRead[0] == ch || charactersToSkipOnNextRead[1] == ch)
439                     {
440                         BufferReader.SkipByte();
441                         charactersToSkipOnNextRead[0] = 0;
442                         charactersToSkipOnNextRead[1] = 0;
443                     }
444                 }
445 
446                 SkipWhitespaceInBufferReader();
447 
448                 if (TryGetByte(out ch))
449                 {
450                     if (ch == JsonGlobals.EndCollectionByte && IsReadingCollection)
451                     {
452                         BufferReader.SkipByte();
453                         SkipWhitespaceInBufferReader();
454                         ExitJsonScope();
455                     }
456                 }
457 
458                 if (BufferReader.EndOfFile)
459                 {
460                     if (scopeDepth > 0)
461                     {
462                         MoveToEndElement();
463                         return true;
464                     }
465                     else
466                     {
467                         MoveToEndOfFile();
468                         return false;
469                     }
470                 }
471             }
472 
473             ch = BufferReader.GetByte();
474 
475             if (scopeDepth == 0)
476             {
477                 ReadNonExistentElementName(StringHandleConstStringType.Root);
478             }
479             else if (IsReadingComplexText)
480             {
481                 switch (complexTextMode)
482                 {
483                     case JsonComplexTextMode.NumericalText:
484                         ReadNumericalText();
485                         break;
486                     case JsonComplexTextMode.QuotedText:
487                         if (ch == (byte)'\\')
488                         {
489                             ReadEscapedCharacter(true); //  moveToText
490                         }
491                         else
492                         {
493                             ReadQuotedText(true); //  moveToText
494                         }
495                         break;
496                     case JsonComplexTextMode.None:
497                         XmlExceptionHelper.ThrowXmlException(this,
498                             new XmlException(SR.GetString(SR.JsonEncounteredUnexpectedCharacter, (char)ch)));
499                         break;
500                 }
501             }
502             else if (IsReadingCollection)
503             {
504                 ReadNonExistentElementName(StringHandleConstStringType.Item);
505             }
506             else if (ch == JsonGlobals.EndCollectionByte)
507             {
508                 BufferReader.SkipByte();
509                 MoveToEndElement();
510                 ExitJsonScope();
511             }
512             else if (ch == JsonGlobals.ObjectByte)
513             {
514                 BufferReader.SkipByte();
515                 SkipWhitespaceInBufferReader();
516                 ch = (byte)BufferReader.GetByte();
517                 if (ch == JsonGlobals.EndObjectByte)
518                 {
519                     BufferReader.SkipByte();
520                     SkipWhitespaceInBufferReader();
521                     if (TryGetByte(out ch))
522                     {
523                         if (ch == JsonGlobals.MemberSeparatorByte)
524                         {
525                             BufferReader.SkipByte();
526                         }
527                     }
528                     else
529                     {
530                         charactersToSkipOnNextRead[0] = JsonGlobals.MemberSeparatorByte;
531                     }
532                     MoveToEndElement();
533                 }
534                 else
535                 {
536                     EnterJsonScope(JsonNodeType.Object);
537                     ParseStartElement();
538                 }
539             }
540             else if (ch == JsonGlobals.EndObjectByte)
541             {
542                 BufferReader.SkipByte();
543                 if (expectingFirstElementInNonPrimitiveChild)
544                 {
545                     SkipWhitespaceInBufferReader();
546                     ch = BufferReader.GetByte();
547                     if ((ch == JsonGlobals.MemberSeparatorByte) ||
548                         (ch == JsonGlobals.EndObjectByte))
549                     {
550                         BufferReader.SkipByte();
551                     }
552                     else
553                     {
554                         XmlExceptionHelper.ThrowXmlException(this,
555                             new XmlException(SR.GetString(SR.JsonEncounteredUnexpectedCharacter,
556                             (char)ch)));
557                     }
558                     expectingFirstElementInNonPrimitiveChild = false;
559                 }
560                 MoveToEndElement();
561             }
562             else if (ch == JsonGlobals.MemberSeparatorByte)
563             {
564                 BufferReader.SkipByte();
565                 MoveToEndElement();
566             }
567             else if (ch == JsonGlobals.QuoteByte)
568             {
569                 if (readServerTypeElement)
570                 {
571                     readServerTypeElement = false;
572                     EnterJsonScope(JsonNodeType.Object);
573                     ParseStartElement();
574                 }
575                 else if (this.Node.NodeType == XmlNodeType.Element)
576                 {
577                     if (expectingFirstElementInNonPrimitiveChild)
578                     {
579                         EnterJsonScope(JsonNodeType.Object);
580                         ParseStartElement();
581                     }
582                     else
583                     {
584                         BufferReader.SkipByte();
585                         ReadQuotedText(true); //  moveToText
586                     }
587                 }
588                 else if (this.Node.NodeType == XmlNodeType.EndElement)
589                 {
590                     EnterJsonScope(JsonNodeType.Element);
591                     ParseStartElement();
592                 }
593                 else
594                 {
595                     XmlExceptionHelper.ThrowXmlException(this,
596                         new XmlException(SR.GetString(SR.JsonEncounteredUnexpectedCharacter,
597                         JsonGlobals.QuoteChar)));
598                 }
599             }
600             else if (ch == (byte)'f')
601             {
602                 int offset;
603                 byte[] buffer = BufferReader.GetBuffer(5, out offset);
604                 if (buffer[offset + 1] != (byte)'a' ||
605                     buffer[offset + 2] != (byte)'l' ||
606                     buffer[offset + 3] != (byte)'s' ||
607                     buffer[offset + 4] != (byte)'e')
608                 {
609                     XmlExceptionHelper.ThrowTokenExpected(this, "false", Encoding.UTF8.GetString(buffer, offset, 5));
610                 }
611                 BufferReader.Advance(5);
612 
613                 if (TryGetByte(out ch))
614                 {
615                     if (!IsWhitespace(ch) && ch != JsonGlobals.MemberSeparatorByte && ch != JsonGlobals.EndObjectChar && ch != JsonGlobals.EndCollectionByte)
616                     {
617                         XmlExceptionHelper.ThrowTokenExpected(this, "false", Encoding.UTF8.GetString(buffer, offset, 4) + (char)ch);
618                     }
619                 }
620                 MoveToAtomicText().Value.SetValue(ValueHandleType.UTF8, offset, 5);
621             }
622             else if (ch == (byte)'t')
623             {
624                 int offset;
625                 byte[] buffer = BufferReader.GetBuffer(4, out offset);
626                 if (buffer[offset + 1] != (byte)'r' ||
627                     buffer[offset + 2] != (byte)'u' ||
628                     buffer[offset + 3] != (byte)'e')
629                 {
630                     XmlExceptionHelper.ThrowTokenExpected(this, "true", Encoding.UTF8.GetString(buffer, offset, 4));
631                 }
632                 BufferReader.Advance(4);
633 
634                 if (TryGetByte(out ch))
635                 {
636                     if (!IsWhitespace(ch) && ch != JsonGlobals.MemberSeparatorByte && ch != JsonGlobals.EndObjectChar && ch != JsonGlobals.EndCollectionByte)
637                     {
638                         XmlExceptionHelper.ThrowTokenExpected(this, "true", Encoding.UTF8.GetString(buffer, offset, 4) + (char)ch);
639                     }
640                 }
641                 MoveToAtomicText().Value.SetValue(ValueHandleType.UTF8, offset, 4);
642             }
643             else if (ch == (byte)'n')
644             {
645                 int offset;
646                 byte[] buffer = BufferReader.GetBuffer(4, out offset);
647                 if (buffer[offset + 1] != (byte)'u' ||
648                     buffer[offset + 2] != (byte)'l' ||
649                     buffer[offset + 3] != (byte)'l')
650                 {
651                     XmlExceptionHelper.ThrowTokenExpected(this, "null", Encoding.UTF8.GetString(buffer, offset, 4));
652                 }
653                 BufferReader.Advance(4);
654                 SkipWhitespaceInBufferReader();
655 
656                 if (TryGetByte(out ch))
657                 {
658                     if (ch == JsonGlobals.MemberSeparatorByte || ch == JsonGlobals.EndObjectChar)
659                     {
660                         BufferReader.SkipByte();
661                     }
662                     else if (ch != JsonGlobals.EndCollectionByte)
663                     {
664                         XmlExceptionHelper.ThrowTokenExpected(this, "null", Encoding.UTF8.GetString(buffer, offset, 4) + (char)ch);
665                     }
666                 }
667                 else
668                 {
669                     charactersToSkipOnNextRead[0] = JsonGlobals.MemberSeparatorByte;
670                     charactersToSkipOnNextRead[1] = JsonGlobals.EndObjectByte;
671                 }
672                 MoveToEndElement();
673             }
674             else if ((ch == (byte)'-') ||
675                 (((byte)'0' <= ch) && (ch <= (byte)'9')) ||
676                 (ch == (byte)'I') ||
677                 (ch == (byte)'N'))
678             {
679                 ReadNumericalText();
680             }
681             else
682             {
683                 XmlExceptionHelper.ThrowXmlException(this,
684                     new XmlException(SR.GetString(SR.JsonEncounteredUnexpectedCharacter, (char)ch)));
685             }
686 
687             return true;
688         }
689 
ReadContentAsDecimal()690         public override decimal ReadContentAsDecimal()
691         {
692             string value = ReadContentAsString();
693             try
694             {
695                 return decimal.Parse(value, NumberStyles.Float, NumberFormatInfo.InvariantInfo);
696             }
697             catch (ArgumentException exception)
698             {
699                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "decimal", exception));
700             }
701             catch (FormatException exception)
702             {
703                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "decimal", exception));
704             }
705             catch (OverflowException exception)
706             {
707                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "decimal", exception));
708             }
709         }
710 
ReadContentAsInt()711         public override int ReadContentAsInt()
712         {
713             return ParseInt(ReadContentAsString(), NumberStyles.Float);
714         }
715 
ReadContentAsLong()716         public override long ReadContentAsLong()
717         {
718             string value = ReadContentAsString();
719             try
720             {
721                 return long.Parse(value, NumberStyles.Float, NumberFormatInfo.InvariantInfo);
722             }
723             catch (ArgumentException exception)
724             {
725                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "Int64", exception));
726             }
727             catch (FormatException exception)
728             {
729                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "Int64", exception));
730             }
731             catch (OverflowException exception)
732             {
733                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "Int64", exception));
734             }
735         }
736 
ReadValueAsBase64(byte[] buffer, int offset, int count)737         public override int ReadValueAsBase64(byte[] buffer, int offset, int count)
738         {
739             if (IsAttributeValue)
740             {
741                 if (buffer == null)
742                 {
743                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("buffer"));
744                 }
745                 if (offset < 0)
746                 {
747                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", System.Runtime.Serialization.SR.GetString(System.Runtime.Serialization.SR.ValueMustBeNonNegative)));
748                 }
749                 if (offset > buffer.Length)
750                 {
751                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", System.Runtime.Serialization.SR.GetString(System.Runtime.Serialization.SR.OffsetExceedsBufferSize, buffer.Length)));
752                 }
753                 if (count < 0)
754                 {
755                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", System.Runtime.Serialization.SR.GetString(System.Runtime.Serialization.SR.ValueMustBeNonNegative)));
756                 }
757                 if (count > buffer.Length - offset)
758                 {
759                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", System.Runtime.Serialization.SR.GetString(System.Runtime.Serialization.SR.SizeExceedsRemainingBufferSpace, buffer.Length - offset)));
760                 }
761 
762                 return 0;
763             }
764 
765             return base.ReadValueAsBase64(buffer, offset, count);
766         }
767 
ReadValueChunk(char[] chars, int offset, int count)768         public override int ReadValueChunk(char[] chars, int offset, int count)
769         {
770             if (IsAttributeValue)
771             {
772                 if (chars == null)
773                 {
774                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("chars"));
775                 }
776                 if (offset < 0)
777                 {
778                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", System.Runtime.Serialization.SR.GetString(System.Runtime.Serialization.SR.ValueMustBeNonNegative)));
779                 }
780                 if (offset > chars.Length)
781                 {
782                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", System.Runtime.Serialization.SR.GetString(System.Runtime.Serialization.SR.OffsetExceedsBufferSize, chars.Length)));
783                 }
784                 if (count < 0)
785                 {
786                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", System.Runtime.Serialization.SR.GetString(System.Runtime.Serialization.SR.ValueMustBeNonNegative)));
787                 }
788                 if (count > chars.Length - offset)
789                 {
790                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", System.Runtime.Serialization.SR.GetString(System.Runtime.Serialization.SR.SizeExceedsRemainingBufferSpace, chars.Length - offset)));
791                 }
792                 int actual;
793 
794                 string value = UnescapeJsonString(this.Node.ValueAsString);
795                 actual = Math.Min(count, value.Length);
796                 if (actual > 0)
797                 {
798                     value.CopyTo(0, chars, offset, actual);
799                     if (this.Node.QNameType == QNameType.Xmlns)
800                     {
801                         this.Node.Namespace.Uri.SetValue(0, 0);
802                     }
803                     else
804                     {
805                         this.Node.Value.SetValue(ValueHandleType.UTF8, 0, 0);
806                     }
807                 }
808                 return actual;
809             }
810 
811             return base.ReadValueChunk(chars, offset, count);
812         }
813 
SetInput(byte[] buffer, int offset, int count, Encoding encoding, XmlDictionaryReaderQuotas quotas, OnXmlDictionaryReaderClose onClose)814         public void SetInput(byte[] buffer, int offset, int count, Encoding encoding, XmlDictionaryReaderQuotas quotas,
815             OnXmlDictionaryReaderClose onClose)
816         {
817             if (buffer == null)
818             {
819                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("buffer");
820             }
821             if (offset < 0)
822             {
823                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
824                     new ArgumentOutOfRangeException("offset", SR.GetString(SR.ValueMustBeNonNegative)));
825             }
826             if (offset > buffer.Length)
827             {
828                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
829                     new ArgumentOutOfRangeException("offset",
830                     SR.GetString(SR.JsonOffsetExceedsBufferSize, buffer.Length)));
831             }
832             if (count < 0)
833             {
834                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
835                     new ArgumentOutOfRangeException("count", SR.GetString(SR.ValueMustBeNonNegative)));
836             }
837             if (count > buffer.Length - offset)
838             {
839                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
840                     new ArgumentOutOfRangeException("count",
841                     SR.GetString(SR.JsonSizeExceedsRemainingBufferSpace,
842                     buffer.Length - offset)));
843             }
844             MoveToInitial(quotas, onClose);
845 
846             ArraySegment<byte> seg = JsonEncodingStreamWrapper.ProcessBuffer(buffer, offset, count, encoding);
847             BufferReader.SetBuffer(seg.Array, seg.Offset, seg.Count, null, null);
848             this.buffered = true;
849             ResetState();
850         }
851 
SetInput(Stream stream, Encoding encoding, XmlDictionaryReaderQuotas quotas, OnXmlDictionaryReaderClose onClose)852         public void SetInput(Stream stream, Encoding encoding, XmlDictionaryReaderQuotas quotas,
853             OnXmlDictionaryReaderClose onClose)
854         {
855             if (stream == null)
856             {
857                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("stream");
858             }
859             MoveToInitial(quotas, onClose);
860 
861             stream = new JsonEncodingStreamWrapper(stream, encoding, true);
862 
863             BufferReader.SetBuffer(stream, null, null);
864             this.buffered = false;
865             ResetState();
866         }
867 
StartCanonicalization(Stream stream, bool includeComments, string[] inclusivePrefixes)868         public override void StartCanonicalization(Stream stream, bool includeComments, string[] inclusivePrefixes)
869         {
870             throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
871         }
872 
CheckArray(Array array, int offset, int count)873         internal static void CheckArray(Array array, int offset, int count)
874         {
875             if (array == null)
876             {
877                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("array"));
878             }
879             if (offset < 0)
880             {
881                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", SR.GetString(SR.ValueMustBeNonNegative)));
882             }
883             if (offset > array.Length)
884             {
885                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", SR.GetString(SR.OffsetExceedsBufferSize, array.Length)));
886             }
887             if (count < 0)
888             {
889                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", SR.GetString(SR.ValueMustBeNonNegative)));
890             }
891             if (count > array.Length - offset)
892             {
893                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", SR.GetString(SR.SizeExceedsRemainingBufferSpace, array.Length - offset)));
894             }
895         }
896 
CreateSigningNodeWriter()897         protected override XmlSigningNodeWriter CreateSigningNodeWriter()
898         {
899             throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonMethodNotSupported, "CreateSigningNodeWriter")));
900         }
901 
BreakText(byte[] buffer, int offset, int length)902         static int BreakText(byte[] buffer, int offset, int length)
903         {
904             // See if we might be breaking a utf8 sequence
905             if (length > 0 && (buffer[offset + length - 1] & 0x80) == 0x80)
906             {
907                 // Find the lead char of the utf8 sequence (0x11xxxxxx)
908                 int originalLength = length;
909                 do
910                 {
911                     length--;
912                 } while (length > 0 && (buffer[offset + length] & 0xC0) != 0xC0);
913                 // Couldn't find the lead char
914                 if (length == 0)
915                 {
916                     return originalLength; // Invalid utf8 sequence - can't break
917                 }
918                 // Count how many bytes follow the lead char
919                 byte b = (byte)(buffer[offset + length] << 2);
920                 int byteCount = 2;
921                 while ((b & 0x80) == 0x80)
922                 {
923                     b = (byte)(b << 1);
924                     byteCount++;
925                     // There shouldn't be more than 3 bytes following the lead char
926                     if (byteCount > 4)
927                     {
928                         return originalLength; // Invalid utf8 sequence - can't break
929                     }
930                 }
931                 if (length + byteCount == originalLength)
932                 {
933                     return originalLength; // sequence fits exactly
934                 }
935                 if (length == 0)
936                 {
937                     return originalLength; // Quota too small to read a char
938                 }
939             }
940             return length;
941         }
942 
ComputeNumericalTextLength(byte[] buffer, int offset, int offsetMax)943         static int ComputeNumericalTextLength(byte[] buffer, int offset, int offsetMax)
944         {
945             int beginOffset = offset;
946             while (offset < offsetMax)
947             {
948                 byte ch = buffer[offset];
949                 if (ch == JsonGlobals.MemberSeparatorByte || ch == JsonGlobals.EndObjectByte || ch == JsonGlobals.EndCollectionByte
950                     || IsWhitespace(ch))
951                 {
952                     break;
953                 }
954                 offset++;
955             }
956             return offset - beginOffset;
957         }
958 
ComputeQuotedTextLengthUntilEndQuote(byte[] buffer, int offset, int offsetMax, out bool escaped)959         static int ComputeQuotedTextLengthUntilEndQuote(byte[] buffer, int offset, int offsetMax, out bool escaped)
960         {
961             // Assumes that for quoted text "someText", the first " has been consumed.
962             // For original text "someText", buffer passed in is someText".
963             // This method returns return 8 for someText" (s, o, m, e, T, e, x, t).
964             int beginOffset = offset;
965             escaped = false;
966 
967             while (offset < offsetMax)
968             {
969                 byte ch = buffer[offset];
970                 if (ch < 0x20)
971                 {
972                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException(SR.GetString(SR.InvalidCharacterEncountered, (char)ch)));
973                 }
974                 else if (ch == (byte)'\\' || ch == 0xEF)
975                 {
976                     escaped = true;
977                     break;
978                 }
979                 else if (ch == JsonGlobals.QuoteByte)
980                 {
981                     break;
982                 }
983 
984                 offset++;
985             }
986 
987             return offset - beginOffset;
988         }
989 
990 
991         // From JSON spec:
992         // ws = *(
993         //    %x20 /              ; Space
994         //    %x09 /              ; Horizontal tab
995         //    %x0A /              ; Line feed or New line
996         //    %x0D                ; Carriage return
997         // )
IsWhitespace(byte ch)998         static bool IsWhitespace(byte ch)
999         {
1000             return ((ch == 0x20) || (ch == 0x09) || (ch == 0x0A) || (ch == 0x0D));
1001         }
1002 
ParseChar(string value, NumberStyles style)1003         static char ParseChar(string value, NumberStyles style)
1004         {
1005             int intValue = ParseInt(value, style);
1006             try
1007             {
1008                 return Convert.ToChar(intValue);
1009             }
1010             catch (OverflowException exception)
1011             {
1012                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "char", exception));
1013             }
1014         }
1015 
ParseInt(string value, NumberStyles style)1016         static int ParseInt(string value, NumberStyles style)
1017         {
1018             try
1019             {
1020                 return int.Parse(value, style, NumberFormatInfo.InvariantInfo);
1021             }
1022             catch (ArgumentException exception)
1023             {
1024                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "Int32", exception));
1025             }
1026             catch (FormatException exception)
1027             {
1028                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "Int32", exception));
1029             }
1030             catch (OverflowException exception)
1031             {
1032                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "Int32", exception));
1033             }
1034         }
1035 
BufferElement()1036         void BufferElement()
1037         {
1038             int elementOffset = BufferReader.Offset;
1039             const int byteCount = 128;
1040             bool done = false;
1041             byte quoteChar = 0;
1042             while (!done)
1043             {
1044                 int offset;
1045                 int offsetMax;
1046                 byte[] buffer = BufferReader.GetBuffer(byteCount, out offset, out offsetMax);
1047                 if (offset + byteCount != offsetMax)
1048                 {
1049                     break;
1050                 }
1051                 for (int i = offset; i < offsetMax && !done; i++)
1052                 {
1053                     byte b = buffer[i];
1054                     if (b == '\\')
1055                     {
1056                         i++;
1057                         if (i >= offsetMax)
1058                         {
1059                             break;
1060                         }
1061                     }
1062                     else if (quoteChar == 0)
1063                     {
1064                         if (b == (byte)'\'' || b == JsonGlobals.QuoteByte)
1065                         {
1066                             quoteChar = b;
1067                         }
1068                         if (b == JsonGlobals.NameValueSeparatorByte)
1069                         {
1070                             done = true;
1071                         }
1072                     }
1073                     else
1074                     {
1075                         if (b == quoteChar)
1076                         {
1077                             quoteChar = 0;
1078                         }
1079                     }
1080                 }
1081                 BufferReader.Advance(byteCount);
1082             }
1083             BufferReader.Offset = elementOffset;
1084         }
1085 
EnterJsonScope(JsonNodeType currentNodeType)1086         void EnterJsonScope(JsonNodeType currentNodeType)
1087         {
1088             scopeDepth++;
1089             if (scopes == null)
1090             {
1091                 scopes = new JsonNodeType[4];
1092             }
1093             else if (scopes.Length == scopeDepth)
1094             {
1095                 JsonNodeType[] newScopes = new JsonNodeType[scopeDepth * 2];
1096                 Array.Copy(scopes, newScopes, scopeDepth);
1097                 scopes = newScopes;
1098             }
1099             scopes[scopeDepth] = currentNodeType;
1100         }
1101 
ExitJsonScope()1102         JsonNodeType ExitJsonScope()
1103         {
1104             JsonNodeType nodeTypeToReturn = scopes[scopeDepth];
1105             scopes[scopeDepth] = JsonNodeType.None;
1106             scopeDepth--;
1107             return nodeTypeToReturn;
1108         }
1109 
MoveToEndElement()1110         new void MoveToEndElement()
1111         {
1112             ExitJsonScope();
1113             base.MoveToEndElement();
1114         }
1115 
MoveToInitial(XmlDictionaryReaderQuotas quotas, OnXmlDictionaryReaderClose onClose)1116         void MoveToInitial(XmlDictionaryReaderQuotas quotas, OnXmlDictionaryReaderClose onClose)
1117         {
1118             MoveToInitial(quotas);
1119             this.maxBytesPerRead = quotas.MaxBytesPerRead;
1120             this.onReaderClose = onClose;
1121         }
1122 
ParseAndSetLocalName()1123         void ParseAndSetLocalName()
1124         {
1125             XmlElementNode elementNode = EnterScope();
1126             elementNode.NameOffset = BufferReader.Offset;
1127 
1128             do
1129             {
1130                 if (BufferReader.GetByte() == '\\')
1131                 {
1132                     ReadEscapedCharacter(false); //  moveToText
1133                 }
1134                 else
1135                 {
1136                     ReadQuotedText(false); //  moveToText
1137                 }
1138             } while (complexTextMode == JsonComplexTextMode.QuotedText);
1139 
1140             int actualOffset = BufferReader.Offset - 1; //  -1 to ignore " at end of local name
1141             elementNode.LocalName.SetValue(elementNode.NameOffset, actualOffset - elementNode.NameOffset);
1142             elementNode.NameLength = actualOffset - elementNode.NameOffset;
1143             elementNode.Namespace.Uri.SetValue(elementNode.NameOffset, 0);
1144             elementNode.Prefix.SetValue(PrefixHandleType.Empty);
1145             elementNode.IsEmptyElement = false;
1146             elementNode.ExitScope = false;
1147             elementNode.BufferOffset = actualOffset;
1148 
1149             int currentCharacter = (int)BufferReader.GetByte(elementNode.NameOffset);
1150             if ((charType[currentCharacter] & CharType.FirstName) == 0)
1151             {
1152                 SetJsonNameWithMapping(elementNode);
1153             }
1154             else
1155             {
1156                 for (int i = 0, offset = elementNode.NameOffset; i < elementNode.NameLength; i++, offset++)
1157                 {
1158                     currentCharacter = (int)BufferReader.GetByte(offset);
1159                     if ((charType[currentCharacter] & CharType.Name) == 0 || currentCharacter >= 0x80)
1160                     {
1161                         SetJsonNameWithMapping(elementNode);
1162                         break;
1163                     }
1164                 }
1165             }
1166         }
1167 
ParseStartElement()1168         void ParseStartElement()
1169         {
1170             if (!buffered)
1171             {
1172                 BufferElement();
1173             }
1174 
1175             expectingFirstElementInNonPrimitiveChild = false;
1176 
1177             byte ch = BufferReader.GetByte();
1178             if (ch == JsonGlobals.QuoteByte)
1179             {
1180                 BufferReader.SkipByte();
1181 
1182                 ParseAndSetLocalName();
1183 
1184                 SkipWhitespaceInBufferReader();
1185                 SkipExpectedByteInBufferReader(JsonGlobals.NameValueSeparatorByte);
1186                 SkipWhitespaceInBufferReader();
1187 
1188 
1189                 if (BufferReader.GetByte() == JsonGlobals.ObjectByte)
1190                 {
1191                     BufferReader.SkipByte();
1192                     expectingFirstElementInNonPrimitiveChild = true;
1193                 }
1194                 ReadAttributes();
1195             }
1196             else
1197             {
1198                 // " and } are the only two valid characters that may follow a {
1199                 XmlExceptionHelper.ThrowTokenExpected(this, "\"", (char)ch);
1200             }
1201         }
1202 
ReadAttributes()1203         void ReadAttributes()
1204         {
1205             XmlAttributeNode attribute = AddAttribute();
1206             attribute.LocalName.SetConstantValue(StringHandleConstStringType.Type);
1207             attribute.Namespace.Uri.SetValue(0, 0);
1208             attribute.Prefix.SetValue(PrefixHandleType.Empty);
1209 
1210             SkipWhitespaceInBufferReader();
1211             byte nextByte = BufferReader.GetByte();
1212             switch (nextByte)
1213             {
1214                 case JsonGlobals.QuoteByte:
1215                     if (!expectingFirstElementInNonPrimitiveChild)
1216                     {
1217                         attribute.Value.SetConstantValue(ValueHandleConstStringType.String);
1218                     }
1219                     else
1220                     {
1221                         attribute.Value.SetConstantValue(ValueHandleConstStringType.Object);
1222                         ReadServerTypeAttribute(true);
1223                     }
1224                     break;
1225                 case (byte)'n':
1226                     attribute.Value.SetConstantValue(ValueHandleConstStringType.Null);
1227                     break;
1228                 case (byte)'t':
1229                 case (byte)'f':
1230                     attribute.Value.SetConstantValue(ValueHandleConstStringType.Boolean);
1231                     break;
1232                 case JsonGlobals.ObjectByte:
1233                     attribute.Value.SetConstantValue(ValueHandleConstStringType.Object);
1234                     ReadServerTypeAttribute(false);
1235                     break;
1236                 case JsonGlobals.EndObjectByte:
1237                     if (expectingFirstElementInNonPrimitiveChild)
1238                     {
1239                         attribute.Value.SetConstantValue(ValueHandleConstStringType.Object);
1240                     }
1241                     else
1242                     {
1243                         XmlExceptionHelper.ThrowXmlException(this,
1244                             new XmlException(SR.GetString(SR.JsonEncounteredUnexpectedCharacter, (char)nextByte)));
1245                     }
1246                     break;
1247                 case JsonGlobals.CollectionByte:
1248                     attribute.Value.SetConstantValue(ValueHandleConstStringType.Array);
1249                     BufferReader.SkipByte();
1250                     EnterJsonScope(JsonNodeType.Collection);
1251                     break;
1252                 default:
1253                     if (nextByte == '-' ||
1254                         (nextByte <= '9' && nextByte >= '0') ||
1255                         nextByte == 'N' ||
1256                         nextByte == 'I')
1257                     {
1258                         attribute.Value.SetConstantValue(ValueHandleConstStringType.Number);
1259                     }
1260                     else
1261                     {
1262                         XmlExceptionHelper.ThrowXmlException(this,
1263                             new XmlException(SR.GetString(SR.JsonEncounteredUnexpectedCharacter, (char)nextByte)));
1264                     }
1265                     break;
1266             }
1267         }
1268 
ReadEscapedCharacter(bool moveToText)1269         void ReadEscapedCharacter(bool moveToText)
1270         {
1271             BufferReader.SkipByte();
1272             char ch = (char)BufferReader.GetByte();
1273             if (ch == 'u')
1274             {
1275                 BufferReader.SkipByte();
1276                 int offset;
1277                 byte[] buffer = BufferReader.GetBuffer(5, out offset);
1278                 string bufferAsString = Encoding.UTF8.GetString(buffer, offset, 4);
1279                 BufferReader.Advance(4);
1280                 int charValue = ParseChar(bufferAsString, NumberStyles.HexNumber);
1281                 if (Char.IsHighSurrogate((char)charValue))
1282                 {
1283                     byte nextByte = BufferReader.GetByte();
1284                     if (nextByte == (byte)'\\')
1285                     {
1286                         BufferReader.SkipByte();
1287                         SkipExpectedByteInBufferReader((byte)'u');
1288                         buffer = BufferReader.GetBuffer(5, out offset);
1289                         bufferAsString = Encoding.UTF8.GetString(buffer, offset, 4);
1290                         BufferReader.Advance(4);
1291                         char lowChar = ParseChar(bufferAsString, NumberStyles.HexNumber);
1292                         if (!Char.IsLowSurrogate(lowChar))
1293                         {
1294                             XmlExceptionHelper.ThrowXmlException(this,
1295                                 new XmlException(System.Runtime.Serialization.SR.GetString(System.Runtime.Serialization.SR.XmlInvalidLowSurrogate, bufferAsString)));
1296                         }
1297                         charValue = new SurrogateChar(lowChar, (char)charValue).Char;
1298                     }
1299                 }
1300 
1301                 if (buffer[offset + 4] == JsonGlobals.QuoteByte)
1302                 {
1303                     BufferReader.SkipByte();
1304                     if (moveToText)
1305                     {
1306                         MoveToAtomicText().Value.SetCharValue(charValue);
1307                     }
1308                     complexTextMode = JsonComplexTextMode.None;
1309                 }
1310                 else
1311                 {
1312                     if (moveToText)
1313                     {
1314                         MoveToComplexText().Value.SetCharValue(charValue);
1315                     }
1316                     complexTextMode = JsonComplexTextMode.QuotedText;
1317                 }
1318             }
1319             else
1320             {
1321                 switch (ch)
1322                 {
1323                     case 'b':
1324                         ch = '\b';
1325                         break;
1326                     case 'f':
1327                         ch = '\f';
1328                         break;
1329                     case 'n':
1330                         ch = '\n';
1331                         break;
1332                     case 'r':
1333                         ch = '\r';
1334                         break;
1335                     case 't':
1336                         ch = '\t';
1337                         break;
1338                     case '\"':
1339                     case '\\':
1340                     case '/':
1341                         // Do nothing. These are the actual unescaped values.
1342                         break;
1343                     default:
1344                         XmlExceptionHelper.ThrowXmlException(this,
1345                             new XmlException(SR.GetString(SR.JsonEncounteredUnexpectedCharacter, (char)ch)));
1346                         break;
1347                 }
1348                 BufferReader.SkipByte();
1349                 if (BufferReader.GetByte() == JsonGlobals.QuoteByte)
1350                 {
1351                     BufferReader.SkipByte();
1352                     if (moveToText)
1353                     {
1354                         MoveToAtomicText().Value.SetCharValue(ch);
1355                     }
1356                     complexTextMode = JsonComplexTextMode.None;
1357                 }
1358                 else
1359                 {
1360                     if (moveToText)
1361                     {
1362                         MoveToComplexText().Value.SetCharValue(ch);
1363                     }
1364                     complexTextMode = JsonComplexTextMode.QuotedText;
1365                 }
1366             }
1367         }
1368 
ReadNonExistentElementName(StringHandleConstStringType elementName)1369         void ReadNonExistentElementName(StringHandleConstStringType elementName)
1370         {
1371             EnterJsonScope(JsonNodeType.Object);
1372             XmlElementNode elementNode = EnterScope();
1373             elementNode.LocalName.SetConstantValue(elementName);
1374             elementNode.Namespace.Uri.SetValue(elementNode.NameOffset, 0);
1375             elementNode.Prefix.SetValue(PrefixHandleType.Empty);
1376             elementNode.BufferOffset = BufferReader.Offset;
1377             elementNode.IsEmptyElement = false;
1378             elementNode.ExitScope = false;
1379             ReadAttributes();
1380         }
1381 
ReadNonFFFE()1382         int ReadNonFFFE()
1383         {
1384             int off;
1385             byte[] buff = BufferReader.GetBuffer(3, out off);
1386             if (buff[off + 1] == 0xBF && (buff[off + 2] == 0xBE || buff[off + 2] == 0xBF))
1387             {
1388                 XmlExceptionHelper.ThrowXmlException(this, new XmlException(SR.GetString(SR.JsonInvalidFFFE)));
1389             }
1390             return 3;
1391         }
1392 
ReadNumericalText()1393         void ReadNumericalText()
1394         {
1395             byte[] buffer;
1396             int offset;
1397             int offsetMax;
1398             int length;
1399 
1400             if (buffered)
1401             {
1402                 buffer = BufferReader.GetBuffer(out offset, out offsetMax);
1403                 length = ComputeNumericalTextLength(buffer, offset, offsetMax);
1404             }
1405             else
1406             {
1407                 buffer = BufferReader.GetBuffer(MaxTextChunk, out offset, out offsetMax);
1408                 length = ComputeNumericalTextLength(buffer, offset, offsetMax);
1409                 length = BreakText(buffer, offset, length);
1410             }
1411             BufferReader.Advance(length);
1412 
1413             if (offset <= offsetMax - length)
1414             {
1415                 MoveToAtomicText().Value.SetValue(ValueHandleType.UTF8, offset, length);
1416                 complexTextMode = JsonComplexTextMode.None;
1417             }
1418             else
1419             {
1420                 MoveToComplexText().Value.SetValue(ValueHandleType.UTF8, offset, length);
1421                 complexTextMode = JsonComplexTextMode.NumericalText;
1422             }
1423         }
1424 
ReadQuotedText(bool moveToText)1425         void ReadQuotedText(bool moveToText)
1426         {
1427             byte[] buffer;
1428             int offset;
1429             int offsetMax;
1430             int length;
1431             bool escaped;
1432             bool endReached;
1433 
1434             if (buffered)
1435             {
1436                 buffer = BufferReader.GetBuffer(out offset, out offsetMax);
1437                 length = ComputeQuotedTextLengthUntilEndQuote(buffer, offset, offsetMax, out escaped);
1438                 endReached = offset < offsetMax - length;
1439             }
1440             else
1441             {
1442                 buffer = BufferReader.GetBuffer(MaxTextChunk, out offset, out offsetMax);
1443                 length = ComputeQuotedTextLengthUntilEndQuote(buffer, offset, offsetMax, out escaped);
1444                 endReached = offset < offsetMax - length;
1445                 length = BreakText(buffer, offset, length);
1446             }
1447 
1448             if (escaped && BufferReader.GetByte() == 0xEF)
1449             {
1450                 offset = BufferReader.Offset;
1451                 length = ReadNonFFFE();
1452             }
1453 
1454             BufferReader.Advance(length);
1455 
1456             if (!escaped && endReached)
1457             {
1458                 if (moveToText)
1459                 {
1460                     MoveToAtomicText().Value.SetValue(ValueHandleType.UTF8, offset, length);
1461                 }
1462                 SkipExpectedByteInBufferReader(JsonGlobals.QuoteByte);
1463                 complexTextMode = JsonComplexTextMode.None;
1464             }
1465             else
1466             {
1467                 if ((length == 0) && escaped)
1468                 {
1469                     ReadEscapedCharacter(moveToText);
1470                 }
1471                 else
1472                 {
1473                     if (moveToText)
1474                     {
1475                         MoveToComplexText().Value.SetValue(ValueHandleType.UTF8, offset, length);
1476                     }
1477                     complexTextMode = JsonComplexTextMode.QuotedText;
1478                 }
1479             }
1480         }
1481 
ReadServerTypeAttribute(bool consumedObjectChar)1482         void ReadServerTypeAttribute(bool consumedObjectChar)
1483         {
1484             if (!consumedObjectChar)
1485             {
1486                 SkipExpectedByteInBufferReader(JsonGlobals.ObjectByte);
1487                 SkipWhitespaceInBufferReader();
1488 
1489                 // we only allow " or } after {
1490                 byte ch = BufferReader.GetByte();
1491                 if (ch != JsonGlobals.QuoteByte && ch != JsonGlobals.EndObjectByte)
1492                 {
1493                     XmlExceptionHelper.ThrowTokenExpected(this, "\"", (char)ch);
1494                 }
1495             }
1496             else
1497             {
1498                 SkipWhitespaceInBufferReader();
1499             }
1500 
1501             int offset;
1502             int offsetMax;
1503             byte[] buffer = BufferReader.GetBuffer(8, out offset, out offsetMax);
1504             if (offset + 8 <= offsetMax)
1505             {
1506                 if (buffer[offset + 0] == (byte)'\"' &&
1507                     buffer[offset + 1] == (byte)'_' &&
1508                     buffer[offset + 2] == (byte)'_' &&
1509                     buffer[offset + 3] == (byte)'t' &&
1510                     buffer[offset + 4] == (byte)'y' &&
1511                     buffer[offset + 5] == (byte)'p' &&
1512                     buffer[offset + 6] == (byte)'e' &&
1513                     buffer[offset + 7] == (byte)'\"')
1514                 {
1515                     XmlAttributeNode attribute = AddAttribute();
1516 
1517                     attribute.LocalName.SetValue(offset + 1, 6);
1518                     attribute.Namespace.Uri.SetValue(0, 0);
1519                     attribute.Prefix.SetValue(PrefixHandleType.Empty);
1520                     BufferReader.Advance(8);
1521 
1522                     if (!buffered)
1523                     {
1524                         BufferElement();
1525                     }
1526 
1527                     SkipWhitespaceInBufferReader();
1528                     SkipExpectedByteInBufferReader(JsonGlobals.NameValueSeparatorByte);
1529                     SkipWhitespaceInBufferReader();
1530                     SkipExpectedByteInBufferReader(JsonGlobals.QuoteByte);
1531 
1532                     buffer = BufferReader.GetBuffer(out offset, out offsetMax);
1533 
1534                     do
1535                     {
1536                         if (BufferReader.GetByte() == '\\')
1537                         {
1538                             ReadEscapedCharacter(false); //  moveToText
1539                         }
1540                         else
1541                         {
1542                             ReadQuotedText(false); //  moveToText
1543                         }
1544                     } while (complexTextMode == JsonComplexTextMode.QuotedText);
1545 
1546                     attribute.Value.SetValue(ValueHandleType.UTF8, offset, BufferReader.Offset - 1 - offset);
1547 
1548                     SkipWhitespaceInBufferReader();
1549 
1550                     if (BufferReader.GetByte() == JsonGlobals.MemberSeparatorByte)
1551                     {
1552                         BufferReader.SkipByte();
1553                         readServerTypeElement = true;
1554                     }
1555                 }
1556             }
1557             if (BufferReader.GetByte() == JsonGlobals.EndObjectByte)
1558             {
1559                 BufferReader.SkipByte();
1560                 readServerTypeElement = false;
1561                 expectingFirstElementInNonPrimitiveChild = false;
1562             }
1563             else
1564             {
1565                 readServerTypeElement = true;
1566             }
1567         }
1568 
ResetState()1569         void ResetState()
1570         {
1571             complexTextMode = JsonComplexTextMode.None;
1572             expectingFirstElementInNonPrimitiveChild = false;
1573             charactersToSkipOnNextRead = new byte[2];
1574             scopeDepth = 0;
1575             if ((scopes != null) && (scopes.Length > JsonGlobals.maxScopeSize))
1576             {
1577                 scopes = null;
1578             }
1579         }
1580 
SetJsonNameWithMapping(XmlElementNode elementNode)1581         void SetJsonNameWithMapping(XmlElementNode elementNode)
1582         {
1583             Namespace ns = AddNamespace();
1584             ns.Prefix.SetValue(PrefixHandleType.A);
1585             ns.Uri.SetConstantValue(StringHandleConstStringType.Item);
1586             AddXmlnsAttribute(ns);
1587 
1588             XmlAttributeNode attribute = AddAttribute();
1589             attribute.LocalName.SetConstantValue(StringHandleConstStringType.Item);
1590             attribute.Namespace.Uri.SetValue(0, 0);
1591             attribute.Prefix.SetValue(PrefixHandleType.Empty);
1592             attribute.Value.SetValue(ValueHandleType.UTF8, elementNode.NameOffset, elementNode.NameLength);
1593 
1594             elementNode.NameLength = 0;
1595             elementNode.Prefix.SetValue(PrefixHandleType.A);
1596             elementNode.LocalName.SetConstantValue(StringHandleConstStringType.Item);
1597             elementNode.Namespace = ns;
1598         }
1599 
SkipExpectedByteInBufferReader(byte characterToSkip)1600         void SkipExpectedByteInBufferReader(byte characterToSkip)
1601         {
1602             if (BufferReader.GetByte() != characterToSkip)
1603             {
1604                 XmlExceptionHelper.ThrowTokenExpected(this, ((char)characterToSkip).ToString(), (char)BufferReader.GetByte());
1605             }
1606             BufferReader.SkipByte();
1607         }
1608 
SkipWhitespaceInBufferReader()1609         void SkipWhitespaceInBufferReader()
1610         {
1611             byte ch;
1612             while (TryGetByte(out ch) && IsWhitespace(ch))
1613             {
1614                 BufferReader.SkipByte();
1615             }
1616         }
1617 
TryGetByte(out byte ch)1618         bool TryGetByte(out byte ch)
1619         {
1620             int offset, offsetMax;
1621             byte[] buffer = BufferReader.GetBuffer(1, out offset, out offsetMax);
1622 
1623             if (offset < offsetMax)
1624             {
1625                 ch = buffer[offset];
1626                 return true;
1627             }
1628             else
1629             {
1630                 ch = (byte)'\0';
1631                 return false;
1632             }
1633         }
1634 
UnescapeJsonString(string val)1635         string UnescapeJsonString(string val)
1636         {
1637             if (val == null)
1638             {
1639                 return null;
1640             }
1641 
1642             StringBuilder sb = null;
1643             int startIndex = 0, count = 0;
1644             for (int i = 0; i < val.Length; i++)
1645             {
1646                 if (val[i] == '\\')
1647                 {
1648                     i++;
1649                     if (sb == null)
1650                     {
1651                         sb = new StringBuilder();
1652                     }
1653                     sb.Append(val, startIndex, count);
1654                     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");
1655                     if (i >= val.Length)
1656                     {
1657                         XmlExceptionHelper.ThrowXmlException(this, new XmlException(SR.GetString(SR.JsonEncounteredUnexpectedCharacter, val[i])));
1658                     }
1659                     switch (val[i])
1660                     {
1661                         case '"':
1662                         case '\'':
1663                         case '/':
1664                         case '\\':
1665                             sb.Append(val[i]);
1666                             break;
1667                         case 'b':
1668                             sb.Append('\b');
1669                             break;
1670                         case 'f':
1671                             sb.Append('\f');
1672                             break;
1673                         case 'n':
1674                             sb.Append('\n');
1675                             break;
1676                         case 'r':
1677                             sb.Append('\r');
1678                             break;
1679                         case 't':
1680                             sb.Append('\t');
1681                             break;
1682                         case 'u':
1683                             if ((i + 3) >= val.Length)
1684                             {
1685                                 XmlExceptionHelper.ThrowXmlException(this,
1686                                     new XmlException(SR.GetString(SR.JsonEncounteredUnexpectedCharacter, val[i])));
1687                             }
1688                             sb.Append(ParseChar(val.Substring(i + 1, 4), NumberStyles.HexNumber));
1689                             i += 4;
1690                             break;
1691                     }
1692                     startIndex = i + 1;
1693                     count = 0;
1694                 }
1695                 else
1696                 {
1697                     count++;
1698                 }
1699             }
1700             if (sb == null)
1701             {
1702                 return val;
1703             }
1704             if (count > 0)
1705             {
1706                 sb.Append(val, startIndex, count);
1707             }
1708 
1709             return sb.ToString();
1710         }
1711 
1712         static class CharType
1713         {
1714             public const byte FirstName = 0x01;
1715             public const byte Name = 0x02;
1716             public const byte None = 0x00;
1717         }
1718     }
1719 }
1720