##// END OF EJS Templates
JsonXmlReader performance tuning...
cin -
r229:5f7a3e1d32b9 v2
parent child
Show More
@@ -0,0 +1,6
1 <?xml version="1.0" encoding="utf-8" ?>
2 <configuration>
3 <startup>
4 <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
5 </startup>
6 </configuration> No newline at end of file
@@ -0,0 +1,68
1 <?xml version="1.0" encoding="utf-8"?>
2 <Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3 <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
4 <PropertyGroup>
5 <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
6 <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
7 <ProjectGuid>{100DFEB0-75BE-436F-ADDF-1F46EF433F46}</ProjectGuid>
8 <OutputType>Exe</OutputType>
9 <AppDesignerFolder>Properties</AppDesignerFolder>
10 <RootNamespace>Implab.Playground</RootNamespace>
11 <AssemblyName>Implab.Playground</AssemblyName>
12 <TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
13 <FileAlignment>512</FileAlignment>
14 <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
15 </PropertyGroup>
16 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
17 <PlatformTarget>AnyCPU</PlatformTarget>
18 <DebugSymbols>true</DebugSymbols>
19 <DebugType>full</DebugType>
20 <Optimize>false</Optimize>
21 <OutputPath>bin\Debug\</OutputPath>
22 <DefineConstants>DEBUG;TRACE</DefineConstants>
23 <ErrorReport>prompt</ErrorReport>
24 <WarningLevel>4</WarningLevel>
25 </PropertyGroup>
26 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
27 <PlatformTarget>AnyCPU</PlatformTarget>
28 <DebugType>pdbonly</DebugType>
29 <Optimize>true</Optimize>
30 <OutputPath>bin\Release\</OutputPath>
31 <DefineConstants>TRACE</DefineConstants>
32 <ErrorReport>prompt</ErrorReport>
33 <WarningLevel>4</WarningLevel>
34 <Prefer32Bit>true</Prefer32Bit>
35 <DebugSymbols>true</DebugSymbols>
36 </PropertyGroup>
37 <ItemGroup>
38 <Reference Include="System" />
39 <Reference Include="System.Core" />
40 <Reference Include="System.Xml.Linq" />
41 <Reference Include="System.Data.DataSetExtensions" />
42 <Reference Include="Microsoft.CSharp" />
43 <Reference Include="System.Data" />
44 <Reference Include="System.Net.Http" />
45 <Reference Include="System.Xml" />
46 </ItemGroup>
47 <ItemGroup>
48 <Compile Include="Program.cs" />
49 <Compile Include="Properties\AssemblyInfo.cs" />
50 </ItemGroup>
51 <ItemGroup>
52 <None Include="App.config" />
53 </ItemGroup>
54 <ItemGroup>
55 <ProjectReference Include="..\Implab\Implab.csproj">
56 <Project>{f550f1f8-8746-4ad0-9614-855f4c4b7f05}</Project>
57 <Name>Implab</Name>
58 </ProjectReference>
59 </ItemGroup>
60 <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
61 <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
62 Other similar extension points exist, see Microsoft.Common.targets.
63 <Target Name="BeforeBuild">
64 </Target>
65 <Target Name="AfterBuild">
66 </Target>
67 -->
68 </Project> No newline at end of file
@@ -0,0 +1,42
1 using Implab.Formats.Json;
2 using Implab.Xml;
3 using System;
4 using System.Collections.Generic;
5 using System.IO;
6 using System.Linq;
7 using System.Text;
8 using System.Threading.Tasks;
9 using System.Xml;
10 using System.Xml.Serialization;
11
12 namespace Implab.Playground {
13 public class Program {
14
15 [XmlRoot(Namespace = "XmlSimpleData")]
16 public class XmlSimpleModel {
17 [XmlElement]
18 public string Name { get; set; }
19
20 [XmlElement]
21 public int Order { get; set; }
22
23 [XmlElement]
24 public string[] Items { get; set; }
25
26 }
27
28 static void Main(string[] args) {
29 var model = new XmlSimpleModel {
30 Name = "Tablet",
31 Order = 10,
32 Items = new string[] { "z1", "z2", "z3" }
33 };
34
35 var doc = SerializationHelpers.SerializeAsXmlDocument(model);
36
37 var m2 = SerializationHelpers.DeserializeFromXmlNode<XmlSimpleModel>(doc.DocumentElement);
38
39 Console.WriteLine("done");
40 }
41 }
42 }
@@ -0,0 +1,36
1 using System.Reflection;
2 using System.Runtime.CompilerServices;
3 using System.Runtime.InteropServices;
4
5 // General Information about an assembly is controlled through the following
6 // set of attributes. Change these attribute values to modify the information
7 // associated with an assembly.
8 [assembly: AssemblyTitle("Implab.Playground")]
9 [assembly: AssemblyDescription("")]
10 [assembly: AssemblyConfiguration("")]
11 [assembly: AssemblyCompany("")]
12 [assembly: AssemblyProduct("Implab.Playground")]
13 [assembly: AssemblyCopyright("Copyright © 2017")]
14 [assembly: AssemblyTrademark("")]
15 [assembly: AssemblyCulture("")]
16
17 // Setting ComVisible to false makes the types in this assembly not visible
18 // to COM components. If you need to access a type in this assembly from
19 // COM, set the ComVisible attribute to true on that type.
20 [assembly: ComVisible(false)]
21
22 // The following GUID is for the ID of the typelib if this project is exposed to COM
23 [assembly: Guid("100dfeb0-75be-436f-addf-1f46ef433f46")]
24
25 // Version information for an assembly consists of the following four values:
26 //
27 // Major Version
28 // Minor Version
29 // Build Number
30 // Revision
31 //
32 // You can specify all the values or you can default the Build and Revision Numbers
33 // by using the '*' as shown below:
34 // [assembly: AssemblyVersion("1.0.*")]
35 [assembly: AssemblyVersion("1.0.0.0")]
36 [assembly: AssemblyFileVersion("1.0.0.0")]
@@ -0,0 +1,75
1 <?xml version="1.0" encoding="UTF-8"?>
2 <VSPerformanceSession Version="1.00">
3 <Options>
4 <Solution>Implab.sln</Solution>
5 <CollectionMethod>Sampling</CollectionMethod>
6 <AllocationMethod>None</AllocationMethod>
7 <AddReport>true</AddReport>
8 <ResourceBasedAnalysisSelected>true</ResourceBasedAnalysisSelected>
9 <UniqueReport>Timestamp</UniqueReport>
10 <SamplingMethod>Cycles</SamplingMethod>
11 <CycleCount>50000</CycleCount>
12 <PageFaultCount>10</PageFaultCount>
13 <SysCallCount>10</SysCallCount>
14 <SamplingCounter Name="" ReloadValue="00000000000f4240" DisplayName="" />
15 <RelocateBinaries>false</RelocateBinaries>
16 <HardwareCounters EnableHWCounters="false" />
17 <EtwSettings />
18 <PdhSettings>
19 <PdhCountersEnabled>false</PdhCountersEnabled>
20 <PdhCountersRate>500</PdhCountersRate>
21 <PdhCounters>
22 <PdhCounter>\Память\Обмен страниц/с</PdhCounter>
23 <PdhCounter>\Процессор(_Total)\% загруженности процессора</PdhCounter>
24 <PdhCounter>\Физический диск(_Total)\Средняя длина очереди диска</PdhCounter>
25 </PdhCounters>
26 </PdhSettings>
27 </Options>
28 <ExcludeSmallFuncs>true</ExcludeSmallFuncs>
29 <InteractionProfilingEnabled>false</InteractionProfilingEnabled>
30 <JScriptProfilingEnabled>false</JScriptProfilingEnabled>
31 <PreinstrumentEvent>
32 <InstrEventExclude>false</InstrEventExclude>
33 </PreinstrumentEvent>
34 <PostinstrumentEvent>
35 <InstrEventExclude>false</InstrEventExclude>
36 </PostinstrumentEvent>
37 <Binaries>
38 <ProjBinary>
39 <Path>Implab.Playground\obj\Debug\Implab.Playground.exe</Path>
40 <ArgumentTimestamp>01/01/0001 00:00:00</ArgumentTimestamp>
41 <Instrument>true</Instrument>
42 <Sample>true</Sample>
43 <ExternalWebsite>false</ExternalWebsite>
44 <InteractionProfilingEnabled>false</InteractionProfilingEnabled>
45 <IsLocalJavascript>false</IsLocalJavascript>
46 <IsWindowsStoreApp>false</IsWindowsStoreApp>
47 <IsWWA>false</IsWWA>
48 <LaunchProject>true</LaunchProject>
49 <OverrideProjectSettings>false</OverrideProjectSettings>
50 <LaunchMethod>Executable</LaunchMethod>
51 <ExecutablePath>Implab.Playground\bin\Release\Implab.Playground.exe</ExecutablePath>
52 <StartupDirectory>Implab.Playground\bin\Release\</StartupDirectory>
53 <Arguments>
54 </Arguments>
55 <NetAppHost>IIS</NetAppHost>
56 <NetBrowser>InternetExplorer</NetBrowser>
57 <ExcludeSmallFuncs>true</ExcludeSmallFuncs>
58 <JScriptProfilingEnabled>false</JScriptProfilingEnabled>
59 <PreinstrumentEvent>
60 <InstrEventExclude>false</InstrEventExclude>
61 </PreinstrumentEvent>
62 <PostinstrumentEvent>
63 <InstrEventExclude>false</InstrEventExclude>
64 </PostinstrumentEvent>
65 <ProjRef>{100DFEB0-75BE-436F-ADDF-1F46EF433F46}|Implab.Playground\Implab.Playground.csproj</ProjRef>
66 <ProjPath>Implab.Playground\Implab.Playground.csproj</ProjPath>
67 <ProjName>Implab.Playground</ProjName>
68 </ProjBinary>
69 </Binaries>
70 <Launches>
71 <ProjBinary>
72 <Path>:PB:{100DFEB0-75BE-436F-ADDF-1F46EF433F46}|Implab.Playground\Implab.Playground.csproj</Path>
73 </ProjBinary>
74 </Launches>
75 </VSPerformanceSession> No newline at end of file
@@ -0,0 +1,45
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading.Tasks;
6 using System.Xml;
7 using System.Xml.Linq;
8
9 namespace Implab.Xml {
10 public static class SerializationHelpers {
11 public static string SerializeAsString<T>(T obj) {
12 return SerializersPool<T>.Instance.SerializeAsString(obj);
13 }
14
15 public static void Serialize<T>(XmlWriter writer, T obj) {
16 SerializersPool<T>.Instance.Serialize(writer, obj);
17 }
18
19 public static XmlDocument SerializeAsXmlDocument<T>(T obj) {
20 var doc = new XmlDocument();
21 using (var writer = doc.CreateNavigator().AppendChild()) {
22 SerializersPool<T>.Instance.Serialize(writer, obj);
23 }
24 return doc;
25 }
26
27 public static XDocument SerializeAsXDocument<T>(T obj) {
28 var doc = new XDocument();
29 using (var writer = doc.CreateWriter()) {
30 SerializersPool<T>.Instance.Serialize(writer, obj);
31 }
32 return doc;
33 }
34
35 public static T DeserializeFromString<T>(string data) {
36 return SerializersPool<T>.Instance.DeserializeFromString(data);
37 }
38
39 public static T DeserializeFromXmlNode<T>(XmlNode node) {
40 Safe.ArgumentNotNull(node, nameof(node));
41 using (var reader = node.CreateNavigator().ReadSubtree())
42 return SerializersPool<T>.Instance.Deserialize(reader);
43 }
44 }
45 }
@@ -0,0 +1,76
1 using Implab.Components;
2 using System;
3 using System.Collections.Generic;
4 using System.IO;
5 using System.Linq;
6 using System.Text;
7 using System.Threading.Tasks;
8 using System.Xml;
9 using System.Xml.Serialization;
10
11 namespace Implab.Xml {
12 public class SerializersPool<T> : ObjectPool<XmlSerializer> {
13
14 static readonly SerializersPool<T> _instance = new SerializersPool<T>();
15
16 public static SerializersPool<T> Instance {
17 get { return _instance; }
18 }
19
20 #region implemented abstract members of ObjectPool
21 protected override XmlSerializer CreateInstance() {
22 return new XmlSerializer(typeof(T));
23 }
24 #endregion
25
26 public T DeserializeFromString(string data) {
27 using (var reader = new StringReader(data)) {
28 return Deserialize(reader);
29 }
30 }
31
32 public T Deserialize(TextReader reader) {
33 var sr = Allocate();
34 try {
35 return (T)sr.Deserialize(reader);
36 } finally {
37 Release(sr);
38 }
39 }
40
41 public T Deserialize(XmlReader reader) {
42 var sr = Allocate();
43 try {
44 return (T)sr.Deserialize(reader);
45 } finally {
46 Release(sr);
47 }
48 }
49
50 public string SerializeAsString(T data) {
51 using (var writer = new StringWriter()) {
52 Serialize(writer, data);
53 return writer.ToString();
54 }
55 }
56
57 public void Serialize(TextWriter writer, T data) {
58 var sr = Allocate();
59 try {
60 sr.Serialize(writer, data);
61 } finally {
62 Release(sr);
63 }
64 }
65
66 public void Serialize(XmlWriter writer, T data) {
67 var sr = Allocate();
68 try {
69 sr.Serialize(writer, data);
70 } finally {
71 Release(sr);
72 }
73 }
74
75 }
76 }
@@ -1,23 +1,25
1 syntax: glob
1 syntax: glob
2 Implab.Test/bin/
2 Implab.Test/bin/
3 *.user
3 *.user
4 Implab.Test/obj/
4 Implab.Test/obj/
5 *.userprefs
5 *.userprefs
6 Implab/bin/
6 Implab/bin/
7 Implab/obj/
7 Implab/obj/
8 TestResults/
8 TestResults/
9 Implab.Fx/obj/
9 Implab.Fx/obj/
10 Implab.Fx/bin/
10 Implab.Fx/bin/
11 Implab.Fx.Test/bin/
11 Implab.Fx.Test/bin/
12 Implab.Fx.Test/obj/
12 Implab.Fx.Test/obj/
13 _ReSharper.Implab/
13 _ReSharper.Implab/
14 Implab.Diagnostics.Interactive/bin/
14 Implab.Diagnostics.Interactive/bin/
15 Implab.Diagnostics.Interactive/obj/
15 Implab.Diagnostics.Interactive/obj/
16 MonoPlay/bin/
16 MonoPlay/bin/
17 MonoPlay/obj/
17 MonoPlay/obj/
18 Implab.Test/Implab.Format.Test/bin/
18 Implab.Test/Implab.Format.Test/bin/
19 Implab.Test/Implab.Format.Test/obj/
19 Implab.Test/Implab.Format.Test/obj/
20 *.suo
20 *.suo
21 Implab.Format.Test/bin/
21 Implab.Format.Test/bin/
22 Implab.Format.Test/obj/
22 Implab.Format.Test/obj/
23 packages/
23 packages/
24 Implab.Playground/obj/
25 Implab.Playground/bin/
@@ -1,146 +1,147
1 using NUnit.Framework;
1 using NUnit.Framework;
2 using System;
2 using System;
3 using Implab.Automaton;
3 using Implab.Automaton;
4 using Implab.Xml;
4 using Implab.Xml;
5 using System.Xml;
5 using System.Xml;
6 using Implab.Formats;
6 using Implab.Formats;
7 using Implab.Formats.Json;
7 using Implab.Formats.Json;
8 using System.IO;
8
9
9 namespace Implab.Format.Test {
10 namespace Implab.Format.Test {
10 [TestFixture]
11 [TestFixture]
11 public class JsonTests {
12 public class JsonTests {
12
13
13 [Test]
14 [Test]
14 public void TestScannerValidTokens() {
15 public void TestScannerValidTokens() {
15 using (var scanner = JsonStringScanner.Create(@"9123, -123, 0, 0.1, -0.2, -0.1e3, 1.3E-3, ""some \t\n\u0020 text"", literal []{}:")) {
16 using (var scanner = JsonStringScanner.Create(@"9123, -123, 0, 0.1, -0.2, -0.1e3, 1.3E-3, ""some \t\n\u0020 text"", literal []{}:")) {
16
17
17 Tuple<JsonTokenType, object>[] expexted = {
18 Tuple<JsonTokenType, object>[] expexted = {
18 new Tuple<JsonTokenType,object>(JsonTokenType.Number, 9123d),
19 new Tuple<JsonTokenType,object>(JsonTokenType.Number, "9123"),
19 new Tuple<JsonTokenType,object>(JsonTokenType.ValueSeparator, null),
20 new Tuple<JsonTokenType,object>(JsonTokenType.ValueSeparator, null),
20 new Tuple<JsonTokenType,object>(JsonTokenType.Number, -123d),
21 new Tuple<JsonTokenType,object>(JsonTokenType.Number, "-123"),
21 new Tuple<JsonTokenType,object>(JsonTokenType.ValueSeparator, null),
22 new Tuple<JsonTokenType,object>(JsonTokenType.ValueSeparator, null),
22 new Tuple<JsonTokenType,object>(JsonTokenType.Number, 0d),
23 new Tuple<JsonTokenType,object>(JsonTokenType.Number, "0"),
23 new Tuple<JsonTokenType,object>(JsonTokenType.ValueSeparator, null),
24 new Tuple<JsonTokenType,object>(JsonTokenType.ValueSeparator, null),
24 new Tuple<JsonTokenType,object>(JsonTokenType.Number, 0.1d),
25 new Tuple<JsonTokenType,object>(JsonTokenType.Number, "0.1"),
25 new Tuple<JsonTokenType,object>(JsonTokenType.ValueSeparator, null),
26 new Tuple<JsonTokenType,object>(JsonTokenType.ValueSeparator, null),
26 new Tuple<JsonTokenType,object>(JsonTokenType.Number, -0.2d),
27 new Tuple<JsonTokenType,object>(JsonTokenType.Number, "-0.2"),
27 new Tuple<JsonTokenType,object>(JsonTokenType.ValueSeparator, null),
28 new Tuple<JsonTokenType,object>(JsonTokenType.ValueSeparator, null),
28 new Tuple<JsonTokenType,object>(JsonTokenType.Number, -0.1e3d),
29 new Tuple<JsonTokenType,object>(JsonTokenType.Number, "-0.1e3"),
29 new Tuple<JsonTokenType,object>(JsonTokenType.ValueSeparator, null),
30 new Tuple<JsonTokenType,object>(JsonTokenType.ValueSeparator, null),
30 new Tuple<JsonTokenType,object>(JsonTokenType.Number, 1.3E-3d),
31 new Tuple<JsonTokenType,object>(JsonTokenType.Number, "1.3E-3"),
31 new Tuple<JsonTokenType,object>(JsonTokenType.ValueSeparator, null),
32 new Tuple<JsonTokenType,object>(JsonTokenType.ValueSeparator, null),
32 new Tuple<JsonTokenType,object>(JsonTokenType.String, "some \t\n text"),
33 new Tuple<JsonTokenType,object>(JsonTokenType.String, "some \t\n text"),
33 new Tuple<JsonTokenType,object>(JsonTokenType.ValueSeparator, null),
34 new Tuple<JsonTokenType,object>(JsonTokenType.ValueSeparator, null),
34 new Tuple<JsonTokenType,object>(JsonTokenType.Literal, "literal"),
35 new Tuple<JsonTokenType,object>(JsonTokenType.Literal, "literal"),
35 new Tuple<JsonTokenType,object>(JsonTokenType.BeginArray, null),
36 new Tuple<JsonTokenType,object>(JsonTokenType.BeginArray, null),
36 new Tuple<JsonTokenType,object>(JsonTokenType.EndArray, null),
37 new Tuple<JsonTokenType,object>(JsonTokenType.EndArray, null),
37 new Tuple<JsonTokenType,object>(JsonTokenType.BeginObject, null),
38 new Tuple<JsonTokenType,object>(JsonTokenType.BeginObject, null),
38 new Tuple<JsonTokenType,object>(JsonTokenType.EndObject, null),
39 new Tuple<JsonTokenType,object>(JsonTokenType.EndObject, null),
39 new Tuple<JsonTokenType,object>(JsonTokenType.NameSeparator, null)
40 new Tuple<JsonTokenType,object>(JsonTokenType.NameSeparator, null)
40 };
41 };
41
42
42 object value;
43 string value;
43 JsonTokenType tokenType;
44 JsonTokenType tokenType;
44 for (var i = 0; i < expexted.Length; i++) {
45 for (var i = 0; i < expexted.Length; i++) {
45
46
46 Assert.IsTrue(scanner.ReadToken(out value, out tokenType));
47 Assert.IsTrue(scanner.ReadToken(out value, out tokenType));
47 Assert.AreEqual(expexted[i].Item1, tokenType);
48 Assert.AreEqual(expexted[i].Item1, tokenType);
48 Assert.AreEqual(expexted[i].Item2, value);
49 Assert.AreEqual(expexted[i].Item2, value);
49 }
50 }
50
51
51 Assert.IsFalse(scanner.ReadToken(out value, out tokenType));
52 Assert.IsFalse(scanner.ReadToken(out value, out tokenType));
52 }
53 }
53 }
54 }
54
55
55 [Test]
56 [Test]
56 public void TestScannerBadTokens() {
57 public void TestScannerBadTokens() {
57 var bad = new[] {
58 var bad = new[] {
58 " 1",
59 " 1",
59 " literal",
60 " literal",
60 " \"",
61 " \"",
61 "\"unclosed string",
62 "\"unclosed string",
62 "1.bad",
63 "1.bad",
63 "001", // should be read as three numbers
64 "001", // should be read as three numbers
64 "--10",
65 "--10",
65 "+10",
66 "+10",
66 "1.0.0",
67 "1.0.0",
67 "1e1.0",
68 "1e1.0",
68 "l1teral0",
69 "l1teral0",
69 ".123",
70 ".123",
70 "-.123"
71 "-.123"
71 };
72 };
72
73
73 foreach (var json in bad) {
74 foreach (var json in bad) {
74 using (var scanner = JsonStringScanner.Create(json)) {
75 using (var scanner = JsonStringScanner.Create(json)) {
75 try {
76 try {
76 object value;
77 string value;
77 JsonTokenType token;
78 JsonTokenType token;
78 scanner.ReadToken(out value, out token);
79 scanner.ReadToken(out value, out token);
79 if (!Object.Equals(value, json)) {
80 if (!Object.Equals(value, json)) {
80 Console.WriteLine("'{0}' is read as {1}", json, value is String ? String.Format("'{0}'", value) : value);
81 Console.WriteLine("'{0}' is read as {1}", json, value is String ? String.Format("'{0}'", value) : value);
81 continue;
82 continue;
82 }
83 }
83 Assert.Fail("Token '{0}' shouldn't pass", json);
84 Assert.Fail("Token '{0}' shouldn't pass", json);
84 } catch (ParserException e) {
85 } catch (ParserException e) {
85 Console.WriteLine(e.Message);
86 Console.WriteLine(e.Message);
86 }
87 }
87 }
88 }
88 }
89 }
89 }
90 }
90
91
91 [Test]
92 [Test]
92 public void JsonXmlReaderSimpleTest() {
93 public void JsonXmlReaderSimpleTest() {
93 var json = "\"some text\"";
94 var json = "\"some text\"";
94 //Console.WriteLine($"JSON: {json}");
95 //Console.WriteLine($"JSON: {json}");
95 //Console.WriteLine("XML");
96 //Console.WriteLine("XML");
96 /*using (var xmlReader = new JsonXmlReader(new JSONParser(json), new JsonXmlReaderOptions { NamespaceUri = "JsonXmlReaderSimpleTest", RootName = "string", NodesPrefix = "json" })) {
97 /*using (var xmlReader = new JsonXmlReader(new JSONParser(json), new JsonXmlReaderOptions { NamespaceUri = "JsonXmlReaderSimpleTest", RootName = "string", NodesPrefix = "json" })) {
97 Assert.AreEqual(xmlReader.ReadState, System.Xml.ReadState.Initial);
98 Assert.AreEqual(xmlReader.ReadState, System.Xml.ReadState.Initial);
98
99
99 AssertRead(xmlReader, XmlNodeType.XmlDeclaration);
100 AssertRead(xmlReader, XmlNodeType.XmlDeclaration);
100 AssertRead(xmlReader, XmlNodeType.Element);
101 AssertRead(xmlReader, XmlNodeType.Element);
101 AssertRead(xmlReader, XmlNodeType.Text);
102 AssertRead(xmlReader, XmlNodeType.Text);
102 AssertRead(xmlReader, XmlNodeType.EndElement);
103 AssertRead(xmlReader, XmlNodeType.EndElement);
103 Assert.IsFalse(xmlReader.Read());
104 Assert.IsFalse(xmlReader.Read());
104 }*/
105 }*/
105
106
106 //DumpJsonParse("\"text value\"");
107 //DumpJsonParse("\"text value\"");
107 //DumpJsonParse("null");
108 //DumpJsonParse("null");
108 //DumpJsonParse("true");
109 //DumpJsonParse("true");
109 //DumpJsonParse("{}");
110 //DumpJsonParse("{}");
110 //DumpJsonParse("[]");
111 //DumpJsonParse("[]");
111 DumpJsonParse("{\"one\":1, \"two\":2}");
112 DumpJsonParse("{\"one\":1, \"two\":2}");
112 DumpJsonParse("[1,2,3]");
113 DumpJsonParse("[1,\"\",2,3]");
113 DumpJsonParse("[{\"info\": [7,8,9]}]");
114 DumpJsonParse("[{\"info\": [7,8,9]}]");
114 DumpJsonFlatParse("[1,2,[3,4],{\"info\": [5,6]},{\"num\": [7,8,null]}, null,[null]]");
115 DumpJsonFlatParse("[1,2,\"\",[3,4],{\"info\": [5,6]},{\"num\": [7,8,null]}, null,[null]]");
115 }
116 }
116
117
117 void AssertRead(XmlReader reader, XmlNodeType expected) {
118 void AssertRead(XmlReader reader, XmlNodeType expected) {
118 Assert.IsTrue(reader.Read());
119 Assert.IsTrue(reader.Read());
119 Console.WriteLine($"{new string(' ', reader.Depth*2)}{reader}");
120 Console.WriteLine($"{new string(' ', reader.Depth*2)}{reader}");
120 Assert.AreEqual(expected, reader.NodeType);
121 Assert.AreEqual(expected, reader.NodeType);
121 }
122 }
122
123
123 void DumpJsonParse(string json) {
124 void DumpJsonParse(string json) {
124 Console.WriteLine($"JSON: {json}");
125 Console.WriteLine($"JSON: {json}");
125 Console.WriteLine("XML");
126 Console.WriteLine("XML");
126 using (var xmlReader = new JsonXmlReader(new JsonParser(json), new JsonXmlReaderOptions { NamespaceUri = "JsonXmlReaderSimpleTest", NodesPrefix = "json" })) {
127 using (var xmlReader = new JsonXmlReader(JsonReader.ParseString(json), new JsonXmlReaderOptions { NamespaceUri = "JsonXmlReaderSimpleTest", NodesPrefix = "json" })) {
127 while (xmlReader.Read())
128 while (xmlReader.Read())
128 Console.WriteLine($"{new string(' ', xmlReader.Depth * 2)}{xmlReader}");
129 Console.WriteLine($"{new string(' ', xmlReader.Depth * 2)}{xmlReader}");
129 }
130 }
130 }
131 }
131
132
132 void DumpJsonFlatParse(string json) {
133 void DumpJsonFlatParse(string json) {
133 Console.WriteLine($"JSON: {json}");
134 Console.WriteLine($"JSON: {json}");
134 Console.WriteLine("XML");
135 Console.WriteLine("XML");
135 using (var xmlWriter = XmlWriter.Create(Console.Out, new XmlWriterSettings {
136 using (var xmlWriter = XmlWriter.Create(Console.Out, new XmlWriterSettings {
136 Indent = true,
137 Indent = true,
137 CloseOutput = false,
138 CloseOutput = false,
138 ConformanceLevel = ConformanceLevel.Document
139 ConformanceLevel = ConformanceLevel.Document
139 }))
140 }))
140 using (var xmlReader = new JsonXmlReader(new JsonParser(json), new JsonXmlReaderOptions { NamespaceUri = "JsonXmlReaderSimpleTest", NodesPrefix = "", FlattenArrays = true })) {
141 using (var xmlReader = new JsonXmlReader(JsonReader.ParseString(json), new JsonXmlReaderOptions { NamespaceUri = "JsonXmlReaderSimpleTest", NodesPrefix = "", FlattenArrays = true })) {
141 xmlWriter.WriteNode(xmlReader, false);
142 xmlWriter.WriteNode(xmlReader, false);
142 }
143 }
143 }
144 }
144 }
145 }
145 }
146 }
146
147
@@ -1,260 +1,263
1 
1 
2 Microsoft Visual Studio Solution File, Format Version 12.00
2 Microsoft Visual Studio Solution File, Format Version 12.00
3 # Visual Studio 14
3 # Visual Studio 14
4 VisualStudioVersion = 14.0.25420.1
4 VisualStudioVersion = 14.0.25420.1
5 MinimumVisualStudioVersion = 10.0.40219.1
5 MinimumVisualStudioVersion = 10.0.40219.1
6 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Implab", "Implab\Implab.csproj", "{F550F1F8-8746-4AD0-9614-855F4C4B7F05}"
6 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Implab", "Implab\Implab.csproj", "{F550F1F8-8746-4AD0-9614-855F4C4B7F05}"
7 EndProject
7 EndProject
8 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{CE8D8D18-437A-445C-B662-4C2CE79A76F6}"
8 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{CE8D8D18-437A-445C-B662-4C2CE79A76F6}"
9 ProjectSection(SolutionItems) = preProject
9 ProjectSection(SolutionItems) = preProject
10 Implab.vsmdi = Implab.vsmdi
10 Implab.vsmdi = Implab.vsmdi
11 Local.testsettings = Local.testsettings
11 Local.testsettings = Local.testsettings
12 TraceAndTestImpact.testsettings = TraceAndTestImpact.testsettings
12 TraceAndTestImpact.testsettings = TraceAndTestImpact.testsettings
13 EndProjectSection
13 EndProjectSection
14 EndProject
14 EndProject
15 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Implab.Test", "Implab.Test\Implab.Test.csproj", "{63F92C0C-61BF-48C0-A377-8D67C3C661D0}"
15 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Implab.Test", "Implab.Test\Implab.Test.csproj", "{63F92C0C-61BF-48C0-A377-8D67C3C661D0}"
16 EndProject
16 EndProject
17 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Implab.Fx", "Implab.Fx\Implab.Fx.csproj", "{06E706F8-6881-43EB-927E-FFC503AF6ABC}"
17 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Implab.Fx", "Implab.Fx\Implab.Fx.csproj", "{06E706F8-6881-43EB-927E-FFC503AF6ABC}"
18 EndProject
18 EndProject
19 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Implab.Fx.Test", "Implab.Fx.Test\Implab.Fx.Test.csproj", "{2F31E405-E267-4195-A05D-574093C21209}"
20 EndProject
21 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Implab.Format.Test", "Implab.Format.Test\Implab.Format.Test.csproj", "{4D364996-7ECD-4193-8F90-F223FFEA49DA}"
19 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Implab.Format.Test", "Implab.Format.Test\Implab.Format.Test.csproj", "{4D364996-7ECD-4193-8F90-F223FFEA49DA}"
22 EndProject
20 EndProject
21 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Implab.Playground", "Implab.Playground\Implab.Playground.csproj", "{100DFEB0-75BE-436F-ADDF-1F46EF433F46}"
22 EndProject
23 Global
23 Global
24 GlobalSection(Performance) = preSolution
25 HasPerformanceSessions = true
26 EndGlobalSection
24 GlobalSection(SolutionConfigurationPlatforms) = preSolution
27 GlobalSection(SolutionConfigurationPlatforms) = preSolution
25 Debug 4.5|Any CPU = Debug 4.5|Any CPU
28 Debug 4.5|Any CPU = Debug 4.5|Any CPU
26 Debug|Any CPU = Debug|Any CPU
29 Debug|Any CPU = Debug|Any CPU
27 Release 4.5|Any CPU = Release 4.5|Any CPU
30 Release 4.5|Any CPU = Release 4.5|Any CPU
28 Release|Any CPU = Release|Any CPU
31 Release|Any CPU = Release|Any CPU
29 EndGlobalSection
32 EndGlobalSection
30 GlobalSection(ProjectConfigurationPlatforms) = postSolution
33 GlobalSection(ProjectConfigurationPlatforms) = postSolution
31 {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Debug 4.5|Any CPU.ActiveCfg = Debug 4.5|Any CPU
34 {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Debug 4.5|Any CPU.ActiveCfg = Debug 4.5|Any CPU
32 {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Debug 4.5|Any CPU.Build.0 = Debug 4.5|Any CPU
35 {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Debug 4.5|Any CPU.Build.0 = Debug 4.5|Any CPU
33 {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
36 {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
34 {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Debug|Any CPU.Build.0 = Debug|Any CPU
37 {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Debug|Any CPU.Build.0 = Debug|Any CPU
35 {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Release 4.5|Any CPU.ActiveCfg = Release 4.5|Any CPU
38 {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Release 4.5|Any CPU.ActiveCfg = Release 4.5|Any CPU
36 {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Release 4.5|Any CPU.Build.0 = Release 4.5|Any CPU
39 {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Release 4.5|Any CPU.Build.0 = Release 4.5|Any CPU
37 {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Release|Any CPU.ActiveCfg = Release|Any CPU
40 {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Release|Any CPU.ActiveCfg = Release|Any CPU
38 {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Release|Any CPU.Build.0 = Release|Any CPU
41 {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Release|Any CPU.Build.0 = Release|Any CPU
39 {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Debug 4.5|Any CPU.ActiveCfg = Debug 4.5|Any CPU
42 {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Debug 4.5|Any CPU.ActiveCfg = Debug 4.5|Any CPU
40 {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Debug 4.5|Any CPU.Build.0 = Debug 4.5|Any CPU
43 {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Debug 4.5|Any CPU.Build.0 = Debug 4.5|Any CPU
41 {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
44 {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
42 {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
45 {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
43 {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Release 4.5|Any CPU.ActiveCfg = Release 4.5|Any CPU
46 {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Release 4.5|Any CPU.ActiveCfg = Release 4.5|Any CPU
44 {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Release 4.5|Any CPU.Build.0 = Release 4.5|Any CPU
47 {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Release 4.5|Any CPU.Build.0 = Release 4.5|Any CPU
45 {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
48 {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
46 {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Release|Any CPU.Build.0 = Release|Any CPU
49 {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Release|Any CPU.Build.0 = Release|Any CPU
47 {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Debug 4.5|Any CPU.ActiveCfg = Debug 4.5|Any CPU
50 {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Debug 4.5|Any CPU.ActiveCfg = Debug 4.5|Any CPU
48 {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Debug 4.5|Any CPU.Build.0 = Debug 4.5|Any CPU
51 {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Debug 4.5|Any CPU.Build.0 = Debug 4.5|Any CPU
49 {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
52 {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
50 {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Debug|Any CPU.Build.0 = Debug|Any CPU
53 {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Debug|Any CPU.Build.0 = Debug|Any CPU
51 {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Release 4.5|Any CPU.ActiveCfg = Release 4.5|Any CPU
54 {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Release 4.5|Any CPU.ActiveCfg = Release 4.5|Any CPU
52 {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Release 4.5|Any CPU.Build.0 = Release 4.5|Any CPU
55 {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Release 4.5|Any CPU.Build.0 = Release 4.5|Any CPU
53 {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Release|Any CPU.ActiveCfg = Release|Any CPU
56 {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Release|Any CPU.ActiveCfg = Release|Any CPU
54 {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Release|Any CPU.Build.0 = Release|Any CPU
57 {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Release|Any CPU.Build.0 = Release|Any CPU
55 {2F31E405-E267-4195-A05D-574093C21209}.Debug 4.5|Any CPU.ActiveCfg = Debug 4.5|Any CPU
56 {2F31E405-E267-4195-A05D-574093C21209}.Debug 4.5|Any CPU.Build.0 = Debug 4.5|Any CPU
57 {2F31E405-E267-4195-A05D-574093C21209}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
58 {2F31E405-E267-4195-A05D-574093C21209}.Debug|Any CPU.Build.0 = Debug|Any CPU
59 {2F31E405-E267-4195-A05D-574093C21209}.Release 4.5|Any CPU.ActiveCfg = Release 4.5|Any CPU
60 {2F31E405-E267-4195-A05D-574093C21209}.Release 4.5|Any CPU.Build.0 = Release 4.5|Any CPU
61 {2F31E405-E267-4195-A05D-574093C21209}.Release|Any CPU.ActiveCfg = Release|Any CPU
62 {2F31E405-E267-4195-A05D-574093C21209}.Release|Any CPU.Build.0 = Release|Any CPU
63 {4D364996-7ECD-4193-8F90-F223FFEA49DA}.Debug 4.5|Any CPU.ActiveCfg = Debug|Any CPU
58 {4D364996-7ECD-4193-8F90-F223FFEA49DA}.Debug 4.5|Any CPU.ActiveCfg = Debug|Any CPU
64 {4D364996-7ECD-4193-8F90-F223FFEA49DA}.Debug 4.5|Any CPU.Build.0 = Debug|Any CPU
59 {4D364996-7ECD-4193-8F90-F223FFEA49DA}.Debug 4.5|Any CPU.Build.0 = Debug|Any CPU
65 {4D364996-7ECD-4193-8F90-F223FFEA49DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
60 {4D364996-7ECD-4193-8F90-F223FFEA49DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
66 {4D364996-7ECD-4193-8F90-F223FFEA49DA}.Debug|Any CPU.Build.0 = Debug|Any CPU
61 {4D364996-7ECD-4193-8F90-F223FFEA49DA}.Debug|Any CPU.Build.0 = Debug|Any CPU
67 {4D364996-7ECD-4193-8F90-F223FFEA49DA}.Release 4.5|Any CPU.ActiveCfg = Release|Any CPU
62 {4D364996-7ECD-4193-8F90-F223FFEA49DA}.Release 4.5|Any CPU.ActiveCfg = Release|Any CPU
68 {4D364996-7ECD-4193-8F90-F223FFEA49DA}.Release 4.5|Any CPU.Build.0 = Release|Any CPU
63 {4D364996-7ECD-4193-8F90-F223FFEA49DA}.Release 4.5|Any CPU.Build.0 = Release|Any CPU
69 {4D364996-7ECD-4193-8F90-F223FFEA49DA}.Release|Any CPU.ActiveCfg = Release|Any CPU
64 {4D364996-7ECD-4193-8F90-F223FFEA49DA}.Release|Any CPU.ActiveCfg = Release|Any CPU
70 {4D364996-7ECD-4193-8F90-F223FFEA49DA}.Release|Any CPU.Build.0 = Release|Any CPU
65 {4D364996-7ECD-4193-8F90-F223FFEA49DA}.Release|Any CPU.Build.0 = Release|Any CPU
66 {100DFEB0-75BE-436F-ADDF-1F46EF433F46}.Debug 4.5|Any CPU.ActiveCfg = Debug|Any CPU
67 {100DFEB0-75BE-436F-ADDF-1F46EF433F46}.Debug 4.5|Any CPU.Build.0 = Debug|Any CPU
68 {100DFEB0-75BE-436F-ADDF-1F46EF433F46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
69 {100DFEB0-75BE-436F-ADDF-1F46EF433F46}.Debug|Any CPU.Build.0 = Debug|Any CPU
70 {100DFEB0-75BE-436F-ADDF-1F46EF433F46}.Release 4.5|Any CPU.ActiveCfg = Release|Any CPU
71 {100DFEB0-75BE-436F-ADDF-1F46EF433F46}.Release 4.5|Any CPU.Build.0 = Release|Any CPU
72 {100DFEB0-75BE-436F-ADDF-1F46EF433F46}.Release|Any CPU.ActiveCfg = Release|Any CPU
73 {100DFEB0-75BE-436F-ADDF-1F46EF433F46}.Release|Any CPU.Build.0 = Release|Any CPU
71 EndGlobalSection
74 EndGlobalSection
72 GlobalSection(SolutionProperties) = preSolution
75 GlobalSection(SolutionProperties) = preSolution
73 HideSolutionNode = FALSE
76 HideSolutionNode = FALSE
74 EndGlobalSection
77 EndGlobalSection
75 GlobalSection(MonoDevelopProperties) = preSolution
78 GlobalSection(MonoDevelopProperties) = preSolution
76 StartupItem = Implab\Implab.csproj
79 StartupItem = Implab\Implab.csproj
77 Policies = $0
80 Policies = $0
78 $0.CSharpFormattingPolicy = $1
81 $0.CSharpFormattingPolicy = $1
79 $1.IndentSwitchBody = True
82 $1.IndentSwitchBody = True
80 $1.NamespaceBraceStyle = EndOfLine
83 $1.NamespaceBraceStyle = EndOfLine
81 $1.ClassBraceStyle = EndOfLine
84 $1.ClassBraceStyle = EndOfLine
82 $1.InterfaceBraceStyle = EndOfLine
85 $1.InterfaceBraceStyle = EndOfLine
83 $1.StructBraceStyle = EndOfLine
86 $1.StructBraceStyle = EndOfLine
84 $1.EnumBraceStyle = EndOfLine
87 $1.EnumBraceStyle = EndOfLine
85 $1.MethodBraceStyle = EndOfLine
88 $1.MethodBraceStyle = EndOfLine
86 $1.ConstructorBraceStyle = EndOfLine
89 $1.ConstructorBraceStyle = EndOfLine
87 $1.DestructorBraceStyle = EndOfLine
90 $1.DestructorBraceStyle = EndOfLine
88 $1.BeforeMethodDeclarationParentheses = False
91 $1.BeforeMethodDeclarationParentheses = False
89 $1.BeforeMethodCallParentheses = False
92 $1.BeforeMethodCallParentheses = False
90 $1.BeforeConstructorDeclarationParentheses = False
93 $1.BeforeConstructorDeclarationParentheses = False
91 $1.NewLineBeforeConstructorInitializerColon = NewLine
94 $1.NewLineBeforeConstructorInitializerColon = NewLine
92 $1.NewLineAfterConstructorInitializerColon = SameLine
95 $1.NewLineAfterConstructorInitializerColon = SameLine
93 $1.BeforeIndexerDeclarationBracket = False
96 $1.BeforeIndexerDeclarationBracket = False
94 $1.BeforeDelegateDeclarationParentheses = False
97 $1.BeforeDelegateDeclarationParentheses = False
95 $1.NewParentheses = False
98 $1.NewParentheses = False
96 $1.SpacesBeforeBrackets = False
99 $1.SpacesBeforeBrackets = False
97 $1.inheritsSet = Mono
100 $1.inheritsSet = Mono
98 $1.inheritsScope = text/x-csharp
101 $1.inheritsScope = text/x-csharp
99 $1.scope = text/x-csharp
102 $1.scope = text/x-csharp
100 $0.TextStylePolicy = $6
103 $0.TextStylePolicy = $6
101 $2.FileWidth = 120
104 $2.FileWidth = 120
102 $2.EolMarker = Unix
105 $2.EolMarker = Unix
103 $2.inheritsSet = VisualStudio
106 $2.inheritsSet = VisualStudio
104 $2.inheritsScope = text/plain
107 $2.inheritsScope = text/plain
105 $2.scope = text/x-csharp
108 $2.scope = text/x-csharp
106 $0.DotNetNamingPolicy = $3
109 $0.DotNetNamingPolicy = $3
107 $3.DirectoryNamespaceAssociation = PrefixedHierarchical
110 $3.DirectoryNamespaceAssociation = PrefixedHierarchical
108 $3.ResourceNamePolicy = MSBuild
111 $3.ResourceNamePolicy = MSBuild
109 $4.FileWidth = 120
112 $4.FileWidth = 120
110 $4.TabsToSpaces = False
113 $4.TabsToSpaces = False
111 $4.inheritsSet = VisualStudio
114 $4.inheritsSet = VisualStudio
112 $4.inheritsScope = text/plain
115 $4.inheritsScope = text/plain
113 $4.scope = application/xml
116 $4.scope = application/xml
114 $0.XmlFormattingPolicy = $5
117 $0.XmlFormattingPolicy = $5
115 $5.inheritsSet = Mono
118 $5.inheritsSet = Mono
116 $5.inheritsScope = application/xml
119 $5.inheritsScope = application/xml
117 $5.scope = application/xml
120 $5.scope = application/xml
118 $6.FileWidth = 120
121 $6.FileWidth = 120
119 $6.TabsToSpaces = False
122 $6.TabsToSpaces = False
120 $6.inheritsSet = VisualStudio
123 $6.inheritsSet = VisualStudio
121 $6.inheritsScope = text/plain
124 $6.inheritsScope = text/plain
122 $6.scope = text/plain
125 $6.scope = text/plain
123 $0.NameConventionPolicy = $7
126 $0.NameConventionPolicy = $7
124 $7.Rules = $8
127 $7.Rules = $8
125 $8.NamingRule = $34
128 $8.NamingRule = $34
126 $9.Name = Namespaces
129 $9.Name = Namespaces
127 $9.AffectedEntity = Namespace
130 $9.AffectedEntity = Namespace
128 $9.VisibilityMask = VisibilityMask
131 $9.VisibilityMask = VisibilityMask
129 $9.NamingStyle = PascalCase
132 $9.NamingStyle = PascalCase
130 $9.IncludeInstanceMembers = True
133 $9.IncludeInstanceMembers = True
131 $9.IncludeStaticEntities = True
134 $9.IncludeStaticEntities = True
132 $10.Name = Types
135 $10.Name = Types
133 $10.AffectedEntity = Class, Struct, Enum, Delegate
136 $10.AffectedEntity = Class, Struct, Enum, Delegate
134 $10.VisibilityMask = VisibilityMask
137 $10.VisibilityMask = VisibilityMask
135 $10.NamingStyle = PascalCase
138 $10.NamingStyle = PascalCase
136 $10.IncludeInstanceMembers = True
139 $10.IncludeInstanceMembers = True
137 $10.IncludeStaticEntities = True
140 $10.IncludeStaticEntities = True
138 $11.Name = Interfaces
141 $11.Name = Interfaces
139 $11.RequiredPrefixes = $12
142 $11.RequiredPrefixes = $12
140 $12.String = I
143 $12.String = I
141 $11.AffectedEntity = Interface
144 $11.AffectedEntity = Interface
142 $11.VisibilityMask = VisibilityMask
145 $11.VisibilityMask = VisibilityMask
143 $11.NamingStyle = PascalCase
146 $11.NamingStyle = PascalCase
144 $11.IncludeInstanceMembers = True
147 $11.IncludeInstanceMembers = True
145 $11.IncludeStaticEntities = True
148 $11.IncludeStaticEntities = True
146 $13.Name = Attributes
149 $13.Name = Attributes
147 $13.RequiredSuffixes = $14
150 $13.RequiredSuffixes = $14
148 $14.String = Attribute
151 $14.String = Attribute
149 $13.AffectedEntity = CustomAttributes
152 $13.AffectedEntity = CustomAttributes
150 $13.VisibilityMask = VisibilityMask
153 $13.VisibilityMask = VisibilityMask
151 $13.NamingStyle = PascalCase
154 $13.NamingStyle = PascalCase
152 $13.IncludeInstanceMembers = True
155 $13.IncludeInstanceMembers = True
153 $13.IncludeStaticEntities = True
156 $13.IncludeStaticEntities = True
154 $15.Name = Event Arguments
157 $15.Name = Event Arguments
155 $15.RequiredSuffixes = $16
158 $15.RequiredSuffixes = $16
156 $16.String = EventArgs
159 $16.String = EventArgs
157 $15.AffectedEntity = CustomEventArgs
160 $15.AffectedEntity = CustomEventArgs
158 $15.VisibilityMask = VisibilityMask
161 $15.VisibilityMask = VisibilityMask
159 $15.NamingStyle = PascalCase
162 $15.NamingStyle = PascalCase
160 $15.IncludeInstanceMembers = True
163 $15.IncludeInstanceMembers = True
161 $15.IncludeStaticEntities = True
164 $15.IncludeStaticEntities = True
162 $17.Name = Exceptions
165 $17.Name = Exceptions
163 $17.RequiredSuffixes = $18
166 $17.RequiredSuffixes = $18
164 $18.String = Exception
167 $18.String = Exception
165 $17.AffectedEntity = CustomExceptions
168 $17.AffectedEntity = CustomExceptions
166 $17.VisibilityMask = VisibilityMask
169 $17.VisibilityMask = VisibilityMask
167 $17.NamingStyle = PascalCase
170 $17.NamingStyle = PascalCase
168 $17.IncludeInstanceMembers = True
171 $17.IncludeInstanceMembers = True
169 $17.IncludeStaticEntities = True
172 $17.IncludeStaticEntities = True
170 $19.Name = Methods
173 $19.Name = Methods
171 $19.AffectedEntity = Methods
174 $19.AffectedEntity = Methods
172 $19.VisibilityMask = VisibilityMask
175 $19.VisibilityMask = VisibilityMask
173 $19.NamingStyle = PascalCase
176 $19.NamingStyle = PascalCase
174 $19.IncludeInstanceMembers = True
177 $19.IncludeInstanceMembers = True
175 $19.IncludeStaticEntities = True
178 $19.IncludeStaticEntities = True
176 $20.Name = Static Readonly Fields
179 $20.Name = Static Readonly Fields
177 $20.AffectedEntity = ReadonlyField
180 $20.AffectedEntity = ReadonlyField
178 $20.VisibilityMask = Internal, Protected, Public
181 $20.VisibilityMask = Internal, Protected, Public
179 $20.NamingStyle = CamelCase
182 $20.NamingStyle = CamelCase
180 $20.IncludeInstanceMembers = False
183 $20.IncludeInstanceMembers = False
181 $20.IncludeStaticEntities = True
184 $20.IncludeStaticEntities = True
182 $21.Name = Fields (Non Private)
185 $21.Name = Fields (Non Private)
183 $21.AffectedEntity = Field
186 $21.AffectedEntity = Field
184 $21.VisibilityMask = Internal, Public
187 $21.VisibilityMask = Internal, Public
185 $21.NamingStyle = CamelCase
188 $21.NamingStyle = CamelCase
186 $21.IncludeInstanceMembers = True
189 $21.IncludeInstanceMembers = True
187 $21.IncludeStaticEntities = True
190 $21.IncludeStaticEntities = True
188 $22.Name = ReadOnly Fields (Non Private)
191 $22.Name = ReadOnly Fields (Non Private)
189 $22.AffectedEntity = ReadonlyField
192 $22.AffectedEntity = ReadonlyField
190 $22.VisibilityMask = Internal, Public
193 $22.VisibilityMask = Internal, Public
191 $22.NamingStyle = CamelCase
194 $22.NamingStyle = CamelCase
192 $22.IncludeInstanceMembers = True
195 $22.IncludeInstanceMembers = True
193 $22.IncludeStaticEntities = False
196 $22.IncludeStaticEntities = False
194 $23.Name = Fields (Private)
197 $23.Name = Fields (Private)
195 $23.RequiredPrefixes = $24
198 $23.RequiredPrefixes = $24
196 $24.String = m_
199 $24.String = m_
197 $23.AffectedEntity = Field, ReadonlyField
200 $23.AffectedEntity = Field, ReadonlyField
198 $23.VisibilityMask = Private, Protected
201 $23.VisibilityMask = Private, Protected
199 $23.NamingStyle = CamelCase
202 $23.NamingStyle = CamelCase
200 $23.IncludeInstanceMembers = True
203 $23.IncludeInstanceMembers = True
201 $23.IncludeStaticEntities = False
204 $23.IncludeStaticEntities = False
202 $25.Name = Static Fields (Private)
205 $25.Name = Static Fields (Private)
203 $25.RequiredPrefixes = $26
206 $25.RequiredPrefixes = $26
204 $26.String = _
207 $26.String = _
205 $25.AffectedEntity = Field
208 $25.AffectedEntity = Field
206 $25.VisibilityMask = Private
209 $25.VisibilityMask = Private
207 $25.NamingStyle = CamelCase
210 $25.NamingStyle = CamelCase
208 $25.IncludeInstanceMembers = False
211 $25.IncludeInstanceMembers = False
209 $25.IncludeStaticEntities = True
212 $25.IncludeStaticEntities = True
210 $27.Name = ReadOnly Fields (Private)
213 $27.Name = ReadOnly Fields (Private)
211 $27.RequiredPrefixes = $28
214 $27.RequiredPrefixes = $28
212 $28.String = m_
215 $28.String = m_
213 $27.AffectedEntity = ReadonlyField
216 $27.AffectedEntity = ReadonlyField
214 $27.VisibilityMask = Private, Protected
217 $27.VisibilityMask = Private, Protected
215 $27.NamingStyle = CamelCase
218 $27.NamingStyle = CamelCase
216 $27.IncludeInstanceMembers = True
219 $27.IncludeInstanceMembers = True
217 $27.IncludeStaticEntities = False
220 $27.IncludeStaticEntities = False
218 $29.Name = Constant Fields
221 $29.Name = Constant Fields
219 $29.AffectedEntity = ConstantField
222 $29.AffectedEntity = ConstantField
220 $29.VisibilityMask = VisibilityMask
223 $29.VisibilityMask = VisibilityMask
221 $29.NamingStyle = AllUpper
224 $29.NamingStyle = AllUpper
222 $29.IncludeInstanceMembers = True
225 $29.IncludeInstanceMembers = True
223 $29.IncludeStaticEntities = True
226 $29.IncludeStaticEntities = True
224 $30.Name = Properties
227 $30.Name = Properties
225 $30.AffectedEntity = Property
228 $30.AffectedEntity = Property
226 $30.VisibilityMask = VisibilityMask
229 $30.VisibilityMask = VisibilityMask
227 $30.NamingStyle = PascalCase
230 $30.NamingStyle = PascalCase
228 $30.IncludeInstanceMembers = True
231 $30.IncludeInstanceMembers = True
229 $30.IncludeStaticEntities = True
232 $30.IncludeStaticEntities = True
230 $31.Name = Events
233 $31.Name = Events
231 $31.AffectedEntity = Event
234 $31.AffectedEntity = Event
232 $31.VisibilityMask = VisibilityMask
235 $31.VisibilityMask = VisibilityMask
233 $31.NamingStyle = PascalCase
236 $31.NamingStyle = PascalCase
234 $31.IncludeInstanceMembers = True
237 $31.IncludeInstanceMembers = True
235 $31.IncludeStaticEntities = True
238 $31.IncludeStaticEntities = True
236 $32.Name = Enum Members
239 $32.Name = Enum Members
237 $32.AffectedEntity = EnumMember
240 $32.AffectedEntity = EnumMember
238 $32.VisibilityMask = VisibilityMask
241 $32.VisibilityMask = VisibilityMask
239 $32.NamingStyle = PascalCase
242 $32.NamingStyle = PascalCase
240 $32.IncludeInstanceMembers = True
243 $32.IncludeInstanceMembers = True
241 $32.IncludeStaticEntities = True
244 $32.IncludeStaticEntities = True
242 $33.Name = Parameters
245 $33.Name = Parameters
243 $33.AffectedEntity = Parameter, LocalVariable
246 $33.AffectedEntity = Parameter, LocalVariable
244 $33.VisibilityMask = VisibilityMask
247 $33.VisibilityMask = VisibilityMask
245 $33.NamingStyle = CamelCase
248 $33.NamingStyle = CamelCase
246 $33.IncludeInstanceMembers = True
249 $33.IncludeInstanceMembers = True
247 $33.IncludeStaticEntities = True
250 $33.IncludeStaticEntities = True
248 $34.Name = Type Parameters
251 $34.Name = Type Parameters
249 $34.RequiredPrefixes = $35
252 $34.RequiredPrefixes = $35
250 $35.String = T
253 $35.String = T
251 $34.AffectedEntity = TypeParameter
254 $34.AffectedEntity = TypeParameter
252 $34.VisibilityMask = VisibilityMask
255 $34.VisibilityMask = VisibilityMask
253 $34.NamingStyle = PascalCase
256 $34.NamingStyle = PascalCase
254 $34.IncludeInstanceMembers = True
257 $34.IncludeInstanceMembers = True
255 $34.IncludeStaticEntities = True
258 $34.IncludeStaticEntities = True
256 EndGlobalSection
259 EndGlobalSection
257 GlobalSection(TestCaseManagementSettings) = postSolution
260 GlobalSection(TestCaseManagementSettings) = postSolution
258 CategoryFile = Implab.vsmdi
261 CategoryFile = Implab.vsmdi
259 EndGlobalSection
262 EndGlobalSection
260 EndGlobal
263 EndGlobal
@@ -1,348 +1,348
1 using Implab;
1 using Implab;
2 using System;
2 using System;
3 using System.Collections.Generic;
3 using System.Collections.Generic;
4 using System.Linq;
4 using System.Linq;
5 using System.Diagnostics;
5 using System.Diagnostics;
6 using System.IO;
6 using System.IO;
7 using System.CodeDom.Compiler;
7 using System.CodeDom.Compiler;
8 using System.CodeDom;
8 using System.CodeDom;
9
9
10 namespace Implab.Automaton {
10 namespace Implab.Automaton {
11 public class DFATable : IDFATableBuilder {
11 public class DFATable : IDFATableBuilder {
12 int m_stateCount;
12 int m_stateCount;
13 int m_symbolCount;
13 int m_symbolCount;
14 int m_initialState;
14 int m_initialState;
15
15
16 readonly HashSet<int> m_finalStates = new HashSet<int>();
16 readonly HashSet<int> m_finalStates = new HashSet<int>();
17 readonly HashSet<AutomatonTransition> m_transitions = new HashSet<AutomatonTransition>();
17 readonly HashSet<AutomatonTransition> m_transitions = new HashSet<AutomatonTransition>();
18
18
19
19
20 #region IDFADefinition implementation
20 #region IDFADefinition implementation
21
21
22 public bool IsFinalState(int s) {
22 public bool IsFinalState(int s) {
23 Safe.ArgumentInRange(s, 0, m_stateCount, "s");
23 Safe.ArgumentInRange(s, 0, m_stateCount, "s");
24
24
25 return m_finalStates.Contains(s);
25 return m_finalStates.Contains(s);
26 }
26 }
27
27
28 public IEnumerable<int> FinalStates {
28 public IEnumerable<int> FinalStates {
29 get {
29 get {
30 return m_finalStates;
30 return m_finalStates;
31 }
31 }
32 }
32 }
33
33
34 public int StateCount {
34 public int StateCount {
35 get { return m_stateCount; }
35 get { return m_stateCount; }
36 }
36 }
37
37
38 public int AlphabetSize {
38 public int AlphabetSize {
39 get { return m_symbolCount; }
39 get { return m_symbolCount; }
40 }
40 }
41
41
42 public int InitialState {
42 public int InitialState {
43 get { return m_initialState; }
43 get { return m_initialState; }
44 }
44 }
45
45
46 #endregion
46 #endregion
47
47
48 public void SetInitialState(int s) {
48 public void SetInitialState(int s) {
49 Safe.ArgumentAssert(s >= 0, "s");
49 Safe.ArgumentAssert(s >= 0, "s");
50 m_stateCount = Math.Max(m_stateCount, s + 1);
50 m_stateCount = Math.Max(m_stateCount, s + 1);
51 m_initialState = s;
51 m_initialState = s;
52 }
52 }
53
53
54 public void MarkFinalState(int state) {
54 public void MarkFinalState(int state) {
55 m_stateCount = Math.Max(m_stateCount, state + 1);
55 m_stateCount = Math.Max(m_stateCount, state + 1);
56 m_finalStates.Add(state);
56 m_finalStates.Add(state);
57 }
57 }
58
58
59 public void Add(AutomatonTransition item) {
59 public void Add(AutomatonTransition item) {
60 Safe.ArgumentAssert(item.s1 >= 0, "item");
60 Safe.ArgumentAssert(item.s1 >= 0, "item");
61 Safe.ArgumentAssert(item.s2 >= 0, "item");
61 Safe.ArgumentAssert(item.s2 >= 0, "item");
62 Safe.ArgumentAssert(item.edge >= 0, "item");
62 Safe.ArgumentAssert(item.edge >= 0, "item");
63
63
64 m_stateCount = Math.Max(m_stateCount, Math.Max(item.s1, item.s2) + 1);
64 m_stateCount = Math.Max(m_stateCount, Math.Max(item.s1, item.s2) + 1);
65 m_symbolCount = Math.Max(m_symbolCount, item.edge + 1);
65 m_symbolCount = Math.Max(m_symbolCount, item.edge + 1);
66
66
67 m_transitions.Add(item);
67 m_transitions.Add(item);
68 }
68 }
69
69
70 public void Clear() {
70 public void Clear() {
71 m_stateCount = 0;
71 m_stateCount = 0;
72 m_symbolCount = 0;
72 m_symbolCount = 0;
73 m_finalStates.Clear();
73 m_finalStates.Clear();
74 m_transitions.Clear();
74 m_transitions.Clear();
75 }
75 }
76
76
77 public bool Contains(AutomatonTransition item) {
77 public bool Contains(AutomatonTransition item) {
78 return m_transitions.Contains(item);
78 return m_transitions.Contains(item);
79 }
79 }
80
80
81 public void CopyTo(AutomatonTransition[] array, int arrayIndex) {
81 public void CopyTo(AutomatonTransition[] array, int arrayIndex) {
82 m_transitions.CopyTo(array, arrayIndex);
82 m_transitions.CopyTo(array, arrayIndex);
83 }
83 }
84
84
85 public bool Remove(AutomatonTransition item) {
85 public bool Remove(AutomatonTransition item) {
86 return m_transitions.Remove(item);
86 return m_transitions.Remove(item);
87 }
87 }
88
88
89 public int Count {
89 public int Count {
90 get {
90 get {
91 return m_transitions.Count;
91 return m_transitions.Count;
92 }
92 }
93 }
93 }
94
94
95 public bool IsReadOnly {
95 public bool IsReadOnly {
96 get {
96 get {
97 return false;
97 return false;
98 }
98 }
99 }
99 }
100
100
101 public IEnumerator<AutomatonTransition> GetEnumerator() {
101 public IEnumerator<AutomatonTransition> GetEnumerator() {
102 return m_transitions.GetEnumerator();
102 return m_transitions.GetEnumerator();
103 }
103 }
104
104
105 System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
105 System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
106 return GetEnumerator();
106 return GetEnumerator();
107 }
107 }
108
108
109 public void AddSymbol(int symbol) {
109 public void AddSymbol(int symbol) {
110 Safe.ArgumentAssert(symbol >= 0, "symbol");
110 Safe.ArgumentAssert(symbol >= 0, "symbol");
111 m_symbolCount = Math.Max(symbol + 1, m_symbolCount);
111 m_symbolCount = Math.Max(symbol + 1, m_symbolCount);
112 }
112 }
113
113
114 public int[,] CreateTransitionTable() {
114 public int[,] CreateTransitionTable() {
115 var table = new int[StateCount,AlphabetSize];
115 var table = new int[StateCount,AlphabetSize];
116
116
117 for (int i = 0; i < StateCount; i++)
117 for (int i = 0; i < StateCount; i++)
118 for (int j = 0; j < AlphabetSize; j++)
118 for (int j = 0; j < AlphabetSize; j++)
119 table[i, j] = AutomatonConst.UNREACHABLE_STATE;
119 table[i, j] = AutomatonConst.UNREACHABLE_STATE;
120
120
121 foreach (var t in this)
121 foreach (var t in this)
122 table[t.s1,t.edge] = t.s2;
122 table[t.s1,t.edge] = (byte)t.s2;
123
123
124 return table;
124 return table;
125 }
125 }
126
126
127 public bool[] CreateFinalStateTable() {
127 public bool[] CreateFinalStateTable() {
128 var table = new bool[StateCount];
128 var table = new bool[StateCount];
129
129
130 foreach (var s in FinalStates)
130 foreach (var s in FinalStates)
131 table[s] = true;
131 table[s] = true;
132
132
133 return table;
133 return table;
134 }
134 }
135
135
136 /// <summary>Формирует множества конечных состояний перед началом работы алгоритма минимизации.</summary>
136 /// <summary>Формирует множества конечных состояний перед началом работы алгоритма минимизации.</summary>
137 /// <remarks>
137 /// <remarks>
138 /// В процессе построения минимального автомата требуется разделить множество состояний,
138 /// В процессе построения минимального автомата требуется разделить множество состояний,
139 /// на два подмножества - конечные состояния и все остальные, после чего эти подмножества
139 /// на два подмножества - конечные состояния и все остальные, после чего эти подмножества
140 /// будут резделены на более мелкие. Иногда требуется гарантировать различия конечных сосотяний,
140 /// будут резделены на более мелкие. Иногда требуется гарантировать различия конечных сосотяний,
141 /// для этого необходимо переопределить даннцю фукнцию, для получения множеств конечных состояний.
141 /// для этого необходимо переопределить даннцю фукнцию, для получения множеств конечных состояний.
142 /// </remarks>
142 /// </remarks>
143 /// <returns>The final states.</returns>
143 /// <returns>The final states.</returns>
144 protected virtual IEnumerable<HashSet<int>> SplitFinalStates(IEnumerable<int> states) {
144 protected virtual IEnumerable<HashSet<int>> SplitFinalStates(IEnumerable<int> states) {
145 return new [] { new HashSet<int>(states) };
145 return new [] { new HashSet<int>(states) };
146 }
146 }
147
147
148 protected void Optimize(
148 protected void Optimize(
149 IDFATableBuilder optimalDFA,
149 IDFATableBuilder optimalDFA,
150 IDictionary<int,int> alphabetMap,
150 IDictionary<int,int> alphabetMap,
151 IDictionary<int,int> stateMap
151 IDictionary<int,int> stateMap
152 ) {
152 ) {
153 Safe.ArgumentNotNull(optimalDFA, "dfa");
153 Safe.ArgumentNotNull(optimalDFA, "dfa");
154 Safe.ArgumentNotNull(alphabetMap, "alphabetMap");
154 Safe.ArgumentNotNull(alphabetMap, "alphabetMap");
155 Safe.ArgumentNotNull(stateMap, "stateMap");
155 Safe.ArgumentNotNull(stateMap, "stateMap");
156
156
157
157
158 var setComparer = new CustomEqualityComparer<HashSet<int>>(
158 var setComparer = new CustomEqualityComparer<HashSet<int>>(
159 (x, y) => x.SetEquals(y),
159 (x, y) => x.SetEquals(y),
160 s => s.Sum(x => x.GetHashCode())
160 s => s.Sum(x => x.GetHashCode())
161 );
161 );
162
162
163 var optimalStates = new HashSet<HashSet<int>>(setComparer);
163 var optimalStates = new HashSet<HashSet<int>>(setComparer);
164 var queue = new HashSet<HashSet<int>>(setComparer);
164 var queue = new HashSet<HashSet<int>>(setComparer);
165
165
166 optimalStates.Add(new HashSet<int>(FinalStates));
166 optimalStates.Add(new HashSet<int>(FinalStates));
167
167
168 var state = new HashSet<int>(
168 var state = new HashSet<int>(
169 Enumerable
169 Enumerable
170 .Range(0, m_stateCount)
170 .Range(0, m_stateCount)
171 .Where(i => !m_finalStates.Contains(i))
171 .Where(i => !m_finalStates.Contains(i))
172 );
172 );
173
173
174 optimalStates.Add(state);
174 optimalStates.Add(state);
175 queue.Add(state);
175 queue.Add(state);
176
176
177 var rmap = m_transitions
177 var rmap = m_transitions
178 .GroupBy(t => t.s2)
178 .GroupBy(t => t.s2)
179 .ToDictionary(
179 .ToDictionary(
180 g => g.Key, // s2
180 g => g.Key, // s2
181 g => g.ToLookup(t => t.edge, t => t.s1)//.ToDictionary(p => p.Key)
181 g => g.ToLookup(t => t.edge, t => t.s1)//.ToDictionary(p => p.Key)
182 );
182 );
183
183
184 while (queue.Count > 0) {
184 while (queue.Count > 0) {
185 var stateA = queue.First();
185 var stateA = queue.First();
186 queue.Remove(stateA);
186 queue.Remove(stateA);
187
187
188 for (int c = 0; c < m_symbolCount; c++) {
188 for (int c = 0; c < m_symbolCount; c++) {
189 var stateX = new HashSet<int>();
189 var stateX = new HashSet<int>();
190 foreach(var a in stateA.Where(rmap.ContainsKey))
190 foreach(var a in stateA.Where(rmap.ContainsKey))
191 stateX.UnionWith(rmap[a][c]); // all states from wich the symbol 'c' leads to the state 'a'
191 stateX.UnionWith(rmap[a][c]); // all states from wich the symbol 'c' leads to the state 'a'
192
192
193 var tmp = optimalStates.ToArray();
193 var tmp = optimalStates.ToArray();
194 foreach (var stateY in tmp) {
194 foreach (var stateY in tmp) {
195 var stateR1 = new HashSet<int>(stateY);
195 var stateR1 = new HashSet<int>(stateY);
196 var stateR2 = new HashSet<int>(stateY);
196 var stateR2 = new HashSet<int>(stateY);
197
197
198 stateR1.IntersectWith(stateX);
198 stateR1.IntersectWith(stateX);
199 stateR2.ExceptWith(stateX);
199 stateR2.ExceptWith(stateX);
200
200
201 if (stateR1.Count > 0 && stateR2.Count > 0) {
201 if (stateR1.Count > 0 && stateR2.Count > 0) {
202
202
203
203
204 optimalStates.Remove(stateY);
204 optimalStates.Remove(stateY);
205 optimalStates.Add(stateR1);
205 optimalStates.Add(stateR1);
206 optimalStates.Add(stateR2);
206 optimalStates.Add(stateR2);
207
207
208 if (queue.Contains(stateY)) {
208 if (queue.Contains(stateY)) {
209 queue.Remove(stateY);
209 queue.Remove(stateY);
210 queue.Add(stateR1);
210 queue.Add(stateR1);
211 queue.Add(stateR2);
211 queue.Add(stateR2);
212 } else {
212 } else {
213 queue.Add(stateR1.Count <= stateR2.Count ? stateR1 : stateR2);
213 queue.Add(stateR1.Count <= stateR2.Count ? stateR1 : stateR2);
214 }
214 }
215 }
215 }
216 }
216 }
217 }
217 }
218 }
218 }
219
219
220 // дополнительно разбиваем конечные состояния
220 // дополнительно разбиваем конечные состояния
221 foreach (var final in optimalStates.Where(s => s.Overlaps(m_finalStates)).ToArray()) {
221 foreach (var final in optimalStates.Where(s => s.Overlaps(m_finalStates)).ToArray()) {
222 optimalStates.Remove(final);
222 optimalStates.Remove(final);
223 foreach (var split in SplitFinalStates(final))
223 foreach (var split in SplitFinalStates(final))
224 optimalStates.Add(split);
224 optimalStates.Add(split);
225 }
225 }
226
226
227
227
228 // карта получения оптимального состояния по соотвествующему ему простому состоянию
228 // карта получения оптимального состояния по соотвествующему ему простому состоянию
229 var nextState = 0;
229 var nextState = 0;
230 foreach (var item in optimalStates) {
230 foreach (var item in optimalStates) {
231 var id = nextState++;
231 var id = nextState++;
232 foreach (var s in item)
232 foreach (var s in item)
233 stateMap[s] = id;
233 stateMap[s] = id;
234 }
234 }
235
235
236 // получаем минимальный алфавит
236 // получаем минимальный алфавит
237 // входные символы не различимы, если Move(s,a1) == Move(s,a2), для любого s
237 // входные символы не различимы, если Move(s,a1) == Move(s,a2), для любого s
238 // для этого используем алгоритм кластеризации, сначала
238 // для этого используем алгоритм кластеризации, сначала
239 // считаем, что все символы не различимы
239 // считаем, что все символы не различимы
240
240
241 var minClasses = new HashSet<HashSet<int>>(setComparer);
241 var minClasses = new HashSet<HashSet<int>>(setComparer);
242 var alphaQueue = new Queue<HashSet<int>>();
242 var alphaQueue = new Queue<HashSet<int>>();
243 alphaQueue.Enqueue(new HashSet<int>(Enumerable.Range(0,AlphabetSize)));
243 alphaQueue.Enqueue(new HashSet<int>(Enumerable.Range(0,AlphabetSize)));
244
244
245 // для всех состояний, будем проверять каждый класс на различимость,
245 // для всех состояний, будем проверять каждый класс на различимость,
246 // т.е. символы различимы, если они приводят к разным состояниям
246 // т.е. символы различимы, если они приводят к разным состояниям
247 for (int s = 0 ; s < optimalStates.Count; s++) {
247 for (int s = 0 ; s < optimalStates.Count; s++) {
248 var newQueue = new Queue<HashSet<int>>();
248 var newQueue = new Queue<HashSet<int>>();
249
249
250 foreach (var A in alphaQueue) {
250 foreach (var A in alphaQueue) {
251 // классы из одного символа делить бесполезно, переводим их сразу в
251 // классы из одного символа делить бесполезно, переводим их сразу в
252 // результирующий алфавит
252 // результирующий алфавит
253 if (A.Count == 1) {
253 if (A.Count == 1) {
254 minClasses.Add(A);
254 minClasses.Add(A);
255 continue;
255 continue;
256 }
256 }
257
257
258 // различаем классы символов, которые переводят в различные оптимальные состояния
258 // различаем классы символов, которые переводят в различные оптимальные состояния
259 // optimalState -> alphaClass
259 // optimalState -> alphaClass
260 var classes = new Dictionary<int, HashSet<int>>();
260 var classes = new Dictionary<int, HashSet<int>>();
261
261
262 foreach (var term in A) {
262 foreach (var term in A) {
263 // ищем все переходы класса по символу term
263 // ищем все переходы класса по символу term
264 var s2 = m_transitions.Where(t => stateMap[t.s1] == s && t.edge == term).Select(t => stateMap[t.s2]).DefaultIfEmpty(-1).First();
264 var s2 = m_transitions.Where(t => stateMap[t.s1] == s && t.edge == term).Select(t => stateMap[t.s2]).DefaultIfEmpty(-1).First();
265
265
266 HashSet<int> a2;
266 HashSet<int> a2;
267 if (!classes.TryGetValue(s2, out a2)) {
267 if (!classes.TryGetValue(s2, out a2)) {
268 a2 = new HashSet<int>();
268 a2 = new HashSet<int>();
269 newQueue.Enqueue(a2);
269 newQueue.Enqueue(a2);
270 classes[s2] = a2;
270 classes[s2] = a2;
271 }
271 }
272 a2.Add(term);
272 a2.Add(term);
273 }
273 }
274 }
274 }
275
275
276 if (newQueue.Count == 0)
276 if (newQueue.Count == 0)
277 break;
277 break;
278 alphaQueue = newQueue;
278 alphaQueue = newQueue;
279 }
279 }
280
280
281 // после окончания работы алгоритма в очереди останутся минимальные различимые классы
281 // после окончания работы алгоритма в очереди останутся минимальные различимые классы
282 // входных символов
282 // входных символов
283 foreach (var A in alphaQueue)
283 foreach (var A in alphaQueue)
284 minClasses.Add(A);
284 minClasses.Add(A);
285
285
286 // построение отображения алфавитов входных символов.
286 // построение отображения алфавитов входных символов.
287 // поскольку символ DFAConst.UNCLASSIFIED_INPUT может иметь
287 // поскольку символ DFAConst.UNCLASSIFIED_INPUT может иметь
288 // специальное значение, тогда сохраним минимальный класс,
288 // специальное значение, тогда сохраним минимальный класс,
289 // содержащий этот символ на томже месте.
289 // содержащий этот символ на томже месте.
290
290
291 var nextCls = 0;
291 var nextCls = 0;
292 foreach (var item in minClasses) {
292 foreach (var item in minClasses) {
293 if (nextCls == AutomatonConst.UNCLASSIFIED_INPUT)
293 if (nextCls == AutomatonConst.UNCLASSIFIED_INPUT)
294 nextCls++;
294 nextCls++;
295
295
296 // сохраняем DFAConst.UNCLASSIFIED_INPUT
296 // сохраняем DFAConst.UNCLASSIFIED_INPUT
297 var cls = item.Contains(AutomatonConst.UNCLASSIFIED_INPUT) ? AutomatonConst.UNCLASSIFIED_INPUT : nextCls++;
297 var cls = item.Contains(AutomatonConst.UNCLASSIFIED_INPUT) ? AutomatonConst.UNCLASSIFIED_INPUT : nextCls++;
298 optimalDFA.AddSymbol(cls);
298 optimalDFA.AddSymbol(cls);
299
299
300 foreach (var a in item)
300 foreach (var a in item)
301 alphabetMap[a] = cls;
301 alphabetMap[a] = cls;
302 }
302 }
303
303
304 // построение автомата
304 // построение автомата
305 optimalDFA.SetInitialState(stateMap[m_initialState]);
305 optimalDFA.SetInitialState(stateMap[m_initialState]);
306
306
307 foreach (var sf in m_finalStates.Select(s => stateMap[s]).Distinct())
307 foreach (var sf in m_finalStates.Select(s => stateMap[s]).Distinct())
308 optimalDFA.MarkFinalState(sf);
308 optimalDFA.MarkFinalState(sf);
309
309
310 foreach (var t in m_transitions.Select(t => new AutomatonTransition(stateMap[t.s1],stateMap[t.s2],alphabetMap[t.edge])).Distinct())
310 foreach (var t in m_transitions.Select(t => new AutomatonTransition(stateMap[t.s1],stateMap[t.s2],alphabetMap[t.edge])).Distinct())
311 optimalDFA.Add(t);
311 optimalDFA.Add(t);
312 }
312 }
313
313
314 protected string PrintDFA<TInput, TState>(IAlphabet<TInput> inputAlphabet, IAlphabet<TState> stateAlphabet) {
314 protected string PrintDFA<TInput, TState>(IAlphabet<TInput> inputAlphabet, IAlphabet<TState> stateAlphabet) {
315 Safe.ArgumentNotNull(inputAlphabet, "inputAlphabet");
315 Safe.ArgumentNotNull(inputAlphabet, "inputAlphabet");
316 Safe.ArgumentNotNull(stateAlphabet, "stateAlphabet");
316 Safe.ArgumentNotNull(stateAlphabet, "stateAlphabet");
317
317
318 var data = new List<string>();
318 var data = new List<string>();
319
319
320 data.Add("digraph dfa {");
320 data.Add("digraph dfa {");
321
321
322 foreach (var final in m_finalStates)
322 foreach (var final in m_finalStates)
323 data.Add(String.Format("{0} [shape=box];",String.Join("", stateAlphabet.GetSymbols(final))));
323 data.Add(String.Format("{0} [shape=box];",String.Join("", stateAlphabet.GetSymbols(final))));
324
324
325 foreach (var t in m_transitions)
325 foreach (var t in m_transitions)
326 data.Add(String.Format(
326 data.Add(String.Format(
327 "{0} -> {2} [label={1}];",
327 "{0} -> {2} [label={1}];",
328 String.Join("", stateAlphabet.GetSymbols(t.s1)),
328 String.Join("", stateAlphabet.GetSymbols(t.s1)),
329 ToLiteral(ToLiteral(String.Join("", t.edge == AutomatonConst.UNCLASSIFIED_INPUT ? new [] { "@" } : inputAlphabet.GetSymbols(t.edge).Select(x => x.ToString())))),
329 ToLiteral(ToLiteral(String.Join("", t.edge == AutomatonConst.UNCLASSIFIED_INPUT ? new [] { "@" } : inputAlphabet.GetSymbols(t.edge).Select(x => x.ToString())))),
330 String.Join("", stateAlphabet.GetSymbols(t.s2))
330 String.Join("", stateAlphabet.GetSymbols(t.s2))
331 ));
331 ));
332 data.Add("}");
332 data.Add("}");
333 return String.Join("\n", data);
333 return String.Join("\n", data);
334 }
334 }
335
335
336 static string ToLiteral(string input)
336 static string ToLiteral(string input)
337 {
337 {
338 using (var writer = new StringWriter())
338 using (var writer = new StringWriter())
339 {
339 {
340 using (var provider = CodeDomProvider.CreateProvider("CSharp"))
340 using (var provider = CodeDomProvider.CreateProvider("CSharp"))
341 {
341 {
342 provider.GenerateCodeFromExpression(new CodePrimitiveExpression(input), writer, null);
342 provider.GenerateCodeFromExpression(new CodePrimitiveExpression(input), writer, null);
343 return writer.ToString();
343 return writer.ToString();
344 }
344 }
345 }
345 }
346 }
346 }
347 }
347 }
348 }
348 }
@@ -1,84 +1,84
1 using Implab.Automaton;
1 using Implab.Automaton;
2 using System;
2 using System;
3 using System.Collections.Generic;
3 using System.Collections.Generic;
4 using System.Linq;
4 using System.Linq;
5 using System.Runtime.CompilerServices;
5 using System.Text;
6 using System.Text;
6 using System.Threading.Tasks;
7 using System.Threading.Tasks;
7
8
8 namespace Implab.Formats {
9 namespace Implab.Formats {
9 public class InputScanner<TTag> {
10 public class InputScanner<TTag> {
10 readonly TTag[] m_tags;
11 readonly TTag[] m_tags;
11 readonly int m_initialState;
12 readonly int m_initialState;
12 readonly int[,] m_dfa;
13 readonly int[,] m_dfa;
13 readonly CharMap m_alphabet;
14 readonly CharMap m_alphabet;
14 readonly bool[] m_final;
15 readonly bool[] m_final;
15
16
16 int m_position;
17 int m_position;
17 int m_state;
18 int m_state;
18
19
19 public InputScanner(int[,] dfaTable, bool[] finalStates, TTag[] tags, int initialState, CharMap alphabet) {
20 public InputScanner(int[,] dfaTable, bool[] finalStates, TTag[] tags, int initialState, CharMap alphabet) {
20 Safe.ArgumentNotNull(dfaTable, nameof(dfaTable));
21 Safe.ArgumentNotNull(dfaTable, nameof(dfaTable));
21 Safe.ArgumentNotNull(finalStates, nameof(finalStates));
22 Safe.ArgumentNotNull(finalStates, nameof(finalStates));
22 Safe.ArgumentNotNull(tags, nameof(tags));
23 Safe.ArgumentNotNull(tags, nameof(tags));
23 Safe.ArgumentNotNull(alphabet, nameof(alphabet));
24 Safe.ArgumentNotNull(alphabet, nameof(alphabet));
24
25
25 m_dfa = dfaTable;
26 m_dfa = dfaTable;
26 m_final = finalStates;
27 m_final = finalStates;
27 m_tags = tags;
28 m_tags = tags;
28 m_initialState = initialState;
29 m_initialState = initialState;
29 m_alphabet = alphabet;
30 m_alphabet = alphabet;
30 }
31 }
31
32
32 public TTag Tag {
33 public TTag Tag {
34 [MethodImpl(MethodImplOptions.AggressiveInlining)]
33 get {
35 get {
34 return m_tags[m_state];
36 return m_tags[m_state];
35 }
37 }
36 }
38 }
37
39
38 public int Position {
40 public int Position {
41 [MethodImpl(MethodImplOptions.AggressiveInlining)]
39 get {
42 get {
40 return m_position;
43 return m_position;
41 }
44 }
42 }
45 }
43
46
44 public bool IsFinal {
47 public bool IsFinal {
48 [MethodImpl(MethodImplOptions.AggressiveInlining)]
45 get {
49 get {
46 return m_final[m_state];
50 return m_final[m_state];
47 }
51 }
48 }
52 }
49
53
50 public void Reset() {
54 [MethodImpl(MethodImplOptions.AggressiveInlining)]
55 public void ResetState() {
51 m_state = m_initialState;
56 m_state = m_initialState;
52 }
57 }
53
58
54 public InputScanner<TTag> Clone() {
59 public InputScanner<TTag> Clone() {
55 var clone = new InputScanner<TTag>(m_dfa, m_final, m_tags, m_initialState, m_alphabet);
60 var clone = new InputScanner<TTag>(m_dfa, m_final, m_tags, m_initialState, m_alphabet);
56 clone.m_state = m_state;
61 clone.m_state = m_state;
57 clone.m_position = m_position;
62 clone.m_position = m_position;
58 return clone;
63 return clone;
59 }
64 }
60
65
61 public bool Scan(char[] data, int offset, int length) {
66 //[MethodImpl(MethodImplOptions.AggressiveInlining)]
62 if (length <= 0) {
67 public bool Scan(char[] data, int offset, int max) {
63 m_position = offset;
64 return false; // EOF
65 }
66
67 var max = offset + length;
68 var next = m_state;
68 var next = m_state;
69
69
70 while(offset < max) {
70 while(offset < max) {
71 next = m_dfa[next, m_alphabet.Translate(data[offset])];
71 next = m_dfa[next, m_alphabet.Translate(data[offset])];
72 if (next == AutomatonConst.UNREACHABLE_STATE) {
72 if (next == AutomatonConst.UNREACHABLE_STATE) {
73 // scanner stops on the next position after last recognized symbol
73 // scanner stops on the next position after last recognized symbol
74 m_position = offset;
74 m_position = offset;
75 return false;
75 return false;
76 }
76 }
77 m_state = next;
77 m_state = next;
78 offset++;
78 offset++;
79 }
79 }
80 m_position = offset;
80 m_position = offset;
81 return true;
81 return true;
82 }
82 }
83 }
83 }
84 }
84 }
@@ -1,294 +1,318
1 using System;
1 using System;
2 using System.Diagnostics;
2 using System.Diagnostics;
3 using System.IO;
3 using System.IO;
4 using Implab.Automaton;
4 using Implab.Automaton;
5 using Implab.Automaton.RegularExpressions;
5 using Implab.Automaton.RegularExpressions;
6 using System.Linq;
6 using System.Linq;
7 using Implab.Components;
7 using Implab.Components;
8 using System.Collections.Generic;
8 using System.Collections.Generic;
9 using System.Text;
10 using System.Globalization;
9
11
10 namespace Implab.Formats.Json {
12 namespace Implab.Formats.Json {
11 /// <summary>
13 /// <summary>
12 /// Pull парсер JSON данных.
14 /// Pull парсер JSON данных.
13 /// </summary>
15 /// </summary>
14 /// <remarks>
16 /// <remarks>
15 /// Следует отметить отдельную интерпретацию свойства <see cref="Level"/>,
17 /// Следует отметить отдельную интерпретацию свойства <see cref="Level"/>,
16 /// оно означает текущий уровень вложенности объектов, однако закрывающий
18 /// оно означает текущий уровень вложенности объектов, однако закрывающий
17 /// элемент объекта и массива имеет уровень меньше, чем сам объект.
19 /// элемент объекта и массива имеет уровень меньше, чем сам объект.
18 /// <code>
20 /// <code>
19 /// { // Level = 1
21 /// { // Level = 1
20 /// "name" : "Peter", // Level = 1
22 /// "name" : "Peter", // Level = 1
21 /// "address" : { // Level = 2
23 /// "address" : { // Level = 2
22 /// city : "Stern" // Level = 2
24 /// city : "Stern" // Level = 2
23 /// } // Level = 1
25 /// } // Level = 1
24 /// } // Level = 0
26 /// } // Level = 0
25 /// </code>
27 /// </code>
26 /// </remarks>
28 /// </remarks>
27 public class JsonParser : Disposable {
29 public class JsonReader : Disposable {
28
30
29 enum MemberContext {
31 enum MemberContext {
30 MemberName,
32 MemberName,
31 MemberValue
33 MemberValue
32 }
34 }
33
35
34 #region Parser rules
36 #region Parser rules
35 struct ParserContext {
37 struct ParserContext {
36 readonly int[,] m_dfa;
38 readonly int[,] m_dfa;
37 int m_state;
39 int m_state;
38
40
39 readonly JsonElementContext m_elementContext;
41 readonly JsonElementContext m_elementContext;
40
42
41 public ParserContext(int[,] dfa, int state, JsonElementContext context) {
43 public ParserContext(int[,] dfa, int state, JsonElementContext context) {
42 m_dfa = dfa;
44 m_dfa = dfa;
43 m_state = state;
45 m_state = state;
44 m_elementContext = context;
46 m_elementContext = context;
45 }
47 }
46
48
47 public bool Move(JsonTokenType token) {
49 public bool Move(JsonTokenType token) {
48 var next = m_dfa[m_state, (int)token];
50 var next = m_dfa[m_state, (int)token];
49 if (next == AutomatonConst.UNREACHABLE_STATE)
51 if (next == AutomatonConst.UNREACHABLE_STATE)
50 return false;
52 return false;
51 m_state = next;
53 m_state = next;
52 return true;
54 return true;
53 }
55 }
54
56
55 public JsonElementContext ElementContext {
57 public JsonElementContext ElementContext {
56 get { return m_elementContext; }
58 get { return m_elementContext; }
57 }
59 }
58 }
60 }
59
61
60 static readonly ParserContext _jsonContext;
62 static readonly ParserContext _jsonContext;
61 static readonly ParserContext _objectContext;
63 static readonly ParserContext _objectContext;
62 static readonly ParserContext _arrayContext;
64 static readonly ParserContext _arrayContext;
63
65
64 static JsonParser() {
66 static JsonReader() {
65
67
66 var valueExpression = MakeToken(JsonTokenType.BeginArray, JsonTokenType.BeginObject, JsonTokenType.Literal, JsonTokenType.Number, JsonTokenType.String);
68 var valueExpression = MakeToken(JsonTokenType.BeginArray, JsonTokenType.BeginObject, JsonTokenType.Literal, JsonTokenType.Number, JsonTokenType.String);
67 var memberExpression = MakeToken(JsonTokenType.String).Cat(MakeToken(JsonTokenType.NameSeparator)).Cat(valueExpression);
69 var memberExpression = MakeToken(JsonTokenType.String).Cat(MakeToken(JsonTokenType.NameSeparator)).Cat(valueExpression);
68
70
69 var objectExpression = memberExpression
71 var objectExpression = memberExpression
70 .Cat(
72 .Cat(
71 MakeToken(JsonTokenType.ValueSeparator)
73 MakeToken(JsonTokenType.ValueSeparator)
72 .Cat(memberExpression)
74 .Cat(memberExpression)
73 .EClosure()
75 .EClosure()
74 )
76 )
75 .Optional()
77 .Optional()
76 .Cat(MakeToken(JsonTokenType.EndObject))
78 .Cat(MakeToken(JsonTokenType.EndObject))
77 .End();
79 .End();
78
80
79 var arrayExpression = valueExpression
81 var arrayExpression = valueExpression
80 .Cat(
82 .Cat(
81 MakeToken(JsonTokenType.ValueSeparator)
83 MakeToken(JsonTokenType.ValueSeparator)
82 .Cat(valueExpression)
84 .Cat(valueExpression)
83 .EClosure()
85 .EClosure()
84 )
86 )
85 .Optional()
87 .Optional()
86 .Cat(MakeToken(JsonTokenType.EndArray))
88 .Cat(MakeToken(JsonTokenType.EndArray))
87 .End();
89 .End();
88
90
89 var jsonExpression = valueExpression.End();
91 var jsonExpression = valueExpression.End();
90
92
91 _jsonContext = CreateParserContext(jsonExpression, JsonElementContext.None);
93 _jsonContext = CreateParserContext(jsonExpression, JsonElementContext.None);
92 _objectContext = CreateParserContext(objectExpression, JsonElementContext.Object);
94 _objectContext = CreateParserContext(objectExpression, JsonElementContext.Object);
93 _arrayContext = CreateParserContext(arrayExpression, JsonElementContext.Array);
95 _arrayContext = CreateParserContext(arrayExpression, JsonElementContext.Array);
94 }
96 }
95
97
96 static Token MakeToken(params JsonTokenType[] input) {
98 static Token MakeToken(params JsonTokenType[] input) {
97 return Token.New( input.Select(t => (int)t).ToArray() );
99 return Token.New( input.Select(t => (int)t).ToArray() );
98 }
100 }
99
101
100 static ParserContext CreateParserContext(Token expr, JsonElementContext context) {
102 static ParserContext CreateParserContext(Token expr, JsonElementContext context) {
101
103
102 var dfa = new DFATable();
104 var dfa = new DFATable();
103 var builder = new RegularExpressionVisitor(dfa);
105 var builder = new RegularExpressionVisitor(dfa);
104 expr.Accept(builder);
106 expr.Accept(builder);
105 builder.BuildDFA();
107 builder.BuildDFA();
106
108
107 return new ParserContext(dfa.CreateTransitionTable(), dfa.InitialState, context);
109 return new ParserContext(dfa.CreateTransitionTable(), dfa.InitialState, context);
108 }
110 }
109
111
110 #endregion
112 #endregion
111
113
112 readonly JsonScanner m_scanner;
114 readonly JsonScanner m_scanner;
113 // json starts from the value context and may content even a single literal
115 // json starts from the value context and may content even a single literal
114 MemberContext m_memberContext = MemberContext.MemberValue;
116 MemberContext m_memberContext = MemberContext.MemberValue;
115
117
116 JsonElementType m_elementType;
118 JsonElementType m_elementType;
117 object m_elementValue;
119 object m_elementValue;
118 string m_memberName = String.Empty;
120 string m_memberName = String.Empty;
119
121
120 Stack<ParserContext> m_stack = new Stack<ParserContext>();
122 Stack<ParserContext> m_stack = new Stack<ParserContext>();
121 ParserContext m_context = _jsonContext;
123 ParserContext m_context = _jsonContext;
122
124
123 /// <summary>
125 /// <summary>
124 /// Создает новый парсер на основе строки, содержащей JSON
126 /// Создает новый парсер на основе строки, содержащей JSON
125 /// </summary>
127 /// </summary>
126 /// <param name="text"></param>
128 /// <param name="text"></param>
127 public JsonParser(string text) {
129 JsonReader(JsonScanner scanner) {
128 Safe.ArgumentNotEmpty(text, "text");
130 m_scanner = scanner;
129 m_scanner = JsonStringScanner.Create(text);
130 }
131
132 /// <summary>
133 /// Создает новый экземпляр парсера, на основе текстового потока.
134 /// </summary>
135 /// <param name="reader">Текстовый поток.</param>
136 public JsonParser(TextReader reader) {
137 Safe.ArgumentNotNull(reader, "reader");
138 m_scanner = JsonTextScanner.Create(reader);
139 }
131 }
140
132
141 public int Level {
133 public int Level {
142 get { return m_stack.Count; }
134 get { return m_stack.Count; }
143 }
135 }
144
136
145 /// <summary>
137 /// <summary>
146 /// Тип текущего элемента на котором стоит парсер.
138 /// Тип текущего элемента на котором стоит парсер.
147 /// </summary>
139 /// </summary>
148 public JsonElementType ElementType {
140 public JsonElementType ElementType {
149 get { return m_elementType; }
141 get { return m_elementType; }
150 }
142 }
151
143
152 /// <summary>
144 /// <summary>
153 /// Имя элемента - имя свойства родительского контейнера. Для элементов массивов и корневого всегда
145 /// Имя элемента - имя свойства родительского контейнера. Для элементов массивов и корневого всегда
154 /// пустая строка.
146 /// пустая строка.
155 /// </summary>
147 /// </summary>
156 public string ElementName {
148 public string ElementName {
157 get { return m_memberName; }
149 get { return m_memberName; }
158 }
150 }
159
151
160 /// <summary>
152 /// <summary>
161 /// Значение элемента. Только для элементов типа <see cref="JsonElementType.Value"/>, для остальных <c>null</c>
153 /// Значение элемента. Только для элементов типа <see cref="JsonElementType.Value"/>, для остальных <c>null</c>
162 /// </summary>
154 /// </summary>
163 public object ElementValue {
155 public object ElementValue {
164 get { return m_elementValue; }
156 get { return m_elementValue; }
165 }
157 }
166
158
167 /// <summary>
159 /// <summary>
168 /// Читает слеюудущий объект из потока
160 /// Читает слеюудущий объект из потока
169 /// </summary>
161 /// </summary>
170 /// <returns><c>true</c> - операция чтения прошла успешно, <c>false</c> - конец данных</returns>
162 /// <returns><c>true</c> - операция чтения прошла успешно, <c>false</c> - конец данных</returns>
171 public bool Read() {
163 public bool Read() {
172 object tokenValue;
164 string tokenValue;
173 JsonTokenType tokenType;
165 JsonTokenType tokenType;
174
166
175 m_memberName = String.Empty;
167 m_memberName = String.Empty;
176
168
177 while (m_scanner.ReadToken(out tokenValue, out tokenType)) {
169 while (m_scanner.ReadToken(out tokenValue, out tokenType)) {
178 if(!m_context.Move(tokenType))
170 if(!m_context.Move(tokenType))
179 UnexpectedToken(tokenValue, tokenType);
171 UnexpectedToken(tokenValue, tokenType);
180
172
181 switch (tokenType) {
173 switch (tokenType) {
182 case JsonTokenType.BeginObject:
174 case JsonTokenType.BeginObject:
183 m_stack.Push(m_context);
175 m_stack.Push(m_context);
184 m_context = _objectContext;
176 m_context = _objectContext;
185
177
186 m_elementValue = null;
178 m_elementValue = null;
187 m_memberContext = MemberContext.MemberName;
179 m_memberContext = MemberContext.MemberName;
188 m_elementType = JsonElementType.BeginObject;
180 m_elementType = JsonElementType.BeginObject;
189 return true;
181 return true;
190 case JsonTokenType.EndObject:
182 case JsonTokenType.EndObject:
191 if (m_stack.Count == 0)
183 if (m_stack.Count == 0)
192 UnexpectedToken(tokenValue, tokenType);
184 UnexpectedToken(tokenValue, tokenType);
193 m_context = m_stack.Pop();
185 m_context = m_stack.Pop();
194
186
195 m_elementValue = null;
187 m_elementValue = null;
196 m_elementType = JsonElementType.EndObject;
188 m_elementType = JsonElementType.EndObject;
197 return true;
189 return true;
198 case JsonTokenType.BeginArray:
190 case JsonTokenType.BeginArray:
199 m_stack.Push(m_context);
191 m_stack.Push(m_context);
200 m_context = _arrayContext;
192 m_context = _arrayContext;
201
193
202 m_elementValue = null;
194 m_elementValue = null;
203 m_memberContext = MemberContext.MemberValue;
195 m_memberContext = MemberContext.MemberValue;
204 m_elementType = JsonElementType.BeginArray;
196 m_elementType = JsonElementType.BeginArray;
205 return true;
197 return true;
206 case JsonTokenType.EndArray:
198 case JsonTokenType.EndArray:
207 if (m_stack.Count == 0)
199 if (m_stack.Count == 0)
208 UnexpectedToken(tokenValue, tokenType);
200 UnexpectedToken(tokenValue, tokenType);
209 m_context = m_stack.Pop();
201 m_context = m_stack.Pop();
210
202
211 m_elementValue = null;
203 m_elementValue = null;
212 m_elementType = JsonElementType.EndArray;
204 m_elementType = JsonElementType.EndArray;
213 return true;
205 return true;
214 case JsonTokenType.String:
206 case JsonTokenType.String:
215 if (m_memberContext == MemberContext.MemberName) {
207 if (m_memberContext == MemberContext.MemberName) {
216 m_memberName = (string)tokenValue;
208 m_memberName = tokenValue;
217 break;
209 break;
218 }
210 }
219 m_elementType = JsonElementType.Value;
211 m_elementType = JsonElementType.Value;
220 m_elementValue = tokenValue;
212 m_elementValue = tokenValue;
221 return true;
213 return true;
222 case JsonTokenType.Number:
214 case JsonTokenType.Number:
223 m_elementType = JsonElementType.Value;
215 m_elementType = JsonElementType.Value;
224 m_elementValue = tokenValue;
216 m_elementValue = double.Parse(tokenValue, CultureInfo.InvariantCulture);
225 return true;
217 return true;
226 case JsonTokenType.Literal:
218 case JsonTokenType.Literal:
227 m_elementType = JsonElementType.Value;
219 m_elementType = JsonElementType.Value;
228 m_elementValue = ParseLiteral((string)tokenValue);
220 m_elementValue = ParseLiteral(tokenValue);
229 return true;
221 return true;
230 case JsonTokenType.NameSeparator:
222 case JsonTokenType.NameSeparator:
231 m_memberContext = MemberContext.MemberValue;
223 m_memberContext = MemberContext.MemberValue;
232 break;
224 break;
233 case JsonTokenType.ValueSeparator:
225 case JsonTokenType.ValueSeparator:
234 m_memberContext = m_context.ElementContext == JsonElementContext.Object ? MemberContext.MemberName : MemberContext.MemberValue;
226 m_memberContext = m_context.ElementContext == JsonElementContext.Object ? MemberContext.MemberName : MemberContext.MemberValue;
235 break;
227 break;
236 default:
228 default:
237 UnexpectedToken(tokenValue, tokenType);
229 UnexpectedToken(tokenValue, tokenType);
238 break;
230 break;
239 }
231 }
240 }
232 }
241 if (m_context.ElementContext != JsonElementContext.None)
233 if (m_context.ElementContext != JsonElementContext.None)
242 throw new ParserException("Unexpedted end of data");
234 throw new ParserException("Unexpedted end of data");
243
235
244 EOF = true;
236 Eof = true;
245
237
246 return false;
238 return false;
247 }
239 }
248
240
249 object ParseLiteral(string literal) {
241 object ParseLiteral(string literal) {
250 switch (literal) {
242 switch (literal) {
251 case "null":
243 case "null":
252 return null;
244 return null;
253 case "false":
245 case "false":
254 return false;
246 return false;
255 case "true":
247 case "true":
256 return true;
248 return true;
257 default:
249 default:
258 UnexpectedToken(literal, JsonTokenType.Literal);
250 UnexpectedToken(literal, JsonTokenType.Literal);
259 return null; // avoid compliler error
251 return null; // avoid compliler error
260 }
252 }
261 }
253 }
262
254
263 void UnexpectedToken(object value, JsonTokenType tokenType) {
255 void UnexpectedToken(object value, JsonTokenType tokenType) {
264 throw new ParserException(String.Format("Unexpected token {0}: '{1}'", tokenType, value));
256 throw new ParserException(String.Format("Unexpected token {0}: '{1}'", tokenType, value));
265 }
257 }
266
258
267
259
268 /// <summary>
260 /// <summary>
269 /// Признак конца потока
261 /// Признак конца потока
270 /// </summary>
262 /// </summary>
271 public bool EOF {
263 public bool Eof {
272 get;
264 get;
273 private set;
265 private set;
274 }
266 }
275
267
276 protected override void Dispose(bool disposing) {
268 protected override void Dispose(bool disposing) {
277 if (disposing)
269 if (disposing)
278 m_scanner.Dispose();
270 m_scanner.Dispose();
279 }
271 }
280
272
281 /// <summary>
273 /// <summary>
282 /// Переходит в конец текущего объекта.
274 /// Переходит в конец текущего объекта.
283 /// </summary>
275 /// </summary>
284 public void SeekElementEnd() {
276 public void SeekElementEnd() {
285 var level = Level - 1;
277 var level = Level - 1;
286
278
287 Debug.Assert(level >= 0);
279 Debug.Assert(level >= 0);
288
280
289 while (Level != level)
281 while (Level != level)
290 Read();
282 Read();
291 }
283 }
284
285 public static JsonReader Create(string file, Encoding encoding) {
286 return new JsonReader(JsonTextScanner.Create(file, encoding));
287 }
288
289 public static JsonReader Create(string file) {
290 return new JsonReader(JsonTextScanner.Create(file));
291 }
292
293 public static JsonReader Create(Stream stream, Encoding encoding) {
294 return new JsonReader(JsonTextScanner.Create(stream, encoding));
295 }
296
297 public static JsonReader Create(Stream stream) {
298 return new JsonReader(JsonTextScanner.Create(stream));
299 }
300
301 public static JsonReader Create(TextReader reader) {
302 return new JsonReader(JsonTextScanner.Create(reader));
303 }
304
305 public static JsonReader ParseString(string data) {
306 return new JsonReader(JsonStringScanner.Create(data));
307 }
308
309 public static JsonReader ParseString(string data, int offset, int length) {
310 return new JsonReader(JsonStringScanner.Create(data, offset, length));
311 }
312
313 public static JsonReader ParseString(char[] data, int offset, int lenght) {
314 return new JsonReader(JsonStringScanner.Create(data, offset, lenght));
315 }
292 }
316 }
293
317
294 }
318 }
@@ -1,134 +1,190
1 using System;
1 using System;
2 using System.Globalization;
2 using System.Globalization;
3 using Implab.Automaton;
3 using Implab.Automaton;
4 using System.Text;
4 using System.Text;
5 using Implab.Components;
5 using Implab.Components;
6 using System.IO;
6 using System.IO;
7
7
8 namespace Implab.Formats.Json {
8 namespace Implab.Formats.Json {
9 /// <summary>
9 /// <summary>
10 /// Сканнер (лексер), разбивающий поток символов на токены JSON.
10 /// Сканнер (лексер), разбивающий поток символов на токены JSON.
11 /// </summary>
11 /// </summary>
12 public abstract class JsonScanner : Disposable {
12 public abstract class JsonScanner : Disposable {
13 readonly InputScanner<JsonGrammar.TokenType> m_jsonContext = JsonGrammar.CreateJsonExpressionScanner();
13 readonly InputScanner<JsonGrammar.TokenType> m_jsonContext = JsonGrammar.CreateJsonExpressionScanner();
14 readonly InputScanner<JsonGrammar.TokenType> m_stringContext = JsonGrammar.CreateStringExpressionScanner();
14 readonly InputScanner<JsonGrammar.TokenType> m_stringContext = JsonGrammar.CreateStringExpressionScanner();
15
15
16 readonly char[] m_unescapeBuf = new char[4];
16 readonly char[] m_unescapeBuf = new char[4];
17 readonly char[] m_buffer;
17 readonly char[] m_buffer;
18 int m_length;
18 int m_length;
19 int m_pos;
19 int m_pos;
20 readonly StringBuilder m_tokenBuilder = new StringBuilder();
20 readonly StringBuilder m_tokenBuilder = new StringBuilder();
21
21
22 protected JsonScanner(char[] buffer, int pos, int length) {
22 protected JsonScanner(char[] buffer, int pos, int length) {
23 m_buffer = buffer;
23 m_buffer = buffer;
24 m_pos = pos;
24 m_pos = pos;
25 m_length = length;
25 m_length = length;
26 }
26 }
27
27
28 bool Read(InputScanner<JsonGrammar.TokenType> scanner, out JsonGrammar.TokenType tokenType) {
28 bool ReadChunk(InputScanner<JsonGrammar.TokenType> scanner, out JsonGrammar.TokenType tokenType) {
29 scanner.Reset();
29 scanner.ResetState();
30
31 while(scanner.Scan(m_buffer, m_pos, m_length)) {
32 // scanner requests new data
30
33
31 if (m_pos == m_length) {
34 if (m_pos != m_length) // capture results for the future
35 m_tokenBuilder.Append(m_buffer, m_pos, m_length - m_pos);
36
37 // read next data
38 m_length = Read(m_buffer, 0, m_buffer.Length);
39
40 if (m_length == 0) {
41 // no data is read
42 if (scanner.Position == m_pos) {
43 // scanned hasn't moved, that's the end
32 m_pos = 0;
44 m_pos = 0;
33 m_length = Read(m_buffer, 0, m_buffer.Length);
34 if (m_length == 0) {
35 tokenType = JsonGrammar.TokenType.None;
45 tokenType = JsonGrammar.TokenType.None;
36 return false; // EOF
46 return false;
47 }
48
49 if (scanner.IsFinal) {
50 m_pos = 0;
51 tokenType = scanner.Tag;
52 return true;
53 } else {
54 throw new ParserException("Unexpected EOF");
37 }
55 }
38 }
56 }
39
57
40 while(scanner.Scan(m_buffer, m_pos, m_length - m_pos)) {
41 m_tokenBuilder.Append(m_buffer, m_pos, m_length - m_pos);
42 m_pos = 0;
58 m_pos = 0;
43 m_length = Read(m_buffer, 0, m_buffer.Length);
44 }
59 }
45 var scannerPos = scanner.Position;
60 var scannerPos = scanner.Position;
61
62 // scanner stops as scannerPos
63 if (!scanner.IsFinal)
64 throw new ParserException($"Unexpected character '{m_buffer[scannerPos + 1]}'");
65
66 tokenType = scanner.Tag;
67 if (scannerPos != m_pos && tokenType == JsonGrammar.TokenType.Number || tokenType == JsonGrammar.TokenType.Literal)
68 m_tokenBuilder.Append(m_buffer, m_pos, scannerPos - m_pos);
69
70 m_pos = scannerPos;
71 return true;
72 }
73
74 bool ReadStringChunk(InputScanner<JsonGrammar.TokenType> scanner, out JsonGrammar.TokenType tokenType) {
75 scanner.ResetState();
76
77 while (scanner.Scan(m_buffer, m_pos, m_length)) {
78 // scanner requests new data
79
80 if (m_pos != m_length) // capture results for the future
81 m_tokenBuilder.Append(m_buffer, m_pos, m_length - m_pos);
82
83 // read next data
84 m_length = Read(m_buffer, 0, m_buffer.Length);
85
86 if (m_length == 0) {
87 // no data is read
88 if (scanner.Position == m_pos) {
89 // scanned hasn't moved, that's the end
90 m_pos = 0;
91 tokenType = JsonGrammar.TokenType.None;
92 return false;
93 }
94
95 if (scanner.IsFinal) {
96 m_pos = 0;
97 tokenType = scanner.Tag;
98 return true;
99 } else {
100 throw new ParserException("Unexpected EOF");
101 }
102 }
103
104 m_pos = 0;
105 }
106 var scannerPos = scanner.Position;
107
108 // scanner stops as scannerPos
109 if (!scanner.IsFinal)
110 throw new ParserException($"Unexpected character '{m_buffer[scannerPos + 1]}'");
111
46 if (scannerPos != m_pos) {
112 if (scannerPos != m_pos) {
47 m_tokenBuilder.Append(m_buffer, m_pos, scannerPos - m_pos);
113 m_tokenBuilder.Append(m_buffer, m_pos, scannerPos - m_pos);
48 m_pos = scannerPos;
114 m_pos = scannerPos;
49 }
115 }
50
51 if (!scanner.IsFinal) {
52 if (m_length == 0) {
53 // unexpected EOF
54 throw new ParserException("Unexpected EOF");
55 } else {
56 // unecpected character
57 throw new ParserException($"Unexpected character '{m_buffer[m_pos + 1]}'");
58 }
59 }
60 tokenType = scanner.Tag;
116 tokenType = scanner.Tag;
61 return true;
117 return true;
62 }
118 }
63
119
64 protected abstract int Read(char[] buffer, int offset, int size);
120 protected abstract int Read(char[] buffer, int offset, int size);
65
121
66
122
67 /// <summary>
123 /// <summary>
68 /// Читает следующий лексический элемент из входных данных.
124 /// Читает следующий лексический элемент из входных данных.
69 /// </summary>
125 /// </summary>
70 /// <param name="tokenValue">Возвращает значение прочитанного токена.</param>
126 /// <param name="tokenValue">Возвращает значение прочитанного токена.</param>
71 /// <param name="tokenType">Возвращает тип прочитанного токена.</param>
127 /// <param name="tokenType">Возвращает тип прочитанного токена.</param>
72 /// <returns><c>true</c> - чтение произведено успешно. <c>false</c> - достигнут конец входных данных</returns>
128 /// <returns><c>true</c> - чтение произведено успешно. <c>false</c> - достигнут конец входных данных</returns>
73 /// <remarks>В случе если токен не распознается, возникает исключение. Значения токенов обрабатываются, т.е.
129 /// <remarks>В случе если токен не распознается, возникает исключение. Значения токенов обрабатываются, т.е.
74 /// в строках обрабатываются экранированные символы, числа становтся типа double.</remarks>
130 /// в строках обрабатываются экранированные символы, числа становтся типа double.</remarks>
75 public bool ReadToken(out object tokenValue, out JsonTokenType tokenType) {
131 public bool ReadToken(out string tokenValue, out JsonTokenType tokenType) {
76 JsonGrammar.TokenType tag;
132 JsonGrammar.TokenType tag;
77 m_tokenBuilder.Clear();
133 m_tokenBuilder.Clear();
78 while (Read(m_jsonContext, out tag)) {
134 while (ReadChunk(m_jsonContext, out tag)) {
79 switch (tag) {
135 switch (tag) {
80 case JsonGrammar.TokenType.StringBound:
136 case JsonGrammar.TokenType.StringBound:
81 tokenValue = ReadString();
137 tokenValue = ReadString();
82 tokenType = JsonTokenType.String;
138 tokenType = JsonTokenType.String;
83 break;
139 break;
84 case JsonGrammar.TokenType.Number:
140 case JsonGrammar.TokenType.Number:
85 tokenValue = Double.Parse(m_tokenBuilder.ToString(), CultureInfo.InvariantCulture);
141 tokenValue = m_tokenBuilder.ToString();
86 tokenType = JsonTokenType.Number;
142 tokenType = JsonTokenType.Number;
87 break;
143 break;
88 case JsonGrammar.TokenType.Literal:
144 case JsonGrammar.TokenType.Literal:
89 tokenType = JsonTokenType.Literal;
145 tokenType = JsonTokenType.Literal;
90 tokenValue = m_tokenBuilder.ToString();
146 tokenValue = m_tokenBuilder.ToString();
91 break;
147 break;
92 case JsonGrammar.TokenType.Whitespace:
148 case JsonGrammar.TokenType.Whitespace:
93 m_tokenBuilder.Clear();
149 m_tokenBuilder.Clear();
94 continue;
150 continue;
95 default:
151 default:
96 tokenType = (JsonTokenType)tag;
152 tokenType = (JsonTokenType)tag;
97 tokenValue = null;
153 tokenValue = null;
98 break;
154 break;
99 }
155 }
100 return true;
156 return true;
101 }
157 }
102 tokenValue = null;
158 tokenValue = null;
103 tokenType = JsonTokenType.None;
159 tokenType = JsonTokenType.None;
104 return false;
160 return false;
105 }
161 }
106
162
107 string ReadString() {
163 string ReadString() {
108 JsonGrammar.TokenType tag;
164 JsonGrammar.TokenType tag;
109 m_tokenBuilder.Clear();
165 m_tokenBuilder.Clear();
110
166
111 while (Read(m_stringContext, out tag)) {
167 while (ReadStringChunk(m_stringContext, out tag)) {
112 switch (tag) {
168 switch (tag) {
113 case JsonGrammar.TokenType.StringBound:
169 case JsonGrammar.TokenType.StringBound:
114 m_tokenBuilder.Length--;
170 m_tokenBuilder.Length--;
115 return m_tokenBuilder.ToString();
171 return m_tokenBuilder.ToString();
116 case JsonGrammar.TokenType.UnescapedChar:
172 case JsonGrammar.TokenType.UnescapedChar:
117 break;
173 break;
118 case JsonGrammar.TokenType.EscapedUnicode: // \xXXXX - unicode escape sequence
174 case JsonGrammar.TokenType.EscapedUnicode: // \xXXXX - unicode escape sequence
119 m_tokenBuilder.CopyTo(m_tokenBuilder.Length - 4, m_unescapeBuf, 0, 4);
175 m_tokenBuilder.CopyTo(m_tokenBuilder.Length - 4, m_unescapeBuf, 0, 4);
120 m_tokenBuilder.Length -= 6;
176 m_tokenBuilder.Length -= 6;
121 m_tokenBuilder.Append(StringTranslator.TranslateHexUnicode(m_unescapeBuf, 0));
177 m_tokenBuilder.Append(StringTranslator.TranslateHexUnicode(m_unescapeBuf, 0));
122 break;
178 break;
123 case JsonGrammar.TokenType.EscapedChar: // \t - escape sequence
179 case JsonGrammar.TokenType.EscapedChar: // \t - escape sequence
124 var ch = m_tokenBuilder[m_tokenBuilder.Length-1];
180 var ch = m_tokenBuilder[m_tokenBuilder.Length-1];
125 m_tokenBuilder.Length -= 2;
181 m_tokenBuilder.Length -= 2;
126 m_tokenBuilder.Append(StringTranslator.TranslateEscapedChar(ch));
182 m_tokenBuilder.Append(StringTranslator.TranslateEscapedChar(ch));
127 break;
183 break;
128 }
184 }
129 }
185 }
130
186
131 throw new ParserException("Unexpected end of data");
187 throw new ParserException("Unexpected end of data");
132 }
188 }
133 }
189 }
134 }
190 }
@@ -1,49 +1,49
1 using System;
1 using System;
2 using System.Collections.Generic;
2 using System.Collections.Generic;
3 using System.IO;
3 using System.IO;
4 using System.Linq;
4 using System.Linq;
5 using System.Text;
5 using System.Text;
6 using System.Threading.Tasks;
6 using System.Threading.Tasks;
7
7
8 namespace Implab.Formats.Json {
8 namespace Implab.Formats.Json {
9 public class JsonTextScanner : JsonScanner {
9 public class JsonTextScanner : JsonScanner {
10 const int _bufferSize = 4096;
10 const int _bufferSize = 16*4096;
11 readonly TextReader m_reader;
11 readonly TextReader m_reader;
12
12
13 JsonTextScanner(TextReader reader, char[] buffer) : base(buffer, 0, 0) {
13 JsonTextScanner(TextReader reader, char[] buffer) : base(buffer, 0, 0) {
14 m_reader = reader;
14 m_reader = reader;
15 }
15 }
16
16
17 protected override int Read(char[] buffer, int offset, int size) {
17 protected override int Read(char[] buffer, int offset, int size) {
18 return m_reader.Read(buffer, offset, size);
18 return m_reader.Read(buffer, offset, size);
19 }
19 }
20
20
21 public static JsonTextScanner Create(string file, Encoding encoding) {
21 public static JsonTextScanner Create(string file, Encoding encoding) {
22 return new JsonTextScanner(new StreamReader(file, encoding), new char[_bufferSize]);
22 return new JsonTextScanner(new StreamReader(file, encoding), new char[_bufferSize]);
23 }
23 }
24
24
25 public static JsonTextScanner Create(string file) {
25 public static JsonTextScanner Create(string file) {
26 return new JsonTextScanner(new StreamReader(file), new char[_bufferSize]);
26 return new JsonTextScanner(new StreamReader(file), new char[_bufferSize]);
27 }
27 }
28
28
29 public static JsonTextScanner Create(Stream stream, Encoding encoding) {
29 public static JsonTextScanner Create(Stream stream, Encoding encoding) {
30 return new JsonTextScanner(new StreamReader(stream, encoding), new char[_bufferSize]);
30 return new JsonTextScanner(new StreamReader(stream, encoding), new char[_bufferSize]);
31 }
31 }
32
32
33 public static JsonTextScanner Create(Stream stream) {
33 public static JsonTextScanner Create(Stream stream) {
34 return new JsonTextScanner(new StreamReader(stream), new char[_bufferSize]);
34 return new JsonTextScanner(new StreamReader(stream), new char[_bufferSize]);
35 }
35 }
36
36
37 public static JsonTextScanner Create(TextReader reader) {
37 public static JsonTextScanner Create(TextReader reader) {
38 Safe.ArgumentNotNull(reader, nameof(reader));
38 Safe.ArgumentNotNull(reader, nameof(reader));
39 return new JsonTextScanner(reader, new char[_bufferSize]);
39 return new JsonTextScanner(reader, new char[_bufferSize]);
40 }
40 }
41
41
42 protected override void Dispose(bool disposing) {
42 protected override void Dispose(bool disposing) {
43 if (disposing)
43 if (disposing)
44 Safe.Dispose(m_reader);
44 Safe.Dispose(m_reader);
45
45
46 base.Dispose(disposing);
46 base.Dispose(disposing);
47 }
47 }
48 }
48 }
49 }
49 }
@@ -1,279 +1,282
1 <?xml version="1.0" encoding="utf-8"?>
1 <?xml version="1.0" encoding="utf-8"?>
2 <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
2 <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3 <PropertyGroup>
3 <PropertyGroup>
4 <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
4 <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
5 <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
5 <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
6 <ProjectGuid>{F550F1F8-8746-4AD0-9614-855F4C4B7F05}</ProjectGuid>
6 <ProjectGuid>{F550F1F8-8746-4AD0-9614-855F4C4B7F05}</ProjectGuid>
7 <OutputType>Library</OutputType>
7 <OutputType>Library</OutputType>
8 <RootNamespace>Implab</RootNamespace>
8 <RootNamespace>Implab</RootNamespace>
9 <AssemblyName>Implab</AssemblyName>
9 <AssemblyName>Implab</AssemblyName>
10 <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
10 <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
11 </PropertyGroup>
11 </PropertyGroup>
12 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
12 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
13 <DebugSymbols>true</DebugSymbols>
13 <DebugSymbols>true</DebugSymbols>
14 <DebugType>full</DebugType>
14 <DebugType>full</DebugType>
15 <Optimize>false</Optimize>
15 <Optimize>false</Optimize>
16 <OutputPath>bin\Debug</OutputPath>
16 <OutputPath>bin\Debug</OutputPath>
17 <DefineConstants>TRACE;DEBUG;</DefineConstants>
17 <DefineConstants>TRACE;DEBUG;</DefineConstants>
18 <ErrorReport>prompt</ErrorReport>
18 <ErrorReport>prompt</ErrorReport>
19 <WarningLevel>4</WarningLevel>
19 <WarningLevel>4</WarningLevel>
20 <ConsolePause>false</ConsolePause>
20 <ConsolePause>false</ConsolePause>
21 <RunCodeAnalysis>true</RunCodeAnalysis>
21 <RunCodeAnalysis>true</RunCodeAnalysis>
22 </PropertyGroup>
22 </PropertyGroup>
23 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
23 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
24 <DebugType>full</DebugType>
24 <DebugType>full</DebugType>
25 <Optimize>true</Optimize>
25 <Optimize>true</Optimize>
26 <OutputPath>bin\Release</OutputPath>
26 <OutputPath>bin\Release</OutputPath>
27 <ErrorReport>prompt</ErrorReport>
27 <ErrorReport>prompt</ErrorReport>
28 <WarningLevel>4</WarningLevel>
28 <WarningLevel>4</WarningLevel>
29 <ConsolePause>false</ConsolePause>
29 <ConsolePause>false</ConsolePause>
30 </PropertyGroup>
30 </PropertyGroup>
31 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug 4.5|AnyCPU' ">
31 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug 4.5|AnyCPU' ">
32 <DebugSymbols>true</DebugSymbols>
32 <DebugSymbols>true</DebugSymbols>
33 <DebugType>full</DebugType>
33 <DebugType>full</DebugType>
34 <Optimize>false</Optimize>
34 <Optimize>false</Optimize>
35 <OutputPath>bin\Debug</OutputPath>
35 <OutputPath>bin\Debug</OutputPath>
36 <DefineConstants>TRACE;DEBUG;NET_4_5</DefineConstants>
36 <DefineConstants>TRACE;DEBUG;NET_4_5</DefineConstants>
37 <ErrorReport>prompt</ErrorReport>
37 <ErrorReport>prompt</ErrorReport>
38 <WarningLevel>4</WarningLevel>
38 <WarningLevel>4</WarningLevel>
39 <RunCodeAnalysis>true</RunCodeAnalysis>
39 <RunCodeAnalysis>true</RunCodeAnalysis>
40 <ConsolePause>false</ConsolePause>
40 <ConsolePause>false</ConsolePause>
41 </PropertyGroup>
41 </PropertyGroup>
42 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release 4.5|AnyCPU' ">
42 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release 4.5|AnyCPU' ">
43 <Optimize>true</Optimize>
43 <Optimize>true</Optimize>
44 <OutputPath>bin\Release</OutputPath>
44 <OutputPath>bin\Release</OutputPath>
45 <ErrorReport>prompt</ErrorReport>
45 <ErrorReport>prompt</ErrorReport>
46 <WarningLevel>4</WarningLevel>
46 <WarningLevel>4</WarningLevel>
47 <ConsolePause>false</ConsolePause>
47 <ConsolePause>false</ConsolePause>
48 <DefineConstants>NET_4_5</DefineConstants>
48 <DefineConstants>NET_4_5</DefineConstants>
49 </PropertyGroup>
49 </PropertyGroup>
50 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'DebugMono|AnyCPU' ">
50 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'DebugMono|AnyCPU' ">
51 <DebugSymbols>true</DebugSymbols>
51 <DebugSymbols>true</DebugSymbols>
52 <DebugType>full</DebugType>
52 <DebugType>full</DebugType>
53 <Optimize>false</Optimize>
53 <Optimize>false</Optimize>
54 <OutputPath>bin\Debug</OutputPath>
54 <OutputPath>bin\Debug</OutputPath>
55 <DefineConstants>TRACE;DEBUG;NET_4_5;MONO</DefineConstants>
55 <DefineConstants>TRACE;DEBUG;NET_4_5;MONO</DefineConstants>
56 <ErrorReport>prompt</ErrorReport>
56 <ErrorReport>prompt</ErrorReport>
57 <WarningLevel>4</WarningLevel>
57 <WarningLevel>4</WarningLevel>
58 <RunCodeAnalysis>true</RunCodeAnalysis>
58 <RunCodeAnalysis>true</RunCodeAnalysis>
59 <ConsolePause>false</ConsolePause>
59 <ConsolePause>false</ConsolePause>
60 </PropertyGroup>
60 </PropertyGroup>
61 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseMono|AnyCPU' ">
61 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseMono|AnyCPU' ">
62 <Optimize>true</Optimize>
62 <Optimize>true</Optimize>
63 <OutputPath>bin\Release</OutputPath>
63 <OutputPath>bin\Release</OutputPath>
64 <DefineConstants>NET_4_5;MONO;</DefineConstants>
64 <DefineConstants>NET_4_5;MONO;</DefineConstants>
65 <ErrorReport>prompt</ErrorReport>
65 <ErrorReport>prompt</ErrorReport>
66 <WarningLevel>4</WarningLevel>
66 <WarningLevel>4</WarningLevel>
67 <ConsolePause>false</ConsolePause>
67 <ConsolePause>false</ConsolePause>
68 </PropertyGroup>
68 </PropertyGroup>
69 <ItemGroup>
69 <ItemGroup>
70 <Reference Include="System" />
70 <Reference Include="System" />
71 <Reference Include="System.Xml" />
71 <Reference Include="System.Xml" />
72 <Reference Include="mscorlib" />
72 <Reference Include="mscorlib" />
73 <Reference Include="System.Xml.Linq" />
73 </ItemGroup>
74 </ItemGroup>
74 <ItemGroup>
75 <ItemGroup>
75 <Compile Include="Components\StateChangeEventArgs.cs" />
76 <Compile Include="Components\StateChangeEventArgs.cs" />
76 <Compile Include="CustomEqualityComparer.cs" />
77 <Compile Include="CustomEqualityComparer.cs" />
77 <Compile Include="Diagnostics\ConsoleTraceListener.cs" />
78 <Compile Include="Diagnostics\ConsoleTraceListener.cs" />
78 <Compile Include="Diagnostics\LogChannel.cs" />
79 <Compile Include="Diagnostics\LogChannel.cs" />
79 <Compile Include="Diagnostics\LogicalOperation.cs" />
80 <Compile Include="Diagnostics\LogicalOperation.cs" />
80 <Compile Include="Diagnostics\TextFileListener.cs" />
81 <Compile Include="Diagnostics\TextFileListener.cs" />
81 <Compile Include="Diagnostics\Trace.cs" />
82 <Compile Include="Diagnostics\Trace.cs" />
82 <Compile Include="Diagnostics\TraceLog.cs" />
83 <Compile Include="Diagnostics\TraceLog.cs" />
83 <Compile Include="Diagnostics\TraceEvent.cs" />
84 <Compile Include="Diagnostics\TraceEvent.cs" />
84 <Compile Include="Diagnostics\TraceEventType.cs" />
85 <Compile Include="Diagnostics\TraceEventType.cs" />
85 <Compile Include="Diagnostics\TraceSourceAttribute.cs" />
86 <Compile Include="Diagnostics\TraceSourceAttribute.cs" />
86 <Compile Include="Formats\CharMap.cs" />
87 <Compile Include="Formats\CharMap.cs" />
87 <Compile Include="Formats\InputScanner.cs" />
88 <Compile Include="Formats\InputScanner.cs" />
88 <Compile Include="Formats\Json\JsonStringScanner.cs" />
89 <Compile Include="Formats\Json\JsonStringScanner.cs" />
89 <Compile Include="Formats\Json\JsonTextScanner.cs" />
90 <Compile Include="Formats\Json\JsonTextScanner.cs" />
90 <Compile Include="ICancellable.cs" />
91 <Compile Include="ICancellable.cs" />
91 <Compile Include="IProgressHandler.cs" />
92 <Compile Include="IProgressHandler.cs" />
92 <Compile Include="IProgressNotifier.cs" />
93 <Compile Include="IProgressNotifier.cs" />
93 <Compile Include="IPromiseT.cs" />
94 <Compile Include="IPromiseT.cs" />
94 <Compile Include="IPromise.cs" />
95 <Compile Include="IPromise.cs" />
95 <Compile Include="IServiceLocator.cs" />
96 <Compile Include="IServiceLocator.cs" />
96 <Compile Include="ITaskController.cs" />
97 <Compile Include="ITaskController.cs" />
97 <Compile Include="Parallels\DispatchPool.cs" />
98 <Compile Include="Parallels\DispatchPool.cs" />
98 <Compile Include="Parallels\ArrayTraits.cs" />
99 <Compile Include="Parallels\ArrayTraits.cs" />
99 <Compile Include="Parallels\MTQueue.cs" />
100 <Compile Include="Parallels\MTQueue.cs" />
100 <Compile Include="Parallels\WorkerPool.cs" />
101 <Compile Include="Parallels\WorkerPool.cs" />
101 <Compile Include="ProgressInitEventArgs.cs" />
102 <Compile Include="ProgressInitEventArgs.cs" />
102 <Compile Include="Properties\AssemblyInfo.cs" />
103 <Compile Include="Properties\AssemblyInfo.cs" />
103 <Compile Include="Parallels\AsyncPool.cs" />
104 <Compile Include="Parallels\AsyncPool.cs" />
104 <Compile Include="Safe.cs" />
105 <Compile Include="Safe.cs" />
105 <Compile Include="SyncContextPromise.cs" />
106 <Compile Include="SyncContextPromise.cs" />
106 <Compile Include="ValueEventArgs.cs" />
107 <Compile Include="ValueEventArgs.cs" />
107 <Compile Include="PromiseExtensions.cs" />
108 <Compile Include="PromiseExtensions.cs" />
108 <Compile Include="SyncContextPromiseT.cs" />
109 <Compile Include="SyncContextPromiseT.cs" />
109 <Compile Include="Diagnostics\OperationContext.cs" />
110 <Compile Include="Diagnostics\OperationContext.cs" />
110 <Compile Include="Diagnostics\TraceContext.cs" />
111 <Compile Include="Diagnostics\TraceContext.cs" />
111 <Compile Include="Diagnostics\LogEventArgs.cs" />
112 <Compile Include="Diagnostics\LogEventArgs.cs" />
112 <Compile Include="Diagnostics\LogEventArgsT.cs" />
113 <Compile Include="Diagnostics\LogEventArgsT.cs" />
113 <Compile Include="Diagnostics\Extensions.cs" />
114 <Compile Include="Diagnostics\Extensions.cs" />
114 <Compile Include="PromiseEventType.cs" />
115 <Compile Include="PromiseEventType.cs" />
115 <Compile Include="Parallels\AsyncQueue.cs" />
116 <Compile Include="Parallels\AsyncQueue.cs" />
116 <Compile Include="PromiseT.cs" />
117 <Compile Include="PromiseT.cs" />
117 <Compile Include="IDeferred.cs" />
118 <Compile Include="IDeferred.cs" />
118 <Compile Include="IDeferredT.cs" />
119 <Compile Include="IDeferredT.cs" />
119 <Compile Include="Promise.cs" />
120 <Compile Include="Promise.cs" />
120 <Compile Include="PromiseTransientException.cs" />
121 <Compile Include="PromiseTransientException.cs" />
121 <Compile Include="Parallels\Signal.cs" />
122 <Compile Include="Parallels\Signal.cs" />
122 <Compile Include="Parallels\SharedLock.cs" />
123 <Compile Include="Parallels\SharedLock.cs" />
123 <Compile Include="Diagnostics\ILogWriter.cs" />
124 <Compile Include="Diagnostics\ILogWriter.cs" />
124 <Compile Include="Diagnostics\ListenerBase.cs" />
125 <Compile Include="Diagnostics\ListenerBase.cs" />
125 <Compile Include="Parallels\BlockingQueue.cs" />
126 <Compile Include="Parallels\BlockingQueue.cs" />
126 <Compile Include="AbstractEvent.cs" />
127 <Compile Include="AbstractEvent.cs" />
127 <Compile Include="AbstractPromise.cs" />
128 <Compile Include="AbstractPromise.cs" />
128 <Compile Include="AbstractPromiseT.cs" />
129 <Compile Include="AbstractPromiseT.cs" />
129 <Compile Include="FuncTask.cs" />
130 <Compile Include="FuncTask.cs" />
130 <Compile Include="FuncTaskBase.cs" />
131 <Compile Include="FuncTaskBase.cs" />
131 <Compile Include="FuncTaskT.cs" />
132 <Compile Include="FuncTaskT.cs" />
132 <Compile Include="ActionChainTaskBase.cs" />
133 <Compile Include="ActionChainTaskBase.cs" />
133 <Compile Include="ActionChainTask.cs" />
134 <Compile Include="ActionChainTask.cs" />
134 <Compile Include="ActionChainTaskT.cs" />
135 <Compile Include="ActionChainTaskT.cs" />
135 <Compile Include="FuncChainTaskBase.cs" />
136 <Compile Include="FuncChainTaskBase.cs" />
136 <Compile Include="FuncChainTask.cs" />
137 <Compile Include="FuncChainTask.cs" />
137 <Compile Include="FuncChainTaskT.cs" />
138 <Compile Include="FuncChainTaskT.cs" />
138 <Compile Include="ActionTaskBase.cs" />
139 <Compile Include="ActionTaskBase.cs" />
139 <Compile Include="ActionTask.cs" />
140 <Compile Include="ActionTask.cs" />
140 <Compile Include="ActionTaskT.cs" />
141 <Compile Include="ActionTaskT.cs" />
141 <Compile Include="ICancellationToken.cs" />
142 <Compile Include="ICancellationToken.cs" />
142 <Compile Include="SuccessPromise.cs" />
143 <Compile Include="SuccessPromise.cs" />
143 <Compile Include="SuccessPromiseT.cs" />
144 <Compile Include="SuccessPromiseT.cs" />
144 <Compile Include="PromiseAwaiterT.cs" />
145 <Compile Include="PromiseAwaiterT.cs" />
145 <Compile Include="PromiseAwaiter.cs" />
146 <Compile Include="PromiseAwaiter.cs" />
146 <Compile Include="Components\ComponentContainer.cs" />
147 <Compile Include="Components\ComponentContainer.cs" />
147 <Compile Include="Components\Disposable.cs" />
148 <Compile Include="Components\Disposable.cs" />
148 <Compile Include="Components\DisposablePool.cs" />
149 <Compile Include="Components\DisposablePool.cs" />
149 <Compile Include="Components\ObjectPool.cs" />
150 <Compile Include="Components\ObjectPool.cs" />
150 <Compile Include="Components\ServiceLocator.cs" />
151 <Compile Include="Components\ServiceLocator.cs" />
151 <Compile Include="Components\IInitializable.cs" />
152 <Compile Include="Components\IInitializable.cs" />
152 <Compile Include="TaskController.cs" />
153 <Compile Include="TaskController.cs" />
153 <Compile Include="Components\App.cs" />
154 <Compile Include="Components\App.cs" />
154 <Compile Include="Components\IRunnable.cs" />
155 <Compile Include="Components\IRunnable.cs" />
155 <Compile Include="Components\ExecutionState.cs" />
156 <Compile Include="Components\ExecutionState.cs" />
156 <Compile Include="Components\RunnableComponent.cs" />
157 <Compile Include="Components\RunnableComponent.cs" />
157 <Compile Include="Components\IFactory.cs" />
158 <Compile Include="Components\IFactory.cs" />
158 <Compile Include="Automaton\IAlphabet.cs" />
159 <Compile Include="Automaton\IAlphabet.cs" />
159 <Compile Include="Automaton\ParserException.cs" />
160 <Compile Include="Automaton\ParserException.cs" />
160 <Compile Include="Automaton\IndexedAlphabetBase.cs" />
161 <Compile Include="Automaton\IndexedAlphabetBase.cs" />
161 <Compile Include="Automaton\IAlphabetBuilder.cs" />
162 <Compile Include="Automaton\IAlphabetBuilder.cs" />
162 <Compile Include="Automaton\RegularExpressions\AltToken.cs" />
163 <Compile Include="Automaton\RegularExpressions\AltToken.cs" />
163 <Compile Include="Automaton\RegularExpressions\BinaryToken.cs" />
164 <Compile Include="Automaton\RegularExpressions\BinaryToken.cs" />
164 <Compile Include="Automaton\RegularExpressions\CatToken.cs" />
165 <Compile Include="Automaton\RegularExpressions\CatToken.cs" />
165 <Compile Include="Automaton\RegularExpressions\StarToken.cs" />
166 <Compile Include="Automaton\RegularExpressions\StarToken.cs" />
166 <Compile Include="Automaton\RegularExpressions\SymbolToken.cs" />
167 <Compile Include="Automaton\RegularExpressions\SymbolToken.cs" />
167 <Compile Include="Automaton\RegularExpressions\EmptyToken.cs" />
168 <Compile Include="Automaton\RegularExpressions\EmptyToken.cs" />
168 <Compile Include="Automaton\RegularExpressions\Token.cs" />
169 <Compile Include="Automaton\RegularExpressions\Token.cs" />
169 <Compile Include="Automaton\RegularExpressions\IVisitor.cs" />
170 <Compile Include="Automaton\RegularExpressions\IVisitor.cs" />
170 <Compile Include="Automaton\AutomatonTransition.cs" />
171 <Compile Include="Automaton\AutomatonTransition.cs" />
171 <Compile Include="Formats\Json\JsonElementContext.cs" />
172 <Compile Include="Formats\Json\JsonElementContext.cs" />
172 <Compile Include="Formats\Json\JsonElementType.cs" />
173 <Compile Include="Formats\Json\JsonElementType.cs" />
173 <Compile Include="Formats\Json\JsonGrammar.cs" />
174 <Compile Include="Formats\Json\JsonGrammar.cs" />
174 <Compile Include="Formats\Json\JsonParser.cs" />
175 <Compile Include="Formats\Json\JsonReader.cs" />
175 <Compile Include="Formats\Json\JsonScanner.cs" />
176 <Compile Include="Formats\Json\JsonScanner.cs" />
176 <Compile Include="Formats\Json\JsonTokenType.cs" />
177 <Compile Include="Formats\Json\JsonTokenType.cs" />
177 <Compile Include="Formats\Json\JsonWriter.cs" />
178 <Compile Include="Formats\Json\JsonWriter.cs" />
178 <Compile Include="Formats\Json\StringTranslator.cs" />
179 <Compile Include="Formats\Json\StringTranslator.cs" />
179 <Compile Include="Automaton\MapAlphabet.cs" />
180 <Compile Include="Automaton\MapAlphabet.cs" />
180 <Compile Include="Formats\CharAlphabet.cs" />
181 <Compile Include="Formats\CharAlphabet.cs" />
181 <Compile Include="Formats\ByteAlphabet.cs" />
182 <Compile Include="Formats\ByteAlphabet.cs" />
182 <Compile Include="Automaton\IDFATable.cs" />
183 <Compile Include="Automaton\IDFATable.cs" />
183 <Compile Include="Automaton\IDFATableBuilder.cs" />
184 <Compile Include="Automaton\IDFATableBuilder.cs" />
184 <Compile Include="Automaton\DFATable.cs" />
185 <Compile Include="Automaton\DFATable.cs" />
185 <Compile Include="Automaton\RegularExpressions\RegularExpressionVisitor.cs" />
186 <Compile Include="Automaton\RegularExpressions\RegularExpressionVisitor.cs" />
186 <Compile Include="Automaton\RegularExpressions\ITaggedDFABuilder.cs" />
187 <Compile Include="Automaton\RegularExpressions\ITaggedDFABuilder.cs" />
187 <Compile Include="Formats\Grammar.cs" />
188 <Compile Include="Formats\Grammar.cs" />
188 <Compile Include="Automaton\RegularExpressions\EndTokenT.cs" />
189 <Compile Include="Automaton\RegularExpressions\EndTokenT.cs" />
189 <Compile Include="Automaton\RegularExpressions\EndToken.cs" />
190 <Compile Include="Automaton\RegularExpressions\EndToken.cs" />
190 <Compile Include="Automaton\RegularExpressions\RegularExpressionVisitorT.cs" />
191 <Compile Include="Automaton\RegularExpressions\RegularExpressionVisitorT.cs" />
191 <Compile Include="Automaton\AutomatonConst.cs" />
192 <Compile Include="Automaton\AutomatonConst.cs" />
192 <Compile Include="Automaton\RegularExpressions\RegularDFA.cs" />
193 <Compile Include="Automaton\RegularExpressions\RegularDFA.cs" />
193 <Compile Include="Components\LazyAndWeak.cs" />
194 <Compile Include="Components\LazyAndWeak.cs" />
194 <Compile Include="AbstractTask.cs" />
195 <Compile Include="AbstractTask.cs" />
195 <Compile Include="AbstractTaskT.cs" />
196 <Compile Include="AbstractTaskT.cs" />
196 <Compile Include="FailedPromise.cs" />
197 <Compile Include="FailedPromise.cs" />
197 <Compile Include="FailedPromiseT.cs" />
198 <Compile Include="FailedPromiseT.cs" />
198 <Compile Include="Components\PollingComponent.cs" />
199 <Compile Include="Components\PollingComponent.cs" />
199 <Compile Include="Xml\JsonXmlReader.cs" />
200 <Compile Include="Xml\JsonXmlReader.cs" />
200 <Compile Include="Xml\JsonXmlReaderOptions.cs" />
201 <Compile Include="Xml\JsonXmlReaderOptions.cs" />
201 <Compile Include="Xml\JsonXmlReaderPosition.cs" />
202 <Compile Include="Xml\JsonXmlReaderPosition.cs" />
203 <Compile Include="Xml\SerializationHelpers.cs" />
204 <Compile Include="Xml\SerializersPool.cs" />
202 <Compile Include="Xml\XmlSimpleAttribute.cs" />
205 <Compile Include="Xml\XmlSimpleAttribute.cs" />
203 <Compile Include="Xml\XmlNameContext.cs" />
206 <Compile Include="Xml\XmlNameContext.cs" />
204 </ItemGroup>
207 </ItemGroup>
205 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
208 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
206 <ItemGroup />
209 <ItemGroup />
207 <ProjectExtensions>
210 <ProjectExtensions>
208 <MonoDevelop>
211 <MonoDevelop>
209 <Properties>
212 <Properties>
210 <Policies>
213 <Policies>
211 <CSharpFormattingPolicy IndentBlock="True" IndentBraces="False" IndentSwitchSection="False" IndentSwitchCaseSection="True" LabelPositioning="OneLess" NewLinesForBracesInProperties="False" NewLinesForBracesInAccessors="False" NewLinesForBracesInAnonymousMethods="False" NewLinesForBracesInControlBlocks="False" NewLinesForBracesInAnonymousTypes="False" NewLinesForBracesInObjectCollectionArrayInitializers="False" NewLinesForBracesInLambdaExpressionBody="False" NewLineForElse="False" NewLineForCatch="False" NewLineForFinally="False" NewLineForMembersInObjectInit="False" NewLineForMembersInAnonymousTypes="False" NewLineForClausesInQuery="False" SpaceWithinMethodDeclarationParenthesis="False" SpaceBetweenEmptyMethodDeclarationParentheses="False" SpaceWithinMethodCallParentheses="False" SpaceBetweenEmptyMethodCallParentheses="False" SpaceAfterControlFlowStatementKeyword="True" SpaceWithinExpressionParentheses="False" SpaceWithinCastParentheses="False" SpaceWithinOtherParentheses="False" SpaceAfterCast="False" SpacesIgnoreAroundVariableDeclaration="False" SpaceBetweenEmptySquareBrackets="False" SpaceWithinSquareBrackets="False" SpaceAfterColonInBaseTypeDeclaration="True" SpaceAfterComma="True" SpaceAfterDot="False" SpaceAfterSemicolonsInForStatement="True" SpaceBeforeComma="False" SpaceBeforeDot="False" SpaceBeforeSemicolonsInForStatement="False" SpacingAroundBinaryOperator="Single" WrappingPreserveSingleLine="True" WrappingKeepStatementsOnSingleLine="True" PlaceSystemDirectiveFirst="True" NewLinesForBracesInTypes="True" NewLinesForBracesInMethods="True" SpacingAfterMethodDeclarationName="True" SpaceAfterMethodCallName="True" SpaceBeforeOpenSquareBracket="True" SpaceBeforeColonInBaseTypeDeclaration="True" scope="text/x-csharp" />
214 <CSharpFormattingPolicy IndentBlock="True" IndentBraces="False" IndentSwitchSection="False" IndentSwitchCaseSection="True" LabelPositioning="OneLess" NewLinesForBracesInProperties="False" NewLinesForBracesInAccessors="False" NewLinesForBracesInAnonymousMethods="False" NewLinesForBracesInControlBlocks="False" NewLinesForBracesInAnonymousTypes="False" NewLinesForBracesInObjectCollectionArrayInitializers="False" NewLinesForBracesInLambdaExpressionBody="False" NewLineForElse="False" NewLineForCatch="False" NewLineForFinally="False" NewLineForMembersInObjectInit="False" NewLineForMembersInAnonymousTypes="False" NewLineForClausesInQuery="False" SpaceWithinMethodDeclarationParenthesis="False" SpaceBetweenEmptyMethodDeclarationParentheses="False" SpaceWithinMethodCallParentheses="False" SpaceBetweenEmptyMethodCallParentheses="False" SpaceAfterControlFlowStatementKeyword="True" SpaceWithinExpressionParentheses="False" SpaceWithinCastParentheses="False" SpaceWithinOtherParentheses="False" SpaceAfterCast="False" SpacesIgnoreAroundVariableDeclaration="False" SpaceBetweenEmptySquareBrackets="False" SpaceWithinSquareBrackets="False" SpaceAfterColonInBaseTypeDeclaration="True" SpaceAfterComma="True" SpaceAfterDot="False" SpaceAfterSemicolonsInForStatement="True" SpaceBeforeComma="False" SpaceBeforeDot="False" SpaceBeforeSemicolonsInForStatement="False" SpacingAroundBinaryOperator="Single" WrappingPreserveSingleLine="True" WrappingKeepStatementsOnSingleLine="True" PlaceSystemDirectiveFirst="True" NewLinesForBracesInTypes="True" NewLinesForBracesInMethods="True" SpacingAfterMethodDeclarationName="True" SpaceAfterMethodCallName="True" SpaceBeforeOpenSquareBracket="True" SpaceBeforeColonInBaseTypeDeclaration="True" scope="text/x-csharp" />
212 <TextStylePolicy FileWidth="120" TabWidth="4" IndentWidth="4" RemoveTrailingWhitespace="True" NoTabsAfterNonTabs="False" TabsToSpaces="True" EolMarker="Unix" scope="text/x-csharp" />
215 <TextStylePolicy FileWidth="120" TabWidth="4" IndentWidth="4" RemoveTrailingWhitespace="True" NoTabsAfterNonTabs="False" TabsToSpaces="True" EolMarker="Unix" scope="text/x-csharp" />
213 <DotNetNamingPolicy DirectoryNamespaceAssociation="PrefixedHierarchical" ResourceNamePolicy="MSBuild" />
216 <DotNetNamingPolicy DirectoryNamespaceAssociation="PrefixedHierarchical" ResourceNamePolicy="MSBuild" />
214 <TextStylePolicy FileWidth="120" TabWidth="4" TabsToSpaces="False" IndentWidth="4" RemoveTrailingWhitespace="True" NoTabsAfterNonTabs="False" EolMarker="Native" scope="application/xml" />
217 <TextStylePolicy FileWidth="120" TabWidth="4" TabsToSpaces="False" IndentWidth="4" RemoveTrailingWhitespace="True" NoTabsAfterNonTabs="False" EolMarker="Native" scope="application/xml" />
215 <XmlFormattingPolicy scope="application/xml">
218 <XmlFormattingPolicy scope="application/xml">
216 <DefaultFormat OmitXmlDeclaration="False" NewLineChars="&#xA;" IndentContent="True" ContentIndentString=" " AttributesInNewLine="False" MaxAttributesPerLine="10" AttributesIndentString=" " WrapAttributes="False" AlignAttributes="False" AlignAttributeValues="False" QuoteChar="&quot;" SpacesBeforeAssignment="0" SpacesAfterAssignment="0" EmptyLinesBeforeStart="0" EmptyLinesAfterStart="0" EmptyLinesBeforeEnd="0" EmptyLinesAfterEnd="0" />
219 <DefaultFormat OmitXmlDeclaration="False" NewLineChars="&#xA;" IndentContent="True" ContentIndentString=" " AttributesInNewLine="False" MaxAttributesPerLine="10" AttributesIndentString=" " WrapAttributes="False" AlignAttributes="False" AlignAttributeValues="False" QuoteChar="&quot;" SpacesBeforeAssignment="0" SpacesAfterAssignment="0" EmptyLinesBeforeStart="0" EmptyLinesAfterStart="0" EmptyLinesBeforeEnd="0" EmptyLinesAfterEnd="0" />
217 </XmlFormattingPolicy>
220 </XmlFormattingPolicy>
218 <TextStylePolicy FileWidth="120" TabWidth="4" TabsToSpaces="False" IndentWidth="4" RemoveTrailingWhitespace="True" NoTabsAfterNonTabs="False" EolMarker="Native" scope="text/plain" />
221 <TextStylePolicy FileWidth="120" TabWidth="4" TabsToSpaces="False" IndentWidth="4" RemoveTrailingWhitespace="True" NoTabsAfterNonTabs="False" EolMarker="Native" scope="text/plain" />
219 <NameConventionPolicy>
222 <NameConventionPolicy>
220 <Rules>
223 <Rules>
221 <NamingRule Name="Namespaces" AffectedEntity="Namespace" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
224 <NamingRule Name="Namespaces" AffectedEntity="Namespace" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
222 <NamingRule Name="Types" AffectedEntity="Class, Struct, Enum, Delegate" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
225 <NamingRule Name="Types" AffectedEntity="Class, Struct, Enum, Delegate" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
223 <NamingRule Name="Interfaces" AffectedEntity="Interface" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
226 <NamingRule Name="Interfaces" AffectedEntity="Interface" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
224 <RequiredPrefixes>
227 <RequiredPrefixes>
225 <String>I</String>
228 <String>I</String>
226 </RequiredPrefixes>
229 </RequiredPrefixes>
227 </NamingRule>
230 </NamingRule>
228 <NamingRule Name="Attributes" AffectedEntity="CustomAttributes" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
231 <NamingRule Name="Attributes" AffectedEntity="CustomAttributes" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
229 <RequiredSuffixes>
232 <RequiredSuffixes>
230 <String>Attribute</String>
233 <String>Attribute</String>
231 </RequiredSuffixes>
234 </RequiredSuffixes>
232 </NamingRule>
235 </NamingRule>
233 <NamingRule Name="Event Arguments" AffectedEntity="CustomEventArgs" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
236 <NamingRule Name="Event Arguments" AffectedEntity="CustomEventArgs" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
234 <RequiredSuffixes>
237 <RequiredSuffixes>
235 <String>EventArgs</String>
238 <String>EventArgs</String>
236 </RequiredSuffixes>
239 </RequiredSuffixes>
237 </NamingRule>
240 </NamingRule>
238 <NamingRule Name="Exceptions" AffectedEntity="CustomExceptions" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
241 <NamingRule Name="Exceptions" AffectedEntity="CustomExceptions" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
239 <RequiredSuffixes>
242 <RequiredSuffixes>
240 <String>Exception</String>
243 <String>Exception</String>
241 </RequiredSuffixes>
244 </RequiredSuffixes>
242 </NamingRule>
245 </NamingRule>
243 <NamingRule Name="Methods" AffectedEntity="Methods" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
246 <NamingRule Name="Methods" AffectedEntity="Methods" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
244 <NamingRule Name="Static Readonly Fields" AffectedEntity="ReadonlyField" VisibilityMask="Internal, Protected, Public" NamingStyle="CamelCase" IncludeInstanceMembers="False" IncludeStaticEntities="True" />
247 <NamingRule Name="Static Readonly Fields" AffectedEntity="ReadonlyField" VisibilityMask="Internal, Protected, Public" NamingStyle="CamelCase" IncludeInstanceMembers="False" IncludeStaticEntities="True" />
245 <NamingRule Name="Fields (Non Private)" AffectedEntity="Field" VisibilityMask="Internal, Public" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
248 <NamingRule Name="Fields (Non Private)" AffectedEntity="Field" VisibilityMask="Internal, Public" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
246 <NamingRule Name="ReadOnly Fields (Non Private)" AffectedEntity="ReadonlyField" VisibilityMask="Internal, Public" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False" />
249 <NamingRule Name="ReadOnly Fields (Non Private)" AffectedEntity="ReadonlyField" VisibilityMask="Internal, Public" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False" />
247 <NamingRule Name="Fields (Private)" AffectedEntity="Field, ReadonlyField" VisibilityMask="Private, Protected" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False">
250 <NamingRule Name="Fields (Private)" AffectedEntity="Field, ReadonlyField" VisibilityMask="Private, Protected" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False">
248 <RequiredPrefixes>
251 <RequiredPrefixes>
249 <String>m_</String>
252 <String>m_</String>
250 </RequiredPrefixes>
253 </RequiredPrefixes>
251 </NamingRule>
254 </NamingRule>
252 <NamingRule Name="Static Fields (Private)" AffectedEntity="Field" VisibilityMask="Private" NamingStyle="CamelCase" IncludeInstanceMembers="False" IncludeStaticEntities="True">
255 <NamingRule Name="Static Fields (Private)" AffectedEntity="Field" VisibilityMask="Private" NamingStyle="CamelCase" IncludeInstanceMembers="False" IncludeStaticEntities="True">
253 <RequiredPrefixes>
256 <RequiredPrefixes>
254 <String>_</String>
257 <String>_</String>
255 </RequiredPrefixes>
258 </RequiredPrefixes>
256 </NamingRule>
259 </NamingRule>
257 <NamingRule Name="ReadOnly Fields (Private)" AffectedEntity="ReadonlyField" VisibilityMask="Private, Protected" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False">
260 <NamingRule Name="ReadOnly Fields (Private)" AffectedEntity="ReadonlyField" VisibilityMask="Private, Protected" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False">
258 <RequiredPrefixes>
261 <RequiredPrefixes>
259 <String>m_</String>
262 <String>m_</String>
260 </RequiredPrefixes>
263 </RequiredPrefixes>
261 </NamingRule>
264 </NamingRule>
262 <NamingRule Name="Constant Fields" AffectedEntity="ConstantField" VisibilityMask="VisibilityMask" NamingStyle="AllUpper" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
265 <NamingRule Name="Constant Fields" AffectedEntity="ConstantField" VisibilityMask="VisibilityMask" NamingStyle="AllUpper" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
263 <NamingRule Name="Properties" AffectedEntity="Property" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
266 <NamingRule Name="Properties" AffectedEntity="Property" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
264 <NamingRule Name="Events" AffectedEntity="Event" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
267 <NamingRule Name="Events" AffectedEntity="Event" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
265 <NamingRule Name="Enum Members" AffectedEntity="EnumMember" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
268 <NamingRule Name="Enum Members" AffectedEntity="EnumMember" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
266 <NamingRule Name="Parameters" AffectedEntity="Parameter, LocalVariable" VisibilityMask="VisibilityMask" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
269 <NamingRule Name="Parameters" AffectedEntity="Parameter, LocalVariable" VisibilityMask="VisibilityMask" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
267 <NamingRule Name="Type Parameters" AffectedEntity="TypeParameter" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
270 <NamingRule Name="Type Parameters" AffectedEntity="TypeParameter" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
268 <RequiredPrefixes>
271 <RequiredPrefixes>
269 <String>T</String>
272 <String>T</String>
270 </RequiredPrefixes>
273 </RequiredPrefixes>
271 </NamingRule>
274 </NamingRule>
272 </Rules>
275 </Rules>
273 </NameConventionPolicy>
276 </NameConventionPolicy>
274 </Policies>
277 </Policies>
275 </Properties>
278 </Properties>
276 </MonoDevelop>
279 </MonoDevelop>
277 </ProjectExtensions>
280 </ProjectExtensions>
278 <ItemGroup />
281 <ItemGroup />
279 </Project> No newline at end of file
282 </Project>
@@ -1,626 +1,626
1 using Implab.Formats.Json;
1 using Implab.Formats.Json;
2 using System;
2 using System;
3 using System.Collections.Generic;
3 using System.Collections.Generic;
4 using System.Globalization;
4 using System.Globalization;
5 using System.Linq;
5 using System.Linq;
6 using System.Xml;
6 using System.Xml;
7
7
8 namespace Implab.Xml {
8 namespace Implab.Xml {
9 public class JsonXmlReader : XmlReader {
9 public class JsonXmlReader : XmlReader {
10 struct JsonContext {
10 struct JsonContext {
11 public string localName;
11 public string localName;
12 public bool skip;
12 public bool skip;
13 }
13 }
14
14
15 JsonParser m_parser;
15 JsonReader m_parser;
16 JsonXmlReaderOptions m_options;
16 JsonXmlReaderOptions m_options;
17 JsonXmlReaderPosition m_position = JsonXmlReaderPosition.Initial;
17 JsonXmlReaderPosition m_position = JsonXmlReaderPosition.Initial;
18 XmlNameTable m_nameTable;
18 XmlNameTable m_nameTable;
19
19
20 readonly string m_jsonRootName;
20 readonly string m_jsonRootName;
21 readonly string m_jsonNamespace;
21 readonly string m_jsonNamespace;
22 readonly string m_jsonPrefix;
22 readonly string m_jsonPrefix;
23 readonly bool m_jsonFlattenArrays;
23 readonly bool m_jsonFlattenArrays;
24 readonly string m_jsonArrayItemName;
24 readonly string m_jsonArrayItemName;
25
25
26 string m_jsonLocalName;
26 string m_jsonLocalName;
27 string m_jsonValueName;
27 string m_jsonValueName;
28 bool m_jsonSkip; // indicates wheather to generate closing tag for objects or arrays
28 bool m_jsonSkip; // indicates wheather to generate closing tag for objects or arrays
29
29
30 readonly Stack<JsonContext> m_jsonNameStack = new Stack<JsonContext>();
30 readonly Stack<JsonContext> m_jsonNameStack = new Stack<JsonContext>();
31
31
32 XmlQualifiedName m_elementQName;
32 XmlQualifiedName m_elementQName;
33 string m_elementPrefix;
33 string m_elementPrefix;
34 int m_elementDepth;
34 int m_elementDepth;
35 bool m_elementIsEmpty;
35 bool m_elementIsEmpty;
36
36
37 XmlQualifiedName m_qName;
37 XmlQualifiedName m_qName;
38 string m_prefix;
38 string m_prefix;
39 int m_xmlDepth;
39 int m_xmlDepth;
40
40
41 XmlSimpleAttribute[] m_attributes;
41 XmlSimpleAttribute[] m_attributes;
42 object m_value;
42 object m_value;
43 bool m_isEmpty;
43 bool m_isEmpty;
44
44
45 XmlNodeType m_nodeType = XmlNodeType.None;
45 XmlNodeType m_nodeType = XmlNodeType.None;
46
46
47 bool m_isAttribute; // indicates that we are reading attribute nodes
47 bool m_isAttribute; // indicates that we are reading attribute nodes
48 int m_currentAttribute;
48 int m_currentAttribute;
49 bool m_currentAttributeRead;
49 bool m_currentAttributeRead;
50
50
51
51
52 XmlNameContext m_context;
52 XmlNameContext m_context;
53
53
54 readonly string m_xmlnsPrefix;
54 readonly string m_xmlnsPrefix;
55 readonly string m_xmlnsNamespace;
55 readonly string m_xmlnsNamespace;
56 readonly string m_xsiPrefix;
56 readonly string m_xsiPrefix;
57 readonly string m_xsiNamespace;
57 readonly string m_xsiNamespace;
58
58
59
59
60 public JsonXmlReader(JsonParser parser, JsonXmlReaderOptions options) {
60 public JsonXmlReader(JsonReader parser, JsonXmlReaderOptions options) {
61 Safe.ArgumentNotNull(parser, nameof(parser));
61 Safe.ArgumentNotNull(parser, nameof(parser));
62 m_parser = parser;
62 m_parser = parser;
63
63
64 m_options = options ?? new JsonXmlReaderOptions();
64 m_options = options ?? new JsonXmlReaderOptions();
65
65
66 m_jsonFlattenArrays = m_options.FlattenArrays;
66 m_jsonFlattenArrays = m_options.FlattenArrays;
67 m_nameTable = m_options.NameTable ?? new NameTable();
67 m_nameTable = m_options.NameTable ?? new NameTable();
68
68
69 m_jsonRootName = m_nameTable.Add(string.IsNullOrEmpty(m_options.RootName) ? "data" : m_options.RootName);
69 m_jsonRootName = m_nameTable.Add(string.IsNullOrEmpty(m_options.RootName) ? "data" : m_options.RootName);
70 m_jsonArrayItemName = m_nameTable.Add(string.IsNullOrEmpty(m_options.ArrayItemName) ? "item" : m_options.ArrayItemName);
70 m_jsonArrayItemName = m_nameTable.Add(string.IsNullOrEmpty(m_options.ArrayItemName) ? "item" : m_options.ArrayItemName);
71 m_jsonNamespace = m_nameTable.Add(m_options.NamespaceUri ?? string.Empty);
71 m_jsonNamespace = m_nameTable.Add(m_options.NamespaceUri ?? string.Empty);
72 m_jsonPrefix = m_nameTable.Add(m_options.NodesPrefix ?? string.Empty);
72 m_jsonPrefix = m_nameTable.Add(m_options.NodesPrefix ?? string.Empty);
73 m_xmlnsPrefix = m_nameTable.Add(XmlNameContext.XmlnsPrefix);
73 m_xmlnsPrefix = m_nameTable.Add(XmlNameContext.XmlnsPrefix);
74 m_xmlnsNamespace = m_nameTable.Add(XmlNameContext.XmlnsNamespace);
74 m_xmlnsNamespace = m_nameTable.Add(XmlNameContext.XmlnsNamespace);
75 m_xsiPrefix = m_nameTable.Add(XmlNameContext.XsiPrefix);
75 m_xsiPrefix = m_nameTable.Add(XmlNameContext.XsiPrefix);
76 m_xsiNamespace = m_nameTable.Add(XmlNameContext.XsiNamespace);
76 m_xsiNamespace = m_nameTable.Add(XmlNameContext.XsiNamespace);
77
77
78 // TODO validate m_jsonRootName, m_jsonArrayItemName
78 // TODO validate m_jsonRootName, m_jsonArrayItemName
79
79
80 m_context = new XmlNameContext(null);
80 m_context = new XmlNameContext(null, 0);
81 }
81 }
82
82
83 public override int AttributeCount {
83 public override int AttributeCount {
84 get {
84 get {
85 return m_attributes == null ? 0 : m_attributes.Length;
85 return m_attributes == null ? 0 : m_attributes.Length;
86 }
86 }
87 }
87 }
88
88
89 public override string BaseURI {
89 public override string BaseURI {
90 get {
90 get {
91 return string.Empty;
91 return string.Empty;
92 }
92 }
93 }
93 }
94
94
95 public override int Depth {
95 public override int Depth {
96 get {
96 get {
97 return m_xmlDepth;
97 return m_xmlDepth;
98 }
98 }
99 }
99 }
100
100
101 public override bool EOF {
101 public override bool EOF {
102 get {
102 get {
103 return m_position == JsonXmlReaderPosition.Eof;
103 return m_position == JsonXmlReaderPosition.Eof;
104 }
104 }
105 }
105 }
106
106
107 public override bool IsEmptyElement {
107 public override bool IsEmptyElement {
108 get { return m_isEmpty; }
108 get { return m_isEmpty; }
109 }
109 }
110
110
111
111
112 public override string LocalName {
112 public override string LocalName {
113 get {
113 get {
114 return m_qName.Name;
114 return m_qName.Name;
115 }
115 }
116 }
116 }
117
117
118 public override string NamespaceURI {
118 public override string NamespaceURI {
119 get {
119 get {
120 return m_qName.Namespace;
120 return m_qName.Namespace;
121 }
121 }
122 }
122 }
123
123
124 public override XmlNameTable NameTable {
124 public override XmlNameTable NameTable {
125 get {
125 get {
126 return m_nameTable;
126 return m_nameTable;
127 }
127 }
128 }
128 }
129
129
130 public override XmlNodeType NodeType {
130 public override XmlNodeType NodeType {
131 get {
131 get {
132 return m_nodeType;
132 return m_nodeType;
133 }
133 }
134 }
134 }
135
135
136 public override string Prefix {
136 public override string Prefix {
137 get {
137 get {
138 return m_prefix;
138 return m_prefix;
139 }
139 }
140 }
140 }
141
141
142 public override ReadState ReadState {
142 public override ReadState ReadState {
143 get {
143 get {
144 switch (m_position) {
144 switch (m_position) {
145 case JsonXmlReaderPosition.Initial:
145 case JsonXmlReaderPosition.Initial:
146 return ReadState.Initial;
146 return ReadState.Initial;
147 case JsonXmlReaderPosition.Eof:
147 case JsonXmlReaderPosition.Eof:
148 return ReadState.EndOfFile;
148 return ReadState.EndOfFile;
149 case JsonXmlReaderPosition.Closed:
149 case JsonXmlReaderPosition.Closed:
150 return ReadState.Closed;
150 return ReadState.Closed;
151 case JsonXmlReaderPosition.Error:
151 case JsonXmlReaderPosition.Error:
152 return ReadState.Error;
152 return ReadState.Error;
153 default:
153 default:
154 return ReadState.Interactive;
154 return ReadState.Interactive;
155 };
155 };
156 }
156 }
157 }
157 }
158
158
159 public override string Value {
159 public override string Value {
160 get {
160 get {
161 return ConvertValueToString(m_value);
161 return ConvertValueToString(m_value);
162 }
162 }
163 }
163 }
164
164
165 static string ConvertValueToString(object value) {
165 static string ConvertValueToString(object value) {
166 if (value == null)
166 if (value == null)
167 return string.Empty;
167 return string.Empty;
168
168
169 switch (Convert.GetTypeCode(value)) {
169 switch (Convert.GetTypeCode(value)) {
170 case TypeCode.Double:
170 case TypeCode.Double:
171 return ((double)value).ToString(CultureInfo.InvariantCulture);
171 return ((double)value).ToString(CultureInfo.InvariantCulture);
172 case TypeCode.String:
172 case TypeCode.String:
173 return (string)value;
173 return (string)value;
174 case TypeCode.Boolean:
174 case TypeCode.Boolean:
175 return (bool)value ? "true" : "false";
175 return (bool)value ? "true" : "false";
176 default:
176 default:
177 return value.ToString();
177 return value.ToString();
178 }
178 }
179 }
179 }
180
180
181 public override string GetAttribute(int i) {
181 public override string GetAttribute(int i) {
182 Safe.ArgumentInRange(i, 0, AttributeCount - 1, nameof(i));
182 Safe.ArgumentInRange(i, 0, AttributeCount - 1, nameof(i));
183 return ConvertValueToString(m_attributes[i].Value);
183 return ConvertValueToString(m_attributes[i].Value);
184 }
184 }
185
185
186 public override string GetAttribute(string name) {
186 public override string GetAttribute(string name) {
187 if (m_attributes == null)
187 if (m_attributes == null)
188 return null;
188 return null;
189 var qName = m_context.Resolve(name);
189 var qName = m_context.Resolve(name);
190 var attr = Array.Find(m_attributes, x => x.QName == qName);
190 var attr = Array.Find(m_attributes, x => x.QName == qName);
191 var value = ConvertValueToString(attr?.Value);
191 var value = ConvertValueToString(attr?.Value);
192 return value == string.Empty ? null : value;
192 return value == string.Empty ? null : value;
193 }
193 }
194
194
195 public override string GetAttribute(string name, string namespaceURI) {
195 public override string GetAttribute(string name, string namespaceURI) {
196 if (m_attributes == null)
196 if (m_attributes == null)
197 return null;
197 return null;
198 var qName = new XmlQualifiedName(name, namespaceURI);
198 var qName = new XmlQualifiedName(name, namespaceURI);
199 var attr = Array.Find(m_attributes, x => x.QName == qName);
199 var attr = Array.Find(m_attributes, x => x.QName == qName);
200 var value = ConvertValueToString(attr?.Value);
200 var value = ConvertValueToString(attr?.Value);
201 return value == string.Empty ? null : value;
201 return value == string.Empty ? null : value;
202 }
202 }
203
203
204 public override string LookupNamespace(string prefix) {
204 public override string LookupNamespace(string prefix) {
205 return m_context.ResolvePrefix(prefix);
205 return m_context.ResolvePrefix(prefix);
206 }
206 }
207
207
208 public override bool MoveToAttribute(string name) {
208 public override bool MoveToAttribute(string name) {
209 if (m_attributes == null || m_attributes.Length == 0)
209 if (m_attributes == null || m_attributes.Length == 0)
210 return false;
210 return false;
211
211
212 var qName = m_context.Resolve(name);
212 var qName = m_context.Resolve(name);
213 var index = Array.FindIndex(m_attributes, x => x.QName == qName);
213 var index = Array.FindIndex(m_attributes, x => x.QName == qName);
214 if (index >= 0) {
214 if (index >= 0) {
215 MoveToAttributeImpl(index);
215 MoveToAttributeImpl(index);
216 return true;
216 return true;
217 }
217 }
218 return false;
218 return false;
219 }
219 }
220
220
221 public override bool MoveToAttribute(string name, string ns) {
221 public override bool MoveToAttribute(string name, string ns) {
222 if (m_attributes == null || m_attributes.Length == 0)
222 if (m_attributes == null || m_attributes.Length == 0)
223 return false;
223 return false;
224
224
225 var qName = m_context.Resolve(name);
225 var qName = m_context.Resolve(name);
226 var index = Array.FindIndex(m_attributes, x => x.QName == qName);
226 var index = Array.FindIndex(m_attributes, x => x.QName == qName);
227 if (index >= 0) {
227 if (index >= 0) {
228 MoveToAttributeImpl(index);
228 MoveToAttributeImpl(index);
229 return true;
229 return true;
230 }
230 }
231 return false;
231 return false;
232 }
232 }
233
233
234 void MoveToAttributeImpl(int i) {
234 void MoveToAttributeImpl(int i) {
235 if (!m_isAttribute) {
235 if (!m_isAttribute) {
236 m_elementQName = m_qName;
236 m_elementQName = m_qName;
237 m_elementDepth = m_xmlDepth;
237 m_elementDepth = m_xmlDepth;
238 m_elementPrefix = m_prefix;
238 m_elementPrefix = m_prefix;
239 m_elementIsEmpty = m_isEmpty;
239 m_elementIsEmpty = m_isEmpty;
240 m_isAttribute = true;
240 m_isAttribute = true;
241 }
241 }
242
242
243 var attr = m_attributes[i];
243 var attr = m_attributes[i];
244
244
245
245
246 m_currentAttribute = i;
246 m_currentAttribute = i;
247 m_currentAttributeRead = false;
247 m_currentAttributeRead = false;
248 m_nodeType = XmlNodeType.Attribute;
248 m_nodeType = XmlNodeType.Attribute;
249
249
250 m_xmlDepth = m_elementDepth + 1;
250 m_xmlDepth = m_elementDepth + 1;
251 m_qName = attr.QName;
251 m_qName = attr.QName;
252 m_value = attr.Value;
252 m_value = attr.Value;
253 m_prefix = attr.Prefix;
253 m_prefix = attr.Prefix;
254 }
254 }
255
255
256 public override bool MoveToElement() {
256 public override bool MoveToElement() {
257 if (m_isAttribute) {
257 if (m_isAttribute) {
258 m_value = null;
258 m_value = null;
259 m_nodeType = XmlNodeType.Element;
259 m_nodeType = XmlNodeType.Element;
260 m_xmlDepth = m_elementDepth;
260 m_xmlDepth = m_elementDepth;
261 m_prefix = m_elementPrefix;
261 m_prefix = m_elementPrefix;
262 m_qName = m_elementQName;
262 m_qName = m_elementQName;
263 m_isEmpty = m_elementIsEmpty;
263 m_isEmpty = m_elementIsEmpty;
264 m_isAttribute = false;
264 m_isAttribute = false;
265 return true;
265 return true;
266 }
266 }
267 return false;
267 return false;
268 }
268 }
269
269
270 public override bool MoveToFirstAttribute() {
270 public override bool MoveToFirstAttribute() {
271 if (m_attributes != null && m_attributes.Length > 0) {
271 if (m_attributes != null && m_attributes.Length > 0) {
272 MoveToAttributeImpl(0);
272 MoveToAttributeImpl(0);
273 return true;
273 return true;
274 }
274 }
275 return false;
275 return false;
276 }
276 }
277
277
278 public override bool MoveToNextAttribute() {
278 public override bool MoveToNextAttribute() {
279 if (m_isAttribute) {
279 if (m_isAttribute) {
280 var next = m_currentAttribute + 1;
280 var next = m_currentAttribute + 1;
281 if (next < AttributeCount) {
281 if (next < AttributeCount) {
282 MoveToAttributeImpl(next);
282 MoveToAttributeImpl(next);
283 return true;
283 return true;
284 }
284 }
285 return false;
285 return false;
286 } else {
286 } else {
287 return MoveToFirstAttribute();
287 return MoveToFirstAttribute();
288 }
288 }
289
289
290 }
290 }
291
291
292 public override bool ReadAttributeValue() {
292 public override bool ReadAttributeValue() {
293 if (!m_isAttribute || m_currentAttributeRead)
293 if (!m_isAttribute || m_currentAttributeRead)
294 return false;
294 return false;
295
295
296 ValueNode(m_attributes[m_currentAttribute].Value);
296 ValueNode(m_attributes[m_currentAttribute].Value);
297 m_currentAttributeRead = true;
297 m_currentAttributeRead = true;
298 return true;
298 return true;
299 }
299 }
300
300
301 public override void ResolveEntity() {
301 public override void ResolveEntity() {
302 /* do nothing */
302 /* do nothing */
303 }
303 }
304
304
305 /// <summary>
305 /// <summary>
306 /// Determines do we need to increase depth after the current node
306 /// Determines do we need to increase depth after the current node
307 /// </summary>
307 /// </summary>
308 /// <returns></returns>
308 /// <returns></returns>
309 public bool IsSibling() {
309 public bool IsSibling() {
310 switch (m_nodeType) {
310 switch (m_nodeType) {
311 case XmlNodeType.None: // start document
311 case XmlNodeType.None: // start document
312 case XmlNodeType.Attribute: // after attribute only it's content can be iterated with ReadAttributeValue method
312 case XmlNodeType.Attribute: // after attribute only it's content can be iterated with ReadAttributeValue method
313 return false;
313 return false;
314 case XmlNodeType.Element:
314 case XmlNodeType.Element:
315 // if the elemnt is empty the next element will be it's sibling
315 // if the elemnt is empty the next element will be it's sibling
316 return m_isEmpty;
316 return m_isEmpty;
317
318 case XmlNodeType.Document:
319 case XmlNodeType.DocumentFragment:
320 case XmlNodeType.Entity:
321 case XmlNodeType.Text:
322 case XmlNodeType.CDATA:
323 case XmlNodeType.EntityReference:
324 case XmlNodeType.ProcessingInstruction:
325 case XmlNodeType.Comment:
326 case XmlNodeType.DocumentType:
327 case XmlNodeType.Notation:
328 case XmlNodeType.Whitespace:
329 case XmlNodeType.SignificantWhitespace:
330 case XmlNodeType.EndElement:
331 case XmlNodeType.EndEntity:
332 case XmlNodeType.XmlDeclaration:
333 default:
317 default:
334 return true;
318 return true;
335 }
319 }
336 }
320 }
337
321
338 void ValueNode(object value) {
322 void ValueNode(object value) {
339 if (!IsSibling()) // the node is nested
323 if (!IsSibling()) // the node is nested
340 m_xmlDepth++;
324 m_xmlDepth++;
341
325
342 m_qName = XmlQualifiedName.Empty;
326 m_qName = XmlQualifiedName.Empty;
343 m_nodeType = XmlNodeType.Text;
327 m_nodeType = XmlNodeType.Text;
344 m_prefix = string.Empty;
328 m_prefix = string.Empty;
345 m_value = value;
329 m_value = value;
346 m_isEmpty = false;
330 m_isEmpty = false;
347 m_attributes = null;
331 m_attributes = null;
348 }
332 }
349
333
350 void ElementNode(string name, string ns, XmlSimpleAttribute[] attrs, bool empty) {
334 void ElementNode(string name, string ns, XmlSimpleAttribute[] attrs, bool empty) {
351 if (!IsSibling()) // the node is nested
335 if (!IsSibling()) // the node is nested
352 m_xmlDepth++;
336 m_xmlDepth++;
353
337
354 m_context = new XmlNameContext(m_context);
338 var context = m_context;
355 List<XmlSimpleAttribute> definedAttrs = null;
339 List<XmlSimpleAttribute> definedAttrs = null;
356
340
357 // define new namespaces
341 // define new namespaces
358 if (attrs != null) {
342 if (attrs != null) {
359 foreach (var attr in attrs) {
343 foreach (var attr in attrs) {
360 if (attr.QName.Name == "xmlns") {
344 if (attr.QName.Name == "xmlns") {
361 m_context.DefinePrefix(ConvertValueToString(attr.Value), string.Empty);
345 if (context == m_context)
346 context = new XmlNameContext(m_context, m_xmlDepth);
347 context.DefinePrefix(ConvertValueToString(attr.Value), string.Empty);
362 } else if (attr.Prefix == m_xmlnsPrefix) {
348 } else if (attr.Prefix == m_xmlnsPrefix) {
363 m_context.DefinePrefix(ConvertValueToString(attr.Value), attr.QName.Name);
349 if (context == m_context)
350 context = new XmlNameContext(m_context, m_xmlDepth);
351 context.DefinePrefix(ConvertValueToString(attr.Value), attr.QName.Name);
364 } else {
352 } else {
365 string attrPrefix;
353 string attrPrefix;
366 if (string.IsNullOrEmpty(attr.QName.Namespace))
354 if (string.IsNullOrEmpty(attr.QName.Namespace))
367 continue;
355 continue;
368
356
369 // auto-define prefixes
357 // auto-define prefixes
370 if (!m_context.LookupNamespacePrefix(attr.QName.Namespace, out attrPrefix) || string.IsNullOrEmpty(attrPrefix)) {
358 if (!context.LookupNamespacePrefix(attr.QName.Namespace, out attrPrefix) || string.IsNullOrEmpty(attrPrefix)) {
371 // new namespace prefix added
359 // new namespace prefix added
372 attrPrefix = m_context.CreateNamespacePrefix(attr.QName.Namespace);
360 attrPrefix = context.CreateNamespacePrefix(attr.QName.Namespace);
373 attr.Prefix = attrPrefix;
361 attr.Prefix = attrPrefix;
374
362
375 if (definedAttrs == null)
363 if (definedAttrs == null)
376 definedAttrs = new List<XmlSimpleAttribute>();
364 definedAttrs = new List<XmlSimpleAttribute>();
377
365
378 definedAttrs.Add(new XmlSimpleAttribute(attrPrefix, m_xmlnsNamespace, m_xmlnsPrefix, attr.QName.Namespace));
366 definedAttrs.Add(new XmlSimpleAttribute(attrPrefix, m_xmlnsNamespace, m_xmlnsPrefix, attr.QName.Namespace));
379 }
367 }
380 }
368 }
381 }
369 }
382 }
370 }
383
371
384 string p;
372 string p;
385 // auto-define prefixes
373 // auto-define prefixes
386 if (!m_context.LookupNamespacePrefix(ns, out p)) {
374 if (!context.LookupNamespacePrefix(ns, out p)) {
387 p = m_context.CreateNamespacePrefix(ns);
375 if (context == m_context)
376 context = new XmlNameContext(m_context, m_xmlDepth);
377 p = context.CreateNamespacePrefix(ns);
388 if (definedAttrs == null)
378 if (definedAttrs == null)
389 definedAttrs = new List<XmlSimpleAttribute>();
379 definedAttrs = new List<XmlSimpleAttribute>();
390
380
391 definedAttrs.Add(new XmlSimpleAttribute(p, m_xmlnsNamespace, m_xmlnsPrefix, ns));
381 definedAttrs.Add(new XmlSimpleAttribute(p, m_xmlnsNamespace, m_xmlnsPrefix, ns));
392 }
382 }
393
383
394 if (definedAttrs != null) {
384 if (definedAttrs != null) {
395 if (attrs != null)
385 if (attrs != null)
396 definedAttrs.AddRange(attrs);
386 definedAttrs.AddRange(attrs);
397 attrs = definedAttrs.ToArray();
387 attrs = definedAttrs.ToArray();
398 }
388 }
399
389
390 if (!empty)
391 m_context = context;
392
400 m_nodeType = XmlNodeType.Element;
393 m_nodeType = XmlNodeType.Element;
401 m_qName = new XmlQualifiedName(name, ns);
394 m_qName = new XmlQualifiedName(name, ns);
402 m_prefix = p;
395 m_prefix = p;
403 m_value = null;
396 m_value = null;
404 m_isEmpty = empty;
397 m_isEmpty = empty;
405 m_attributes = attrs;
398 m_attributes = attrs;
406 }
399 }
407
400
408 void EndElementNode(string name, string ns) {
401 void EndElementNode(string name, string ns) {
409 if (IsSibling()) // closing the element which has children
402 if (IsSibling()) {
403 // closing the element which has children
410 m_xmlDepth--;
404 m_xmlDepth--;
405 }
411
406
412 string p;
407 string p;
413 if (!m_context.LookupNamespacePrefix(ns, out p))
408 if (!m_context.LookupNamespacePrefix(ns, out p))
414 throw new Exception($"Failed to lookup namespace '{ns}'");
409 throw new Exception($"Failed to lookup namespace '{ns}'");
415
410
411 if (m_context.Depth == m_xmlDepth)
416 m_context = m_context.ParentContext;
412 m_context = m_context.ParentContext;
413
417 m_nodeType = XmlNodeType.EndElement;
414 m_nodeType = XmlNodeType.EndElement;
418 m_prefix = p;
415 m_prefix = p;
419 m_qName = new XmlQualifiedName(name, ns);
416 m_qName = new XmlQualifiedName(name, ns);
420 m_value = null;
417 m_value = null;
421 m_attributes = null;
418 m_attributes = null;
422 m_isEmpty = false;
419 m_isEmpty = false;
423 }
420 }
424
421
425 void XmlDeclaration() {
422 void XmlDeclaration() {
426 if (!IsSibling()) // the node is nested
423 if (!IsSibling()) // the node is nested
427 m_xmlDepth++;
424 m_xmlDepth++;
428 m_nodeType = XmlNodeType.XmlDeclaration;
425 m_nodeType = XmlNodeType.XmlDeclaration;
429 m_qName = new XmlQualifiedName("xml");
426 m_qName = new XmlQualifiedName("xml");
430 m_value = "version='1.0'";
427 m_value = "version='1.0'";
431 m_prefix = string.Empty;
428 m_prefix = string.Empty;
432 m_attributes = null;
429 m_attributes = null;
433 m_isEmpty = false;
430 m_isEmpty = false;
434 }
431 }
435
432
436 public override bool Read() {
433 public override bool Read() {
437 try {
434 try {
438 string elementName;
435 string elementName;
439 XmlSimpleAttribute[] elementAttrs = null;
436 XmlSimpleAttribute[] elementAttrs = null;
440 MoveToElement();
437 MoveToElement();
441
438
442 switch (m_position) {
439 switch (m_position) {
443 case JsonXmlReaderPosition.Initial:
440 case JsonXmlReaderPosition.Initial:
444 m_jsonLocalName = m_jsonRootName;
441 m_jsonLocalName = m_jsonRootName;
445 m_jsonSkip = false;
442 m_jsonSkip = false;
446 XmlDeclaration();
443 XmlDeclaration();
447 m_position = JsonXmlReaderPosition.Declaration;
444 m_position = JsonXmlReaderPosition.Declaration;
448 return true;
445 return true;
449 case JsonXmlReaderPosition.Declaration:
446 case JsonXmlReaderPosition.Declaration:
450 elementAttrs = new[] {
447 elementAttrs = new[] {
451 new XmlSimpleAttribute(m_xsiPrefix, m_xmlnsNamespace, m_xmlnsPrefix, m_xsiNamespace),
448 new XmlSimpleAttribute(m_xsiPrefix, m_xmlnsNamespace, m_xmlnsPrefix, m_xsiNamespace),
452 string.IsNullOrEmpty(m_jsonPrefix) ?
449 string.IsNullOrEmpty(m_jsonPrefix) ?
453 new XmlSimpleAttribute(m_xmlnsPrefix, string.Empty, string.Empty, m_jsonNamespace) :
450 new XmlSimpleAttribute(m_xmlnsPrefix, string.Empty, string.Empty, m_jsonNamespace) :
454 new XmlSimpleAttribute(m_jsonPrefix, m_xmlnsNamespace, m_xmlnsPrefix, m_jsonNamespace)
451 new XmlSimpleAttribute(m_jsonPrefix, m_xmlnsNamespace, m_xmlnsPrefix, m_jsonNamespace)
455 };
452 };
456 break;
453 break;
457 case JsonXmlReaderPosition.ValueElement:
454 case JsonXmlReaderPosition.ValueElement:
458 if (!m_isEmpty) {
455 if (!m_isEmpty) {
456 if (m_parser.ElementValue != null && !m_parser.ElementValue.Equals(string.Empty))
459 ValueNode(m_parser.ElementValue);
457 ValueNode(m_parser.ElementValue);
458 else
459 goto case JsonXmlReaderPosition.ValueContent;
460 m_position = JsonXmlReaderPosition.ValueContent;
460 m_position = JsonXmlReaderPosition.ValueContent;
461 return true;
461 return true;
462 } else {
462 } else {
463 m_position = JsonXmlReaderPosition.ValueEndElement;
463 m_position = JsonXmlReaderPosition.ValueEndElement;
464 break;
464 break;
465 }
465 }
466 case JsonXmlReaderPosition.ValueContent:
466 case JsonXmlReaderPosition.ValueContent:
467 EndElementNode(m_jsonValueName, m_jsonNamespace);
467 EndElementNode(m_jsonValueName, m_jsonNamespace);
468 m_position = JsonXmlReaderPosition.ValueEndElement;
468 m_position = JsonXmlReaderPosition.ValueEndElement;
469 return true;
469 return true;
470 case JsonXmlReaderPosition.Eof:
470 case JsonXmlReaderPosition.Eof:
471 case JsonXmlReaderPosition.Closed:
471 case JsonXmlReaderPosition.Closed:
472 case JsonXmlReaderPosition.Error:
472 case JsonXmlReaderPosition.Error:
473 return false;
473 return false;
474 }
474 }
475
475
476 while (m_parser.Read()) {
476 while (m_parser.Read()) {
477 var jsonName = m_nameTable.Add(m_parser.ElementName);
477 var jsonName = m_nameTable.Add(m_parser.ElementName);
478
478
479 switch (m_parser.ElementType) {
479 switch (m_parser.ElementType) {
480 case JsonElementType.BeginObject:
480 case JsonElementType.BeginObject:
481 if (!EnterJsonObject(jsonName, out elementName))
481 if (!EnterJsonObject(jsonName, out elementName))
482 continue;
482 continue;
483
483
484 m_position = JsonXmlReaderPosition.BeginObject;
484 m_position = JsonXmlReaderPosition.BeginObject;
485 ElementNode(elementName, m_jsonNamespace, elementAttrs, false);
485 ElementNode(elementName, m_jsonNamespace, elementAttrs, false);
486 break;
486 break;
487 case JsonElementType.EndObject:
487 case JsonElementType.EndObject:
488 if (!LeaveJsonScope(out elementName))
488 if (!LeaveJsonScope(out elementName))
489 continue;
489 continue;
490
490
491 m_position = JsonXmlReaderPosition.EndObject;
491 m_position = JsonXmlReaderPosition.EndObject;
492 EndElementNode(elementName, m_jsonNamespace);
492 EndElementNode(elementName, m_jsonNamespace);
493 break;
493 break;
494 case JsonElementType.BeginArray:
494 case JsonElementType.BeginArray:
495 if (!EnterJsonArray(jsonName, out elementName))
495 if (!EnterJsonArray(jsonName, out elementName))
496 continue;
496 continue;
497
497
498 m_position = JsonXmlReaderPosition.BeginArray;
498 m_position = JsonXmlReaderPosition.BeginArray;
499 ElementNode(elementName, m_jsonNamespace, elementAttrs, false);
499 ElementNode(elementName, m_jsonNamespace, elementAttrs, false);
500 break;
500 break;
501 case JsonElementType.EndArray:
501 case JsonElementType.EndArray:
502 if (!LeaveJsonScope(out elementName))
502 if (!LeaveJsonScope(out elementName))
503 continue;
503 continue;
504
504
505 m_position = JsonXmlReaderPosition.EndArray;
505 m_position = JsonXmlReaderPosition.EndArray;
506 EndElementNode(elementName, m_jsonNamespace);
506 EndElementNode(elementName, m_jsonNamespace);
507 break;
507 break;
508 case JsonElementType.Value:
508 case JsonElementType.Value:
509 if (!VisitJsonValue(jsonName, out m_jsonValueName))
509 if (!VisitJsonValue(jsonName, out m_jsonValueName))
510 continue;
510 continue;
511
511
512 m_position = JsonXmlReaderPosition.ValueElement;
512 m_position = JsonXmlReaderPosition.ValueElement;
513 if (m_parser.ElementValue == null)
513 if (m_parser.ElementValue == null)
514 // generate empty element with xsi:nil="true" attribute
514 // generate empty element with xsi:nil="true" attribute
515 ElementNode(
515 ElementNode(
516 m_jsonValueName,
516 m_jsonValueName,
517 m_jsonNamespace,
517 m_jsonNamespace,
518 new[] {
518 new[] {
519 new XmlSimpleAttribute("nil", m_xsiNamespace, m_xsiPrefix, true)
519 new XmlSimpleAttribute("nil", m_xsiNamespace, m_xsiPrefix, true)
520 },
520 },
521 true
521 true
522 );
522 );
523 else
523 else
524 ElementNode(m_jsonValueName, m_jsonNamespace, elementAttrs, m_parser.ElementValue as string == string.Empty);
524 ElementNode(m_jsonValueName, m_jsonNamespace, elementAttrs, m_parser.ElementValue.Equals(string.Empty));
525 break;
525 break;
526 default:
526 default:
527 throw new Exception($"Unexpected JSON element {m_parser.ElementType}: {m_parser.ElementName}");
527 throw new Exception($"Unexpected JSON element {m_parser.ElementType}: {m_parser.ElementName}");
528 }
528 }
529 return true;
529 return true;
530 }
530 }
531
531
532 m_position = JsonXmlReaderPosition.Eof;
532 m_position = JsonXmlReaderPosition.Eof;
533 return false;
533 return false;
534 } catch {
534 } catch {
535 m_position = JsonXmlReaderPosition.Error;
535 m_position = JsonXmlReaderPosition.Error;
536 throw;
536 throw;
537 }
537 }
538 }
538 }
539
539
540 void SaveJsonName() {
540 void SaveJsonName() {
541 m_jsonNameStack.Push(new JsonContext {
541 m_jsonNameStack.Push(new JsonContext {
542 skip = m_jsonSkip,
542 skip = m_jsonSkip,
543 localName = m_jsonLocalName
543 localName = m_jsonLocalName
544 });
544 });
545
545
546 }
546 }
547
547
548 bool EnterJsonObject(string name, out string elementName) {
548 bool EnterJsonObject(string name, out string elementName) {
549 SaveJsonName();
549 SaveJsonName();
550 m_jsonSkip = false;
550 m_jsonSkip = false;
551
551
552 if (string.IsNullOrEmpty(name)) {
552 if (string.IsNullOrEmpty(name)) {
553 if (m_jsonNameStack.Count != 1 && !m_jsonFlattenArrays)
553 if (m_jsonNameStack.Count != 1 && !m_jsonFlattenArrays)
554 m_jsonLocalName = m_jsonArrayItemName;
554 m_jsonLocalName = m_jsonArrayItemName;
555 } else {
555 } else {
556 m_jsonLocalName = name;
556 m_jsonLocalName = name;
557 }
557 }
558
558
559 elementName = m_jsonLocalName;
559 elementName = m_jsonLocalName;
560 return true;
560 return true;
561 }
561 }
562
562
563 /// <summary>
563 /// <summary>
564 /// Called when JSON parser visits BeginArray ('[') element.
564 /// Called when JSON parser visits BeginArray ('[') element.
565 /// </summary>
565 /// </summary>
566 /// <param name="name">Optional property name if the array is the member of an object</param>
566 /// <param name="name">Optional property name if the array is the member of an object</param>
567 /// <returns>true if element should be emited, false otherwise</returns>
567 /// <returns>true if element should be emited, false otherwise</returns>
568 bool EnterJsonArray(string name, out string elementName) {
568 bool EnterJsonArray(string name, out string elementName) {
569 SaveJsonName();
569 SaveJsonName();
570
570
571 if (string.IsNullOrEmpty(name)) {
571 if (string.IsNullOrEmpty(name)) {
572 // m_jsonNameStack.Count == 1 means the root node
572 // m_jsonNameStack.Count == 1 means the root node
573 if (m_jsonNameStack.Count != 1 && !m_jsonFlattenArrays)
573 if (m_jsonNameStack.Count != 1 && !m_jsonFlattenArrays)
574 m_jsonLocalName = m_jsonArrayItemName;
574 m_jsonLocalName = m_jsonArrayItemName;
575
575
576 m_jsonSkip = false; // we should not flatten arrays inside arrays or in the document root
576 m_jsonSkip = false; // we should not flatten arrays inside arrays or in the document root
577 } else {
577 } else {
578 m_jsonLocalName = name;
578 m_jsonLocalName = name;
579 m_jsonSkip = m_jsonFlattenArrays;
579 m_jsonSkip = m_jsonFlattenArrays;
580 }
580 }
581 elementName = m_jsonLocalName;
581 elementName = m_jsonLocalName;
582
582
583 return !m_jsonSkip;
583 return !m_jsonSkip;
584 }
584 }
585
585
586 bool VisitJsonValue(string name, out string elementName) {
586 bool VisitJsonValue(string name, out string elementName) {
587 if (string.IsNullOrEmpty(name)) {
587 if (string.IsNullOrEmpty(name)) {
588 // m_jsonNameStack.Count == 0 means that JSON document consists from simple value
588 // m_jsonNameStack.Count == 0 means that JSON document consists from simple value
589 elementName = (m_jsonNameStack.Count == 0 || m_jsonFlattenArrays) ? m_jsonLocalName : m_jsonArrayItemName;
589 elementName = (m_jsonNameStack.Count == 0 || m_jsonFlattenArrays) ? m_jsonLocalName : m_jsonArrayItemName;
590 } else {
590 } else {
591 elementName = name;
591 elementName = name;
592 }
592 }
593 return true;
593 return true;
594 }
594 }
595
595
596 bool LeaveJsonScope(out string elementName) {
596 bool LeaveJsonScope(out string elementName) {
597 elementName = m_jsonLocalName;
597 elementName = m_jsonLocalName;
598 var skip = m_jsonSkip;
598 var skip = m_jsonSkip;
599
599
600 var prev = m_jsonNameStack.Pop();
600 var prev = m_jsonNameStack.Pop();
601 m_jsonLocalName = prev.localName;
601 m_jsonLocalName = prev.localName;
602 m_jsonSkip = prev.skip;
602 m_jsonSkip = prev.skip;
603
603
604 return !skip;
604 return !skip;
605 }
605 }
606
606
607 public override string ToString() {
607 public override string ToString() {
608 switch (NodeType) {
608 switch (NodeType) {
609 case XmlNodeType.Element:
609 case XmlNodeType.Element:
610 return $"<{Name} {string.Join(" ", (m_attributes ?? new XmlSimpleAttribute[0]).Select(x => $"{x.Prefix}{(string.IsNullOrEmpty(x.Prefix) ? "" : ":")}{x.QName.Name}='{ConvertValueToString(x.Value)}'"))} {(IsEmptyElement ? "/" : "")}>";
610 return $"<{Name} {string.Join(" ", (m_attributes ?? new XmlSimpleAttribute[0]).Select(x => $"{x.Prefix}{(string.IsNullOrEmpty(x.Prefix) ? "" : ":")}{x.QName.Name}='{ConvertValueToString(x.Value)}'"))} {(IsEmptyElement ? "/" : "")}>";
611 case XmlNodeType.Attribute:
611 case XmlNodeType.Attribute:
612 return $"@{Name}";
612 return $"@{Name}";
613 case XmlNodeType.Text:
613 case XmlNodeType.Text:
614 return $"{Value}";
614 return $"{Value}";
615 case XmlNodeType.CDATA:
615 case XmlNodeType.CDATA:
616 return $"<![CDATA[{Value}]]>";
616 return $"<![CDATA[{Value}]]>";
617 case XmlNodeType.EntityReference:
617 case XmlNodeType.EntityReference:
618 return $"&{Name};";
618 return $"&{Name};";
619 case XmlNodeType.EndElement:
619 case XmlNodeType.EndElement:
620 return $"</{Name}>";
620 return $"</{Name}>";
621 default:
621 default:
622 return $".{NodeType} {Name} {Value}";
622 return $".{NodeType} {Name} {Value}";
623 }
623 }
624 }
624 }
625 }
625 }
626 }
626 }
@@ -1,22 +1,22
1 using System;
1 using System;
2 using System.Collections.Generic;
2 using System.Collections.Generic;
3 using System.Linq;
3 using System.Linq;
4 using System.Text;
4 using System.Text;
5 using System.Threading.Tasks;
5 using System.Threading.Tasks;
6
6
7 namespace Implab.Xml {
7 namespace Implab.Xml {
8 public enum JsonXmlReaderPosition {
8 enum JsonXmlReaderPosition {
9 Initial,
9 Initial,
10 Declaration,
10 Declaration,
11 BeginArray,
11 BeginArray,
12 BeginObject,
12 BeginObject,
13 EndArray,
13 EndArray,
14 EndObject,
14 EndObject,
15 ValueElement,
15 ValueElement,
16 ValueContent,
16 ValueContent,
17 ValueEndElement,
17 ValueEndElement,
18 Eof,
18 Eof,
19 Closed,
19 Closed,
20 Error
20 Error
21 }
21 }
22 }
22 }
@@ -1,111 +1,119
1 using System;
1 using System;
2 using System.Collections.Generic;
2 using System.Collections.Generic;
3 using System.Linq;
3 using System.Linq;
4 using System.Text;
4 using System.Text;
5 using System.Threading.Tasks;
5 using System.Threading.Tasks;
6 using System.Xml;
6 using System.Xml;
7
7
8 namespace Implab.Xml {
8 namespace Implab.Xml {
9 public class XmlNameContext {
9 class XmlNameContext {
10 public const string XmlnsNamespace = "http://www.w3.org/2000/xmlns/";
10 public const string XmlnsNamespace = "http://www.w3.org/2000/xmlns/";
11 public const string XmlnsPrefix = "xmlns";
11 public const string XmlnsPrefix = "xmlns";
12 public const string XmlNamespace = "http://www.w3.org/XML/1998/namespace";
12 public const string XmlNamespace = "http://www.w3.org/XML/1998/namespace";
13 public const string XmlPrefix = "xml";
13 public const string XmlPrefix = "xml";
14 public const string XsiNamespace = "http://www.w3.org/2001/XMLSchema-instance";
14 public const string XsiNamespace = "http://www.w3.org/2001/XMLSchema-instance";
15 public const string XsiPrefix = "xsi";
15 public const string XsiPrefix = "xsi";
16
16
17 readonly static char[] _qNameDelim = new[] { ':' };
17 readonly static char[] _qNameDelim = new[] { ':' };
18
18
19 Dictionary<string, string> m_ns2prefix;
19 Dictionary<string, string> m_ns2prefix;
20 Dictionary<string, string> m_prefix2ns;
20 Dictionary<string, string> m_prefix2ns;
21 int m_nextPrefix = 1;
21 int m_nextPrefix = 1;
22 string m_lastNs;
23 string m_lastPrefix;
22
24
23 public XmlNameContext ParentContext { get; private set; }
25 public XmlNameContext ParentContext { get; private set; }
24
26
25 public XmlNameContext(XmlNameContext parent) {
27 public int Depth { get; private set; }
28
29 public XmlNameContext(XmlNameContext parent, int depth) {
26 ParentContext = parent;
30 ParentContext = parent;
31 Depth = depth;
32
27 if (parent == null) {
33 if (parent == null) {
28 DefinePrefixNoCheck(XmlnsNamespace, XmlnsPrefix);
34 DefinePrefixNoCheck(XmlnsNamespace, XmlnsPrefix);
29 DefinePrefixNoCheck(XmlNamespace, XmlPrefix);
35 DefinePrefixNoCheck(XmlNamespace, XmlPrefix);
30 } else {
36 } else {
31 m_nextPrefix = parent.m_nextPrefix;
37 m_nextPrefix = parent.m_nextPrefix;
32 }
38 }
33 }
39 }
34
40
35 public bool LookupNamespacePrefix(string ns, out string prefix) {
41 public bool LookupNamespacePrefix(string ns, out string prefix) {
36 if (ns == null)
42 if (ns == null)
37 ns = string.Empty;
43 ns = string.Empty;
44 if (ns == m_lastNs) {
45 prefix = m_lastPrefix;
46 return true;
47 }
48
38
49
39 prefix = null;
50 prefix = null;
40 for (var ctx = this; ctx != null; ctx = ctx.ParentContext) {
51 for (var ctx = this; ctx != null; ctx = ctx.ParentContext) {
41 if (ctx.m_ns2prefix?.TryGetValue(ns, out prefix) == true) {
52 if (ctx.m_ns2prefix != null && ctx.m_ns2prefix.TryGetValue(ns, out prefix)) {
42 if (ctx != this) // cache for the future use
53 m_lastNs = ns;
43 DefinePrefixNoCheck(ns, prefix);
54 m_lastPrefix = prefix;
44 return true;
55 return true;
45 }
56 }
46 }
57 }
47 return false;
58 return false;
48 }
59 }
49
60
50 public string CreateNamespacePrefix(string ns) {
61 public string CreateNamespacePrefix(string ns) {
51 var prefix = $"p{m_nextPrefix++}";
62 var prefix = $"p{m_nextPrefix++}";
52 DefinePrefixNoCheck(ns, prefix);
63 DefinePrefixNoCheck(ns, prefix);
53 return prefix;
64 return prefix;
54 }
65 }
55
66
56 void DefinePrefixNoCheck(string ns, string prefix) {
67 void DefinePrefixNoCheck(string ns, string prefix) {
57 if (ns == null)
68 if (ns == null)
58 ns = string.Empty;
69 ns = string.Empty;
59 if (prefix == null)
70 if (prefix == null)
60 prefix = string.Empty;
71 prefix = string.Empty;
61
72
62 if (m_ns2prefix == null)
73 if (m_ns2prefix == null)
63 m_ns2prefix = new Dictionary<string, string>();
74 m_ns2prefix = new Dictionary<string, string>();
64 m_ns2prefix[ns] = prefix;
75 m_ns2prefix[ns] = prefix;
65
76
66 if (m_prefix2ns == null)
77 if (m_prefix2ns == null)
67 m_prefix2ns = new Dictionary<string, string>();
78 m_prefix2ns = new Dictionary<string, string>();
68 m_prefix2ns[prefix] = ns;
79 m_prefix2ns[prefix] = ns;
69 }
80 }
70
81
71 public void DefinePrefix(string ns, string prefix) {
82 public void DefinePrefix(string ns, string prefix) {
72 // according to https://www.w3.org/TR/xml-names/#ns-decl
83 // according to https://www.w3.org/TR/xml-names/#ns-decl
73
84
74 // It MUST NOT be declared . Other prefixes MUST NOT be bound to this namespace name, and it MUST NOT be declared as the default namespace
85 // It MUST NOT be declared . Other prefixes MUST NOT be bound to this namespace name, and it MUST NOT be declared as the default namespace
75 if (ns == XmlnsNamespace)
86 if (ns == XmlnsNamespace)
76 throw new Exception($"Attempt to define xmlns:{prefix}='{ns}'");
87 throw new Exception($"Attempt to define xmlns:{prefix}='{ns}'");
77
88
78 // It MAY, but need not, be declared, and MUST NOT be bound to any other namespace name
89 // It MAY, but need not, be declared, and MUST NOT be bound to any other namespace name
79 if (ns == XmlNamespace && prefix != XmlPrefix)
90 if (ns == XmlNamespace && prefix != XmlPrefix)
80 throw new Exception($"Attempt to define xmlns:{prefix}='{ns}'");
91 throw new Exception($"Attempt to define xmlns:{prefix}='{ns}'");
81
92
82 // add mapping
93 // add mapping
83 DefinePrefixNoCheck(ns, prefix);
94 DefinePrefixNoCheck(ns, prefix);
84 }
95 }
85
96
86 public string ResolvePrefix(string prefix) {
97 public string ResolvePrefix(string prefix) {
87 if (prefix == null)
98 if (prefix == null)
88 prefix = string.Empty;
99 prefix = string.Empty;
89 string ns = null;
100 string ns = null;
90 for(var ctx = this; ctx != null; ctx = ctx.ParentContext) {
101 for(var ctx = this; ctx != null; ctx = ctx.ParentContext) {
91 if (ctx.m_prefix2ns?.TryGetValue(prefix, out ns) == true) {
102 if (ctx.m_prefix2ns != null && ctx.m_prefix2ns.TryGetValue(prefix, out ns) == true)
92 if (ctx != this) // cache for the future use
93 DefinePrefixNoCheck(ns, prefix);
94 return ns;
103 return ns;
95 }
104 }
96 }
97 return null;
105 return null;
98 }
106 }
99
107
100 public XmlQualifiedName Resolve(string name) {
108 public XmlQualifiedName Resolve(string name) {
101 Safe.ArgumentNotEmpty(name, nameof(name));
109 Safe.ArgumentNotEmpty(name, nameof(name));
102 var parts = name.Split(_qNameDelim, 2, StringSplitOptions.RemoveEmptyEntries);
110 var parts = name.Split(_qNameDelim, 2, StringSplitOptions.RemoveEmptyEntries);
103
111
104 if (parts.Length == 2) {
112 if (parts.Length == 2) {
105 return new XmlQualifiedName(parts[1], ResolvePrefix(parts[0]));
113 return new XmlQualifiedName(parts[1], ResolvePrefix(parts[0]));
106 } else {
114 } else {
107 return new XmlQualifiedName(parts[0], ResolvePrefix(string.Empty));
115 return new XmlQualifiedName(parts[0], ResolvePrefix(string.Empty));
108 }
116 }
109 }
117 }
110 }
118 }
111 }
119 }
General Comments 3
Under Review
author

Auto status change to "Under Review"

Approved
author

ok, latest stable version should be in default

You need to be logged in to leave comments. Login now