diff Implab/JSON/JSONXmlReader.cs @ 58:1710dcda34bb

Added JSONXmlReader
author cin
date Tue, 17 Jun 2014 19:40:43 +0400
parents
children 21611344d366
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Implab/JSON/JSONXmlReader.cs	Tue Jun 17 19:40:43 2014 +0400
@@ -0,0 +1,278 @@
+using Implab;
+using Implab.JSON;
+using Implab.Parsing;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Xml;
+
+namespace ConsPlay {
+    public class JSONXmlReader : XmlReader {
+
+        enum ValueContext {
+            Undefined,
+            ElementStart,
+            ElementValue,
+            ElementEnd,
+            ElementEmpty
+        }
+
+        struct LocalNameContext {
+            public string localName;
+            public bool isArray;
+        }
+
+        JSONParser m_parser;
+        ValueContext m_valueContext;
+        ReadState m_state = ReadState.Initial;
+        Stack<LocalNameContext> m_localNameStack = new Stack<LocalNameContext>();
+        LocalNameContext m_localName;
+        string m_rootName = "json";
+        string m_prefix = String.Empty;
+        string m_namespaceUri = String.Empty;
+        bool m_flattenArrays = false;
+        NameTable m_nameTable = new NameTable();
+        int m_depthCorrection = 0;
+
+        public JSONXmlReader(JSONParser parser) {
+            Safe.ArgumentNotNull(parser, "parser");
+            m_parser = parser;
+        }
+
+        /// <summary>
+        /// Always 0, JSON doesn't support attributes
+        /// </summary>
+        public override int AttributeCount {
+            get { return 0; }
+        }
+
+        public override string BaseURI {
+            get { return String.Empty; }
+        }
+
+        public override int Depth {
+            get {
+                return m_localNameStack.Count+m_depthCorrection;
+            }
+        }
+
+        public override bool EOF {
+            get { return m_parser.EOF; }
+        }
+
+        /// <summary>
+        /// Always throws an exception
+        /// </summary>
+        /// <param name="i"></param>
+        /// <returns></returns>
+        public override string GetAttribute(int i) {
+            throw new ArgumentOutOfRangeException();
+        }
+
+        /// <summary>
+        /// Always returns empty string
+        /// </summary>
+        /// <param name="name"></param>
+        /// <param name="namespaceURI"></param>
+        /// <returns></returns>
+        public override string GetAttribute(string name, string namespaceURI) {
+            return String.Empty;
+        }
+
+        /// <summary>
+        /// Always returns empty string
+        /// </summary>
+        /// <param name="name"></param>
+        /// <returns></returns>
+        public override string GetAttribute(string name) {
+            return String.Empty;
+        }
+
+        public override bool IsEmptyElement {
+            get { return m_parser.ElementType == JSONElementType.Value && m_valueContext == ValueContext.ElementEmpty; }
+        }
+
+        public override string LocalName {
+            get { return m_localName.localName; }
+        }
+
+        public override string LookupNamespace(string prefix) {
+            if (String.IsNullOrEmpty(prefix) || prefix == m_prefix)
+                return m_namespaceUri;
+            else
+                return String.Empty;
+        }
+
+        public override bool MoveToAttribute(string name, string ns) {
+            return false;
+        }
+
+        public override bool MoveToAttribute(string name) {
+            return false;
+        }
+
+        public override bool MoveToElement() {
+            return false;
+        }
+
+        public override bool MoveToFirstAttribute() {
+            return false;
+        }
+
+        public override bool MoveToNextAttribute() {
+            return false;
+        }
+
+        public override XmlNameTable NameTable {
+            get { return m_nameTable; }
+        }
+
+        public override string NamespaceURI {
+            get { return m_namespaceUri; }
+        }
+
+        public override XmlNodeType NodeType {
+            get {
+                switch (m_parser.ElementType) {
+                    case JSONElementType.BeginObject:
+                    case JSONElementType.BeginArray:
+                        return XmlNodeType.Element;
+                    case JSONElementType.EndObject:
+                    case JSONElementType.EndArray:
+                        return XmlNodeType.EndElement;
+                    case JSONElementType.Value:
+                        switch (m_valueContext) {
+                            case ValueContext.ElementStart:
+                            case ValueContext.ElementEmpty:
+                                return XmlNodeType.Element;
+                            case ValueContext.ElementValue:
+                                return XmlNodeType.Text;
+                            case ValueContext.ElementEnd:
+                                return XmlNodeType.EndElement;
+                            default:
+                                throw new InvalidOperationException();
+                        }
+                    default:
+                        throw new InvalidOperationException();
+                }
+            }
+        }
+
+        public override string Prefix {
+            get { return m_prefix; }
+        }
+
+        public override bool Read() {
+            if (m_state != System.Xml.ReadState.Interactive && m_state != System.Xml.ReadState.Initial)
+                return false;
+
+            if (m_state == ReadState.Initial)
+                m_state = System.Xml.ReadState.Interactive;
+
+            try {
+                switch (m_parser.ElementType) {
+                    case JSONElementType.Value:
+                        switch (m_valueContext) {
+                            case ValueContext.ElementStart:
+                                SetLocalName(String.Empty);
+                                m_valueContext = ValueContext.ElementValue;
+                                return true;
+                            case ValueContext.ElementValue:
+                                RestoreLocalName();
+                                m_valueContext = ValueContext.ElementEnd;
+                                return true;
+                            case ValueContext.ElementEmpty:
+                            case ValueContext.ElementEnd:
+                                RestoreLocalName();
+                                break;
+                        }
+                        break;
+                    case JSONElementType.EndArray:
+                    case JSONElementType.EndObject:
+                        RestoreLocalName();
+                        break;
+                }
+                string itemName = m_parser.ElementType == JSONElementType.None ? m_rootName : m_flattenArrays ? m_localName.localName : "item";
+                while (m_parser.Read()) {
+                    if (!String.IsNullOrEmpty(m_parser.ElementName))
+                        itemName = m_parser.ElementName;
+
+                    switch (m_parser.ElementType) {
+                        case JSONElementType.BeginArray:
+                            if (m_flattenArrays && !m_localName.isArray) {
+                                m_depthCorrection--;
+                                SetLocalName(itemName, true);
+                                continue;
+                            } else {
+                                SetLocalName(itemName, true);
+                            }
+                            break;
+                        case JSONElementType.BeginObject:
+                            SetLocalName(itemName);
+                            break;
+                        case JSONElementType.EndArray:
+                            if (m_flattenArrays && !m_localNameStack.Peek().isArray) {
+                                RestoreLocalName();
+                                m_depthCorrection++;
+                                continue;
+                            }
+                            break;
+                        case JSONElementType.EndObject:
+                            break;
+                        case JSONElementType.Value:
+                            SetLocalName(itemName);
+                            m_valueContext = m_parser.ElementValue == null ? ValueContext.ElementEmpty : ValueContext.ElementStart;
+                            break;
+                        default:
+                            break;
+                    }
+                    return true;
+                }
+
+                m_state = System.Xml.ReadState.EndOfFile;
+                return false;
+            } catch {
+                m_state = System.Xml.ReadState.Error;
+                throw;
+            }
+        }
+
+        public override bool ReadAttributeValue() {
+            return false;
+        }
+
+        public override ReadState ReadState {
+            get { return m_state; }
+        }
+
+        public override void ResolveEntity() {
+            // do nothing
+        }
+
+        public override string Value {
+            get { return m_parser.ElementValue == null ? String.Empty : m_parser.ElementValue.ToString(); }
+        }
+
+        void SetLocalName(string name) {
+            m_localNameStack.Push(m_localName);
+            m_localName.localName = name;
+            m_localName.isArray = false;
+        }
+
+        void SetLocalName(string name, bool isArray) {
+            m_localNameStack.Push(m_localName);
+            m_localName.localName = name;
+            m_localName.isArray = isArray;
+        }
+
+        void RestoreLocalName() {
+            m_localName = m_localNameStack.Pop();
+        }
+
+        public override void Close() {
+            m_state = System.Xml.ReadState.EndOfFile ;
+        }
+    }
+}