2002-03-11 Duncan Mak <duncan@ximian.com>
[mono.git] / mcs / class / System.XML / System.Xml / XmlTextReader.cs
index 82c5800873126b6e479b91adbfa9685017a470d3..f49090793fda12c7f819c229a3e532921910c429 100644 (file)
@@ -1,5 +1,5 @@
 //
-// XmlTextReader.cs
+// System.Xml.XmlTextReader
 //
 // Author:
 //   Jason Diamond (jason@injektilo.org)
 //   There's also no checking being done for either well-formedness
 //   or validity.
 //
-//   ParserContext and NameTables aren't being used yet.
+//   NameTables aren't being used everywhere yet.
 //
 //   Some thought needs to be given to performance. There's too many
 //   strings being allocated.
 //
-//   None of the MoveTo methods have been implemented yet.
+//   Some of the MoveTo methods haven't been implemented yet.
 //
 //   LineNumber and LinePosition aren't being tracked.
 //
@@ -60,6 +60,9 @@ namespace System.Xml
                [MonoTODO]
                public XmlTextReader (TextReader input)
                {
+                       XmlNameTable nt = new NameTable ();
+                       XmlNamespaceManager nsMgr = new XmlNamespaceManager (nt);
+                       parserContext = new XmlParserContext (null, nsMgr, null, XmlSpace.None);
                        Init ();
                        reader = input;
                }
@@ -230,7 +233,7 @@ namespace System.Xml
 
                public override XmlNameTable NameTable
                {
-                       get { return nameTable; }
+                       get { return parserContext.NameTable; }
                }
 
                public override XmlNodeType NodeType
@@ -331,7 +334,7 @@ namespace System.Xml
                                                        return attributes [thisName] as string;
                                        }
                                } else if (localName == "xmlns" && namespaceURI == "http://www.w3.org/2000/xmlns/" && thisName == "xmlns")
-                                       return attributes[thisName] as string;
+                                       return attributes [thisName] as string;
                        }
 
                        return String.Empty;
@@ -351,7 +354,7 @@ namespace System.Xml
 
                public override string LookupNamespace (string prefix)
                {
-                       return namespaceManager.LookupNamespace (prefix);
+                       return parserContext.NamespaceManager.LookupNamespace (prefix);
                }
 
                [MonoTODO]
@@ -372,16 +375,20 @@ namespace System.Xml
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
                public override bool MoveToElement ()
                {
-                       throw new NotImplementedException ();
+                       if (nodeType == XmlNodeType.Attribute) {
+                               RestoreProperties ();
+                               return true;
+                       }
+
+                       return false;
                }
 
-               [MonoTODO]
                public override bool MoveToFirstAttribute ()
                {
-                       throw new NotImplementedException ();
+                       MoveToElement ();
+                       return MoveToNextAttribute ();
                }
 
                public override bool MoveToNextAttribute ()
@@ -389,8 +396,10 @@ namespace System.Xml
                        if (attributes == null)
                                return false;
 
-                       if (attributeEnumerator == null)
-                               attributeEnumerator = attributes.GetEnumerator();
+                       if (attributeEnumerator == null) {
+                               SaveProperties ();
+                               attributeEnumerator = attributes.GetEnumerator ();
+                       }
 
                        if (attributeEnumerator.MoveNext ()) {
                                string name = attributeEnumerator.Key as string;
@@ -426,19 +435,19 @@ namespace System.Xml
                }
 
                [MonoTODO]
-               public int ReadBase64 (byte[] buffer, int offset, int length)
+               public int ReadBase64 (byte [] buffer, int offset, int length)
                {
                        throw new NotImplementedException ();
                }
 
                [MonoTODO]
-               public int ReadBinHex (byte[] buffer, int offset, int length)
+               public int ReadBinHex (byte [] buffer, int offset, int length)
                {
                        throw new NotImplementedException ();
                }
 
                [MonoTODO]
-               public int ReadChars (char[] buffer, int offset, int length)
+               public int ReadChars (char [] buffer, int offset, int length)
                {
                        throw new NotImplementedException ();
                }
@@ -477,14 +486,14 @@ namespace System.Xml
 
                // privates
 
+               private XmlParserContext parserContext;
+
                private TextReader reader;
                private ReadState readState;
 
                private int depth;
                private bool depthDown;
 
-               private XmlNameTable nameTable;
-               private XmlNamespaceManager namespaceManager;
                private bool popScope;
 
                private XmlNodeType nodeType;
@@ -494,52 +503,57 @@ namespace System.Xml
                private string namespaceURI;
                private bool isEmptyElement;
                private string value;
+
+               private XmlNodeType saveNodeType;
+               private string saveName;
+               private string savePrefix;
+               private string saveLocalName;
+               private string saveNamespaceURI;
+               private bool saveIsEmptyElement;
+       
                private Hashtable attributes;
                private IDictionaryEnumerator attributeEnumerator;
 
                private bool returnEntityReference;
                private string entityReferenceName;
 
-               private char[] nameBuffer;
+               private char [] nameBuffer;
                private int nameLength;
                private int nameCapacity;
                private const int initialNameCapacity = 256;
 
-               private char[] valueBuffer;
+               private char [] valueBuffer;
                private int valueLength;
                private int valueCapacity;
                private const int initialValueCapacity = 8192;
 
                private void Init ()
                {
-                       if (nameTable == null)
-                               nameTable = new NameTable ();
-
-                       namespaceManager = new XmlNamespaceManager (nameTable);
-                       popScope = false;
-
                        readState = ReadState.Initial;
 
                        depth = -1;
                        depthDown = false;
 
+                       popScope = false;
+
                        nodeType = XmlNodeType.None;
                        name = String.Empty;
                        prefix = String.Empty;
                        localName = string.Empty;
                        isEmptyElement = false;
                        value = String.Empty;
+
                        attributes = new Hashtable ();
                        attributeEnumerator = null;
-                       
+
                        returnEntityReference = false;
                        entityReferenceName = String.Empty;
 
-                       nameBuffer = new char[initialNameCapacity];
+                       nameBuffer = new char [initialNameCapacity];
                        nameLength = 0;
                        nameCapacity = initialNameCapacity;
 
-                       valueBuffer = new char[initialValueCapacity];
+                       valueBuffer = new char [initialValueCapacity];
                        valueLength = 0;
                        valueCapacity = initialValueCapacity;
                }
@@ -577,6 +591,28 @@ namespace System.Xml
                        namespaceURI = LookupNamespace (prefix);
                }
 
+               private void SaveProperties ()
+               {
+                       saveNodeType = nodeType;
+                       saveName = name;
+                       savePrefix = prefix;
+                       saveLocalName = localName;
+                       saveNamespaceURI = namespaceURI;
+                       saveIsEmptyElement = isEmptyElement;
+                       // An element's value is always String.Empty.
+               }
+
+               private void RestoreProperties ()
+               {
+                       nodeType = saveNodeType;
+                       name = saveName;
+                       prefix = savePrefix;
+                       localName = saveLocalName;
+                       namespaceURI = saveNamespaceURI;
+                       isEmptyElement = saveIsEmptyElement;
+                       value = String.Empty;
+               }
+
                private void AddAttribute (string name, string value)
                {
                        attributes.Add (name, value);
@@ -608,7 +644,7 @@ namespace System.Xml
                        bool more = false;
 
                        if (popScope) {
-                               namespaceManager.PopScope ();
+                               parserContext.NamespaceManager.PopScope ();
                                popScope = false;
                        }
 
@@ -688,7 +724,7 @@ namespace System.Xml
                // The leading '<' has already been consumed.
                private void ReadStartTag ()
                {
-                       namespaceManager.PushScope ();
+                       parserContext.NamespaceManager.PushScope ();
 
                        string name = ReadName ();
                        SkipWhitespace ();
@@ -744,15 +780,15 @@ namespace System.Xml
                private void AppendNameChar (int ch)
                {
                        CheckNameCapacity ();
-                       nameBuffer[nameLength++] = (char)ch;
+                       nameBuffer [nameLength++] = (char)ch;
                }
 
                private void CheckNameCapacity ()
                {
                        if (nameLength == nameCapacity) {
                                nameCapacity = nameCapacity * 2;
-                               char[] oldNameBuffer = nameBuffer;
-                               nameBuffer = new char[nameCapacity];
+                               char [] oldNameBuffer = nameBuffer;
+                               nameBuffer = new char [nameCapacity];
                                Array.Copy (oldNameBuffer, nameBuffer, nameLength);
                        }
                }
@@ -765,15 +801,15 @@ namespace System.Xml
                private void AppendValueChar (int ch)
                {
                        CheckValueCapacity ();
-                       valueBuffer[valueLength++] = (char)ch;
+                       valueBuffer [valueLength++] = (char)ch;
                }
 
                private void CheckValueCapacity ()
                {
                        if (valueLength == valueCapacity) {
                                valueCapacity = valueCapacity * 2;
-                               char[] oldValueBuffer = valueBuffer;
-                               valueBuffer = new char[valueCapacity];
+                               char [] oldValueBuffer = valueBuffer;
+                               valueBuffer = new char [valueCapacity];
                                Array.Copy (oldValueBuffer, valueBuffer, valueLength);
                        }
                }
@@ -942,9 +978,9 @@ namespace System.Xml
                                SkipWhitespace ();
 
                                if (name == "xmlns")
-                                       namespaceManager.AddNamespace (String.Empty, value);
+                                       parserContext.NamespaceManager.AddNamespace (String.Empty, value);
                                else if (name.StartsWith ("xmlns:"))
-                                       namespaceManager.AddNamespace (name.Substring (6), value);
+                                       parserContext.NamespaceManager.AddNamespace (name.Substring (6), value);
 
                                AddAttribute (name, value);
                        } while (PeekChar () != '/' && PeekChar () != '>' && PeekChar () != -1);