The Labs \ Source Viewer \ SSCLI \ System.Xml \ NodeData

  1. //------------------------------------------------------------------------------
  2. // <copyright file="XmlSubtreeReader.cs" company="Microsoft">
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // </copyright>
  14. //------------------------------------------------------------------------------
  15. using System;
  16. using System.Xml;
  17. using System.Xml.Schema;
  18. using System.Diagnostics;
  19. using System.Collections;
  20. using System.Globalization;
  21. using System.Collections.Generic;
  22. namespace System.Xml
  23. {
  24.    
  25.     internal sealed class XmlSubtreeReader : XmlWrappingReader, IXmlNamespaceResolver
  26.     {
  27.         //
  28.         // Private types
  29.         //
  30.         class NodeData
  31.         {
  32.             internal XmlNodeType type;
  33.             internal string localName;
  34.             internal string prefix;
  35.             internal string name;
  36.             internal string namespaceUri;
  37.             internal string value;
  38.            
  39.             internal NodeData()
  40.             {
  41.             }
  42.            
  43.             internal void Set(XmlNodeType nodeType, string localName, string prefix, string name, string namespaceUri, string value)
  44.             {
  45.                 this.type = nodeType;
  46.                 this.localName = localName;
  47.                 this.prefix = prefix;
  48.                 this.name = name;
  49.                 this.namespaceUri = namespaceUri;
  50.                 this.value = value;
  51.             }
  52.         }
  53.        
  54.         enum State
  55.         {
  56.             Initial = ReadState.Initial,
  57.             Interactive = ReadState.Interactive,
  58.             Error = ReadState.Error,
  59.             EndOfFile = ReadState.EndOfFile,
  60.             Closed = ReadState.Closed,
  61.             PopNamespaceScope,
  62.             ClearNsAttributes,
  63.             ReadElementContentAsBase64,
  64.             ReadElementContentAsBinHex,
  65.             ReadContentAsBase64,
  66.             ReadContentAsBinHex
  67.         }
  68.        
  69.         const int AttributeActiveStates = 98;
  70.         // 00001100010 bin
  71.         const int NamespaceActiveStates = 2018;
  72.         // 11111100010 bin
  73.         //
  74.         // Fields
  75.         //
  76.         int initialDepth;
  77.         State state;
  78.        
  79.         // namespace management
  80.         XmlNamespaceManager nsManager;
  81.         NodeData[] nsAttributes;
  82.         int nsAttrCount;
  83.         int curNsAttr = -1;
  84.         string xmlns;
  85.         string xmlnsUri;
  86.        
  87.         // cached nodes
  88.         bool useCurNode;
  89.         NodeData curNode;
  90.         // node used for a text node of ReadAttributeValue or as Initial or EOF node
  91.         NodeData tmpNode;
  92.        
  93.         //
  94.         // Constants
  95.         //
  96.         internal int InitialNamespaceAttributeCount = 4;
  97.        
  98.         //
  99.         // Constructor
  100.         //
  101.         internal XmlSubtreeReader(XmlReader reader) : base(reader)
  102.         {
  103.             initialDepth = reader.Depth;
  104.             state = State.Initial;
  105.             nsManager = new XmlNamespaceManager(reader.NameTable);
  106.             xmlns = reader.NameTable.Add("xmlns");
  107.             xmlnsUri = reader.NameTable.Add(XmlReservedNs.NsXmlNs);
  108.            
  109.             tmpNode = new NodeData();
  110.             tmpNode.Set(XmlNodeType.None, string.Empty, string.Empty, string.Empty, string.Empty, string.Empty);
  111.            
  112.             SetCurrentNode(tmpNode);
  113.         }
  114.        
  115.         //
  116.         // XmlReader implementation
  117.         //
  118.         public override XmlReaderSettings Settings {
  119.             get { return reader.Settings; }
  120.         }
  121.        
  122.         public override XmlNodeType NodeType {
  123.             get { return (useCurNode) ? curNode.type : reader.NodeType; }
  124.         }
  125.        
  126.         public override string Name {
  127.             get { return (useCurNode) ? curNode.name : reader.Name; }
  128.         }
  129.        
  130.         public override string LocalName {
  131.             get { return (useCurNode) ? curNode.localName : reader.LocalName; }
  132.         }
  133.        
  134.         public override string NamespaceURI {
  135.             get { return (useCurNode) ? curNode.namespaceUri : reader.NamespaceURI; }
  136.         }
  137.        
  138.         public override string Prefix {
  139.             get { return (useCurNode) ? curNode.prefix : reader.Prefix; }
  140.         }
  141.        
  142.         public override string Value {
  143.             get { return (useCurNode) ? curNode.value : reader.Value; }
  144.         }
  145.        
  146.         public override int Depth {
  147.             get {
  148.                 int depth = reader.Depth - initialDepth;
  149.                 if (curNsAttr != -1) {
  150.                     if (curNode.type == XmlNodeType.Text) {
  151.                         // we are on namespace attribute value
  152.                         depth += 2;
  153.                     }
  154.                     else {
  155.                         depth++;
  156.                     }
  157.                 }
  158.                 return depth;
  159.             }
  160.         }
  161.        
  162.         public override string BaseURI {
  163.             get { return reader.BaseURI; }
  164.         }
  165.        
  166.         public override bool CanResolveEntity {
  167.             get { return reader.CanResolveEntity; }
  168.         }
  169.        
  170.         public override bool EOF {
  171.             get { return state == State.EndOfFile || state == State.Closed; }
  172.         }
  173.        
  174.         public override ReadState ReadState {
  175.             get {
  176.                 if (reader.ReadState == ReadState.Error) {
  177.                     return ReadState.Error;
  178.                 }
  179.                 else {
  180.                     if ((int)state <= (int)State.Closed) {
  181.                         return (ReadState)(int)state;
  182.                     }
  183.                     else {
  184.                         return ReadState.Interactive;
  185.                     }
  186.                 }
  187.             }
  188.         }
  189.        
  190.         public override XmlNameTable NameTable {
  191.             get { return reader.NameTable; }
  192.         }
  193.        
  194.         public override int AttributeCount {
  195.             get { return InAttributeActiveState ? reader.AttributeCount + nsAttrCount : 0; }
  196.         }
  197.        
  198.         public override string GetAttribute(string name)
  199.         {
  200.             if (!InAttributeActiveState) {
  201.                 return null;
  202.             }
  203.             string attr = reader.GetAttribute(name);
  204.             if (attr != null) {
  205.                 return attr;
  206.             }
  207.             for (int i = 0; i < nsAttrCount; i++) {
  208.                 if (name == nsAttributes[i].name) {
  209.                     return nsAttributes[i].value;
  210.                 }
  211.             }
  212.             return null;
  213.         }
  214.        
  215.         public override string GetAttribute(string name, string namespaceURI)
  216.         {
  217.             if (!InAttributeActiveState) {
  218.                 return null;
  219.             }
  220.             string attr = reader.GetAttribute(name, namespaceURI);
  221.             if (attr != null) {
  222.                 return attr;
  223.             }
  224.             for (int i = 0; i < nsAttrCount; i++) {
  225.                 if (name == nsAttributes[i].localName && namespaceURI == xmlnsUri) {
  226.                     return nsAttributes[i].value;
  227.                 }
  228.             }
  229.             return null;
  230.            
  231.         }
  232.        
  233.         public override string GetAttribute(int i)
  234.         {
  235.             if (!InAttributeActiveState) {
  236.                 throw new ArgumentOutOfRangeException("i");
  237.             }
  238.             int n = reader.AttributeCount;
  239.             if (i < n) {
  240.                 return reader.GetAttribute(i);
  241.             }
  242.             else if (i - n < nsAttrCount) {
  243.                 return nsAttributes[i - n].value;
  244.             }
  245.             else {
  246.                 throw new ArgumentOutOfRangeException("i");
  247.             }
  248.         }
  249.        
  250.         public override bool MoveToAttribute(string name)
  251.         {
  252.             if (!InAttributeActiveState) {
  253.                 return false;
  254.             }
  255.             if (reader.MoveToAttribute(name)) {
  256.                 curNsAttr = -1;
  257.                 useCurNode = false;
  258.                 return true;
  259.             }
  260.             for (int i = 0; i < nsAttrCount; i++) {
  261.                 if (name == nsAttributes[i].name) {
  262.                     MoveToNsAttribute(i);
  263.                     return true;
  264.                 }
  265.             }
  266.             return false;
  267.         }
  268.        
  269.         public override bool MoveToAttribute(string name, string ns)
  270.         {
  271.             if (!InAttributeActiveState) {
  272.                 return false;
  273.             }
  274.             if (reader.MoveToAttribute(name, ns)) {
  275.                 curNsAttr = -1;
  276.                 useCurNode = false;
  277.                 return true;
  278.             }
  279.             for (int i = 0; i < nsAttrCount; i++) {
  280.                 if (name == nsAttributes[i].localName && ns == xmlnsUri) {
  281.                     MoveToNsAttribute(i);
  282.                     return true;
  283.                 }
  284.             }
  285.             return false;
  286.         }
  287.        
  288.         public override void MoveToAttribute(int i)
  289.         {
  290.             if (!InAttributeActiveState) {
  291.                 throw new ArgumentOutOfRangeException("i");
  292.             }
  293.             int n = reader.AttributeCount;
  294.             if (i < n) {
  295.                 reader.MoveToAttribute(i);
  296.                 curNsAttr = -1;
  297.                 useCurNode = false;
  298.             }
  299.             else if (i - n < nsAttrCount) {
  300.                 MoveToNsAttribute(i - n);
  301.             }
  302.             else {
  303.                 throw new ArgumentOutOfRangeException("i");
  304.             }
  305.         }
  306.        
  307.         public override bool MoveToFirstAttribute()
  308.         {
  309.             if (!InAttributeActiveState) {
  310.                 return false;
  311.             }
  312.             if (reader.MoveToFirstAttribute()) {
  313.                 useCurNode = false;
  314.                 return true;
  315.             }
  316.             if (nsAttrCount > 0) {
  317.                 MoveToNsAttribute(0);
  318.                 return true;
  319.             }
  320.             return false;
  321.         }
  322.        
  323.         public override bool MoveToNextAttribute()
  324.         {
  325.             if (!InAttributeActiveState) {
  326.                 return false;
  327.             }
  328.             if (curNsAttr == -1 && reader.MoveToNextAttribute()) {
  329.                 return true;
  330.             }
  331.             if (curNsAttr + 1 < nsAttrCount) {
  332.                 MoveToNsAttribute(curNsAttr + 1);
  333.                 return true;
  334.             }
  335.             return false;
  336.         }
  337.        
  338.         public override bool MoveToElement()
  339.         {
  340.             if (!InAttributeActiveState) {
  341.                 return false;
  342.             }
  343.             curNsAttr = -1;
  344.             useCurNode = false;
  345.             return reader.MoveToElement();
  346.         }
  347.        
  348.         public override bool ReadAttributeValue()
  349.         {
  350.             if (!InAttributeActiveState) {
  351.                 return false;
  352.             }
  353.             if (curNsAttr == -1) {
  354.                 return reader.ReadAttributeValue();
  355.             }
  356.             else if (curNode.type == XmlNodeType.Text) {
  357.                 // we are on namespace attribute value
  358.                 return false;
  359.             }
  360.             else {
  361.                 Debug.Assert(curNode.type == XmlNodeType.Attribute);
  362.                 tmpNode.type = XmlNodeType.Text;
  363.                 tmpNode.value = curNode.value;
  364.                 SetCurrentNode(tmpNode);
  365.                 return true;
  366.             }
  367.         }
  368.        
  369.         public override bool Read()
  370.         {
  371.            
  372.             switch (state) {
  373.                 case State.Initial:
  374.                     useCurNode = false;
  375.                     state = State.Interactive;
  376.                     ProcessNamespaces();
  377.                     return true;
  378.                 case State.Interactive:
  379.                    
  380.                     curNsAttr = -1;
  381.                     useCurNode = false;
  382.                     reader.MoveToElement();
  383.                     Debug.Assert(reader.Depth >= initialDepth);
  384.                     if (reader.Depth == initialDepth) {
  385.                         if (reader.NodeType == XmlNodeType.EndElement || (reader.NodeType == XmlNodeType.Element && reader.IsEmptyElement)) {
  386.                             state = State.EndOfFile;
  387.                             SetEmptyNode();
  388.                             return false;
  389.                         }
  390.                         Debug.Assert(reader.NodeType == XmlNodeType.Element && !reader.IsEmptyElement);
  391.                     }
  392.                     if (reader.Read()) {
  393.                         ProcessNamespaces();
  394.                         return true;
  395.                     }
  396.                     else {
  397.                         SetEmptyNode();
  398.                         return false;
  399.                     }
  400.                     break;
  401.                 case State.EndOfFile:
  402.                 case State.Closed:
  403.                    
  404.                     return false;
  405.                 case State.PopNamespaceScope:
  406.                    
  407.                     nsManager.PopScope();
  408.                     goto case State.ClearNsAttributes;
  409.                     break;
  410.                 case State.ClearNsAttributes:
  411.                    
  412.                     nsAttrCount = 0;
  413.                     state = State.Interactive;
  414.                     goto case State.Interactive;
  415.                     break;
  416.                 case State.ReadElementContentAsBase64:
  417.                 case State.ReadElementContentAsBinHex:
  418.                    
  419.                     if (!FinishReadElementContentAsBinary()) {
  420.                         return false;
  421.                     }
  422.                     return Read();
  423.                 case State.ReadContentAsBase64:
  424.                 case State.ReadContentAsBinHex:
  425.                    
  426.                     if (!FinishReadContentAsBinary()) {
  427.                         return false;
  428.                     }
  429.                     return Read();
  430.                 default:
  431.                    
  432.                     Debug.Assert(false);
  433.                     return false;
  434.             }
  435.         }
  436.        
  437.         public override void Close()
  438.         {
  439.             if (state == State.Closed) {
  440.                 return;
  441.             }
  442.             try {
  443.                 while ((int)reader.ReadState <= (int)ReadState.Interactive && state != State.EndOfFile) {
  444.                     Skip();
  445.                 }
  446.             }
  447.             catch {
  448.                 // never fail...
  449.             }
  450.             finally {
  451.                 state = State.Closed;
  452.                 SetEmptyNode();
  453.             }
  454.         }
  455.        
  456.         public override void Skip()
  457.         {
  458.            
  459.             switch (state) {
  460.                 case State.Initial:
  461.                     Read();
  462.                     return;
  463.                 case State.Interactive:
  464.                    
  465.                     curNsAttr = -1;
  466.                     useCurNode = false;
  467.                     reader.MoveToElement();
  468.                     Debug.Assert(reader.Depth >= initialDepth);
  469.                     if (reader.Depth == initialDepth) {
  470.                         if (reader.NodeType == XmlNodeType.Element && !reader.IsEmptyElement) {
  471.                             // we are on root of the subtree -> skip to the end element and set to Eof state
  472.                             reader.Read();
  473.                             while (reader.NodeType != XmlNodeType.EndElement && reader.Depth > initialDepth) {
  474.                                 reader.Skip();
  475.                             }
  476.                         }
  477.                         Debug.Assert(reader.NodeType == XmlNodeType.EndElement || reader.NodeType == XmlNodeType.Element && reader.IsEmptyElement);
  478.                         state = State.EndOfFile;
  479.                         SetEmptyNode();
  480.                         return;
  481.                     }
  482.                    
  483.                     if (reader.NodeType == XmlNodeType.Element && !reader.IsEmptyElement) {
  484.                         nsManager.PopScope();
  485.                     }
  486.                     reader.Skip();
  487.                     ProcessNamespaces();
  488.                    
  489.                     Debug.Assert(reader.Depth >= initialDepth);
  490.                     return;
  491.                 case State.Closed:
  492.                 case State.EndOfFile:
  493.                    
  494.                     return;
  495.                 case State.PopNamespaceScope:
  496.                    
  497.                     nsManager.PopScope();
  498.                     goto case State.ClearNsAttributes;
  499.                     break;
  500.                 case State.ClearNsAttributes:
  501.                    
  502.                     nsAttrCount = 0;
  503.                     state = State.Interactive;
  504.                     goto case State.Interactive;
  505.                     break;
  506.                 case State.ReadElementContentAsBase64:
  507.                 case State.ReadElementContentAsBinHex:
  508.                    
  509.                     if (FinishReadElementContentAsBinary()) {
  510.                         Skip();
  511.                     }
  512.                     break;
  513.                 case State.ReadContentAsBase64:
  514.                 case State.ReadContentAsBinHex:
  515.                    
  516.                     if (FinishReadContentAsBinary()) {
  517.                         Skip();
  518.                     }
  519.                     break;
  520.                 default:
  521.                    
  522.                     Debug.Assert(false);
  523.                     return;
  524.             }
  525.         }
  526.        
  527.         public override object ReadContentAsObject()
  528.         {
  529.             try {
  530.                 InitReadContentAsType("ReadContentAsObject");
  531.                 object value = reader.ReadContentAsObject();
  532.                 FinishReadContentAsType();
  533.                 return value;
  534.             }
  535.             catch {
  536.                 state = State.Error;
  537.                 throw;
  538.             }
  539.         }
  540.        
  541.         public override bool ReadContentAsBoolean()
  542.         {
  543.             try {
  544.                 InitReadContentAsType("ReadContentAsBoolean");
  545.                 bool value = reader.ReadContentAsBoolean();
  546.                 FinishReadContentAsType();
  547.                 return value;
  548.             }
  549.             catch {
  550.                 state = State.Error;
  551.                 throw;
  552.             }
  553.         }
  554.        
  555.         public override DateTime ReadContentAsDateTime()
  556.         {
  557.             try {
  558.                 InitReadContentAsType("ReadContentAsDateTime");
  559.                 DateTime value = reader.ReadContentAsDateTime();
  560.                 FinishReadContentAsType();
  561.                 return value;
  562.             }
  563.             catch {
  564.                 state = State.Error;
  565.                 throw;
  566.             }
  567.         }
  568.        
  569.         public override double ReadContentAsDouble()
  570.         {
  571.             try {
  572.                 InitReadContentAsType("ReadContentAsDouble");
  573.                 double value = reader.ReadContentAsDouble();
  574.                 FinishReadContentAsType();
  575.                 return value;
  576.             }
  577.             catch {
  578.                 state = State.Error;
  579.                 throw;
  580.             }
  581.         }
  582.        
  583.         public override float ReadContentAsFloat()
  584.         {
  585.             try {
  586.                 InitReadContentAsType("ReadContentAsFloat");
  587.                 float value = reader.ReadContentAsFloat();
  588.                 FinishReadContentAsType();
  589.                 return value;
  590.             }
  591.             catch {
  592.                 state = State.Error;
  593.                 throw;
  594.             }
  595.         }
  596.        
  597.         public override decimal ReadContentAsDecimal()
  598.         {
  599.             try {
  600.                 InitReadContentAsType("ReadContentAsDecimal");
  601.                 decimal value = reader.ReadContentAsDecimal();
  602.                 FinishReadContentAsType();
  603.                 return value;
  604.             }
  605.             catch {
  606.                 state = State.Error;
  607.                 throw;
  608.             }
  609.         }
  610.        
  611.         public override int ReadContentAsInt()
  612.         {
  613.             try {
  614.                 InitReadContentAsType("ReadContentAsInt");
  615.                 int value = reader.ReadContentAsInt();
  616.                 FinishReadContentAsType();
  617.                 return value;
  618.             }
  619.             catch {
  620.                 state = State.Error;
  621.                 throw;
  622.             }
  623.         }
  624.        
  625.         public override long ReadContentAsLong()
  626.         {
  627.             try {
  628.                 InitReadContentAsType("ReadContentAsLong");
  629.                 long value = reader.ReadContentAsLong();
  630.                 FinishReadContentAsType();
  631.                 return value;
  632.             }
  633.             catch {
  634.                 state = State.Error;
  635.                 throw;
  636.             }
  637.         }
  638.        
  639.         public override string ReadContentAsString()
  640.         {
  641.             try {
  642.                 InitReadContentAsType("ReadContentAsString");
  643.                 string value = reader.ReadContentAsString();
  644.                 FinishReadContentAsType();
  645.                 return value;
  646.             }
  647.             catch {
  648.                 state = State.Error;
  649.                 throw;
  650.             }
  651.         }
  652.        
  653.         public override object ReadContentAs(Type returnType, IXmlNamespaceResolver namespaceResolver)
  654.         {
  655.             try {
  656.                 InitReadContentAsType("ReadContentAs");
  657.                 object value = reader.ReadContentAs(returnType, namespaceResolver);
  658.                 FinishReadContentAsType();
  659.                 return value;
  660.             }
  661.             catch {
  662.                 state = State.Error;
  663.                 throw;
  664.             }
  665.         }
  666.        
  667.         public override bool CanReadBinaryContent {
  668.             get { return reader.CanReadBinaryContent; }
  669.         }
  670.        
  671.         public override int ReadContentAsBase64(byte[] buffer, int index, int count)
  672.         {
  673.             switch (state) {
  674.                 case State.Initial:
  675.                 case State.EndOfFile:
  676.                 case State.Closed:
  677.                     return 0;
  678.                 case State.ClearNsAttributes:
  679.                 case State.PopNamespaceScope:
  680.                    
  681.                     switch (NodeType) {
  682.                         case XmlNodeType.Element:
  683.                             throw CreateReadContentAsException("ReadContentAsBase64");
  684.                             break;
  685.                         case XmlNodeType.EndElement:
  686.                             return 0;
  687.                         case XmlNodeType.Attribute:
  688.                         case XmlNodeType.Text:
  689.                             Debug.Assert(AttributeCount > 0);
  690.                             return reader.ReadContentAsBase64(buffer, index, count);
  691.                         default:
  692.                             Debug.Assert(false);
  693.                             return 0;
  694.                     }
  695.                     break;
  696.                 case State.Interactive:
  697.                    
  698.                     state = State.ReadContentAsBase64;
  699.                     goto case State.ReadContentAsBase64;
  700.                     break;
  701.                 case State.ReadContentAsBase64:
  702.                    
  703.                     int read = reader.ReadContentAsBase64(buffer, index, count);
  704.                     if (read == 0) {
  705.                         state = State.Interactive;
  706.                         ProcessNamespaces();
  707.                     }
  708.                     return read;
  709.                 case State.ReadContentAsBinHex:
  710.                 case State.ReadElementContentAsBase64:
  711.                 case State.ReadElementContentAsBinHex:
  712.                    
  713.                     throw new InvalidOperationException(Res.GetString(Res.Xml_MixingBinaryContentMethods));
  714.                     break;
  715.                 default:
  716.                    
  717.                     Debug.Assert(false);
  718.                     return 0;
  719.             }
  720.         }
  721.        
  722.         public override int ReadElementContentAsBase64(byte[] buffer, int index, int count)
  723.         {
  724.             switch (state) {
  725.                 case State.Initial:
  726.                 case State.EndOfFile:
  727.                 case State.Closed:
  728.                     return 0;
  729.                 case State.Interactive:
  730.                 case State.PopNamespaceScope:
  731.                 case State.ClearNsAttributes:
  732.                    
  733.                     if (!InitReadElementContentAsBinary(State.ReadElementContentAsBase64)) {
  734.                         return 0;
  735.                     }
  736.                     goto case State.ReadElementContentAsBase64;
  737.                     break;
  738.                 case State.ReadElementContentAsBase64:
  739.                    
  740.                     int read = reader.ReadContentAsBase64(buffer, index, count);
  741.                     if (read > 0) {
  742.                         return read;
  743.                     }
  744.                     if (NodeType != XmlNodeType.EndElement) {
  745.                         throw new XmlException(Res.Xml_InvalidNodeType, reader.NodeType.ToString(), reader as IXmlLineInfo);
  746.                     }
  747.                    
  748.                     // pop namespace scope
  749.                     state = State.Interactive;
  750.                     ProcessNamespaces();
  751.                    
  752.                     // set eof state or move off the end element
  753.                     if (reader.Depth == initialDepth) {
  754.                         state = State.EndOfFile;
  755.                         SetEmptyNode();
  756.                     }
  757.                     else {
  758.                         Read();
  759.                     }
  760.                     return 0;
  761.                 case State.ReadContentAsBase64:
  762.                 case State.ReadContentAsBinHex:
  763.                 case State.ReadElementContentAsBinHex:
  764.                    
  765.                     throw new InvalidOperationException(Res.GetString(Res.Xml_MixingBinaryContentMethods));
  766.                     break;
  767.                 default:
  768.                    
  769.                     Debug.Assert(false);
  770.                     return 0;
  771.             }
  772.         }
  773.        
  774.         public override int ReadContentAsBinHex(byte[] buffer, int index, int count)
  775.         {
  776.             switch (state) {
  777.                 case State.Initial:
  778.                 case State.EndOfFile:
  779.                 case State.Closed:
  780.                     return 0;
  781.                 case State.ClearNsAttributes:
  782.                 case State.PopNamespaceScope:
  783.                    
  784.                     switch (NodeType) {
  785.                         case XmlNodeType.Element:
  786.                             throw CreateReadContentAsException("ReadContentAsBinHex");
  787.                             break;
  788.                         case XmlNodeType.EndElement:
  789.                             return 0;
  790.                         case XmlNodeType.Attribute:
  791.                         case XmlNodeType.Text:
  792.                             Debug.Assert(AttributeCount > 0);
  793.                             return reader.ReadContentAsBinHex(buffer, index, count);
  794.                         default:
  795.                             Debug.Assert(false);
  796.                             return 0;
  797.                     }
  798.                     break;
  799.                 case State.Interactive:
  800.                    
  801.                     state = State.ReadContentAsBinHex;
  802.                     goto case State.ReadContentAsBinHex;
  803.                     break;
  804.                 case State.ReadContentAsBinHex:
  805.                    
  806.                     int read = reader.ReadContentAsBinHex(buffer, index, count);
  807.                     if (read == 0) {
  808.                         state = State.Interactive;
  809.                         ProcessNamespaces();
  810.                     }
  811.                     return read;
  812.                 case State.ReadContentAsBase64:
  813.                 case State.ReadElementContentAsBase64:
  814.                 case State.ReadElementContentAsBinHex:
  815.                    
  816.                     throw new InvalidOperationException(Res.GetString(Res.Xml_MixingBinaryContentMethods));
  817.                     break;
  818.                 default:
  819.                    
  820.                     Debug.Assert(false);
  821.                     return 0;
  822.             }
  823.         }
  824.        
  825.         public override int ReadElementContentAsBinHex(byte[] buffer, int index, int count)
  826.         {
  827.             switch (state) {
  828.                 case State.Initial:
  829.                 case State.EndOfFile:
  830.                 case State.Closed:
  831.                     return 0;
  832.                 case State.Interactive:
  833.                 case State.PopNamespaceScope:
  834.                 case State.ClearNsAttributes:
  835.                    
  836.                     if (!InitReadElementContentAsBinary(State.ReadElementContentAsBinHex)) {
  837.                         return 0;
  838.                     }
  839.                     goto case State.ReadElementContentAsBinHex;
  840.                     break;
  841.                 case State.ReadElementContentAsBinHex:
  842.                     int read = reader.ReadContentAsBinHex(buffer, index, count);
  843.                     if (read > 0) {
  844.                         return read;
  845.                     }
  846.                     if (NodeType != XmlNodeType.EndElement) {
  847.                         throw new XmlException(Res.Xml_InvalidNodeType, reader.NodeType.ToString(), reader as IXmlLineInfo);
  848.                     }
  849.                    
  850.                     // pop namespace scope
  851.                     state = State.Interactive;
  852.                     ProcessNamespaces();
  853.                    
  854.                     // set eof state or move off the end element
  855.                     if (reader.Depth == initialDepth) {
  856.                         state = State.EndOfFile;
  857.                         SetEmptyNode();
  858.                     }
  859.                     else {
  860.                         Read();
  861.                     }
  862.                     return 0;
  863.                 case State.ReadContentAsBase64:
  864.                 case State.ReadContentAsBinHex:
  865.                 case State.ReadElementContentAsBase64:
  866.                    
  867.                     throw new InvalidOperationException(Res.GetString(Res.Xml_MixingBinaryContentMethods));
  868.                     break;
  869.                 default:
  870.                    
  871.                     Debug.Assert(false);
  872.                     return 0;
  873.             }
  874.         }
  875.        
  876.         public override bool CanReadValueChunk {
  877.             get { return reader.CanReadValueChunk; }
  878.         }
  879.        
  880.         public override int ReadValueChunk(char[] buffer, int index, int count)
  881.         {
  882.             switch (state) {
  883.                 case State.Initial:
  884.                 case State.EndOfFile:
  885.                 case State.Closed:
  886.                 case State.Error:
  887.                     return 0;
  888.                 case State.ClearNsAttributes:
  889.                 case State.PopNamespaceScope:
  890.                    
  891.                     // no need to clean ns attributes or pop scope because the reader when ReadValueChunk is called
  892.                     // - on Element errors
  893.                     // - on EndElement errors
  894.                     // - on Attribute does not move
  895.                     // and that's all where State.ClearNsAttributes or State.PopnamespaceScope can be set
  896.                     goto case State.Interactive;
  897.                     break;
  898.                 case State.Interactive:
  899.                    
  900.                     return reader.ReadValueChunk(buffer, index, count);
  901.                 case State.ReadElementContentAsBase64:
  902.                 case State.ReadElementContentAsBinHex:
  903.                 case State.ReadContentAsBase64:
  904.                 case State.ReadContentAsBinHex:
  905.                    
  906.                     throw new InvalidOperationException(Res.GetString(Res.Xml_MixingReadValueChunkWithBinary));
  907.                     break;
  908.                 default:
  909.                    
  910.                     Debug.Assert(false);
  911.                     return 0;
  912.             }
  913.         }
  914.        
  915.         //
  916.         // IDisposable interface
  917.         //
  918.         protected override void Dispose(bool disposing)
  919.         {
  920.             // note: we do not want to dispose the underlying reader
  921.             this.Close();
  922.         }
  923.        
  924.         //
  925.         // IXmlLineInfo members
  926.         //
  927.         public override int LineNumber {
  928.             get { return (readerAsIXmlLineInfo == null || useCurNode) ? 0 : readerAsIXmlLineInfo.LineNumber; }
  929.         }
  930.        
  931.         public override int LinePosition {
  932.             get { return (readerAsIXmlLineInfo == null || useCurNode) ? 0 : readerAsIXmlLineInfo.LinePosition; }
  933.         }
  934.        
  935.         public override string LookupNamespace(string prefix)
  936.         {
  937.             return ((IXmlNamespaceResolver)this).LookupNamespace(prefix);
  938.         }
  939.        
  940.         //
  941.         // IXmlNamespaceResolver implementation
  942.         //
  943.         IDictionary<string, string> IXmlNamespaceResolver.GetNamespacesInScope(XmlNamespaceScope scope)
  944.         {
  945.             if (!InNamespaceActiveState) {
  946.                 return new Dictionary<string, string>();
  947.             }
  948.             return nsManager.GetNamespacesInScope(scope);
  949.         }
  950.        
  951.         string IXmlNamespaceResolver.LookupNamespace(string prefix)
  952.         {
  953.             if (!InNamespaceActiveState) {
  954.                 return null;
  955.             }
  956.             return nsManager.LookupNamespace(prefix);
  957.         }
  958.        
  959.         string IXmlNamespaceResolver.LookupPrefix(string namespaceName)
  960.         {
  961.             if (!InNamespaceActiveState) {
  962.                 return null;
  963.             }
  964.             return nsManager.LookupPrefix(namespaceName);
  965.         }
  966.        
  967.         //
  968.         // Internal methods
  969.         //
  970.        
  971.         internal override SchemaInfo DtdSchemaInfo {
  972.             get { return null; }
  973.         }
  974.        
  975.         //
  976.         // Private methods
  977.         //
  978.         private void ProcessNamespaces()
  979.         {
  980.             switch (reader.NodeType) {
  981.                 case XmlNodeType.Element:
  982.                     nsManager.PushScope();
  983.                    
  984.                     string prefix = reader.Prefix;
  985.                     string ns = reader.NamespaceURI;
  986.                     if (nsManager.LookupNamespace(prefix) != ns) {
  987.                         AddNamespace(prefix, ns);
  988.                     }
  989.                    
  990.                     if (reader.MoveToFirstAttribute()) {
  991.                         do {
  992.                             prefix = reader.Prefix;
  993.                             ns = reader.NamespaceURI;
  994.                            
  995.                             if (Ref.Equal(ns, xmlnsUri)) {
  996.                                 if (prefix.Length == 0) {
  997.                                     nsManager.AddNamespace(string.Empty, reader.Value);
  998.                                     RemoveNamespace(string.Empty, xmlns);
  999.                                 }
  1000.                                 else {
  1001.                                     prefix = reader.LocalName;
  1002.                                     nsManager.AddNamespace(prefix, reader.Value);
  1003.                                     RemoveNamespace(xmlns, prefix);
  1004.                                 }
  1005.                             }
  1006.                             else if (prefix.Length != 0 && nsManager.LookupNamespace(prefix) != ns) {
  1007.                                 AddNamespace(prefix, ns);
  1008.                             }
  1009.                         }
  1010.                         while (reader.MoveToNextAttribute());
  1011.                         reader.MoveToElement();
  1012.                     }
  1013.                    
  1014.                     if (reader.IsEmptyElement) {
  1015.                         state = State.PopNamespaceScope;
  1016.                     }
  1017.                     break;
  1018.                 case XmlNodeType.EndElement:
  1019.                     state = State.PopNamespaceScope;
  1020.                     break;
  1021.             }
  1022.         }
  1023.        
  1024.         private void AddNamespace(string prefix, string ns)
  1025.         {
  1026.             nsManager.AddNamespace(prefix, ns);
  1027.            
  1028.             int index = nsAttrCount++;
  1029.             if (nsAttributes == null) {
  1030.                 nsAttributes = new NodeData[InitialNamespaceAttributeCount];
  1031.             }
  1032.             if (index == nsAttributes.Length) {
  1033.                 NodeData[] newNsAttrs = new NodeData[nsAttributes.Length * 2];
  1034.                 Array.Copy(nsAttributes, 0, newNsAttrs, 0, index);
  1035.                 nsAttributes = newNsAttrs;
  1036.             }
  1037.            
  1038.             if (nsAttributes[index] == null) {
  1039.                 nsAttributes[index] = new NodeData();
  1040.             }
  1041.             if (prefix.Length == 0) {
  1042.                 nsAttributes[index].Set(XmlNodeType.Attribute, xmlns, string.Empty, xmlns, XmlReservedNs.NsXmlNs, ns);
  1043.             }
  1044.             else {
  1045.                 nsAttributes[index].Set(XmlNodeType.Attribute, prefix, xmlns, string.Concat(prefix, ":", xmlns), XmlReservedNs.NsXmlNs, ns);
  1046.             }
  1047.            
  1048.             Debug.Assert(state == State.ClearNsAttributes || state == State.Interactive || state == State.PopNamespaceScope);
  1049.             state = State.ClearNsAttributes;
  1050.            
  1051.             curNsAttr = -1;
  1052.         }
  1053.        
  1054.         private void RemoveNamespace(string prefix, string localName)
  1055.         {
  1056.             for (int i = 0; i < nsAttrCount; i++) {
  1057.                 if (Ref.Equal(prefix, nsAttributes[i].prefix) && Ref.Equal(localName, nsAttributes[i].localName)) {
  1058.                     if (i < nsAttrCount - 1) {
  1059.                         nsAttributes[i] = nsAttributes[nsAttrCount - 1];
  1060.                     }
  1061.                     nsAttrCount--;
  1062.                     break;
  1063.                 }
  1064.             }
  1065.         }
  1066.        
  1067.         private void MoveToNsAttribute(int index)
  1068.         {
  1069.             Debug.Assert(index >= 0 && index <= nsAttrCount);
  1070.             reader.MoveToElement();
  1071.             curNsAttr = index;
  1072.             SetCurrentNode(nsAttributes[index]);
  1073.         }
  1074.        
  1075.         private bool InitReadElementContentAsBinary(State binaryState)
  1076.         {
  1077.             if (NodeType != XmlNodeType.Element) {
  1078.                 throw reader.CreateReadElementContentAsException("ReadElementContentAsBase64");
  1079.             }
  1080.            
  1081.             bool isEmpty = IsEmptyElement;
  1082.            
  1083.             // move to content or off the empty element
  1084.             if (!Read() || isEmpty) {
  1085.                 return false;
  1086.             }
  1087.             // special-case child element and end element
  1088.             switch (NodeType) {
  1089.                 case XmlNodeType.Element:
  1090.                     throw new XmlException(Res.Xml_InvalidNodeType, reader.NodeType.ToString(), reader as IXmlLineInfo);
  1091.                     break;
  1092.                 case XmlNodeType.EndElement:
  1093.                     // pop scope & move off end element
  1094.                     ProcessNamespaces();
  1095.                     Read();
  1096.                     return false;
  1097.             }
  1098.            
  1099.             Debug.Assert(state == State.Interactive);
  1100.             state = binaryState;
  1101.             return true;
  1102.         }
  1103.        
  1104.         private bool FinishReadElementContentAsBinary()
  1105.         {
  1106.             Debug.Assert(state == State.ReadElementContentAsBase64 || state == State.ReadElementContentAsBinHex);
  1107.            
  1108.             byte[] bytes = new byte[256];
  1109.             if (state == State.ReadElementContentAsBase64) {
  1110.                 while (reader.ReadContentAsBase64(bytes, 0, 256) > 0)
  1111.                     ;
  1112.             }
  1113.             else {
  1114.                 while (reader.ReadContentAsBinHex(bytes, 0, 256) > 0)
  1115.                     ;
  1116.             }
  1117.            
  1118.             if (NodeType != XmlNodeType.EndElement) {
  1119.                 throw new XmlException(Res.Xml_InvalidNodeType, reader.NodeType.ToString(), reader as IXmlLineInfo);
  1120.             }
  1121.            
  1122.             // pop namespace scope
  1123.             state = State.Interactive;
  1124.             ProcessNamespaces();
  1125.            
  1126.             // check eof
  1127.             if (reader.Depth == initialDepth) {
  1128.                 state = State.EndOfFile;
  1129.                 SetEmptyNode();
  1130.                 return false;
  1131.             }
  1132.             // move off end element
  1133.             return Read();
  1134.         }
  1135.        
  1136.         private bool FinishReadContentAsBinary()
  1137.         {
  1138.             Debug.Assert(state == State.ReadContentAsBase64 || state == State.ReadContentAsBinHex);
  1139.            
  1140.             byte[] bytes = new byte[256];
  1141.             if (state == State.ReadContentAsBase64) {
  1142.                 while (reader.ReadContentAsBase64(bytes, 0, 256) > 0)
  1143.                     ;
  1144.             }
  1145.             else {
  1146.                 while (reader.ReadContentAsBinHex(bytes, 0, 256) > 0)
  1147.                     ;
  1148.             }
  1149.            
  1150.             state = State.Interactive;
  1151.             ProcessNamespaces();
  1152.            
  1153.             // check eof
  1154.             if (reader.Depth == initialDepth) {
  1155.                 state = State.EndOfFile;
  1156.                 SetEmptyNode();
  1157.                 return false;
  1158.             }
  1159.             return true;
  1160.         }
  1161.        
  1162.         private bool InAttributeActiveState {
  1163.             get {
  1164.                 #if DEBUG
  1165.                 Debug.Assert(0 == (AttributeActiveStates & (1 << (int)State.Initial)));
  1166.                 Debug.Assert(0 != (AttributeActiveStates & (1 << (int)State.Interactive)));
  1167.                 Debug.Assert(0 == (AttributeActiveStates & (1 << (int)State.Error)));
  1168.                 Debug.Assert(0 == (AttributeActiveStates & (1 << (int)State.EndOfFile)));
  1169.                 Debug.Assert(0 == (AttributeActiveStates & (1 << (int)State.Closed)));
  1170.                 Debug.Assert(0 != (AttributeActiveStates & (1 << (int)State.PopNamespaceScope)));
  1171.                 Debug.Assert(0 != (AttributeActiveStates & (1 << (int)State.ClearNsAttributes)));
  1172.                 Debug.Assert(0 == (AttributeActiveStates & (1 << (int)State.ReadElementContentAsBase64)));
  1173.                 Debug.Assert(0 == (AttributeActiveStates & (1 << (int)State.ReadElementContentAsBinHex)));
  1174.                 Debug.Assert(0 == (AttributeActiveStates & (1 << (int)State.ReadContentAsBase64)));
  1175.                 Debug.Assert(0 == (AttributeActiveStates & (1 << (int)State.ReadContentAsBinHex)));
  1176.                 #endif
  1177.                 return 0 != (AttributeActiveStates & (1 << (int)state));
  1178.             }
  1179.         }
  1180.        
  1181.         private bool InNamespaceActiveState {
  1182.             get {
  1183.                 #if DEBUG
  1184.                 Debug.Assert(0 == (NamespaceActiveStates & (1 << (int)State.Initial)));
  1185.                 Debug.Assert(0 != (NamespaceActiveStates & (1 << (int)State.Interactive)));
  1186.                 Debug.Assert(0 == (NamespaceActiveStates & (1 << (int)State.Error)));
  1187.                 Debug.Assert(0 == (NamespaceActiveStates & (1 << (int)State.EndOfFile)));
  1188.                 Debug.Assert(0 == (NamespaceActiveStates & (1 << (int)State.Closed)));
  1189.                 Debug.Assert(0 != (NamespaceActiveStates & (1 << (int)State.PopNamespaceScope)));
  1190.                 Debug.Assert(0 != (NamespaceActiveStates & (1 << (int)State.ClearNsAttributes)));
  1191.                 Debug.Assert(0 != (NamespaceActiveStates & (1 << (int)State.ReadElementContentAsBase64)));
  1192.                 Debug.Assert(0 != (NamespaceActiveStates & (1 << (int)State.ReadElementContentAsBinHex)));
  1193.                 Debug.Assert(0 != (NamespaceActiveStates & (1 << (int)State.ReadContentAsBase64)));
  1194.                 Debug.Assert(0 != (NamespaceActiveStates & (1 << (int)State.ReadContentAsBinHex)));
  1195.                 #endif
  1196.                 return 0 != (NamespaceActiveStates & (1 << (int)state));
  1197.             }
  1198.         }
  1199.        
  1200.         void SetEmptyNode()
  1201.         {
  1202.             Debug.Assert(tmpNode.localName == string.Empty && tmpNode.prefix == string.Empty && tmpNode.name == string.Empty && tmpNode.namespaceUri == string.Empty);
  1203.             tmpNode.type = XmlNodeType.None;
  1204.             tmpNode.value = string.Empty;
  1205.            
  1206.             curNode = tmpNode;
  1207.             useCurNode = true;
  1208.         }
  1209.        
  1210.         void SetCurrentNode(NodeData node)
  1211.         {
  1212.             curNode = node;
  1213.             useCurNode = true;
  1214.         }
  1215.        
  1216.         void InitReadContentAsType(string methodName)
  1217.         {
  1218.             switch (state) {
  1219.                 case State.Initial:
  1220.                 case State.EndOfFile:
  1221.                 case State.Closed:
  1222.                 case State.Error:
  1223.                     break;
  1224.                 case State.Interactive:
  1225.                    
  1226.                     return;
  1227.                 case State.PopNamespaceScope:
  1228.                 case State.ClearNsAttributes:
  1229.                    
  1230.                     // no need to clean ns attributes or pop scope because the reader when ReadContentAs is called
  1231.                     // - on Element errors
  1232.                     // - on Attribute does not move
  1233.                     // - on EndElement does not move
  1234.                     // and that's all where State.ClearNsAttributes or State.PopNamespacScope can be set
  1235.                     return;
  1236.                 case State.ReadElementContentAsBase64:
  1237.                 case State.ReadElementContentAsBinHex:
  1238.                 case State.ReadContentAsBase64:
  1239.                 case State.ReadContentAsBinHex:
  1240.                    
  1241.                     throw new InvalidOperationException(Res.GetString(Res.Xml_MixingReadValueChunkWithBinary));
  1242.                     break;
  1243.                 default:
  1244.                    
  1245.                     Debug.Assert(false);
  1246.                     break;
  1247.             }
  1248.             throw CreateReadContentAsException(methodName);
  1249.         }
  1250.        
  1251.         void FinishReadContentAsType()
  1252.         {
  1253.             Debug.Assert(state == State.Interactive || state == State.PopNamespaceScope || state == State.ClearNsAttributes);
  1254.            
  1255.             switch (NodeType) {
  1256.                 case XmlNodeType.Element:
  1257.                     // new element we moved to - process namespaces
  1258.                     ProcessNamespaces();
  1259.                     break;
  1260.                 case XmlNodeType.EndElement:
  1261.                     // end element we've stayed on or have been moved to
  1262.                     state = State.PopNamespaceScope;
  1263.                     break;
  1264.                 case XmlNodeType.Attribute:
  1265.                     // stayed on attribute, do nothing
  1266.                     break;
  1267.             }
  1268.         }
  1269.     }
  1270. }

Developer Fusion