1 //------------------------------------------------------------ 2 // Copyright (c) Microsoft Corporation. All rights reserved. 3 //------------------------------------------------------------ 4 // PERF, Microsoft, Microsoft: Make LookupNamespace do something smarter when lots of names 5 // PERF, Microsoft, Microsoft: Make Attribute lookup smarter when lots of attributes 6 namespace System.Xml 7 { 8 using System; 9 using System.Collections; 10 using System.Globalization; 11 using System.IO; 12 using System.Runtime; 13 using System.Runtime.Serialization; 14 using System.Text; 15 16 // Large numbers of attributes 17 // Use delimiter on node for figuring out Element/EndElement? 18 // Optimize StringHandle.CompareTo 19 // Fix FixXmlAttribute - Temporary until we actually write an XmlAttribute node 20 21 abstract class XmlBaseReader : XmlDictionaryReader 22 { 23 XmlBufferReader bufferReader; 24 XmlNode node; 25 NamespaceManager nsMgr; 26 XmlElementNode[] elementNodes; 27 XmlAttributeNode[] attributeNodes; 28 XmlAtomicTextNode atomicTextNode; 29 int depth; 30 int attributeCount; 31 int attributeStart; // Starting index for searching 32 XmlDictionaryReaderQuotas quotas; 33 34 XmlNameTable nameTable; 35 XmlDeclarationNode declarationNode; 36 XmlComplexTextNode complexTextNode; 37 XmlWhitespaceTextNode whitespaceTextNode; 38 XmlCDataNode cdataNode; 39 XmlCommentNode commentNode; 40 XmlElementNode rootElementNode; 41 int attributeIndex; // Index for iteration 42 char[] chars; 43 string prefix; 44 string localName; 45 string ns; 46 string value; 47 int trailCharCount; 48 int trailByteCount; 49 char[] trailChars; 50 byte[] trailBytes; 51 bool rootElement; 52 bool readingElement; 53 XmlSigningNodeWriter signingWriter; 54 bool signing; 55 AttributeSorter attributeSorter; 56 57 static XmlInitialNode initialNode = new XmlInitialNode(XmlBufferReader.Empty); 58 static XmlEndOfFileNode endOfFileNode = new XmlEndOfFileNode(XmlBufferReader.Empty); 59 static XmlClosedNode closedNode = new XmlClosedNode(XmlBufferReader.Empty); 60 static BinHexEncoding binhexEncoding; 61 static Base64Encoding base64Encoding; 62 63 const string xmlns = "xmlns"; 64 const string xml = "xml"; 65 const string xmlnsNamespace = "http://www.w3.org/2000/xmlns/"; 66 const string xmlNamespace = "http://www.w3.org/XML/1998/namespace"; 67 XmlBaseReader()68 protected XmlBaseReader() 69 { 70 this.bufferReader = new XmlBufferReader(this); 71 this.nsMgr = new NamespaceManager(bufferReader); 72 this.quotas = new XmlDictionaryReaderQuotas(); 73 this.rootElementNode = new XmlElementNode(bufferReader); 74 this.atomicTextNode = new XmlAtomicTextNode(bufferReader); 75 this.node = closedNode; 76 } 77 78 static BinHexEncoding BinHexEncoding 79 { 80 get 81 { 82 if (binhexEncoding == null) 83 binhexEncoding = new BinHexEncoding(); 84 return binhexEncoding; 85 } 86 } 87 88 static Base64Encoding Base64Encoding 89 { 90 get 91 { 92 if (base64Encoding == null) 93 base64Encoding = new Base64Encoding(); 94 return base64Encoding; 95 } 96 } 97 98 protected XmlBufferReader BufferReader 99 { 100 get 101 { 102 return bufferReader; 103 } 104 } 105 106 public override XmlDictionaryReaderQuotas Quotas 107 { 108 get 109 { 110 return quotas; 111 } 112 } 113 114 protected XmlNode Node 115 { 116 get 117 { 118 return node; 119 } 120 } 121 MoveToNode(XmlNode node)122 protected void MoveToNode(XmlNode node) 123 { 124 this.node = node; 125 this.ns = null; 126 this.localName = null; 127 this.prefix = null; 128 this.value = null; 129 } 130 MoveToInitial(XmlDictionaryReaderQuotas quotas)131 protected void MoveToInitial(XmlDictionaryReaderQuotas quotas) 132 { 133 if (quotas == null) 134 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("quotas"); 135 136 quotas.InternalCopyTo(this.quotas); 137 this.quotas.MakeReadOnly(); 138 this.nsMgr.Clear(); 139 this.depth = 0; 140 this.attributeCount = 0; 141 this.attributeStart = -1; 142 this.attributeIndex = -1; 143 this.rootElement = false; 144 this.readingElement = false; 145 this.signing = false; 146 MoveToNode(initialNode); 147 } 148 MoveToDeclaration()149 protected XmlDeclarationNode MoveToDeclaration() 150 { 151 if (attributeCount < 1) 152 XmlExceptionHelper.ThrowXmlException(this, new XmlException(SR.GetString(SR.XmlDeclMissingVersion))); 153 154 if (attributeCount > 3) 155 XmlExceptionHelper.ThrowXmlException(this, new XmlException(SR.GetString(SR.XmlMalformedDecl))); 156 157 // version 158 if (!CheckDeclAttribute(0, "version", "1.0", false, SR.XmlInvalidVersion)) 159 XmlExceptionHelper.ThrowXmlException(this, new XmlException(SR.GetString(SR.XmlDeclMissingVersion))); 160 161 // encoding/standalone 162 // We only validate that they are the only attributes that exist. Encoding can have any value. 163 if (attributeCount > 1) 164 { 165 if (CheckDeclAttribute(1, "encoding", null, true, SR.XmlInvalidEncoding)) 166 { 167 if (attributeCount == 3 && !CheckStandalone(2)) 168 XmlExceptionHelper.ThrowXmlException(this, new XmlException(SR.GetString(SR.XmlMalformedDecl))); 169 } 170 else if (!CheckStandalone(1) || attributeCount > 2) 171 { 172 XmlExceptionHelper.ThrowXmlException(this, new XmlException(SR.GetString(SR.XmlMalformedDecl))); 173 } 174 } 175 176 if (declarationNode == null) 177 { 178 declarationNode = new XmlDeclarationNode(bufferReader); 179 } 180 MoveToNode(declarationNode); 181 return declarationNode; 182 } 183 CheckStandalone(int attr)184 bool CheckStandalone(int attr) 185 { 186 XmlAttributeNode node = attributeNodes[attr]; 187 if (!node.Prefix.IsEmpty) 188 XmlExceptionHelper.ThrowXmlException(this, new XmlException(SR.GetString(SR.XmlMalformedDecl))); 189 190 if (node.LocalName != "standalone") 191 return false; 192 193 if (!node.Value.Equals2("yes", false) && !node.Value.Equals2("no", false)) 194 XmlExceptionHelper.ThrowXmlException(this, new XmlException(SR.GetString(SR.XmlInvalidStandalone))); 195 196 return true; 197 } 198 CheckDeclAttribute(int index, string localName, string value, bool checkLower, string valueSR)199 bool CheckDeclAttribute(int index, string localName, string value, bool checkLower, string valueSR) 200 { 201 XmlAttributeNode node = attributeNodes[index]; 202 if (!node.Prefix.IsEmpty) 203 XmlExceptionHelper.ThrowXmlException(this, new XmlException(SR.GetString(SR.XmlMalformedDecl))); 204 205 if (node.LocalName != localName) 206 return false; 207 208 if (value != null && !node.Value.Equals2(value, checkLower)) 209 XmlExceptionHelper.ThrowXmlException(this, new XmlException(SR.GetString(valueSR))); 210 211 return true; 212 } 213 MoveToComment()214 protected XmlCommentNode MoveToComment() 215 { 216 if (commentNode == null) 217 { 218 commentNode = new XmlCommentNode(bufferReader); 219 } 220 MoveToNode(commentNode); 221 return commentNode; 222 } 223 MoveToCData()224 protected XmlCDataNode MoveToCData() 225 { 226 if (cdataNode == null) 227 { 228 this.cdataNode = new XmlCDataNode(bufferReader); 229 } 230 MoveToNode(cdataNode); 231 return cdataNode; 232 } 233 MoveToAtomicText()234 protected XmlAtomicTextNode MoveToAtomicText() 235 { 236 XmlAtomicTextNode textNode = this.atomicTextNode; 237 MoveToNode(textNode); 238 return textNode; 239 } 240 MoveToComplexText()241 protected XmlComplexTextNode MoveToComplexText() 242 { 243 if (complexTextNode == null) 244 { 245 complexTextNode = new XmlComplexTextNode(bufferReader); 246 } 247 MoveToNode(complexTextNode); 248 return complexTextNode; 249 } 250 MoveToWhitespaceText()251 protected XmlTextNode MoveToWhitespaceText() 252 { 253 if (whitespaceTextNode == null) 254 { 255 whitespaceTextNode = new XmlWhitespaceTextNode(bufferReader); 256 } 257 if (nsMgr.XmlSpace == XmlSpace.Preserve) 258 whitespaceTextNode.NodeType = XmlNodeType.SignificantWhitespace; 259 else 260 whitespaceTextNode.NodeType = XmlNodeType.Whitespace; 261 MoveToNode(whitespaceTextNode); 262 return whitespaceTextNode; 263 } 264 265 protected XmlElementNode ElementNode 266 { 267 get 268 { 269 if (depth == 0) 270 return rootElementNode; 271 else 272 return elementNodes[depth]; 273 } 274 } 275 MoveToEndElement()276 protected void MoveToEndElement() 277 { 278 if (depth == 0) 279 XmlExceptionHelper.ThrowInvalidBinaryFormat(this); 280 XmlElementNode elementNode = elementNodes[depth]; 281 XmlEndElementNode endElementNode = elementNode.EndElement; 282 endElementNode.Namespace = elementNode.Namespace; 283 MoveToNode(endElementNode); 284 } 285 MoveToEndOfFile()286 protected void MoveToEndOfFile() 287 { 288 if (depth != 0) 289 XmlExceptionHelper.ThrowUnexpectedEndOfFile(this); 290 MoveToNode(endOfFileNode); 291 } 292 EnterScope()293 protected XmlElementNode EnterScope() 294 { 295 if (depth == 0) 296 { 297 if (rootElement) 298 XmlExceptionHelper.ThrowMultipleRootElements(this); 299 rootElement = true; 300 } 301 nsMgr.EnterScope(); 302 depth++; 303 if (depth > quotas.MaxDepth) 304 XmlExceptionHelper.ThrowMaxDepthExceeded(this, quotas.MaxDepth); 305 if (elementNodes == null) 306 { 307 elementNodes = new XmlElementNode[4]; 308 } 309 else if (elementNodes.Length == depth) 310 { 311 XmlElementNode[] newElementNodes = new XmlElementNode[depth * 2]; 312 Array.Copy(elementNodes, newElementNodes, depth); 313 elementNodes = newElementNodes; 314 } 315 XmlElementNode elementNode = elementNodes[depth]; 316 if (elementNode == null) 317 { 318 elementNode = new XmlElementNode(bufferReader); 319 elementNodes[depth] = elementNode; 320 } 321 this.attributeCount = 0; 322 this.attributeStart = -1; 323 this.attributeIndex = -1; 324 MoveToNode(elementNode); 325 return elementNode; 326 } 327 ExitScope()328 protected void ExitScope() 329 { 330 if (depth == 0) 331 XmlExceptionHelper.ThrowUnexpectedEndElement(this); 332 depth--; 333 nsMgr.ExitScope(); 334 } 335 AddAttribute(QNameType qnameType, bool isAtomicValue)336 XmlAttributeNode AddAttribute(QNameType qnameType, bool isAtomicValue) 337 { 338 int attributeIndex = this.attributeCount; 339 if (attributeNodes == null) 340 { 341 attributeNodes = new XmlAttributeNode[4]; 342 } 343 else if (attributeNodes.Length == attributeIndex) 344 { 345 XmlAttributeNode[] newAttributeNodes = new XmlAttributeNode[attributeIndex * 2]; 346 Array.Copy(attributeNodes, newAttributeNodes, attributeIndex); 347 attributeNodes = newAttributeNodes; 348 } 349 XmlAttributeNode attributeNode = attributeNodes[attributeIndex]; 350 if (attributeNode == null) 351 { 352 attributeNode = new XmlAttributeNode(bufferReader); 353 attributeNodes[attributeIndex] = attributeNode; 354 } 355 attributeNode.QNameType = qnameType; 356 attributeNode.IsAtomicValue = isAtomicValue; 357 attributeNode.AttributeText.QNameType = qnameType; 358 attributeNode.AttributeText.IsAtomicValue = isAtomicValue; 359 this.attributeCount++; 360 return attributeNode; 361 } 362 AddNamespace()363 protected Namespace AddNamespace() 364 { 365 return nsMgr.AddNamespace(); 366 } 367 AddAttribute()368 protected XmlAttributeNode AddAttribute() 369 { 370 return AddAttribute(QNameType.Normal, true); 371 } 372 AddXmlAttribute()373 protected XmlAttributeNode AddXmlAttribute() 374 { 375 return AddAttribute(QNameType.Normal, true); 376 } 377 AddXmlnsAttribute(Namespace ns)378 protected XmlAttributeNode AddXmlnsAttribute(Namespace ns) 379 { 380 if (!ns.Prefix.IsEmpty && ns.Uri.IsEmpty) 381 XmlExceptionHelper.ThrowEmptyNamespace(this); 382 383 // Some prefixes can only be bound to a particular namespace 384 if (ns.Prefix.IsXml && ns.Uri != xmlNamespace) 385 { 386 XmlExceptionHelper.ThrowXmlException(this, new XmlException(SR.GetString(SR.XmlSpecificBindingPrefix, "xml", xmlNamespace))); 387 } 388 else if (ns.Prefix.IsXmlns && ns.Uri != xmlnsNamespace) 389 { 390 XmlExceptionHelper.ThrowXmlException(this, new XmlException(SR.GetString(SR.XmlSpecificBindingPrefix, "xmlns", xmlnsNamespace))); 391 } 392 393 nsMgr.Register(ns); 394 XmlAttributeNode attributeNode = AddAttribute(QNameType.Xmlns, false); 395 attributeNode.Namespace = ns; 396 attributeNode.AttributeText.Namespace = ns; 397 return attributeNode; 398 } 399 FixXmlAttribute(XmlAttributeNode attributeNode)400 protected void FixXmlAttribute(XmlAttributeNode attributeNode) 401 { 402 if (attributeNode.Prefix == xml) 403 { 404 if (attributeNode.LocalName == "lang") 405 { 406 nsMgr.AddLangAttribute(attributeNode.Value.GetString()); 407 } 408 else if (attributeNode.LocalName == "space") 409 { 410 string value = attributeNode.Value.GetString(); 411 if (value == "preserve") 412 { 413 nsMgr.AddSpaceAttribute(XmlSpace.Preserve); 414 } 415 else if (value == "default") 416 { 417 nsMgr.AddSpaceAttribute(XmlSpace.Default); 418 } 419 } 420 } 421 } 422 423 protected bool OutsideRootElement 424 { 425 get 426 { 427 return depth == 0; 428 } 429 } 430 431 public override bool CanReadBinaryContent 432 { 433 get { return true; } 434 } 435 436 public override bool CanReadValueChunk 437 { 438 get { return true; } 439 } 440 441 public override string BaseURI 442 { 443 get 444 { 445 return string.Empty; 446 } 447 } 448 449 public override bool HasValue 450 { 451 get 452 { 453 return node.HasValue; 454 } 455 } 456 457 public override bool IsDefault 458 { 459 get 460 { 461 return false; 462 } 463 } 464 465 public override string this[int index] 466 { 467 get 468 { 469 return GetAttribute(index); 470 } 471 } 472 473 public override string this[string name] 474 { 475 get 476 { 477 return GetAttribute(name); 478 } 479 } 480 481 public override string this[string localName, string namespaceUri] 482 { 483 get 484 { 485 return GetAttribute(localName, namespaceUri); 486 } 487 } 488 489 public override int AttributeCount 490 { 491 get 492 { 493 if (node.CanGetAttribute) 494 return attributeCount; 495 return 0; 496 } 497 } 498 Close()499 public override void Close() 500 { 501 MoveToNode(closedNode); 502 nameTable = null; 503 if (attributeNodes != null && attributeNodes.Length > 16) 504 attributeNodes = null; 505 if (elementNodes != null && elementNodes.Length > 16) 506 elementNodes = null; 507 nsMgr.Close(); 508 bufferReader.Close(); 509 if (signingWriter != null) 510 signingWriter.Close(); 511 if (attributeSorter != null) 512 attributeSorter.Close(); 513 } 514 515 public sealed override int Depth 516 { 517 get 518 { 519 // Internally, depth is simply measured by Element/EndElement. What XmlReader exposes is a little different 520 // so we need to account for this with some minor adjustments. 521 522 // We increment depth immediately when we see an element, but XmlTextReader waits until its consumed 523 // We decrement depth when its consumed, but XmlTextReader decrements depth immediately 524 525 // If we're on Attribute Text (i.e. ReadAttributeValue), then its considered a level deeper 526 return this.depth + node.DepthDelta; 527 } 528 } 529 530 public override bool EOF 531 { 532 get 533 { 534 return node.ReadState == ReadState.EndOfFile; 535 } 536 } 537 GetAttributeNode(int index)538 XmlAttributeNode GetAttributeNode(int index) 539 { 540 if (!node.CanGetAttribute) 541 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("index", SR.GetString(SR.XmlElementAttributes))); 542 if (index < 0) 543 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("index", SR.GetString(SR.ValueMustBeNonNegative))); 544 if (index >= attributeCount) 545 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("index", SR.GetString(SR.OffsetExceedsBufferSize, attributeCount))); 546 return attributeNodes[index]; 547 } 548 GetAttributeNode(string name)549 XmlAttributeNode GetAttributeNode(string name) 550 { 551 if (name == null) 552 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("name")); 553 if (!node.CanGetAttribute) 554 return null; 555 int index = name.IndexOf(':'); 556 string prefix; 557 string localName; 558 if (index == -1) 559 { 560 if (name == xmlns) 561 { 562 prefix = xmlns; 563 localName = string.Empty; 564 } 565 else 566 { 567 prefix = string.Empty; 568 localName = name; 569 } 570 } 571 else 572 { 573 // If this function becomes a performance issue because of the allocated strings then we can 574 // make a version of Equals that takes an offset and count into the string. 575 prefix = name.Substring(0, index); 576 localName = name.Substring(index + 1); 577 } 578 XmlAttributeNode[] attributeNodes = this.attributeNodes; 579 int attributeCount = this.attributeCount; 580 int attributeIndex = this.attributeStart; 581 for (int i = 0; i < attributeCount; i++) 582 { 583 if (++attributeIndex >= attributeCount) 584 { 585 attributeIndex = 0; 586 } 587 XmlAttributeNode attributeNode = attributeNodes[attributeIndex]; 588 if (attributeNode.IsPrefixAndLocalName(prefix, localName)) 589 { 590 this.attributeStart = attributeIndex; 591 return attributeNode; 592 } 593 } 594 return null; 595 } 596 GetAttributeNode(string localName, string namespaceUri)597 XmlAttributeNode GetAttributeNode(string localName, string namespaceUri) 598 { 599 if (localName == null) 600 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("localName")); 601 if (namespaceUri == null) 602 namespaceUri = string.Empty; 603 if (!node.CanGetAttribute) 604 return null; 605 XmlAttributeNode[] attributeNodes = this.attributeNodes; 606 int attributeCount = this.attributeCount; 607 int attributeIndex = this.attributeStart; 608 for (int i = 0; i < attributeCount; i++) 609 { 610 if (++attributeIndex >= attributeCount) 611 { 612 attributeIndex = 0; 613 } 614 XmlAttributeNode attributeNode = attributeNodes[attributeIndex]; 615 if (attributeNode.IsLocalNameAndNamespaceUri(localName, namespaceUri)) 616 { 617 this.attributeStart = attributeIndex; 618 return attributeNode; 619 } 620 } 621 return null; 622 } 623 GetAttributeNode(XmlDictionaryString localName, XmlDictionaryString namespaceUri)624 XmlAttributeNode GetAttributeNode(XmlDictionaryString localName, XmlDictionaryString namespaceUri) 625 { 626 if (localName == null) 627 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("localName")); 628 if (namespaceUri == null) 629 namespaceUri = XmlDictionaryString.Empty; 630 if (!node.CanGetAttribute) 631 return null; 632 XmlAttributeNode[] attributeNodes = this.attributeNodes; 633 int attributeCount = this.attributeCount; 634 int attributeIndex = this.attributeStart; 635 for (int i = 0; i < attributeCount; i++) 636 { 637 if (++attributeIndex >= attributeCount) 638 { 639 attributeIndex = 0; 640 } 641 XmlAttributeNode attributeNode = attributeNodes[attributeIndex]; 642 if (attributeNode.IsLocalNameAndNamespaceUri(localName, namespaceUri)) 643 { 644 this.attributeStart = attributeIndex; 645 return attributeNode; 646 } 647 } 648 return null; 649 } 650 GetAttribute(int index)651 public override string GetAttribute(int index) 652 { 653 return GetAttributeNode(index).ValueAsString; 654 } 655 GetAttribute(string name)656 public override string GetAttribute(string name) 657 { 658 XmlAttributeNode attributeNode = GetAttributeNode(name); 659 if (attributeNode == null) 660 return null; 661 return attributeNode.ValueAsString; 662 } 663 GetAttribute(string localName, string namespaceUri)664 public override string GetAttribute(string localName, string namespaceUri) 665 { 666 XmlAttributeNode attributeNode = GetAttributeNode(localName, namespaceUri); 667 if (attributeNode == null) 668 return null; 669 return attributeNode.ValueAsString; 670 } 671 GetAttribute(XmlDictionaryString localName, XmlDictionaryString namespaceUri)672 public override string GetAttribute(XmlDictionaryString localName, XmlDictionaryString namespaceUri) 673 { 674 XmlAttributeNode attributeNode = GetAttributeNode(localName, namespaceUri); 675 if (attributeNode == null) 676 return null; 677 return attributeNode.ValueAsString; 678 } 679 680 public sealed override bool IsEmptyElement 681 { 682 get 683 { 684 return node.IsEmptyElement; 685 } 686 } 687 688 public override string LocalName 689 { 690 get 691 { 692 if (this.localName == null) 693 { 694 this.localName = GetLocalName(true); 695 } 696 697 return this.localName; 698 } 699 } 700 LookupNamespace(string prefix)701 public override string LookupNamespace(string prefix) 702 { 703 Namespace ns = nsMgr.LookupNamespace(prefix); 704 if (ns != null) 705 return ns.Uri.GetString(NameTable); 706 if (prefix == xmlns) 707 return xmlnsNamespace; 708 return null; 709 } 710 LookupNamespace(PrefixHandleType prefix)711 protected Namespace LookupNamespace(PrefixHandleType prefix) 712 { 713 Namespace ns = nsMgr.LookupNamespace(prefix); 714 if (ns == null) 715 XmlExceptionHelper.ThrowUndefinedPrefix(this, PrefixHandle.GetString(prefix)); 716 return ns; 717 } 718 LookupNamespace(PrefixHandle prefix)719 protected Namespace LookupNamespace(PrefixHandle prefix) 720 { 721 Namespace ns = nsMgr.LookupNamespace(prefix); 722 if (ns == null) 723 XmlExceptionHelper.ThrowUndefinedPrefix(this, prefix.GetString()); 724 return ns; 725 } 726 ProcessAttributes()727 protected void ProcessAttributes() 728 { 729 if (attributeCount > 0) 730 { 731 ProcessAttributes(attributeNodes, attributeCount); 732 } 733 } 734 ProcessAttributes(XmlAttributeNode[] attributeNodes, int attributeCount)735 void ProcessAttributes(XmlAttributeNode[] attributeNodes, int attributeCount) 736 { 737 for (int i = 0; i < attributeCount; i++) 738 { 739 XmlAttributeNode attributeNode = attributeNodes[i]; 740 if (attributeNode.QNameType == QNameType.Normal) 741 { 742 PrefixHandle prefix = attributeNode.Prefix; 743 if (!prefix.IsEmpty) 744 { 745 attributeNode.Namespace = LookupNamespace(prefix); 746 } 747 else 748 { 749 attributeNode.Namespace = NamespaceManager.EmptyNamespace; 750 } 751 attributeNode.AttributeText.Namespace = attributeNode.Namespace; 752 } 753 } 754 755 if (attributeCount > 1) 756 { 757 if (attributeCount < 12) 758 { 759 // For small numbers of attributes, a naive n * (n - 1) / 2 comparisons to check for uniqueness is faster 760 for (int i = 0; i < attributeCount - 1; i++) 761 { 762 XmlAttributeNode attributeNode1 = attributeNodes[i]; 763 QNameType qnameType = attributeNode1.QNameType; 764 if (qnameType == QNameType.Normal) 765 { 766 for (int j = i + 1; j < attributeCount; j++) 767 { 768 XmlAttributeNode attributeNode2 = attributeNodes[j]; 769 if (attributeNode2.QNameType == QNameType.Normal && attributeNode1.LocalName == attributeNode2.LocalName && attributeNode1.Namespace.Uri == attributeNode2.Namespace.Uri) 770 { 771 XmlExceptionHelper.ThrowDuplicateAttribute(this, attributeNode1.Prefix.GetString(), attributeNode2.Prefix.GetString(), attributeNode1.LocalName.GetString(), attributeNode1.Namespace.Uri.GetString()); 772 } 773 } 774 } 775 else 776 { 777 Fx.Assert(qnameType == QNameType.Xmlns, ""); 778 for (int j = i + 1; j < attributeCount; j++) 779 { 780 XmlAttributeNode attributeNode2 = attributeNodes[j]; 781 if (attributeNode2.QNameType == QNameType.Xmlns && attributeNode1.Namespace.Prefix == attributeNode2.Namespace.Prefix) 782 XmlExceptionHelper.ThrowDuplicateAttribute(this, xmlns, xmlns, attributeNode1.Namespace.Prefix.GetString(), xmlnsNamespace); 783 } 784 } 785 } 786 } 787 else 788 { 789 CheckAttributes(attributeNodes, attributeCount); 790 } 791 } 792 } 793 CheckAttributes(XmlAttributeNode[] attributeNodes, int attributeCount)794 void CheckAttributes(XmlAttributeNode[] attributeNodes, int attributeCount) 795 { 796 // For large numbers of attributes, sorting the attributes (n * lg(n)) is faster 797 if (attributeSorter == null) 798 attributeSorter = new AttributeSorter(); 799 800 if (!attributeSorter.Sort(attributeNodes, attributeCount)) 801 { 802 int attribute1, attribute2; 803 attributeSorter.GetIndeces(out attribute1, out attribute2); 804 if (attributeNodes[attribute1].QNameType == QNameType.Xmlns) 805 XmlExceptionHelper.ThrowDuplicateXmlnsAttribute(this, attributeNodes[attribute1].Namespace.Prefix.GetString(), xmlnsNamespace); 806 else 807 XmlExceptionHelper.ThrowDuplicateAttribute(this, attributeNodes[attribute1].Prefix.GetString(), attributeNodes[attribute2].Prefix.GetString(), attributeNodes[attribute1].LocalName.GetString(), attributeNodes[attribute1].Namespace.Uri.GetString()); 808 } 809 } 810 MoveToAttribute(int index)811 public override void MoveToAttribute(int index) 812 { 813 MoveToNode(GetAttributeNode(index)); 814 this.attributeIndex = index; 815 } 816 MoveToAttribute(string name)817 public override bool MoveToAttribute(string name) 818 { 819 XmlNode attributeNode = GetAttributeNode(name); 820 if (attributeNode == null) 821 return false; 822 MoveToNode(attributeNode); 823 this.attributeIndex = this.attributeStart; 824 return true; 825 } 826 MoveToAttribute(string localName, string namespaceUri)827 public override bool MoveToAttribute(string localName, string namespaceUri) 828 { 829 XmlNode attributeNode = GetAttributeNode(localName, namespaceUri); 830 if (attributeNode == null) 831 return false; 832 MoveToNode(attributeNode); 833 this.attributeIndex = this.attributeStart; 834 return true; 835 } 836 MoveToElement()837 public override bool MoveToElement() 838 { 839 if (!node.CanMoveToElement) 840 return false; 841 if (depth == 0) 842 MoveToDeclaration(); 843 else 844 MoveToNode(elementNodes[depth]); 845 this.attributeIndex = -1; 846 return true; 847 } 848 MoveToContent()849 public override XmlNodeType MoveToContent() 850 { 851 do 852 { 853 if (node.HasContent) 854 { 855 if (node.NodeType != XmlNodeType.Text && node.NodeType != XmlNodeType.CDATA) 856 break; 857 858 if (trailByteCount > 0) 859 { 860 break; 861 } 862 863 if (this.value == null) 864 { 865 if (!node.Value.IsWhitespace()) 866 break; 867 } 868 else 869 { 870 if (!XmlConverter.IsWhitespace(this.value)) 871 break; 872 } 873 } 874 else 875 { 876 if (node.NodeType == XmlNodeType.Attribute) 877 { 878 MoveToElement(); 879 break; 880 } 881 } 882 } 883 while (Read()); 884 return node.NodeType; 885 } 886 MoveToFirstAttribute()887 public override bool MoveToFirstAttribute() 888 { 889 if (!node.CanGetAttribute || attributeCount == 0) 890 return false; 891 MoveToNode(GetAttributeNode(0)); 892 this.attributeIndex = 0; 893 return true; 894 } 895 MoveToNextAttribute()896 public override bool MoveToNextAttribute() 897 { 898 if (!node.CanGetAttribute) 899 return false; 900 int attributeIndex = this.attributeIndex + 1; 901 if (attributeIndex >= attributeCount) 902 return false; 903 MoveToNode(GetAttributeNode(attributeIndex)); 904 this.attributeIndex = attributeIndex; 905 return true; 906 } 907 908 public override string NamespaceURI 909 { 910 get 911 { 912 if (this.ns == null) 913 { 914 this.ns = GetNamespaceUri(true); 915 } 916 return this.ns; 917 } 918 } 919 920 public override XmlNameTable NameTable 921 { 922 get 923 { 924 if (nameTable == null) 925 { 926 nameTable = new QuotaNameTable(this, quotas.MaxNameTableCharCount); 927 nameTable.Add(xml); 928 nameTable.Add(xmlns); 929 nameTable.Add(xmlnsNamespace); 930 nameTable.Add(xmlNamespace); 931 for (PrefixHandleType i = PrefixHandleType.A; i <= PrefixHandleType.Z; i++) 932 { 933 nameTable.Add(PrefixHandle.GetString(i)); 934 } 935 } 936 937 return nameTable; 938 } 939 } 940 941 public sealed override XmlNodeType NodeType 942 { 943 get 944 { 945 return node.NodeType; 946 } 947 } 948 949 public override string Prefix 950 { 951 get 952 { 953 if (prefix == null) 954 { 955 QNameType qnameType = node.QNameType; 956 if (qnameType == QNameType.Normal) 957 { 958 prefix = node.Prefix.GetString(NameTable); 959 } 960 else if (qnameType == QNameType.Xmlns) 961 { 962 if (node.Namespace.Prefix.IsEmpty) 963 prefix = string.Empty; 964 else 965 prefix = xmlns; 966 } 967 else 968 { 969 prefix = xml; 970 } 971 } 972 973 return prefix; 974 } 975 } 976 977 public override char QuoteChar 978 { 979 get 980 { 981 return node.QuoteChar; 982 } 983 } 984 GetLocalName(bool enforceAtomization)985 string GetLocalName(bool enforceAtomization) 986 { 987 if (this.localName != null) 988 { 989 return this.localName; 990 } 991 992 QNameType qnameType = node.QNameType; 993 if (qnameType == QNameType.Normal) 994 { 995 if (enforceAtomization || nameTable != null) 996 { 997 return node.LocalName.GetString(NameTable); 998 } 999 else 1000 { 1001 return node.LocalName.GetString(); 1002 } 1003 } 1004 else 1005 { 1006 Fx.Assert(qnameType == QNameType.Xmlns, ""); 1007 if (node.Namespace.Prefix.IsEmpty) 1008 { 1009 return xmlns; 1010 } 1011 else 1012 { 1013 if (enforceAtomization || nameTable != null) 1014 { 1015 return node.Namespace.Prefix.GetString(NameTable); 1016 } 1017 else 1018 { 1019 return node.Namespace.Prefix.GetString(); 1020 } 1021 } 1022 } 1023 } 1024 GetNamespaceUri(bool enforceAtomization)1025 string GetNamespaceUri(bool enforceAtomization) 1026 { 1027 if (this.ns != null) 1028 { 1029 return this.ns; 1030 } 1031 1032 QNameType qnameType = node.QNameType; 1033 if (qnameType == QNameType.Normal) 1034 { 1035 if (enforceAtomization || nameTable != null) 1036 { 1037 return node.Namespace.Uri.GetString(NameTable); 1038 } 1039 else 1040 { 1041 return node.Namespace.Uri.GetString(); 1042 } 1043 } 1044 else 1045 { 1046 Fx.Assert(qnameType == QNameType.Xmlns, ""); 1047 return xmlnsNamespace; 1048 } 1049 } 1050 1051 // In a XmlReader names of elements and attributes should be returned atomized 1052 // (see XmlReader.NameTable on MSDN for more information) 1053 // to allow a comparison based on object instance comparison instead of string comparison 1054 // This method allows to receive the localName and namespaceUri without enforcing atomization 1055 // to avoid the cost of atomization if this is not necessary. GetNonAtomizedNames(out string localName, out string namespaceUri)1056 public override void GetNonAtomizedNames(out string localName, out string namespaceUri) 1057 { 1058 localName = GetLocalName(false); 1059 namespaceUri = GetNamespaceUri(false); 1060 } 1061 IsLocalName(string localName)1062 public override bool IsLocalName(string localName) 1063 { 1064 if (localName == null) 1065 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("localName")); 1066 return node.IsLocalName(localName); 1067 } 1068 IsLocalName(XmlDictionaryString localName)1069 public override bool IsLocalName(XmlDictionaryString localName) 1070 { 1071 if (localName == null) 1072 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("localName")); 1073 return node.IsLocalName(localName); 1074 } 1075 IsNamespaceUri(string namespaceUri)1076 public override bool IsNamespaceUri(string namespaceUri) 1077 { 1078 if (namespaceUri == null) 1079 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("namespaceUri"); 1080 return node.IsNamespaceUri(namespaceUri); 1081 } 1082 IsNamespaceUri(XmlDictionaryString namespaceUri)1083 public override bool IsNamespaceUri(XmlDictionaryString namespaceUri) 1084 { 1085 if (namespaceUri == null) 1086 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("namespaceUri"); 1087 return node.IsNamespaceUri(namespaceUri); 1088 } 1089 IsStartElement()1090 public override sealed bool IsStartElement() 1091 { 1092 XmlNodeType nodeType = node.NodeType; 1093 if (nodeType == XmlNodeType.Element) 1094 return true; 1095 if (nodeType == XmlNodeType.EndElement) 1096 return false; 1097 if (nodeType == XmlNodeType.None) 1098 { 1099 Read(); 1100 if (node.NodeType == XmlNodeType.Element) 1101 return true; 1102 } 1103 return (MoveToContent() == XmlNodeType.Element); 1104 } 1105 IsStartElement(string name)1106 public override bool IsStartElement(string name) 1107 { 1108 if (name == null) 1109 return false; 1110 int index = name.IndexOf(':'); 1111 string prefix; 1112 string localName; 1113 if (index == -1) 1114 { 1115 prefix = string.Empty; 1116 localName = name; 1117 } 1118 else 1119 { 1120 prefix = name.Substring(0, index); 1121 localName = name.Substring(index + 1); 1122 } 1123 return (node.NodeType == XmlNodeType.Element || IsStartElement()) && node.Prefix == prefix && node.LocalName == localName; 1124 } 1125 IsStartElement(string localName, string namespaceUri)1126 public override bool IsStartElement(string localName, string namespaceUri) 1127 { 1128 if (localName == null) 1129 return false; 1130 if (namespaceUri == null) 1131 return false; 1132 return (node.NodeType == XmlNodeType.Element || IsStartElement()) && node.LocalName == localName && node.IsNamespaceUri(namespaceUri); 1133 } 1134 IsStartElement(XmlDictionaryString localName, XmlDictionaryString namespaceUri)1135 public override bool IsStartElement(XmlDictionaryString localName, XmlDictionaryString namespaceUri) 1136 { 1137 if (localName == null) 1138 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("localName"); 1139 if (namespaceUri == null) 1140 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("namespaceUri"); 1141 return (node.NodeType == XmlNodeType.Element || IsStartElement()) && node.LocalName == localName && node.IsNamespaceUri(namespaceUri); 1142 } 1143 IndexOfLocalName(string[] localNames, string namespaceUri)1144 public override int IndexOfLocalName(string[] localNames, string namespaceUri) 1145 { 1146 if (localNames == null) 1147 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("localNames"); 1148 if (namespaceUri == null) 1149 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("namespaceUri"); 1150 QNameType qnameType = node.QNameType; 1151 if (node.IsNamespaceUri(namespaceUri)) 1152 { 1153 if (qnameType == QNameType.Normal) 1154 { 1155 StringHandle localName = node.LocalName; 1156 for (int i = 0; i < localNames.Length; i++) 1157 { 1158 string value = localNames[i]; 1159 if (value == null) 1160 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(string.Format(CultureInfo.InvariantCulture, "localNames[{0}]", i)); 1161 if (localName == value) 1162 { 1163 return i; 1164 } 1165 } 1166 } 1167 else 1168 { 1169 Fx.Assert(qnameType == QNameType.Xmlns, ""); 1170 PrefixHandle prefix = node.Namespace.Prefix; 1171 for (int i = 0; i < localNames.Length; i++) 1172 { 1173 string value = localNames[i]; 1174 if (value == null) 1175 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(string.Format(CultureInfo.InvariantCulture, "localNames[{0}]", i)); 1176 if (prefix == value) 1177 { 1178 return i; 1179 } 1180 } 1181 } 1182 } 1183 return -1; 1184 } 1185 IndexOfLocalName(XmlDictionaryString[] localNames, XmlDictionaryString namespaceUri)1186 public override int IndexOfLocalName(XmlDictionaryString[] localNames, XmlDictionaryString namespaceUri) 1187 { 1188 if (localNames == null) 1189 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("localNames"); 1190 if (namespaceUri == null) 1191 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("namespaceUri"); 1192 QNameType qnameType = node.QNameType; 1193 if (node.IsNamespaceUri(namespaceUri)) 1194 { 1195 if (qnameType == QNameType.Normal) 1196 { 1197 StringHandle localName = node.LocalName; 1198 for (int i = 0; i < localNames.Length; i++) 1199 { 1200 XmlDictionaryString value = localNames[i]; 1201 if (value == null) 1202 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(string.Format(CultureInfo.InvariantCulture, "localNames[{0}]", i)); 1203 if (localName == value) 1204 { 1205 return i; 1206 } 1207 } 1208 } 1209 else 1210 { 1211 Fx.Assert(qnameType == QNameType.Xmlns, ""); 1212 PrefixHandle prefix = node.Namespace.Prefix; 1213 for (int i = 0; i < localNames.Length; i++) 1214 { 1215 XmlDictionaryString value = localNames[i]; 1216 if (value == null) 1217 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(string.Format(CultureInfo.InvariantCulture, "localNames[{0}]", i)); 1218 if (prefix == value) 1219 { 1220 return i; 1221 } 1222 } 1223 } 1224 } 1225 return -1; 1226 } 1227 ReadValueChunk(char[] chars, int offset, int count)1228 public override int ReadValueChunk(char[] chars, int offset, int count) 1229 { 1230 if (chars == null) 1231 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("chars")); 1232 if (offset < 0) 1233 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", SR.GetString(SR.ValueMustBeNonNegative))); 1234 if (offset > chars.Length) 1235 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", SR.GetString(SR.OffsetExceedsBufferSize, chars.Length))); 1236 if (count < 0) 1237 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", SR.GetString(SR.ValueMustBeNonNegative))); 1238 if (count > chars.Length - offset) 1239 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", SR.GetString(SR.SizeExceedsRemainingBufferSpace, chars.Length - offset))); 1240 int actual; 1241 1242 if (this.value == null) 1243 { 1244 if (node.QNameType == QNameType.Normal) 1245 { 1246 if (node.Value.TryReadChars(chars, offset, count, out actual)) 1247 return actual; 1248 } 1249 } 1250 1251 string value = this.Value; 1252 actual = Math.Min(count, value.Length); 1253 value.CopyTo(0, chars, offset, actual); 1254 this.value = value.Substring(actual); 1255 return actual; 1256 } 1257 ReadValueAsBase64(byte[] buffer, int offset, int count)1258 public override int ReadValueAsBase64(byte[] buffer, int offset, int count) 1259 { 1260 if (buffer == null) 1261 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("buffer")); 1262 if (offset < 0) 1263 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", SR.GetString(SR.ValueMustBeNonNegative))); 1264 if (offset > buffer.Length) 1265 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", SR.GetString(SR.OffsetExceedsBufferSize, buffer.Length))); 1266 if (count < 0) 1267 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", SR.GetString(SR.ValueMustBeNonNegative))); 1268 if (count > buffer.Length - offset) 1269 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", SR.GetString(SR.SizeExceedsRemainingBufferSpace, buffer.Length - offset))); 1270 if (count == 0) 1271 return 0; 1272 int actual; 1273 if (this.value == null) 1274 { 1275 if (trailByteCount == 0 && trailCharCount == 0) 1276 { 1277 if (node.QNameType == QNameType.Normal) 1278 { 1279 if (node.Value.TryReadBase64(buffer, offset, count, out actual)) 1280 return actual; 1281 } 1282 } 1283 } 1284 return ReadBytes(Base64Encoding, 3, 4, buffer, offset, Math.Min(count, 512), false); 1285 } 1286 ReadElementContentAsString()1287 public override string ReadElementContentAsString() 1288 { 1289 if (node.NodeType != XmlNodeType.Element) 1290 MoveToStartElement(); 1291 1292 if (node.IsEmptyElement) 1293 { 1294 Read(); 1295 return string.Empty; 1296 } 1297 else 1298 { 1299 Read(); 1300 string s = ReadContentAsString(); 1301 ReadEndElement(); 1302 return s; 1303 } 1304 } 1305 ReadElementString()1306 public override string ReadElementString() 1307 { 1308 MoveToStartElement(); 1309 if (IsEmptyElement) 1310 { 1311 Read(); 1312 return string.Empty; 1313 } 1314 else 1315 { 1316 Read(); 1317 string s = ReadString(); 1318 ReadEndElement(); 1319 return s; 1320 } 1321 } 1322 ReadElementString(string name)1323 public override string ReadElementString(string name) 1324 { 1325 MoveToStartElement(name); 1326 return ReadElementString(); 1327 } 1328 ReadElementString(string localName, string namespaceUri)1329 public override string ReadElementString(string localName, string namespaceUri) 1330 { 1331 MoveToStartElement(localName, namespaceUri); 1332 return ReadElementString(); 1333 } 1334 ReadStartElement()1335 public override void ReadStartElement() 1336 { 1337 if (node.NodeType != XmlNodeType.Element) 1338 MoveToStartElement(); 1339 Read(); 1340 } 1341 ReadStartElement(string name)1342 public override void ReadStartElement(string name) 1343 { 1344 MoveToStartElement(name); 1345 Read(); 1346 } 1347 ReadStartElement(string localName, string namespaceUri)1348 public override void ReadStartElement(string localName, string namespaceUri) 1349 { 1350 MoveToStartElement(localName, namespaceUri); 1351 Read(); 1352 } 1353 ReadEndElement()1354 public override void ReadEndElement() 1355 { 1356 if (node.NodeType != XmlNodeType.EndElement && MoveToContent() != XmlNodeType.EndElement) 1357 { 1358 int nodeDepth = node.NodeType == XmlNodeType.Element ? this.depth - 1 : this.depth; 1359 if (nodeDepth == 0) 1360 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.XmlEndElementNoOpenNodes))); 1361 // If depth is non-zero, then the document isn't what was expected 1362 XmlElementNode elementNode = elementNodes[nodeDepth]; 1363 XmlExceptionHelper.ThrowEndElementExpected(this, elementNode.LocalName.GetString(), elementNode.Namespace.Uri.GetString()); 1364 } 1365 Read(); 1366 } 1367 ReadAttributeValue()1368 public override bool ReadAttributeValue() 1369 { 1370 XmlAttributeTextNode attributeTextNode = node.AttributeText; 1371 if (attributeTextNode == null) 1372 return false; 1373 MoveToNode(attributeTextNode); 1374 return true; 1375 } 1376 1377 public override ReadState ReadState 1378 { 1379 get 1380 { 1381 return node.ReadState; 1382 } 1383 } 1384 SkipValue(XmlNode node)1385 void SkipValue(XmlNode node) 1386 { 1387 if (node.SkipValue) 1388 Read(); 1389 } 1390 TryGetBase64ContentLength(out int length)1391 public override bool TryGetBase64ContentLength(out int length) 1392 { 1393 if (trailByteCount == 0 && trailCharCount == 0 && this.value == null) 1394 { 1395 XmlNode node = this.Node; 1396 if (node.IsAtomicValue) 1397 return node.Value.TryGetByteArrayLength(out length); 1398 } 1399 return base.TryGetBase64ContentLength(out length); 1400 } 1401 ReadContentAsBase64()1402 public override byte[] ReadContentAsBase64() 1403 { 1404 if (trailByteCount == 0 && trailCharCount == 0 && this.value == null) 1405 { 1406 XmlNode node = this.Node; 1407 if (node.IsAtomicValue) 1408 { 1409 byte[] value = node.Value.ToByteArray(); 1410 if (value.Length > quotas.MaxArrayLength) 1411 XmlExceptionHelper.ThrowMaxArrayLengthExceeded(this, quotas.MaxArrayLength); 1412 SkipValue(node); 1413 return value; 1414 } 1415 } 1416 1417 if (!bufferReader.IsStreamed) 1418 return ReadContentAsBase64(quotas.MaxArrayLength, bufferReader.Buffer.Length); 1419 1420 return ReadContentAsBase64(quotas.MaxArrayLength, XmlDictionaryReader.MaxInitialArrayLength); // Initial count will get ignored 1421 } 1422 ReadElementContentAsBase64(byte[] buffer, int offset, int count)1423 public override int ReadElementContentAsBase64(byte[] buffer, int offset, int count) 1424 { 1425 if (!readingElement) 1426 { 1427 if (IsEmptyElement) 1428 { 1429 Read(); 1430 return 0; 1431 } 1432 1433 ReadStartElement(); 1434 readingElement = true; 1435 } 1436 1437 int i = ReadContentAsBase64(buffer, offset, count); 1438 1439 if (i == 0) 1440 { 1441 ReadEndElement(); 1442 readingElement = false; 1443 } 1444 1445 return i; 1446 } 1447 ReadContentAsBase64(byte[] buffer, int offset, int count)1448 public override int ReadContentAsBase64(byte[] buffer, int offset, int count) 1449 { 1450 if (buffer == null) 1451 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("buffer")); 1452 if (offset < 0) 1453 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", SR.GetString(SR.ValueMustBeNonNegative))); 1454 if (offset > buffer.Length) 1455 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", SR.GetString(SR.OffsetExceedsBufferSize, buffer.Length))); 1456 if (count < 0) 1457 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", SR.GetString(SR.ValueMustBeNonNegative))); 1458 if (count > buffer.Length - offset) 1459 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", SR.GetString(SR.SizeExceedsRemainingBufferSpace, buffer.Length - offset))); 1460 if (count == 0) 1461 return 0; 1462 int actual; 1463 if (trailByteCount == 0 && trailCharCount == 0 && this.value == null) 1464 { 1465 if (node.QNameType == QNameType.Normal) 1466 { 1467 while (node.NodeType != XmlNodeType.Comment && node.Value.TryReadBase64(buffer, offset, count, out actual)) 1468 { 1469 if (actual != 0) 1470 return actual; 1471 Read(); 1472 } 1473 } 1474 } 1475 XmlNodeType nodeType = node.NodeType; 1476 if (nodeType == XmlNodeType.Element || nodeType == XmlNodeType.EndElement) 1477 return 0; 1478 return ReadBytes(Base64Encoding, 3, 4, buffer, offset, Math.Min(count, 512), true); 1479 } 1480 ReadContentAsBinHex()1481 public override byte[] ReadContentAsBinHex() 1482 { 1483 return ReadContentAsBinHex(quotas.MaxArrayLength); 1484 } 1485 ReadElementContentAsBinHex(byte[] buffer, int offset, int count)1486 public override int ReadElementContentAsBinHex(byte[] buffer, int offset, int count) 1487 { 1488 if (!readingElement) 1489 { 1490 if (IsEmptyElement) 1491 { 1492 Read(); 1493 return 0; 1494 } 1495 1496 ReadStartElement(); 1497 readingElement = true; 1498 } 1499 1500 int i = ReadContentAsBinHex(buffer, offset, count); 1501 1502 if (i == 0) 1503 { 1504 ReadEndElement(); 1505 readingElement = false; 1506 } 1507 1508 return i; 1509 } 1510 ReadContentAsBinHex(byte[] buffer, int offset, int count)1511 public override int ReadContentAsBinHex(byte[] buffer, int offset, int count) 1512 { 1513 if (buffer == null) 1514 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("buffer")); 1515 if (offset < 0) 1516 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", SR.GetString(SR.ValueMustBeNonNegative))); 1517 if (offset > buffer.Length) 1518 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", SR.GetString(SR.OffsetExceedsBufferSize, buffer.Length))); 1519 if (count < 0) 1520 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", SR.GetString(SR.ValueMustBeNonNegative))); 1521 if (count > buffer.Length - offset) 1522 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", SR.GetString(SR.SizeExceedsRemainingBufferSpace, buffer.Length - offset))); 1523 if (count == 0) 1524 return 0; 1525 return ReadBytes(BinHexEncoding, 1, 2, buffer, offset, Math.Min(count, 512), true); 1526 } 1527 ReadBytes(Encoding encoding, int byteBlock, int charBlock, byte[] buffer, int offset, int byteCount, bool readContent)1528 int ReadBytes(Encoding encoding, int byteBlock, int charBlock, byte[] buffer, int offset, int byteCount, bool readContent) 1529 { 1530 // If there are any trailing buffer return them. 1531 if (trailByteCount > 0) 1532 { 1533 int actual = Math.Min(trailByteCount, byteCount); 1534 Array.Copy(trailBytes, 0, buffer, offset, actual); 1535 trailByteCount -= actual; 1536 Array.Copy(trailBytes, actual, trailBytes, 0, trailByteCount); 1537 return actual; 1538 } 1539 XmlNodeType nodeType = node.NodeType; 1540 if (nodeType == XmlNodeType.Element || nodeType == XmlNodeType.EndElement) 1541 return 0; 1542 int maxCharCount; 1543 if (byteCount < byteBlock) 1544 { 1545 // Convert at least charBlock chars 1546 maxCharCount = charBlock; 1547 } 1548 else 1549 { 1550 // Round down to the nearest multiple of charBlock 1551 maxCharCount = byteCount / byteBlock * charBlock; 1552 } 1553 char[] chars = GetCharBuffer(maxCharCount); 1554 int charCount = 0; 1555 while (true) 1556 { 1557 // If we didn't align on the boundary, then we might have some remaining characters 1558 if (trailCharCount > 0) 1559 { 1560 Array.Copy(trailChars, 0, chars, charCount, trailCharCount); 1561 charCount += trailCharCount; 1562 trailCharCount = 0; 1563 } 1564 // Read until we at least get a charBlock 1565 while (charCount < charBlock) 1566 { 1567 int actualCharCount; 1568 if (readContent) 1569 { 1570 actualCharCount = ReadContentAsChars(chars, charCount, maxCharCount - charCount); 1571 // When deserializing base64 content which contains new line chars (CR, LF) chars from ReadObject, the reader reads in chunks of base64 content, LF char, base64 content, LF char and so on 1572 // Relying on encoding.GetBytes' exception to handle LF char would result in performance degradation so skipping LF char here 1573 if (actualCharCount == 1 && chars[charCount] == '\n') 1574 continue; 1575 } 1576 else 1577 actualCharCount = ReadValueChunk(chars, charCount, maxCharCount - charCount); 1578 if (actualCharCount == 0) 1579 break; 1580 charCount += actualCharCount; 1581 } 1582 // Trim so its a multiple of charBlock 1583 if (charCount >= charBlock) 1584 { 1585 trailCharCount = (charCount % charBlock); 1586 if (trailCharCount > 0) 1587 { 1588 if (trailChars == null) 1589 trailChars = new char[4]; 1590 charCount = charCount - trailCharCount; 1591 Array.Copy(chars, charCount, trailChars, 0, trailCharCount); 1592 } 1593 } 1594 try 1595 { 1596 if (byteCount < byteBlock) 1597 { 1598 if (trailBytes == null) 1599 trailBytes = new byte[3]; 1600 trailByteCount = encoding.GetBytes(chars, 0, charCount, trailBytes, 0); 1601 int actual = Math.Min(trailByteCount, byteCount); 1602 Array.Copy(trailBytes, 0, buffer, offset, actual); 1603 trailByteCount -= actual; 1604 Array.Copy(trailBytes, actual, trailBytes, 0, trailByteCount); 1605 return actual; 1606 } 1607 else 1608 { 1609 // charCount is a multiple of charBlock and we have enough room to convert everything 1610 return encoding.GetBytes(chars, 0, charCount, buffer, offset); 1611 } 1612 } 1613 catch (FormatException exception) 1614 { 1615 // Something was wrong with the format, see if we can strip the spaces 1616 int i = 0; 1617 int j = 0; 1618 while (true) 1619 { 1620 while (j < charCount && XmlConverter.IsWhitespace(chars[j])) 1621 j++; 1622 if (j == charCount) 1623 break; 1624 chars[i++] = chars[j++]; 1625 } 1626 // No spaces, so don't try again 1627 if (i == charCount) 1628 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(exception.Message, exception.InnerException)); 1629 charCount = i; 1630 } 1631 } 1632 } 1633 ReadContentAsString()1634 public override string ReadContentAsString() 1635 { 1636 string value; 1637 XmlNode node = this.Node; 1638 if (node.IsAtomicValue) 1639 { 1640 if (this.value != null) 1641 { 1642 value = this.value; 1643 if (node.AttributeText == null) 1644 this.value = string.Empty; 1645 } 1646 else 1647 { 1648 value = node.Value.GetString(); 1649 SkipValue(node); 1650 if (value.Length > quotas.MaxStringContentLength) 1651 XmlExceptionHelper.ThrowMaxStringContentLengthExceeded(this, quotas.MaxStringContentLength); 1652 } 1653 return value; 1654 } 1655 return base.ReadContentAsString(quotas.MaxStringContentLength); 1656 } 1657 ReadContentAsBoolean()1658 public override Boolean ReadContentAsBoolean() 1659 { 1660 XmlNode node = this.Node; 1661 if (this.value == null && node.IsAtomicValue) 1662 { 1663 bool value = node.Value.ToBoolean(); 1664 SkipValue(node); 1665 return value; 1666 } 1667 return XmlConverter.ToBoolean(ReadContentAsString()); 1668 } 1669 ReadContentAsLong()1670 public override Int64 ReadContentAsLong() 1671 { 1672 XmlNode node = this.Node; 1673 if (this.value == null && node.IsAtomicValue) 1674 { 1675 Int64 value = node.Value.ToLong(); 1676 SkipValue(node); 1677 return value; 1678 } 1679 return XmlConverter.ToInt64(ReadContentAsString()); 1680 } 1681 ReadContentAsInt()1682 public override Int32 ReadContentAsInt() 1683 { 1684 XmlNode node = this.Node; 1685 if (this.value == null && node.IsAtomicValue) 1686 { 1687 Int32 value = node.Value.ToInt(); 1688 SkipValue(node); 1689 return value; 1690 } 1691 return XmlConverter.ToInt32(ReadContentAsString()); 1692 } 1693 ReadContentAsDateTime()1694 public override DateTime ReadContentAsDateTime() 1695 { 1696 XmlNode node = this.Node; 1697 if (this.value == null && node.IsAtomicValue) 1698 { 1699 DateTime value = node.Value.ToDateTime(); 1700 SkipValue(node); 1701 return value; 1702 } 1703 return XmlConverter.ToDateTime(ReadContentAsString()); 1704 } 1705 ReadContentAsDouble()1706 public override Double ReadContentAsDouble() 1707 { 1708 XmlNode node = this.Node; 1709 if (this.value == null && node.IsAtomicValue) 1710 { 1711 double value = node.Value.ToDouble(); 1712 SkipValue(node); 1713 return value; 1714 } 1715 return XmlConverter.ToDouble(ReadContentAsString()); 1716 } 1717 ReadContentAsFloat()1718 public override Single ReadContentAsFloat() 1719 { 1720 XmlNode node = this.Node; 1721 if (this.value == null && node.IsAtomicValue) 1722 { 1723 float value = node.Value.ToSingle(); 1724 SkipValue(node); 1725 return value; 1726 } 1727 return XmlConverter.ToSingle(ReadContentAsString()); 1728 } 1729 ReadContentAsDecimal()1730 public override Decimal ReadContentAsDecimal() 1731 { 1732 XmlNode node = this.Node; 1733 if (this.value == null && node.IsAtomicValue) 1734 { 1735 decimal value = node.Value.ToDecimal(); 1736 SkipValue(node); 1737 return value; 1738 } 1739 return XmlConverter.ToDecimal(ReadContentAsString()); 1740 } 1741 ReadContentAsUniqueId()1742 public override UniqueId ReadContentAsUniqueId() 1743 { 1744 XmlNode node = this.Node; 1745 if (this.value == null && node.IsAtomicValue) 1746 { 1747 UniqueId value = node.Value.ToUniqueId(); 1748 SkipValue(node); 1749 return value; 1750 } 1751 return XmlConverter.ToUniqueId(ReadContentAsString()); 1752 } 1753 ReadContentAsTimeSpan()1754 public override TimeSpan ReadContentAsTimeSpan() 1755 { 1756 XmlNode node = this.Node; 1757 if (this.value == null && node.IsAtomicValue) 1758 { 1759 TimeSpan value = node.Value.ToTimeSpan(); 1760 SkipValue(node); 1761 return value; 1762 } 1763 return XmlConverter.ToTimeSpan(ReadContentAsString()); 1764 } 1765 ReadContentAsGuid()1766 public override Guid ReadContentAsGuid() 1767 { 1768 XmlNode node = this.Node; 1769 if (this.value == null && node.IsAtomicValue) 1770 { 1771 Guid value = node.Value.ToGuid(); 1772 SkipValue(node); 1773 return value; 1774 } 1775 return XmlConverter.ToGuid(ReadContentAsString()); 1776 } 1777 ReadContentAsObject()1778 public override object ReadContentAsObject() 1779 { 1780 XmlNode node = this.Node; 1781 if (this.value == null && node.IsAtomicValue) 1782 { 1783 object obj = node.Value.ToObject(); 1784 SkipValue(node); 1785 return obj; 1786 } 1787 return ReadContentAsString(); 1788 } 1789 ReadContentAs(Type type, IXmlNamespaceResolver namespaceResolver)1790 public override object ReadContentAs(Type type, IXmlNamespaceResolver namespaceResolver) 1791 { 1792 if (type == typeof(ulong)) 1793 { 1794 if (this.value == null && node.IsAtomicValue) 1795 { 1796 ulong value = node.Value.ToULong(); 1797 SkipValue(node); 1798 return value; 1799 } 1800 else 1801 { 1802 return XmlConverter.ToUInt64(ReadContentAsString()); 1803 } 1804 } 1805 else if (type == typeof(bool)) 1806 return ReadContentAsBoolean(); 1807 else if (type == typeof(int)) 1808 return ReadContentAsInt(); 1809 else if (type == typeof(long)) 1810 return ReadContentAsLong(); 1811 else if (type == typeof(float)) 1812 return ReadContentAsFloat(); 1813 else if (type == typeof(double)) 1814 return ReadContentAsDouble(); 1815 else if (type == typeof(decimal)) 1816 return ReadContentAsDecimal(); 1817 else if (type == typeof(DateTime)) 1818 return ReadContentAsDateTime(); 1819 else if (type == typeof(UniqueId)) 1820 return ReadContentAsUniqueId(); 1821 else if (type == typeof(Guid)) 1822 return ReadContentAsGuid(); 1823 else if (type == typeof(TimeSpan)) 1824 return ReadContentAsTimeSpan(); 1825 else if (type == typeof(object)) 1826 return ReadContentAsObject(); 1827 else 1828 return base.ReadContentAs(type, namespaceResolver); 1829 } 1830 ResolveEntity()1831 public override void ResolveEntity() 1832 { 1833 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.XmlInvalidOperation))); 1834 } 1835 Skip()1836 public override void Skip() 1837 { 1838 if (node.ReadState != ReadState.Interactive) 1839 return; 1840 if ((node.NodeType == XmlNodeType.Element || MoveToElement()) && !IsEmptyElement) 1841 { 1842 int depth = Depth; 1843 while (Read() && depth < Depth) 1844 { 1845 // Nothing, just read on 1846 } 1847 // consume end tag 1848 if (node.NodeType == XmlNodeType.EndElement) 1849 Read(); 1850 } 1851 else 1852 { 1853 Read(); 1854 } 1855 } 1856 1857 public override string Value 1858 { 1859 get 1860 { 1861 if (value == null) 1862 { 1863 value = node.ValueAsString; 1864 } 1865 1866 return value; 1867 } 1868 } 1869 1870 public override Type ValueType 1871 { 1872 get 1873 { 1874 if (this.value == null && node.QNameType == QNameType.Normal) 1875 { 1876 Type type = node.Value.ToType(); 1877 if (node.IsAtomicValue) 1878 return type; 1879 if (type == typeof(byte[])) 1880 return type; 1881 } 1882 return typeof(string); 1883 } 1884 } 1885 1886 public override string XmlLang 1887 { 1888 get 1889 { 1890 return nsMgr.XmlLang; 1891 } 1892 } 1893 1894 public override XmlSpace XmlSpace 1895 { 1896 get 1897 { 1898 return nsMgr.XmlSpace; 1899 } 1900 } 1901 TryGetLocalNameAsDictionaryString(out XmlDictionaryString localName)1902 public override bool TryGetLocalNameAsDictionaryString(out XmlDictionaryString localName) 1903 { 1904 return node.TryGetLocalNameAsDictionaryString(out localName); 1905 } 1906 TryGetNamespaceUriAsDictionaryString(out XmlDictionaryString localName)1907 public override bool TryGetNamespaceUriAsDictionaryString(out XmlDictionaryString localName) 1908 { 1909 return node.TryGetNamespaceUriAsDictionaryString(out localName); 1910 } 1911 TryGetValueAsDictionaryString(out XmlDictionaryString value)1912 public override bool TryGetValueAsDictionaryString(out XmlDictionaryString value) 1913 { 1914 return node.TryGetValueAsDictionaryString(out value); 1915 } 1916 ReadInt16Array(string localName, string namespaceUri)1917 public override Int16[] ReadInt16Array(string localName, string namespaceUri) 1918 { 1919 return Int16ArrayHelperWithString.Instance.ReadArray(this, localName, namespaceUri, quotas.MaxArrayLength); 1920 } 1921 ReadInt16Array(XmlDictionaryString localName, XmlDictionaryString namespaceUri)1922 public override Int16[] ReadInt16Array(XmlDictionaryString localName, XmlDictionaryString namespaceUri) 1923 { 1924 return Int16ArrayHelperWithDictionaryString.Instance.ReadArray(this, localName, namespaceUri, quotas.MaxArrayLength); 1925 } 1926 ReadInt32Array(string localName, string namespaceUri)1927 public override Int32[] ReadInt32Array(string localName, string namespaceUri) 1928 { 1929 return Int32ArrayHelperWithString.Instance.ReadArray(this, localName, namespaceUri, quotas.MaxArrayLength); 1930 } 1931 ReadInt32Array(XmlDictionaryString localName, XmlDictionaryString namespaceUri)1932 public override Int32[] ReadInt32Array(XmlDictionaryString localName, XmlDictionaryString namespaceUri) 1933 { 1934 return Int32ArrayHelperWithDictionaryString.Instance.ReadArray(this, localName, namespaceUri, quotas.MaxArrayLength); 1935 } 1936 ReadInt64Array(string localName, string namespaceUri)1937 public override Int64[] ReadInt64Array(string localName, string namespaceUri) 1938 { 1939 return Int64ArrayHelperWithString.Instance.ReadArray(this, localName, namespaceUri, quotas.MaxArrayLength); 1940 } 1941 ReadInt64Array(XmlDictionaryString localName, XmlDictionaryString namespaceUri)1942 public override Int64[] ReadInt64Array(XmlDictionaryString localName, XmlDictionaryString namespaceUri) 1943 { 1944 return Int64ArrayHelperWithDictionaryString.Instance.ReadArray(this, localName, namespaceUri, quotas.MaxArrayLength); 1945 } 1946 ReadSingleArray(string localName, string namespaceUri)1947 public override float[] ReadSingleArray(string localName, string namespaceUri) 1948 { 1949 return SingleArrayHelperWithString.Instance.ReadArray(this, localName, namespaceUri, quotas.MaxArrayLength); 1950 } 1951 ReadSingleArray(XmlDictionaryString localName, XmlDictionaryString namespaceUri)1952 public override float[] ReadSingleArray(XmlDictionaryString localName, XmlDictionaryString namespaceUri) 1953 { 1954 return SingleArrayHelperWithDictionaryString.Instance.ReadArray(this, localName, namespaceUri, quotas.MaxArrayLength); 1955 } 1956 ReadDoubleArray(string localName, string namespaceUri)1957 public override double[] ReadDoubleArray(string localName, string namespaceUri) 1958 { 1959 return DoubleArrayHelperWithString.Instance.ReadArray(this, localName, namespaceUri, quotas.MaxArrayLength); 1960 } 1961 ReadDoubleArray(XmlDictionaryString localName, XmlDictionaryString namespaceUri)1962 public override double[] ReadDoubleArray(XmlDictionaryString localName, XmlDictionaryString namespaceUri) 1963 { 1964 return DoubleArrayHelperWithDictionaryString.Instance.ReadArray(this, localName, namespaceUri, quotas.MaxArrayLength); 1965 } 1966 ReadDecimalArray(string localName, string namespaceUri)1967 public override decimal[] ReadDecimalArray(string localName, string namespaceUri) 1968 { 1969 return DecimalArrayHelperWithString.Instance.ReadArray(this, localName, namespaceUri, quotas.MaxArrayLength); 1970 } 1971 ReadDecimalArray(XmlDictionaryString localName, XmlDictionaryString namespaceUri)1972 public override decimal[] ReadDecimalArray(XmlDictionaryString localName, XmlDictionaryString namespaceUri) 1973 { 1974 return DecimalArrayHelperWithDictionaryString.Instance.ReadArray(this, localName, namespaceUri, quotas.MaxArrayLength); 1975 } 1976 ReadDateTimeArray(string localName, string namespaceUri)1977 public override DateTime[] ReadDateTimeArray(string localName, string namespaceUri) 1978 { 1979 return DateTimeArrayHelperWithString.Instance.ReadArray(this, localName, namespaceUri, quotas.MaxArrayLength); 1980 } 1981 ReadDateTimeArray(XmlDictionaryString localName, XmlDictionaryString namespaceUri)1982 public override DateTime[] ReadDateTimeArray(XmlDictionaryString localName, XmlDictionaryString namespaceUri) 1983 { 1984 return DateTimeArrayHelperWithDictionaryString.Instance.ReadArray(this, localName, namespaceUri, quotas.MaxArrayLength); 1985 } 1986 ReadGuidArray(string localName, string namespaceUri)1987 public override Guid[] ReadGuidArray(string localName, string namespaceUri) 1988 { 1989 return GuidArrayHelperWithString.Instance.ReadArray(this, localName, namespaceUri, quotas.MaxArrayLength); 1990 } 1991 ReadGuidArray(XmlDictionaryString localName, XmlDictionaryString namespaceUri)1992 public override Guid[] ReadGuidArray(XmlDictionaryString localName, XmlDictionaryString namespaceUri) 1993 { 1994 return GuidArrayHelperWithDictionaryString.Instance.ReadArray(this, localName, namespaceUri, quotas.MaxArrayLength); 1995 } 1996 ReadTimeSpanArray(string localName, string namespaceUri)1997 public override TimeSpan[] ReadTimeSpanArray(string localName, string namespaceUri) 1998 { 1999 return TimeSpanArrayHelperWithString.Instance.ReadArray(this, localName, namespaceUri, quotas.MaxArrayLength); 2000 } 2001 ReadTimeSpanArray(XmlDictionaryString localName, XmlDictionaryString namespaceUri)2002 public override TimeSpan[] ReadTimeSpanArray(XmlDictionaryString localName, XmlDictionaryString namespaceUri) 2003 { 2004 return TimeSpanArrayHelperWithDictionaryString.Instance.ReadArray(this, localName, namespaceUri, quotas.MaxArrayLength); 2005 } 2006 GetOpenElements()2007 public string GetOpenElements() 2008 { 2009 string s = string.Empty; 2010 for (int i = depth; i > 0; i--) 2011 { 2012 string localName = elementNodes[i].LocalName.GetString(); 2013 if (i != depth) 2014 s += ", "; 2015 s += localName; 2016 } 2017 return s; 2018 } 2019 GetCharBuffer(int count)2020 char[] GetCharBuffer(int count) 2021 { 2022 if (count > 1024) 2023 return new char[count]; 2024 2025 if (chars == null || chars.Length < count) 2026 chars = new char[count]; 2027 2028 return chars; 2029 } 2030 SignStartElement(XmlSigningNodeWriter writer)2031 void SignStartElement(XmlSigningNodeWriter writer) 2032 { 2033 int prefixOffset, prefixLength; 2034 byte[] prefixBuffer = node.Prefix.GetString(out prefixOffset, out prefixLength); 2035 int localNameOffset, localNameLength; 2036 byte[] localNameBuffer = node.LocalName.GetString(out localNameOffset, out localNameLength); 2037 writer.WriteStartElement(prefixBuffer, prefixOffset, prefixLength, localNameBuffer, localNameOffset, localNameLength); 2038 } 2039 SignAttribute(XmlSigningNodeWriter writer, XmlAttributeNode attributeNode)2040 void SignAttribute(XmlSigningNodeWriter writer, XmlAttributeNode attributeNode) 2041 { 2042 QNameType qnameType = attributeNode.QNameType; 2043 if (qnameType == QNameType.Normal) 2044 { 2045 int prefixOffset, prefixLength; 2046 byte[] prefixBuffer = attributeNode.Prefix.GetString(out prefixOffset, out prefixLength); 2047 int localNameOffset, localNameLength; 2048 byte[] localNameBuffer = attributeNode.LocalName.GetString(out localNameOffset, out localNameLength); 2049 writer.WriteStartAttribute(prefixBuffer, prefixOffset, prefixLength, localNameBuffer, localNameOffset, localNameLength); 2050 attributeNode.Value.Sign(writer); 2051 writer.WriteEndAttribute(); 2052 } 2053 else 2054 { 2055 Fx.Assert(qnameType == QNameType.Xmlns, ""); 2056 int prefixOffset, prefixLength; 2057 byte[] prefixBuffer = attributeNode.Namespace.Prefix.GetString(out prefixOffset, out prefixLength); 2058 int nsOffset, nsLength; 2059 byte[] nsBuffer = attributeNode.Namespace.Uri.GetString(out nsOffset, out nsLength); 2060 writer.WriteXmlnsAttribute(prefixBuffer, prefixOffset, prefixLength, nsBuffer, nsOffset, nsLength); 2061 } 2062 } 2063 SignEndElement(XmlSigningNodeWriter writer)2064 void SignEndElement(XmlSigningNodeWriter writer) 2065 { 2066 int prefixOffset, prefixLength; 2067 byte[] prefixBuffer = node.Prefix.GetString(out prefixOffset, out prefixLength); 2068 int localNameOffset, localNameLength; 2069 byte[] localNameBuffer = node.LocalName.GetString(out localNameOffset, out localNameLength); 2070 writer.WriteEndElement(prefixBuffer, prefixOffset, prefixLength, localNameBuffer, localNameOffset, localNameLength); 2071 } 2072 SignNode(XmlSigningNodeWriter writer)2073 void SignNode(XmlSigningNodeWriter writer) 2074 { 2075 switch (node.NodeType) 2076 { 2077 case XmlNodeType.None: 2078 break; 2079 case XmlNodeType.Element: 2080 SignStartElement(writer); 2081 for (int i = 0; i < attributeCount; i++) 2082 SignAttribute(writer, attributeNodes[i]); 2083 writer.WriteEndStartElement(node.IsEmptyElement); 2084 break; 2085 case XmlNodeType.Text: 2086 case XmlNodeType.Whitespace: 2087 case XmlNodeType.SignificantWhitespace: 2088 case XmlNodeType.CDATA: 2089 node.Value.Sign(writer); 2090 break; 2091 case XmlNodeType.XmlDeclaration: 2092 writer.WriteDeclaration(); 2093 break; 2094 case XmlNodeType.Comment: 2095 writer.WriteComment(node.Value.GetString()); 2096 break; 2097 case XmlNodeType.EndElement: 2098 SignEndElement(writer); 2099 break; 2100 default: 2101 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException()); 2102 } 2103 } 2104 2105 public override bool CanCanonicalize 2106 { 2107 get 2108 { 2109 return true; 2110 } 2111 } 2112 2113 protected bool Signing 2114 { 2115 get 2116 { 2117 return signing; 2118 } 2119 } 2120 SignNode()2121 protected void SignNode() 2122 { 2123 if (signing) 2124 { 2125 SignNode(signingWriter); 2126 } 2127 } 2128 StartCanonicalization(Stream stream, bool includeComments, string[] inclusivePrefixes)2129 public override void StartCanonicalization(Stream stream, bool includeComments, string[] inclusivePrefixes) 2130 { 2131 if (signing) 2132 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.XmlCanonicalizationStarted))); 2133 2134 if (signingWriter == null) 2135 signingWriter = CreateSigningNodeWriter(); 2136 2137 signingWriter.SetOutput(XmlNodeWriter.Null, stream, includeComments, inclusivePrefixes); 2138 nsMgr.Sign(signingWriter); 2139 signing = true; 2140 } 2141 EndCanonicalization()2142 public override void EndCanonicalization() 2143 { 2144 if (!signing) 2145 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.XmlCanonicalizationNotStarted))); 2146 2147 signingWriter.Flush(); 2148 signingWriter.Close(); 2149 signing = false; 2150 } 2151 CreateSigningNodeWriter()2152 protected abstract XmlSigningNodeWriter CreateSigningNodeWriter(); 2153 2154 protected enum QNameType 2155 { 2156 Normal, 2157 Xmlns, 2158 } 2159 2160 protected class XmlNode 2161 { 2162 XmlNodeType nodeType; 2163 PrefixHandle prefix; 2164 StringHandle localName; 2165 ValueHandle value; 2166 Namespace ns; 2167 bool hasValue; 2168 bool canGetAttribute; 2169 bool canMoveToElement; 2170 ReadState readState; 2171 XmlAttributeTextNode attributeTextNode; 2172 bool exitScope; 2173 int depthDelta; 2174 bool isAtomicValue; 2175 bool skipValue; 2176 QNameType qnameType; 2177 bool hasContent; 2178 bool isEmptyElement; 2179 char quoteChar; 2180 2181 protected enum XmlNodeFlags 2182 { 2183 None = 0x00, 2184 CanGetAttribute = 0x01, 2185 CanMoveToElement = 0x02, 2186 HasValue = 0x04, 2187 AtomicValue = 0x08, 2188 SkipValue = 0x10, 2189 HasContent = 0x20 2190 } 2191 XmlNode(XmlNodeType nodeType, PrefixHandle prefix, StringHandle localName, ValueHandle value, XmlNodeFlags nodeFlags, ReadState readState, XmlAttributeTextNode attributeTextNode, int depthDelta)2192 protected XmlNode(XmlNodeType nodeType, 2193 PrefixHandle prefix, 2194 StringHandle localName, 2195 ValueHandle value, 2196 XmlNodeFlags nodeFlags, 2197 ReadState readState, 2198 XmlAttributeTextNode attributeTextNode, 2199 int depthDelta) 2200 { 2201 this.nodeType = nodeType; 2202 this.prefix = prefix; 2203 this.localName = localName; 2204 this.value = value; 2205 this.ns = NamespaceManager.EmptyNamespace; 2206 this.hasValue = ((nodeFlags & XmlNodeFlags.HasValue) != 0); 2207 this.canGetAttribute = ((nodeFlags & XmlNodeFlags.CanGetAttribute) != 0); 2208 this.canMoveToElement = ((nodeFlags & XmlNodeFlags.CanMoveToElement) != 0); 2209 this.isAtomicValue = ((nodeFlags & XmlNodeFlags.AtomicValue) != 0); 2210 this.skipValue = ((nodeFlags & XmlNodeFlags.SkipValue) != 0); 2211 this.hasContent = ((nodeFlags & XmlNodeFlags.HasContent) != 0); 2212 this.readState = readState; 2213 this.attributeTextNode = attributeTextNode; 2214 this.exitScope = (nodeType == XmlNodeType.EndElement); 2215 this.depthDelta = depthDelta; 2216 this.isEmptyElement = false; 2217 this.quoteChar = '"'; 2218 this.qnameType = QNameType.Normal; 2219 } 2220 2221 // Most nodes are read-only and fixed for the particular node type, but a few need to be tweaked 2222 // QNameType needs to get set for all nodes with a qname (Element/Attribute) 2223 // NodeType gets set for WhiteSpace vs. SignificantWhitespace 2224 // ExitScope/IsEmptyElement is only updated by text for empty elements 2225 // QuoteChar is only updated by text for attributes 2226 // IsAtomicValue is set to false for XmlnsAttributes so we don't have to check QNameType 2227 2228 public bool HasValue { get { return hasValue; } } 2229 public ReadState ReadState { get { return readState; } } 2230 public StringHandle LocalName { get { Fx.Assert(qnameType != QNameType.Xmlns, ""); return localName; } } 2231 public PrefixHandle Prefix { get { Fx.Assert(qnameType != QNameType.Xmlns, ""); return prefix; } } 2232 public bool CanGetAttribute { get { return canGetAttribute; } } 2233 public bool CanMoveToElement { get { return canMoveToElement; } } 2234 public XmlAttributeTextNode AttributeText { get { return attributeTextNode; } } 2235 public bool SkipValue { get { return skipValue; } } 2236 public ValueHandle Value { get { Fx.Assert(qnameType != QNameType.Xmlns, ""); return value; } } 2237 public int DepthDelta { get { return depthDelta; } } 2238 public bool HasContent { get { return hasContent; } } 2239 2240 public XmlNodeType NodeType 2241 { 2242 get 2243 { 2244 return nodeType; 2245 } 2246 set 2247 { 2248 nodeType = value; 2249 } 2250 } 2251 2252 public QNameType QNameType 2253 { 2254 get 2255 { 2256 return qnameType; 2257 } 2258 set 2259 { 2260 qnameType = value; 2261 } 2262 } 2263 2264 public Namespace Namespace 2265 { 2266 get 2267 { 2268 return ns; 2269 } 2270 set 2271 { 2272 ns = value; 2273 } 2274 } 2275 2276 public bool IsAtomicValue 2277 { 2278 get 2279 { 2280 return isAtomicValue; 2281 } 2282 set 2283 { 2284 isAtomicValue = value; 2285 } 2286 } 2287 2288 public bool ExitScope 2289 { 2290 get 2291 { 2292 return exitScope; 2293 } 2294 set 2295 { 2296 exitScope = value; 2297 } 2298 } 2299 2300 public bool IsEmptyElement 2301 { 2302 get 2303 { 2304 return isEmptyElement; 2305 } 2306 set 2307 { 2308 isEmptyElement = value; 2309 } 2310 } 2311 2312 public char QuoteChar 2313 { 2314 get 2315 { 2316 return quoteChar; 2317 } 2318 set 2319 { 2320 quoteChar = value; 2321 } 2322 } 2323 IsLocalName(string localName)2324 public bool IsLocalName(string localName) 2325 { 2326 if (qnameType == QNameType.Normal) 2327 { 2328 return this.LocalName == localName; 2329 } 2330 else 2331 { 2332 Fx.Assert(qnameType == QNameType.Xmlns, ""); 2333 return this.Namespace.Prefix == localName; 2334 } 2335 } 2336 IsLocalName(XmlDictionaryString localName)2337 public bool IsLocalName(XmlDictionaryString localName) 2338 { 2339 if (qnameType == QNameType.Normal) 2340 { 2341 return this.LocalName == localName; 2342 } 2343 else 2344 { 2345 Fx.Assert(qnameType == QNameType.Xmlns, ""); 2346 return this.Namespace.Prefix == localName; 2347 } 2348 } 2349 IsNamespaceUri(string ns)2350 public bool IsNamespaceUri(string ns) 2351 { 2352 if (qnameType == QNameType.Normal) 2353 { 2354 return this.Namespace.IsUri(ns); 2355 } 2356 else 2357 { 2358 Fx.Assert(qnameType == QNameType.Xmlns, ""); 2359 return ns == xmlnsNamespace; 2360 } 2361 } 2362 IsNamespaceUri(XmlDictionaryString ns)2363 public bool IsNamespaceUri(XmlDictionaryString ns) 2364 { 2365 if (qnameType == QNameType.Normal) 2366 { 2367 return this.Namespace.IsUri(ns); 2368 } 2369 else 2370 { 2371 Fx.Assert(qnameType == QNameType.Xmlns, ""); 2372 return ns.Value == xmlnsNamespace; 2373 } 2374 } 2375 IsLocalNameAndNamespaceUri(string localName, string ns)2376 public bool IsLocalNameAndNamespaceUri(string localName, string ns) 2377 { 2378 if (qnameType == QNameType.Normal) 2379 { 2380 return this.LocalName == localName && this.Namespace.IsUri(ns); 2381 } 2382 else 2383 { 2384 Fx.Assert(qnameType == QNameType.Xmlns, ""); 2385 return this.Namespace.Prefix == localName && ns == xmlnsNamespace; 2386 } 2387 } 2388 IsLocalNameAndNamespaceUri(XmlDictionaryString localName, XmlDictionaryString ns)2389 public bool IsLocalNameAndNamespaceUri(XmlDictionaryString localName, XmlDictionaryString ns) 2390 { 2391 if (qnameType == QNameType.Normal) 2392 { 2393 return this.LocalName == localName && this.Namespace.IsUri(ns); 2394 } 2395 else 2396 { 2397 Fx.Assert(qnameType == QNameType.Xmlns, ""); 2398 return this.Namespace.Prefix == localName && ns.Value == xmlnsNamespace; 2399 } 2400 } 2401 IsPrefixAndLocalName(string prefix, string localName)2402 public bool IsPrefixAndLocalName(string prefix, string localName) 2403 { 2404 if (qnameType == QNameType.Normal) 2405 { 2406 return this.Prefix == prefix && this.LocalName == localName; 2407 } 2408 else 2409 { 2410 Fx.Assert(qnameType == QNameType.Xmlns, ""); 2411 return prefix == xmlns && this.Namespace.Prefix == localName; 2412 } 2413 } 2414 TryGetLocalNameAsDictionaryString(out XmlDictionaryString localName)2415 public bool TryGetLocalNameAsDictionaryString(out XmlDictionaryString localName) 2416 { 2417 if (qnameType == QNameType.Normal) 2418 { 2419 return this.LocalName.TryGetDictionaryString(out localName); 2420 } 2421 else 2422 { 2423 Fx.Assert(qnameType == QNameType.Xmlns, ""); 2424 localName = null; 2425 return false; 2426 } 2427 } 2428 TryGetNamespaceUriAsDictionaryString(out XmlDictionaryString ns)2429 public bool TryGetNamespaceUriAsDictionaryString(out XmlDictionaryString ns) 2430 { 2431 if (qnameType == QNameType.Normal) 2432 { 2433 return this.Namespace.Uri.TryGetDictionaryString(out ns); 2434 } 2435 else 2436 { 2437 Fx.Assert(qnameType == QNameType.Xmlns, ""); 2438 ns = null; 2439 return false; 2440 } 2441 } 2442 TryGetValueAsDictionaryString(out XmlDictionaryString value)2443 public bool TryGetValueAsDictionaryString(out XmlDictionaryString value) 2444 { 2445 if (qnameType == QNameType.Normal) 2446 { 2447 return this.Value.TryGetDictionaryString(out value); 2448 } 2449 else 2450 { 2451 Fx.Assert(qnameType == QNameType.Xmlns, ""); 2452 value = null; 2453 return false; 2454 } 2455 } 2456 2457 public string ValueAsString 2458 { 2459 get 2460 { 2461 if (qnameType == QNameType.Normal) 2462 { 2463 return Value.GetString(); 2464 } 2465 else 2466 { 2467 Fx.Assert(qnameType == QNameType.Xmlns, ""); 2468 return Namespace.Uri.GetString(); 2469 } 2470 } 2471 } 2472 } 2473 2474 protected class XmlElementNode : XmlNode 2475 { 2476 XmlEndElementNode endElementNode; 2477 int bufferOffset; 2478 XmlElementNode(XmlBufferReader bufferReader)2479 public XmlElementNode(XmlBufferReader bufferReader) 2480 : this(new PrefixHandle(bufferReader), 2481 new StringHandle(bufferReader), 2482 new ValueHandle(bufferReader)) 2483 { 2484 } 2485 XmlElementNode(PrefixHandle prefix, StringHandle localName, ValueHandle value)2486 XmlElementNode(PrefixHandle prefix, StringHandle localName, ValueHandle value) 2487 : base(XmlNodeType.Element, 2488 prefix, 2489 localName, 2490 value, 2491 XmlNodeFlags.CanGetAttribute | XmlNodeFlags.HasContent, 2492 ReadState.Interactive, 2493 null, 2494 -1) 2495 { 2496 this.endElementNode = new XmlEndElementNode(prefix, localName, value); 2497 } 2498 2499 public XmlEndElementNode EndElement 2500 { 2501 get 2502 { 2503 return endElementNode; 2504 } 2505 } 2506 2507 public int BufferOffset 2508 { 2509 get 2510 { 2511 return bufferOffset; 2512 } 2513 set 2514 { 2515 bufferOffset = value; 2516 } 2517 } 2518 2519 public int NameOffset; 2520 public int NameLength; 2521 } 2522 2523 protected class XmlAttributeNode : XmlNode 2524 { XmlAttributeNode(XmlBufferReader bufferReader)2525 public XmlAttributeNode(XmlBufferReader bufferReader) 2526 : this(new PrefixHandle(bufferReader), new StringHandle(bufferReader), new ValueHandle(bufferReader)) 2527 { 2528 } 2529 XmlAttributeNode(PrefixHandle prefix, StringHandle localName, ValueHandle value)2530 XmlAttributeNode(PrefixHandle prefix, StringHandle localName, ValueHandle value) 2531 : base(XmlNodeType.Attribute, 2532 prefix, 2533 localName, 2534 value, 2535 XmlNodeFlags.CanGetAttribute | XmlNodeFlags.CanMoveToElement | XmlNodeFlags.HasValue | XmlNodeFlags.AtomicValue, 2536 ReadState.Interactive, 2537 new XmlAttributeTextNode(prefix, localName, value), 2538 0) 2539 { 2540 } 2541 } 2542 2543 protected class XmlEndElementNode : XmlNode 2544 { XmlEndElementNode(PrefixHandle prefix, StringHandle localName, ValueHandle value)2545 public XmlEndElementNode(PrefixHandle prefix, StringHandle localName, ValueHandle value) 2546 : base(XmlNodeType.EndElement, 2547 prefix, 2548 localName, 2549 value, 2550 XmlNodeFlags.HasContent, 2551 ReadState.Interactive, 2552 null, 2553 -1) 2554 { 2555 } 2556 } 2557 2558 protected class XmlTextNode : XmlNode 2559 { XmlTextNode(XmlNodeType nodeType, PrefixHandle prefix, StringHandle localName, ValueHandle value, XmlNodeFlags nodeFlags, ReadState readState, XmlAttributeTextNode attributeTextNode, int depthDelta)2560 protected XmlTextNode(XmlNodeType nodeType, 2561 PrefixHandle prefix, 2562 StringHandle localName, 2563 ValueHandle value, 2564 XmlNodeFlags nodeFlags, 2565 ReadState readState, 2566 XmlAttributeTextNode attributeTextNode, 2567 int depthDelta) 2568 : 2569 base(nodeType, prefix, localName, value, nodeFlags, readState, attributeTextNode, depthDelta) 2570 { 2571 } 2572 } 2573 2574 protected class XmlAtomicTextNode : XmlTextNode 2575 { XmlAtomicTextNode(XmlBufferReader bufferReader)2576 public XmlAtomicTextNode(XmlBufferReader bufferReader) 2577 : base(XmlNodeType.Text, 2578 new PrefixHandle(bufferReader), 2579 new StringHandle(bufferReader), 2580 new ValueHandle(bufferReader), 2581 XmlNodeFlags.HasValue | XmlNodeFlags.AtomicValue | XmlNodeFlags.SkipValue | XmlNodeFlags.HasContent, 2582 ReadState.Interactive, 2583 null, 2584 0) 2585 { 2586 } 2587 } 2588 2589 protected class XmlComplexTextNode : XmlTextNode 2590 { XmlComplexTextNode(XmlBufferReader bufferReader)2591 public XmlComplexTextNode(XmlBufferReader bufferReader) 2592 : base(XmlNodeType.Text, 2593 new PrefixHandle(bufferReader), 2594 new StringHandle(bufferReader), 2595 new ValueHandle(bufferReader), 2596 XmlNodeFlags.HasValue | XmlNodeFlags.HasContent, 2597 ReadState.Interactive, 2598 null, 2599 0) 2600 { 2601 } 2602 } 2603 2604 protected class XmlWhitespaceTextNode : XmlTextNode 2605 { XmlWhitespaceTextNode(XmlBufferReader bufferReader)2606 public XmlWhitespaceTextNode(XmlBufferReader bufferReader) 2607 : base(XmlNodeType.Whitespace, 2608 new PrefixHandle(bufferReader), 2609 new StringHandle(bufferReader), 2610 new ValueHandle(bufferReader), 2611 XmlNodeFlags.HasValue, 2612 ReadState.Interactive, 2613 null, 2614 0) 2615 { 2616 } 2617 } 2618 2619 protected class XmlCDataNode : XmlTextNode 2620 { XmlCDataNode(XmlBufferReader bufferReader)2621 public XmlCDataNode(XmlBufferReader bufferReader) 2622 : base(XmlNodeType.CDATA, 2623 new PrefixHandle(bufferReader), 2624 new StringHandle(bufferReader), 2625 new ValueHandle(bufferReader), 2626 XmlNodeFlags.HasValue | XmlNodeFlags.HasContent, 2627 ReadState.Interactive, 2628 null, 2629 0) 2630 { 2631 } 2632 } 2633 2634 protected class XmlAttributeTextNode : XmlTextNode 2635 { XmlAttributeTextNode(PrefixHandle prefix, StringHandle localName, ValueHandle value)2636 public XmlAttributeTextNode(PrefixHandle prefix, StringHandle localName, ValueHandle value) 2637 : base(XmlNodeType.Text, 2638 prefix, 2639 localName, 2640 value, 2641 XmlNodeFlags.HasValue | XmlNodeFlags.CanGetAttribute | XmlNodeFlags.CanMoveToElement | XmlNodeFlags.AtomicValue | XmlNodeFlags.HasContent, 2642 ReadState.Interactive, 2643 null, 2644 1) 2645 { 2646 } 2647 } 2648 2649 protected class XmlInitialNode : XmlNode 2650 { XmlInitialNode(XmlBufferReader bufferReader)2651 public XmlInitialNode(XmlBufferReader bufferReader) 2652 : base(XmlNodeType.None, 2653 new PrefixHandle(bufferReader), 2654 new StringHandle(bufferReader), 2655 new ValueHandle(bufferReader), 2656 XmlNodeFlags.None, 2657 ReadState.Initial, 2658 null, 2659 0) 2660 { 2661 } 2662 } 2663 2664 protected class XmlDeclarationNode : XmlNode 2665 { XmlDeclarationNode(XmlBufferReader bufferReader)2666 public XmlDeclarationNode(XmlBufferReader bufferReader) 2667 : base(XmlNodeType.XmlDeclaration, 2668 new PrefixHandle(bufferReader), 2669 new StringHandle(bufferReader), 2670 new ValueHandle(bufferReader), 2671 XmlNodeFlags.CanGetAttribute, 2672 ReadState.Interactive, 2673 null, 2674 0) 2675 { 2676 } 2677 } 2678 2679 protected class XmlCommentNode : XmlNode 2680 { XmlCommentNode(XmlBufferReader bufferReader)2681 public XmlCommentNode(XmlBufferReader bufferReader) 2682 : base(XmlNodeType.Comment, 2683 new PrefixHandle(bufferReader), 2684 new StringHandle(bufferReader), 2685 new ValueHandle(bufferReader), 2686 XmlNodeFlags.HasValue, 2687 ReadState.Interactive, 2688 null, 2689 0) 2690 { 2691 } 2692 } 2693 2694 protected class XmlEndOfFileNode : XmlNode 2695 { XmlEndOfFileNode(XmlBufferReader bufferReader)2696 public XmlEndOfFileNode(XmlBufferReader bufferReader) 2697 : base(XmlNodeType.None, 2698 new PrefixHandle(bufferReader), 2699 new StringHandle(bufferReader), 2700 new ValueHandle(bufferReader), 2701 XmlNodeFlags.None, 2702 ReadState.EndOfFile, 2703 null, 2704 0) 2705 { 2706 } 2707 } 2708 2709 protected class XmlClosedNode : XmlNode 2710 { XmlClosedNode(XmlBufferReader bufferReader)2711 public XmlClosedNode(XmlBufferReader bufferReader) 2712 : base(XmlNodeType.None, 2713 new PrefixHandle(bufferReader), 2714 new StringHandle(bufferReader), 2715 new ValueHandle(bufferReader), 2716 XmlNodeFlags.None, 2717 ReadState.Closed, 2718 null, 2719 0) 2720 { 2721 } 2722 } 2723 2724 class AttributeSorter : IComparer 2725 { 2726 object[] indeces; 2727 XmlAttributeNode[] attributeNodes; 2728 int attributeCount; 2729 int attributeIndex1; 2730 int attributeIndex2; 2731 Sort(XmlAttributeNode[] attributeNodes, int attributeCount)2732 public bool Sort(XmlAttributeNode[] attributeNodes, int attributeCount) 2733 { 2734 this.attributeIndex1 = -1; 2735 this.attributeIndex2 = -1; 2736 this.attributeNodes = attributeNodes; 2737 this.attributeCount = attributeCount; 2738 bool sorted = Sort(); 2739 this.attributeNodes = null; 2740 this.attributeCount = 0; 2741 return sorted; 2742 } 2743 GetIndeces(out int attributeIndex1, out int attributeIndex2)2744 public void GetIndeces(out int attributeIndex1, out int attributeIndex2) 2745 { 2746 attributeIndex1 = this.attributeIndex1; 2747 attributeIndex2 = this.attributeIndex2; 2748 } 2749 Close()2750 public void Close() 2751 { 2752 if (indeces != null && indeces.Length > 32) 2753 { 2754 indeces = null; 2755 } 2756 } 2757 Sort()2758 bool Sort() 2759 { 2760 // Optimistically use the last sort order and check to see if that works. This helps the case 2761 // where elements with large numbers of attributes are repeated. 2762 if (indeces != null && indeces.Length == attributeCount && IsSorted()) 2763 return true; 2764 2765 object[] newIndeces = new object[attributeCount]; 2766 for (int i = 0; i < newIndeces.Length; i++) 2767 newIndeces[i] = i; 2768 this.indeces = newIndeces; 2769 Array.Sort(indeces, 0, attributeCount, this); 2770 return IsSorted(); 2771 } 2772 IsSorted()2773 bool IsSorted() 2774 { 2775 for (int i = 0; i < indeces.Length - 1; i++) 2776 { 2777 if (Compare(indeces[i], indeces[i + 1]) >= 0) 2778 { 2779 attributeIndex1 = (int)indeces[i]; 2780 attributeIndex2 = (int)indeces[i + 1]; 2781 return false; 2782 } 2783 } 2784 return true; 2785 } 2786 Compare(object obj1, object obj2)2787 public int Compare(object obj1, object obj2) 2788 { 2789 int index1 = (int)obj1; 2790 int index2 = (int)obj2; 2791 XmlAttributeNode attribute1 = attributeNodes[index1]; 2792 XmlAttributeNode attribute2 = attributeNodes[index2]; 2793 2794 int i = CompareQNameType(attribute1.QNameType, attribute2.QNameType); 2795 if (i == 0) 2796 { 2797 QNameType qnameType = attribute1.QNameType; 2798 if (qnameType == QNameType.Normal) 2799 { 2800 i = attribute1.LocalName.CompareTo(attribute2.LocalName); 2801 if (i == 0) 2802 { 2803 i = attribute1.Namespace.Uri.CompareTo(attribute2.Namespace.Uri); 2804 } 2805 } 2806 else 2807 { 2808 Fx.Assert(qnameType == QNameType.Xmlns, ""); 2809 i = attribute1.Namespace.Prefix.CompareTo(attribute2.Namespace.Prefix); 2810 } 2811 } 2812 2813 return i; 2814 } 2815 CompareQNameType(QNameType type1, QNameType type2)2816 public int CompareQNameType(QNameType type1, QNameType type2) 2817 { 2818 return (int)type1 - (int)type2; 2819 } 2820 } 2821 2822 class NamespaceManager 2823 { 2824 XmlBufferReader bufferReader; 2825 Namespace[] namespaces; 2826 int nsCount; 2827 int depth; 2828 Namespace[] shortPrefixUri; 2829 static Namespace emptyNamespace = new Namespace(XmlBufferReader.Empty); 2830 static Namespace xmlNamespace; 2831 XmlAttribute[] attributes; 2832 int attributeCount; 2833 XmlSpace space; 2834 string lang; 2835 NamespaceManager(XmlBufferReader bufferReader)2836 public NamespaceManager(XmlBufferReader bufferReader) 2837 { 2838 this.bufferReader = bufferReader; 2839 this.shortPrefixUri = new Namespace[(int)PrefixHandleType.Max]; 2840 this.shortPrefixUri[(int)PrefixHandleType.Empty] = emptyNamespace; 2841 this.namespaces = null; 2842 this.nsCount = 0; 2843 this.attributes = null; 2844 this.attributeCount = 0; 2845 this.space = XmlSpace.None; 2846 this.lang = string.Empty; 2847 this.depth = 0; 2848 } 2849 Close()2850 public void Close() 2851 { 2852 if (namespaces != null && namespaces.Length > 32) 2853 namespaces = null; 2854 if (attributes != null && attributes.Length > 4) 2855 attributes = null; 2856 lang = string.Empty; 2857 } 2858 2859 static public Namespace XmlNamespace 2860 { 2861 get 2862 { 2863 if (xmlNamespace == null) 2864 { 2865 byte[] xmlBuffer = 2866 { 2867 (byte)'x', (byte)'m', (byte)'l', 2868 (byte)'h', (byte)'t', (byte)'t', (byte)'p', (byte)':', (byte)'/', (byte)'/', (byte)'w', 2869 (byte)'w', (byte)'w', (byte)'.', (byte)'w', (byte)'3', (byte)'.', (byte)'o', (byte)'r', 2870 (byte)'g', (byte)'/', (byte)'X', (byte)'M', (byte)'L', (byte)'/', (byte)'1', (byte)'9', 2871 (byte)'9', (byte)'8', (byte)'/', (byte)'n', (byte)'a', (byte)'m', (byte)'e', (byte)'s', 2872 (byte)'p', (byte)'a', (byte)'c', (byte)'e' 2873 }; 2874 Namespace nameSpace = new Namespace(new XmlBufferReader(xmlBuffer)); 2875 nameSpace.Prefix.SetValue(0, 3); 2876 nameSpace.Uri.SetValue(3, xmlBuffer.Length - 3); 2877 xmlNamespace = nameSpace; 2878 } 2879 return xmlNamespace; 2880 } 2881 } 2882 2883 static public Namespace EmptyNamespace 2884 { 2885 get 2886 { 2887 return emptyNamespace; 2888 } 2889 } 2890 2891 public string XmlLang 2892 { 2893 get 2894 { 2895 return lang; 2896 } 2897 } 2898 2899 public XmlSpace XmlSpace 2900 { 2901 get 2902 { 2903 return space; 2904 } 2905 } 2906 Clear()2907 public void Clear() 2908 { 2909 if (nsCount != 0) 2910 { 2911 if (shortPrefixUri != null) 2912 { 2913 for (int i = 0; i < shortPrefixUri.Length; i++) 2914 { 2915 shortPrefixUri[i] = null; 2916 } 2917 } 2918 shortPrefixUri[(int)PrefixHandleType.Empty] = emptyNamespace; 2919 nsCount = 0; 2920 } 2921 this.attributeCount = 0; 2922 this.space = XmlSpace.None; 2923 this.lang = string.Empty; 2924 this.depth = 0; 2925 } 2926 EnterScope()2927 public void EnterScope() 2928 { 2929 depth++; 2930 } 2931 ExitScope()2932 public void ExitScope() 2933 { 2934 while (nsCount > 0) 2935 { 2936 Namespace nameSpace = namespaces[nsCount - 1]; 2937 if (nameSpace.Depth != depth) 2938 break; 2939 PrefixHandleType shortPrefix; 2940 if (nameSpace.Prefix.TryGetShortPrefix(out shortPrefix)) 2941 { 2942 shortPrefixUri[(int)shortPrefix] = nameSpace.OuterUri; 2943 } 2944 nsCount--; 2945 } 2946 while (attributeCount > 0) 2947 { 2948 XmlAttribute attribute = attributes[attributeCount - 1]; 2949 if (attribute.Depth != depth) 2950 break; 2951 space = attribute.XmlSpace; 2952 lang = attribute.XmlLang; 2953 attributeCount--; 2954 } 2955 depth--; 2956 } 2957 Sign(XmlSigningNodeWriter writer)2958 public void Sign(XmlSigningNodeWriter writer) 2959 { 2960 for (int i = 0; i < nsCount; i++) 2961 { 2962 PrefixHandle prefix = namespaces[i].Prefix; 2963 bool found = false; 2964 for (int j = i + 1; j < nsCount; j++) 2965 { 2966 if (Equals(prefix, namespaces[j].Prefix)) 2967 { 2968 found = true; 2969 break; 2970 } 2971 } 2972 if (!found) 2973 { 2974 int prefixOffset, prefixLength; 2975 byte[] prefixBuffer = prefix.GetString(out prefixOffset, out prefixLength); 2976 int nsOffset, nsLength; 2977 byte[] nsBuffer = namespaces[i].Uri.GetString(out nsOffset, out nsLength); 2978 writer.WriteXmlnsAttribute(prefixBuffer, prefixOffset, prefixLength, nsBuffer, nsOffset, nsLength); 2979 } 2980 } 2981 } 2982 AddLangAttribute(string lang)2983 public void AddLangAttribute(string lang) 2984 { 2985 AddAttribute(); 2986 this.lang = lang; 2987 } 2988 AddSpaceAttribute(XmlSpace space)2989 public void AddSpaceAttribute(XmlSpace space) 2990 { 2991 AddAttribute(); 2992 this.space = space; 2993 } 2994 AddAttribute()2995 void AddAttribute() 2996 { 2997 if (attributes == null) 2998 { 2999 attributes = new XmlAttribute[1]; 3000 } 3001 else if (attributes.Length == attributeCount) 3002 { 3003 XmlAttribute[] newAttributes = new XmlAttribute[attributeCount * 2]; 3004 Array.Copy(attributes, newAttributes, attributeCount); 3005 attributes = newAttributes; 3006 } 3007 XmlAttribute attribute = attributes[attributeCount]; 3008 if (attribute == null) 3009 { 3010 attribute = new XmlAttribute(); 3011 attributes[attributeCount] = attribute; 3012 } 3013 attribute.XmlLang = this.lang; 3014 attribute.XmlSpace = this.space; 3015 attribute.Depth = depth; 3016 attributeCount++; 3017 } 3018 Register(Namespace nameSpace)3019 public void Register(Namespace nameSpace) 3020 { 3021 PrefixHandleType shortPrefix; 3022 if (nameSpace.Prefix.TryGetShortPrefix(out shortPrefix)) 3023 { 3024 nameSpace.OuterUri = shortPrefixUri[(int)shortPrefix]; 3025 shortPrefixUri[(int)shortPrefix] = nameSpace; 3026 } 3027 else 3028 { 3029 nameSpace.OuterUri = null; 3030 } 3031 } 3032 AddNamespace()3033 public Namespace AddNamespace() 3034 { 3035 if (namespaces == null) 3036 { 3037 namespaces = new Namespace[4]; 3038 } 3039 else if (namespaces.Length == nsCount) 3040 { 3041 Namespace[] newNamespaces = new Namespace[nsCount * 2]; 3042 Array.Copy(namespaces, newNamespaces, nsCount); 3043 namespaces = newNamespaces; 3044 } 3045 Namespace nameSpace = namespaces[nsCount]; 3046 if (nameSpace == null) 3047 { 3048 nameSpace = new Namespace(bufferReader); 3049 namespaces[nsCount] = nameSpace; 3050 } 3051 nameSpace.Clear(); 3052 nameSpace.Depth = depth; 3053 nsCount++; 3054 return nameSpace; 3055 } 3056 LookupNamespace(PrefixHandleType prefix)3057 public Namespace LookupNamespace(PrefixHandleType prefix) 3058 { 3059 return shortPrefixUri[(int)prefix]; 3060 } 3061 LookupNamespace(PrefixHandle prefix)3062 public Namespace LookupNamespace(PrefixHandle prefix) 3063 { 3064 PrefixHandleType shortPrefix; 3065 if (prefix.TryGetShortPrefix(out shortPrefix)) 3066 return LookupNamespace(shortPrefix); 3067 for (int i = nsCount - 1; i >= 0; i--) 3068 { 3069 Namespace nameSpace = namespaces[i]; 3070 if (nameSpace.Prefix == prefix) 3071 return nameSpace; 3072 } 3073 if (prefix.IsXml) 3074 return XmlNamespace; 3075 return null; 3076 } 3077 LookupNamespace(string prefix)3078 public Namespace LookupNamespace(string prefix) 3079 { 3080 PrefixHandleType shortPrefix; 3081 if (TryGetShortPrefix(prefix, out shortPrefix)) 3082 return LookupNamespace(shortPrefix); 3083 for (int i = nsCount - 1; i >= 0; i--) 3084 { 3085 Namespace nameSpace = namespaces[i]; 3086 if (nameSpace.Prefix == prefix) 3087 return nameSpace; 3088 } 3089 if (prefix == "xml") 3090 return XmlNamespace; 3091 return null; 3092 } 3093 TryGetShortPrefix(string s, out PrefixHandleType shortPrefix)3094 bool TryGetShortPrefix(string s, out PrefixHandleType shortPrefix) 3095 { 3096 int length = s.Length; 3097 if (length == 0) 3098 { 3099 shortPrefix = PrefixHandleType.Empty; 3100 return true; 3101 } 3102 if (length == 1) 3103 { 3104 char ch = s[0]; 3105 if (ch >= 'a' && ch <= 'z') 3106 { 3107 shortPrefix = PrefixHandle.GetAlphaPrefix(ch - 'a'); 3108 return true; 3109 } 3110 } 3111 shortPrefix = PrefixHandleType.Empty; 3112 return false; 3113 } 3114 3115 class XmlAttribute 3116 { 3117 XmlSpace space; 3118 string lang; 3119 int depth; 3120 XmlAttribute()3121 public XmlAttribute() 3122 { 3123 } 3124 3125 public int Depth 3126 { 3127 get 3128 { 3129 return depth; 3130 } 3131 set 3132 { 3133 depth = value; 3134 } 3135 } 3136 3137 public string XmlLang 3138 { 3139 get 3140 { 3141 return lang; 3142 } 3143 set 3144 { 3145 lang = value; 3146 } 3147 } 3148 3149 public XmlSpace XmlSpace 3150 { 3151 get 3152 { 3153 return space; 3154 } 3155 set 3156 { 3157 space = value; 3158 } 3159 } 3160 } 3161 } 3162 3163 protected class Namespace 3164 { 3165 PrefixHandle prefix; 3166 StringHandle uri; 3167 int depth; 3168 Namespace outerUri; 3169 string uriString; 3170 Namespace(XmlBufferReader bufferReader)3171 public Namespace(XmlBufferReader bufferReader) 3172 { 3173 this.prefix = new PrefixHandle(bufferReader); 3174 this.uri = new StringHandle(bufferReader); 3175 this.outerUri = null; 3176 this.uriString = null; 3177 } 3178 Clear()3179 public void Clear() 3180 { 3181 this.uriString = null; 3182 } 3183 3184 public int Depth 3185 { 3186 get 3187 { 3188 return depth; 3189 } 3190 set 3191 { 3192 depth = value; 3193 } 3194 } 3195 3196 public PrefixHandle Prefix 3197 { 3198 get 3199 { 3200 return prefix; 3201 } 3202 } 3203 IsUri(string s)3204 public bool IsUri(string s) 3205 { 3206 Fx.Assert(s != null, ""); 3207 if (object.ReferenceEquals(s, uriString)) 3208 return true; 3209 if (uri == s) 3210 { 3211 uriString = s; 3212 return true; 3213 } 3214 return false; 3215 } 3216 IsUri(XmlDictionaryString s)3217 public bool IsUri(XmlDictionaryString s) 3218 { 3219 if (object.ReferenceEquals(s.Value, uriString)) 3220 return true; 3221 if (uri == s) 3222 { 3223 uriString = s.Value; 3224 return true; 3225 } 3226 return false; 3227 } 3228 3229 public StringHandle Uri 3230 { 3231 get 3232 { 3233 return uri; 3234 } 3235 } 3236 3237 public Namespace OuterUri 3238 { 3239 get 3240 { 3241 return outerUri; 3242 } 3243 set 3244 { 3245 outerUri = value; 3246 } 3247 } 3248 } 3249 3250 class QuotaNameTable : XmlNameTable 3251 { 3252 XmlDictionaryReader reader; 3253 XmlNameTable nameTable; 3254 int maxCharCount; 3255 int charCount; 3256 QuotaNameTable(XmlDictionaryReader reader, int maxCharCount)3257 public QuotaNameTable(XmlDictionaryReader reader, int maxCharCount) 3258 { 3259 this.reader = reader; 3260 this.nameTable = new NameTable(); 3261 this.maxCharCount = maxCharCount; 3262 this.charCount = 0; 3263 } 3264 Get(char[] chars, int offset, int count)3265 public override string Get(char[] chars, int offset, int count) 3266 { 3267 return nameTable.Get(chars, offset, count); 3268 } 3269 Get(string value)3270 public override string Get(string value) 3271 { 3272 return nameTable.Get(value); 3273 } 3274 Add(int charCount)3275 void Add(int charCount) 3276 { 3277 if (charCount > this.maxCharCount - this.charCount) 3278 XmlExceptionHelper.ThrowMaxNameTableCharCountExceeded(reader, maxCharCount); 3279 this.charCount += charCount; 3280 } 3281 Add(char[] chars, int offset, int count)3282 public override string Add(char[] chars, int offset, int count) 3283 { 3284 string s = nameTable.Get(chars, offset, count); 3285 if (s != null) 3286 return s; 3287 Add(count); 3288 return nameTable.Add(chars, offset, count); 3289 } 3290 Add(string value)3291 public override string Add(string value) 3292 { 3293 string s = nameTable.Get(value); 3294 if (s != null) 3295 return s; 3296 Add(value.Length); 3297 return nameTable.Add(value); 3298 } 3299 } 3300 } 3301 } 3302