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