diff --git a/Implab/Implab.csproj b/Implab/Implab.csproj --- a/Implab/Implab.csproj +++ b/Implab/Implab.csproj @@ -63,6 +63,7 @@ + diff --git a/Implab/JSON/JSONScanner.cs b/Implab/JSON/JSONScanner.cs --- a/Implab/JSON/JSONScanner.cs +++ b/Implab/JSON/JSONScanner.cs @@ -8,13 +8,16 @@ using System.Threading.Tasks; namespace Implab.JSON { /// - /// Сканнер, разбивающий поток символов на токены JSON. + /// Сканнер (лексер), разбивающий поток символов на токены JSON. /// public class JSONScanner : Scanner { char[] m_stringBuffer; DFAStateDescriptior[] m_stringDFA; int[] m_stringAlphabet; + /// + /// Создает новый экземпляр сканнера + /// public JSONScanner() : base(JSONGrammar.Instance.JsonDFA) { m_stringBuffer = new char[1024]; @@ -23,6 +26,14 @@ namespace Implab.JSON { m_stringDFA = dfa.States; } + /// + /// Читает следующий лексический элемент из входных данных. + /// + /// Возвращает значение прочитанного токена. + /// Возвращает тип прочитанного токена. + /// true - чтение произведено успешно. false - достигнут конец входных данных + /// В случе если токен не распознается, возникает исключение. Значения токенов обрабатываются, т.е. + /// в строках обрабатываются экранированные символы, числа становтся типа double. public bool ReadToken(out object tokenValue, out JsonTokenType tokenType) { if (ReadTokenInternal()) { switch ((JSONGrammar.TokenType)m_currentState.tag[0]) { diff --git a/Implab/JSON/JSONXmlReader.cs b/Implab/JSON/JSONXmlReader.cs --- a/Implab/JSON/JSONXmlReader.cs +++ b/Implab/JSON/JSONXmlReader.cs @@ -1,14 +1,14 @@ using Implab; -using Implab.JSON; using Implab.Parsing; using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Xml; -namespace ConsPlay { +namespace Implab.JSON { public class JSONXmlReader : XmlReader { enum ValueContext { @@ -29,16 +29,34 @@ namespace ConsPlay { ReadState m_state = ReadState.Initial; Stack m_localNameStack = new Stack(); 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) { + readonly string m_rootName; + readonly string m_prefix; + readonly string m_namespaceUri; + readonly bool m_flattenArrays; + readonly string m_arrayItemName; + readonly XmlNameTable m_nameTable; + + public JSONXmlReader(JSONParser parser, JSONXmlReaderOptions options) { Safe.ArgumentNotNull(parser, "parser"); m_parser = parser; + + if (options != null) { + m_prefix = options.NodesPrefix ?? String.Empty; + m_namespaceUri = options.NamespaceURI ?? String.Empty; + m_rootName = options.RootName ?? "json"; + m_flattenArrays = options.FlattenArrays; + m_arrayItemName = options.ArrayItemName ?? "item"; + m_nameTable = options.NameTable ?? new NameTable(); + } else { + m_prefix = String.Empty; + m_namespaceUri = String.Empty; + m_rootName = "json"; + m_flattenArrays = false; + m_arrayItemName = "item"; + m_nameTable = new NameTable(); + } } /// @@ -194,7 +212,7 @@ namespace ConsPlay { RestoreLocalName(); break; } - string itemName = m_parser.ElementType == JSONElementType.None ? m_rootName : m_flattenArrays ? m_localName.localName : "item"; + string itemName = m_parser.ElementType == JSONElementType.None ? m_rootName : m_flattenArrays ? m_localName.localName : m_arrayItemName; while (m_parser.Read()) { if (!String.IsNullOrEmpty(m_parser.ElementName)) itemName = m_parser.ElementName; @@ -282,5 +300,11 @@ namespace ConsPlay { base.Dispose(disposing); } + + public static JSONXmlReader OpenFile(string file, JSONXmlReaderOptions options) { + var stream = File.OpenText(file); + var parser = new JSONParser(stream, true); + return new JSONXmlReader(parser, options); + } } } diff --git a/Implab/JSON/JSONXmlReaderOptions.cs b/Implab/JSON/JSONXmlReaderOptions.cs new file mode 100644 --- /dev/null +++ b/Implab/JSON/JSONXmlReaderOptions.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Xml; + +namespace Implab.JSON { + /// + /// Набор необязательных параметров для , позволяющий управлять процессом + /// интерпретации JSON документа. + /// + public class JSONXmlReaderOptions { + /// + /// Пространство имен в котором будут располагаться читаемые элементы документа + /// + public string NamespaceURI { + get; + set; + } + + /// + /// Интерпретировать массивы как множественные элементы (убирает один уровень вложенности) + /// + public bool FlattenArrays { + get; + set; + } + + /// + /// Префикс, для узлов документа + /// + public string NodesPrefix { + get; + set; + } + + /// + /// Имя корневого элемента в xml документе + /// + public string RootName { + get; + set; + } + + /// + /// Имя элемента для массивов, если не включена опция . + /// + public string ArrayItemName { + get; + set; + } + + /// + /// Таблица атомизированных строк для построения документа. + /// + public XmlNameTable NameTable { + get; + set; + } + } +} diff --git a/Implab/Parsing/Scanner.cs b/Implab/Parsing/Scanner.cs --- a/Implab/Parsing/Scanner.cs +++ b/Implab/Parsing/Scanner.cs @@ -167,7 +167,8 @@ namespace Implab.Parsing { m_pointer++; if (m_pointer >= m_bufferSize) { - return ReadNextChunk(); + if (!ReadNextChunk()) + return false; } m_previewCode = m_alphabetMap[m_buffer[m_pointer]];