##// 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 }
@@ -21,3 +21,5 Implab.Test/Implab.Format.Test/obj/
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/
@@ -5,6 +5,7 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]
@@ -15,19 +16,19 namespace Implab.Format.Test {
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),
@@ -39,7 +40,7 namespace Implab.Format.Test {
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
@@ -73,7 +74,7 namespace Implab.Format.Test {
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)) {
@@ -109,11 +110,11 namespace Implab.Format.Test {
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}");
@@ -123,7 +124,7 namespace Implab.Format.Test {
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 }
@@ -137,7 +138,7 namespace Implab.Format.Test {
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 }
@@ -16,11 +16,14 Project("{FAE04EC0-301F-11D3-BF4B-00C04F
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
@@ -52,14 +55,6 Global
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
@@ -68,6 +63,14 Global
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
@@ -119,7 +119,7 namespace Implab.Automaton {
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 }
@@ -2,6 +2,7
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
@@ -30,24 +31,28 namespace Implab.Formats {
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
@@ -58,13 +63,8 namespace Implab.Formats {
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) {
@@ -6,6 +6,8 using Implab.Automaton.RegularExpression
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>
@@ -24,7 +26,7 namespace Implab.Formats.Json {
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,
@@ -61,7 +63,7 namespace Implab.Formats.Json {
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);
@@ -124,20 +126,10 namespace Implab.Formats.Json {
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 }
131
132
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 }
140
141 public int Level {
133 public int Level {
142 get { return m_stack.Count; }
134 get { return m_stack.Count; }
143 }
135 }
@@ -169,7 +161,7 namespace Implab.Formats.Json {
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;
@@ -213,7 +205,7 namespace Implab.Formats.Json {
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;
@@ -221,11 +213,11 namespace Implab.Formats.Json {
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;
@@ -241,7 +233,7 namespace Implab.Formats.Json {
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 }
@@ -268,7 +260,7 namespace Implab.Formats.Json {
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 }
@@ -289,6 +281,38 namespace Implab.Formats.Json {
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 }
@@ -25,38 +25,94 namespace Implab.Formats.Json {
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
32 m_pos = 0;
35 m_tokenBuilder.Append(m_buffer, m_pos, m_length - m_pos);
36
37 // read next data
33 m_length = Read(m_buffer, 0, m_buffer.Length);
38 m_length = Read(m_buffer, 0, m_buffer.Length);
39
34 if (m_length == 0) {
40 if (m_length == 0) {
35 tokenType = JsonGrammar.TokenType.None;
41 // no data is read
36 return false; // EOF
42 if (scanner.Position == m_pos) {
43 // scanned hasn't moved, that's the end
44 m_pos = 0;
45 tokenType = JsonGrammar.TokenType.None;
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");
55 }
37 }
56 }
38 }
57
39
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 }
@@ -72,17 +128,17 namespace Implab.Formats.Json {
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:
@@ -108,7 +164,7 namespace Implab.Formats.Json {
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--;
@@ -7,7 +7,7 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) {
@@ -70,6 +70,7
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" />
@@ -171,7 +172,7
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" />
@@ -199,6 +200,8
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>
@@ -12,7 +12,7 namespace Implab.Xml {
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;
@@ -57,7 +57,7 namespace Implab.Xml {
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
@@ -77,7 +77,7 namespace Implab.Xml {
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 {
@@ -314,22 +314,6 namespace Implab.Xml {
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 }
@@ -351,25 +335,29 namespace Implab.Xml {
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)
@@ -383,8 +371,10 namespace Implab.Xml {
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
@@ -397,6 +387,9 namespace Implab.Xml {
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;
@@ -406,14 +399,18 namespace Implab.Xml {
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
416 m_context = m_context.ParentContext;
411 if (m_context.Depth == m_xmlDepth)
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);
@@ -456,7 +453,10 namespace Implab.Xml {
456 break;
453 break;
457 case JsonXmlReaderPosition.ValueElement:
454 case JsonXmlReaderPosition.ValueElement:
458 if (!m_isEmpty) {
455 if (!m_isEmpty) {
459 ValueNode(m_parser.ElementValue);
456 if (m_parser.ElementValue != null && !m_parser.ElementValue.Equals(string.Empty))
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 {
@@ -521,7 +521,7 namespace Implab.Xml {
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}");
@@ -5,7 +5,7 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,
@@ -6,7 +6,7 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";
@@ -19,11 +19,17 namespace Implab.Xml {
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);
@@ -35,12 +41,17 namespace Implab.Xml {
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 }
@@ -88,11 +99,8 namespace Implab.Xml {
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 }
96 }
104 }
97 return null;
105 return null;
98 }
106 }
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