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