Auto status change to "Under Review"
@@ -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 | 21 | Implab.Format.Test/bin/ |
|
22 | 22 | Implab.Format.Test/obj/ |
|
23 | 23 | packages/ |
|
24 | Implab.Playground/obj/ | |
|
25 | Implab.Playground/bin/ |
@@ -5,6 +5,7 using Implab.Xml; | |||
|
5 | 5 | using System.Xml; |
|
6 | 6 | using Implab.Formats; |
|
7 | 7 | using Implab.Formats.Json; |
|
8 | using System.IO; | |
|
8 | 9 | |
|
9 | 10 | namespace Implab.Format.Test { |
|
10 | 11 | [TestFixture] |
@@ -15,19 +16,19 namespace Implab.Format.Test { | |||
|
15 | 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 | 18 | Tuple<JsonTokenType, object>[] expexted = { |
|
18 |
new Tuple<JsonTokenType,object>(JsonTokenType.Number, |
|
|
19 | new Tuple<JsonTokenType,object>(JsonTokenType.Number, "9123"), | |
|
19 | 20 | new Tuple<JsonTokenType,object>(JsonTokenType.ValueSeparator, null), |
|
20 |
new Tuple<JsonTokenType,object>(JsonTokenType.Number, |
|
|
21 | new Tuple<JsonTokenType,object>(JsonTokenType.Number, "-123"), | |
|
21 | 22 | new Tuple<JsonTokenType,object>(JsonTokenType.ValueSeparator, null), |
|
22 |
new Tuple<JsonTokenType,object>(JsonTokenType.Number, |
|
|
23 | new Tuple<JsonTokenType,object>(JsonTokenType.Number, "0"), | |
|
23 | 24 | new Tuple<JsonTokenType,object>(JsonTokenType.ValueSeparator, null), |
|
24 |
new Tuple<JsonTokenType,object>(JsonTokenType.Number, |
|
|
25 | new Tuple<JsonTokenType,object>(JsonTokenType.Number, "0.1"), | |
|
25 | 26 | new Tuple<JsonTokenType,object>(JsonTokenType.ValueSeparator, null), |
|
26 |
new Tuple<JsonTokenType,object>(JsonTokenType.Number, |
|
|
27 | new Tuple<JsonTokenType,object>(JsonTokenType.Number, "-0.2"), | |
|
27 | 28 | new Tuple<JsonTokenType,object>(JsonTokenType.ValueSeparator, null), |
|
28 |
new Tuple<JsonTokenType,object>(JsonTokenType.Number, -0.1e3 |
|
|
29 | new Tuple<JsonTokenType,object>(JsonTokenType.Number, "-0.1e3"), | |
|
29 | 30 | new Tuple<JsonTokenType,object>(JsonTokenType.ValueSeparator, null), |
|
30 |
new Tuple<JsonTokenType,object>(JsonTokenType.Number, 1.3E-3 |
|
|
31 | new Tuple<JsonTokenType,object>(JsonTokenType.Number, "1.3E-3"), | |
|
31 | 32 | new Tuple<JsonTokenType,object>(JsonTokenType.ValueSeparator, null), |
|
32 | 33 | new Tuple<JsonTokenType,object>(JsonTokenType.String, "some \t\n text"), |
|
33 | 34 | new Tuple<JsonTokenType,object>(JsonTokenType.ValueSeparator, null), |
@@ -39,7 +40,7 namespace Implab.Format.Test { | |||
|
39 | 40 | new Tuple<JsonTokenType,object>(JsonTokenType.NameSeparator, null) |
|
40 | 41 | }; |
|
41 | 42 | |
|
42 |
|
|
|
43 | string value; | |
|
43 | 44 | JsonTokenType tokenType; |
|
44 | 45 | for (var i = 0; i < expexted.Length; i++) { |
|
45 | 46 | |
@@ -73,7 +74,7 namespace Implab.Format.Test { | |||
|
73 | 74 | foreach (var json in bad) { |
|
74 | 75 | using (var scanner = JsonStringScanner.Create(json)) { |
|
75 | 76 | try { |
|
76 |
|
|
|
77 | string value; | |
|
77 | 78 | JsonTokenType token; |
|
78 | 79 | scanner.ReadToken(out value, out token); |
|
79 | 80 | if (!Object.Equals(value, json)) { |
@@ -109,9 +110,9 namespace Implab.Format.Test { | |||
|
109 | 110 | //DumpJsonParse("{}"); |
|
110 | 111 | //DumpJsonParse("[]"); |
|
111 | 112 | DumpJsonParse("{\"one\":1, \"two\":2}"); |
|
112 | DumpJsonParse("[1,2,3]"); | |
|
113 | DumpJsonParse("[1,\"\",2,3]"); | |
|
113 | 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 | 118 | void AssertRead(XmlReader reader, XmlNodeType expected) { |
@@ -123,7 +124,7 namespace Implab.Format.Test { | |||
|
123 | 124 | void DumpJsonParse(string json) { |
|
124 | 125 | Console.WriteLine($"JSON: {json}"); |
|
125 | 126 | Console.WriteLine("XML"); |
|
126 |
using (var xmlReader = new JsonXmlReader( |
|
|
127 | using (var xmlReader = new JsonXmlReader(JsonReader.ParseString(json), new JsonXmlReaderOptions { NamespaceUri = "JsonXmlReaderSimpleTest", NodesPrefix = "json" })) { | |
|
127 | 128 | while (xmlReader.Read()) |
|
128 | 129 | Console.WriteLine($"{new string(' ', xmlReader.Depth * 2)}{xmlReader}"); |
|
129 | 130 | } |
@@ -137,7 +138,7 namespace Implab.Format.Test { | |||
|
137 | 138 | CloseOutput = false, |
|
138 | 139 | ConformanceLevel = ConformanceLevel.Document |
|
139 | 140 | })) |
|
140 |
using (var xmlReader = new JsonXmlReader( |
|
|
141 | using (var xmlReader = new JsonXmlReader(JsonReader.ParseString(json), new JsonXmlReaderOptions { NamespaceUri = "JsonXmlReaderSimpleTest", NodesPrefix = "", FlattenArrays = true })) { | |
|
141 | 142 | xmlWriter.WriteNode(xmlReader, false); |
|
142 | 143 | } |
|
143 | 144 | } |
@@ -16,11 +16,14 Project("{FAE04EC0-301F-11D3-BF4B-00C04F | |||
|
16 | 16 | EndProject |
|
17 | 17 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Implab.Fx", "Implab.Fx\Implab.Fx.csproj", "{06E706F8-6881-43EB-927E-FFC503AF6ABC}" |
|
18 | 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 | 19 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Implab.Format.Test", "Implab.Format.Test\Implab.Format.Test.csproj", "{4D364996-7ECD-4193-8F90-F223FFEA49DA}" |
|
22 | 20 | EndProject |
|
21 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Implab.Playground", "Implab.Playground\Implab.Playground.csproj", "{100DFEB0-75BE-436F-ADDF-1F46EF433F46}" | |
|
22 | EndProject | |
|
23 | 23 | Global |
|
24 | GlobalSection(Performance) = preSolution | |
|
25 | HasPerformanceSessions = true | |
|
26 | EndGlobalSection | |
|
24 | 27 | GlobalSection(SolutionConfigurationPlatforms) = preSolution |
|
25 | 28 | Debug 4.5|Any CPU = Debug 4.5|Any CPU |
|
26 | 29 | Debug|Any CPU = Debug|Any CPU |
@@ -52,14 +55,6 Global | |||
|
52 | 55 | {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Release 4.5|Any CPU.Build.0 = Release 4.5|Any CPU |
|
53 | 56 | {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|
54 | 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 | 58 | {4D364996-7ECD-4193-8F90-F223FFEA49DA}.Debug 4.5|Any CPU.ActiveCfg = Debug|Any CPU |
|
64 | 59 | {4D364996-7ECD-4193-8F90-F223FFEA49DA}.Debug 4.5|Any CPU.Build.0 = Debug|Any CPU |
|
65 | 60 | {4D364996-7ECD-4193-8F90-F223FFEA49DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
@@ -68,6 +63,14 Global | |||
|
68 | 63 | {4D364996-7ECD-4193-8F90-F223FFEA49DA}.Release 4.5|Any CPU.Build.0 = Release|Any CPU |
|
69 | 64 | {4D364996-7ECD-4193-8F90-F223FFEA49DA}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|
70 | 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 | 74 | EndGlobalSection |
|
72 | 75 | GlobalSection(SolutionProperties) = preSolution |
|
73 | 76 | HideSolutionNode = FALSE |
@@ -119,7 +119,7 namespace Implab.Automaton { | |||
|
119 | 119 | table[i, j] = AutomatonConst.UNREACHABLE_STATE; |
|
120 | 120 | |
|
121 | 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 | 124 | return table; |
|
125 | 125 | } |
@@ -2,6 +2,7 | |||
|
2 | 2 | using System; |
|
3 | 3 | using System.Collections.Generic; |
|
4 | 4 | using System.Linq; |
|
5 | using System.Runtime.CompilerServices; | |
|
5 | 6 | using System.Text; |
|
6 | 7 | using System.Threading.Tasks; |
|
7 | 8 | |
@@ -30,24 +31,28 namespace Implab.Formats { | |||
|
30 | 31 | } |
|
31 | 32 | |
|
32 | 33 | public TTag Tag { |
|
34 | [MethodImpl(MethodImplOptions.AggressiveInlining)] | |
|
33 | 35 | get { |
|
34 | 36 | return m_tags[m_state]; |
|
35 | 37 | } |
|
36 | 38 | } |
|
37 | 39 | |
|
38 | 40 | public int Position { |
|
41 | [MethodImpl(MethodImplOptions.AggressiveInlining)] | |
|
39 | 42 | get { |
|
40 | 43 | return m_position; |
|
41 | 44 | } |
|
42 | 45 | } |
|
43 | 46 | |
|
44 | 47 | public bool IsFinal { |
|
48 | [MethodImpl(MethodImplOptions.AggressiveInlining)] | |
|
45 | 49 | get { |
|
46 | 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 | 56 | m_state = m_initialState; |
|
52 | 57 | } |
|
53 | 58 | |
@@ -58,13 +63,8 namespace Implab.Formats { | |||
|
58 | 63 | return clone; |
|
59 | 64 | } |
|
60 | 65 | |
|
61 | public bool Scan(char[] data, int offset, int length) { | |
|
62 | if (length <= 0) { | |
|
63 | m_position = offset; | |
|
64 | return false; // EOF | |
|
65 | } | |
|
66 | ||
|
67 | var max = offset + length; | |
|
66 | //[MethodImpl(MethodImplOptions.AggressiveInlining)] | |
|
67 | public bool Scan(char[] data, int offset, int max) { | |
|
68 | 68 | var next = m_state; |
|
69 | 69 | |
|
70 | 70 | while(offset < max) { |
@@ -6,6 +6,8 using Implab.Automaton.RegularExpression | |||
|
6 | 6 | using System.Linq; |
|
7 | 7 | using Implab.Components; |
|
8 | 8 | using System.Collections.Generic; |
|
9 | using System.Text; | |
|
10 | using System.Globalization; | |
|
9 | 11 | |
|
10 | 12 | namespace Implab.Formats.Json { |
|
11 | 13 | /// <summary> |
@@ -24,7 +26,7 namespace Implab.Formats.Json { | |||
|
24 | 26 | /// } // Level = 0 |
|
25 | 27 | /// </code> |
|
26 | 28 | /// </remarks> |
|
27 |
public class Json |
|
|
29 | public class JsonReader : Disposable { | |
|
28 | 30 | |
|
29 | 31 | enum MemberContext { |
|
30 | 32 | MemberName, |
@@ -61,7 +63,7 namespace Implab.Formats.Json { | |||
|
61 | 63 | static readonly ParserContext _objectContext; |
|
62 | 64 | static readonly ParserContext _arrayContext; |
|
63 | 65 | |
|
64 |
static Json |
|
|
66 | static JsonReader() { | |
|
65 | 67 | |
|
66 | 68 | var valueExpression = MakeToken(JsonTokenType.BeginArray, JsonTokenType.BeginObject, JsonTokenType.Literal, JsonTokenType.Number, JsonTokenType.String); |
|
67 | 69 | var memberExpression = MakeToken(JsonTokenType.String).Cat(MakeToken(JsonTokenType.NameSeparator)).Cat(valueExpression); |
@@ -124,18 +126,8 namespace Implab.Formats.Json { | |||
|
124 | 126 | /// Создает новый парсер на основе строки, содержащей JSON |
|
125 | 127 | /// </summary> |
|
126 | 128 | /// <param name="text"></param> |
|
127 | public JsonParser(string text) { | |
|
128 | Safe.ArgumentNotEmpty(text, "text"); | |
|
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); | |
|
129 | JsonReader(JsonScanner scanner) { | |
|
130 | m_scanner = scanner; | |
|
139 | 131 | } |
|
140 | 132 | |
|
141 | 133 | public int Level { |
@@ -169,7 +161,7 namespace Implab.Formats.Json { | |||
|
169 | 161 | /// </summary> |
|
170 | 162 | /// <returns><c>true</c> - операция чтения прошла успешно, <c>false</c> - конец данных</returns> |
|
171 | 163 | public bool Read() { |
|
172 |
|
|
|
164 | string tokenValue; | |
|
173 | 165 | JsonTokenType tokenType; |
|
174 | 166 | |
|
175 | 167 | m_memberName = String.Empty; |
@@ -213,7 +205,7 namespace Implab.Formats.Json { | |||
|
213 | 205 | return true; |
|
214 | 206 | case JsonTokenType.String: |
|
215 | 207 | if (m_memberContext == MemberContext.MemberName) { |
|
216 |
m_memberName = |
|
|
208 | m_memberName = tokenValue; | |
|
217 | 209 | break; |
|
218 | 210 | } |
|
219 | 211 | m_elementType = JsonElementType.Value; |
@@ -221,11 +213,11 namespace Implab.Formats.Json { | |||
|
221 | 213 | return true; |
|
222 | 214 | case JsonTokenType.Number: |
|
223 | 215 | m_elementType = JsonElementType.Value; |
|
224 | m_elementValue = tokenValue; | |
|
216 | m_elementValue = double.Parse(tokenValue, CultureInfo.InvariantCulture); | |
|
225 | 217 | return true; |
|
226 | 218 | case JsonTokenType.Literal: |
|
227 | 219 | m_elementType = JsonElementType.Value; |
|
228 |
m_elementValue = ParseLiteral( |
|
|
220 | m_elementValue = ParseLiteral(tokenValue); | |
|
229 | 221 | return true; |
|
230 | 222 | case JsonTokenType.NameSeparator: |
|
231 | 223 | m_memberContext = MemberContext.MemberValue; |
@@ -241,7 +233,7 namespace Implab.Formats.Json { | |||
|
241 | 233 | if (m_context.ElementContext != JsonElementContext.None) |
|
242 | 234 | throw new ParserException("Unexpedted end of data"); |
|
243 | 235 | |
|
244 |
E |
|
|
236 | Eof = true; | |
|
245 | 237 | |
|
246 | 238 | return false; |
|
247 | 239 | } |
@@ -268,7 +260,7 namespace Implab.Formats.Json { | |||
|
268 | 260 | /// <summary> |
|
269 | 261 | /// Признак конца потока |
|
270 | 262 | /// </summary> |
|
271 |
public bool E |
|
|
263 | public bool Eof { | |
|
272 | 264 | get; |
|
273 | 265 | private set; |
|
274 | 266 | } |
@@ -289,6 +281,38 namespace Implab.Formats.Json { | |||
|
289 | 281 | while (Level != level) |
|
290 | 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 | 25 | m_length = length; |
|
26 | 26 | } |
|
27 | 27 | |
|
28 | bool Read(InputScanner<JsonGrammar.TokenType> scanner, out JsonGrammar.TokenType tokenType) { | |
|
29 | scanner.Reset(); | |
|
28 | bool ReadChunk(InputScanner<JsonGrammar.TokenType> scanner, out JsonGrammar.TokenType tokenType) { | |
|
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 |
|
|
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 | 44 | m_pos = 0; |
|
33 | m_length = Read(m_buffer, 0, m_buffer.Length); | |
|
34 | if (m_length == 0) { | |
|
35 | 45 | tokenType = JsonGrammar.TokenType.None; |
|
36 |
return false; |
|
|
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 | 58 | m_pos = 0; |
|
43 | m_length = Read(m_buffer, 0, m_buffer.Length); | |
|
44 | 59 | } |
|
45 | 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 | 112 | if (scannerPos != m_pos) { |
|
47 | 113 | m_tokenBuilder.Append(m_buffer, m_pos, scannerPos - m_pos); |
|
48 | 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 | 116 | tokenType = scanner.Tag; |
|
61 | 117 | return true; |
|
62 | 118 | } |
@@ -72,17 +128,17 namespace Implab.Formats.Json { | |||
|
72 | 128 | /// <returns><c>true</c> - чтение произведено успешно. <c>false</c> - достигнут конец входных данных</returns> |
|
73 | 129 | /// <remarks>В случе если токен не распознается, возникает исключение. Значения токенов обрабатываются, т.е. |
|
74 | 130 | /// в строках обрабатываются экранированные символы, числа становтся типа double.</remarks> |
|
75 |
public bool ReadToken(out |
|
|
131 | public bool ReadToken(out string tokenValue, out JsonTokenType tokenType) { | |
|
76 | 132 | JsonGrammar.TokenType tag; |
|
77 | 133 | m_tokenBuilder.Clear(); |
|
78 | while (Read(m_jsonContext, out tag)) { | |
|
134 | while (ReadChunk(m_jsonContext, out tag)) { | |
|
79 | 135 | switch (tag) { |
|
80 | 136 | case JsonGrammar.TokenType.StringBound: |
|
81 | 137 | tokenValue = ReadString(); |
|
82 | 138 | tokenType = JsonTokenType.String; |
|
83 | 139 | break; |
|
84 | 140 | case JsonGrammar.TokenType.Number: |
|
85 |
tokenValue = |
|
|
141 | tokenValue = m_tokenBuilder.ToString(); | |
|
86 | 142 | tokenType = JsonTokenType.Number; |
|
87 | 143 | break; |
|
88 | 144 | case JsonGrammar.TokenType.Literal: |
@@ -108,7 +164,7 namespace Implab.Formats.Json { | |||
|
108 | 164 | JsonGrammar.TokenType tag; |
|
109 | 165 | m_tokenBuilder.Clear(); |
|
110 | 166 | |
|
111 | while (Read(m_stringContext, out tag)) { | |
|
167 | while (ReadStringChunk(m_stringContext, out tag)) { | |
|
112 | 168 | switch (tag) { |
|
113 | 169 | case JsonGrammar.TokenType.StringBound: |
|
114 | 170 | m_tokenBuilder.Length--; |
@@ -7,7 +7,7 using System.Threading.Tasks; | |||
|
7 | 7 | |
|
8 | 8 | namespace Implab.Formats.Json { |
|
9 | 9 | public class JsonTextScanner : JsonScanner { |
|
10 | const int _bufferSize = 4096; | |
|
10 | const int _bufferSize = 16*4096; | |
|
11 | 11 | readonly TextReader m_reader; |
|
12 | 12 | |
|
13 | 13 | JsonTextScanner(TextReader reader, char[] buffer) : base(buffer, 0, 0) { |
@@ -70,6 +70,7 | |||
|
70 | 70 | <Reference Include="System" /> |
|
71 | 71 | <Reference Include="System.Xml" /> |
|
72 | 72 | <Reference Include="mscorlib" /> |
|
73 | <Reference Include="System.Xml.Linq" /> | |
|
73 | 74 | </ItemGroup> |
|
74 | 75 | <ItemGroup> |
|
75 | 76 | <Compile Include="Components\StateChangeEventArgs.cs" /> |
@@ -171,7 +172,7 | |||
|
171 | 172 | <Compile Include="Formats\Json\JsonElementContext.cs" /> |
|
172 | 173 | <Compile Include="Formats\Json\JsonElementType.cs" /> |
|
173 | 174 | <Compile Include="Formats\Json\JsonGrammar.cs" /> |
|
174 |
<Compile Include="Formats\Json\Json |
|
|
175 | <Compile Include="Formats\Json\JsonReader.cs" /> | |
|
175 | 176 | <Compile Include="Formats\Json\JsonScanner.cs" /> |
|
176 | 177 | <Compile Include="Formats\Json\JsonTokenType.cs" /> |
|
177 | 178 | <Compile Include="Formats\Json\JsonWriter.cs" /> |
@@ -199,6 +200,8 | |||
|
199 | 200 | <Compile Include="Xml\JsonXmlReader.cs" /> |
|
200 | 201 | <Compile Include="Xml\JsonXmlReaderOptions.cs" /> |
|
201 | 202 | <Compile Include="Xml\JsonXmlReaderPosition.cs" /> |
|
203 | <Compile Include="Xml\SerializationHelpers.cs" /> | |
|
204 | <Compile Include="Xml\SerializersPool.cs" /> | |
|
202 | 205 | <Compile Include="Xml\XmlSimpleAttribute.cs" /> |
|
203 | 206 | <Compile Include="Xml\XmlNameContext.cs" /> |
|
204 | 207 | </ItemGroup> |
@@ -12,7 +12,7 namespace Implab.Xml { | |||
|
12 | 12 | public bool skip; |
|
13 | 13 | } |
|
14 | 14 | |
|
15 |
Json |
|
|
15 | JsonReader m_parser; | |
|
16 | 16 | JsonXmlReaderOptions m_options; |
|
17 | 17 | JsonXmlReaderPosition m_position = JsonXmlReaderPosition.Initial; |
|
18 | 18 | XmlNameTable m_nameTable; |
@@ -57,7 +57,7 namespace Implab.Xml { | |||
|
57 | 57 | readonly string m_xsiNamespace; |
|
58 | 58 | |
|
59 | 59 | |
|
60 |
public JsonXmlReader(Json |
|
|
60 | public JsonXmlReader(JsonReader parser, JsonXmlReaderOptions options) { | |
|
61 | 61 | Safe.ArgumentNotNull(parser, nameof(parser)); |
|
62 | 62 | m_parser = parser; |
|
63 | 63 | |
@@ -77,7 +77,7 namespace Implab.Xml { | |||
|
77 | 77 | |
|
78 | 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 | 83 | public override int AttributeCount { |
@@ -314,22 +314,6 namespace Implab.Xml { | |||
|
314 | 314 | case XmlNodeType.Element: |
|
315 | 315 | // if the elemnt is empty the next element will be it's sibling |
|
316 | 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 | 317 | default: |
|
334 | 318 | return true; |
|
335 | 319 | } |
@@ -351,25 +335,29 namespace Implab.Xml { | |||
|
351 | 335 | if (!IsSibling()) // the node is nested |
|
352 | 336 | m_xmlDepth++; |
|
353 | 337 | |
|
354 |
|
|
|
338 | var context = m_context; | |
|
355 | 339 | List<XmlSimpleAttribute> definedAttrs = null; |
|
356 | 340 | |
|
357 | 341 | // define new namespaces |
|
358 | 342 | if (attrs != null) { |
|
359 | 343 | foreach (var attr in attrs) { |
|
360 | 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 | 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 | 352 | } else { |
|
365 | 353 | string attrPrefix; |
|
366 | 354 | if (string.IsNullOrEmpty(attr.QName.Namespace)) |
|
367 | 355 | continue; |
|
368 | 356 | |
|
369 | 357 | // auto-define prefixes |
|
370 |
if (! |
|
|
358 | if (!context.LookupNamespacePrefix(attr.QName.Namespace, out attrPrefix) || string.IsNullOrEmpty(attrPrefix)) { | |
|
371 | 359 | // new namespace prefix added |
|
372 |
attrPrefix = |
|
|
360 | attrPrefix = context.CreateNamespacePrefix(attr.QName.Namespace); | |
|
373 | 361 | attr.Prefix = attrPrefix; |
|
374 | 362 | |
|
375 | 363 | if (definedAttrs == null) |
@@ -383,8 +371,10 namespace Implab.Xml { | |||
|
383 | 371 | |
|
384 | 372 | string p; |
|
385 | 373 | // auto-define prefixes |
|
386 |
if (! |
|
|
387 | p = m_context.CreateNamespacePrefix(ns); | |
|
374 | if (!context.LookupNamespacePrefix(ns, out p)) { | |
|
375 | if (context == m_context) | |
|
376 | context = new XmlNameContext(m_context, m_xmlDepth); | |
|
377 | p = context.CreateNamespacePrefix(ns); | |
|
388 | 378 | if (definedAttrs == null) |
|
389 | 379 | definedAttrs = new List<XmlSimpleAttribute>(); |
|
390 | 380 | |
@@ -397,6 +387,9 namespace Implab.Xml { | |||
|
397 | 387 | attrs = definedAttrs.ToArray(); |
|
398 | 388 | } |
|
399 | 389 | |
|
390 | if (!empty) | |
|
391 | m_context = context; | |
|
392 | ||
|
400 | 393 | m_nodeType = XmlNodeType.Element; |
|
401 | 394 | m_qName = new XmlQualifiedName(name, ns); |
|
402 | 395 | m_prefix = p; |
@@ -406,14 +399,18 namespace Implab.Xml { | |||
|
406 | 399 | } |
|
407 | 400 | |
|
408 | 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 | 404 | m_xmlDepth--; |
|
405 | } | |
|
411 | 406 | |
|
412 | 407 | string p; |
|
413 | 408 | if (!m_context.LookupNamespacePrefix(ns, out p)) |
|
414 | 409 | throw new Exception($"Failed to lookup namespace '{ns}'"); |
|
415 | 410 | |
|
411 | if (m_context.Depth == m_xmlDepth) | |
|
416 | 412 | m_context = m_context.ParentContext; |
|
413 | ||
|
417 | 414 | m_nodeType = XmlNodeType.EndElement; |
|
418 | 415 | m_prefix = p; |
|
419 | 416 | m_qName = new XmlQualifiedName(name, ns); |
@@ -456,7 +453,10 namespace Implab.Xml { | |||
|
456 | 453 | break; |
|
457 | 454 | case JsonXmlReaderPosition.ValueElement: |
|
458 | 455 | if (!m_isEmpty) { |
|
456 | if (m_parser.ElementValue != null && !m_parser.ElementValue.Equals(string.Empty)) | |
|
459 | 457 | ValueNode(m_parser.ElementValue); |
|
458 | else | |
|
459 | goto case JsonXmlReaderPosition.ValueContent; | |
|
460 | 460 | m_position = JsonXmlReaderPosition.ValueContent; |
|
461 | 461 | return true; |
|
462 | 462 | } else { |
@@ -521,7 +521,7 namespace Implab.Xml { | |||
|
521 | 521 | true |
|
522 | 522 | ); |
|
523 | 523 | else |
|
524 |
ElementNode(m_jsonValueName, m_jsonNamespace, elementAttrs, m_parser.ElementValue |
|
|
524 | ElementNode(m_jsonValueName, m_jsonNamespace, elementAttrs, m_parser.ElementValue.Equals(string.Empty)); | |
|
525 | 525 | break; |
|
526 | 526 | default: |
|
527 | 527 | throw new Exception($"Unexpected JSON element {m_parser.ElementType}: {m_parser.ElementName}"); |
@@ -5,7 +5,7 using System.Text; | |||
|
5 | 5 | using System.Threading.Tasks; |
|
6 | 6 | |
|
7 | 7 | namespace Implab.Xml { |
|
8 |
|
|
|
8 | enum JsonXmlReaderPosition { | |
|
9 | 9 | Initial, |
|
10 | 10 | Declaration, |
|
11 | 11 | BeginArray, |
@@ -6,7 +6,7 using System.Threading.Tasks; | |||
|
6 | 6 | using System.Xml; |
|
7 | 7 | |
|
8 | 8 | namespace Implab.Xml { |
|
9 |
|
|
|
9 | class XmlNameContext { | |
|
10 | 10 | public const string XmlnsNamespace = "http://www.w3.org/2000/xmlns/"; |
|
11 | 11 | public const string XmlnsPrefix = "xmlns"; |
|
12 | 12 | public const string XmlNamespace = "http://www.w3.org/XML/1998/namespace"; |
@@ -19,11 +19,17 namespace Implab.Xml { | |||
|
19 | 19 | Dictionary<string, string> m_ns2prefix; |
|
20 | 20 | Dictionary<string, string> m_prefix2ns; |
|
21 | 21 | int m_nextPrefix = 1; |
|
22 | string m_lastNs; | |
|
23 | string m_lastPrefix; | |
|
22 | 24 | |
|
23 | 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 | 30 | ParentContext = parent; |
|
31 | Depth = depth; | |
|
32 | ||
|
27 | 33 | if (parent == null) { |
|
28 | 34 | DefinePrefixNoCheck(XmlnsNamespace, XmlnsPrefix); |
|
29 | 35 | DefinePrefixNoCheck(XmlNamespace, XmlPrefix); |
@@ -35,12 +41,17 namespace Implab.Xml { | |||
|
35 | 41 | public bool LookupNamespacePrefix(string ns, out string prefix) { |
|
36 | 42 | if (ns == null) |
|
37 | 43 | ns = string.Empty; |
|
44 | if (ns == m_lastNs) { | |
|
45 | prefix = m_lastPrefix; | |
|
46 | return true; | |
|
47 | } | |
|
48 | ||
|
38 | 49 | |
|
39 | 50 | prefix = null; |
|
40 | 51 | for (var ctx = this; ctx != null; ctx = ctx.ParentContext) { |
|
41 |
if (ctx.m_ns2prefix |
|
|
42 | if (ctx != this) // cache for the future use | |
|
43 |
|
|
|
52 | if (ctx.m_ns2prefix != null && ctx.m_ns2prefix.TryGetValue(ns, out prefix)) { | |
|
53 | m_lastNs = ns; | |
|
54 | m_lastPrefix = prefix; | |
|
44 | 55 | return true; |
|
45 | 56 | } |
|
46 | 57 | } |
@@ -88,12 +99,9 namespace Implab.Xml { | |||
|
88 | 99 | prefix = string.Empty; |
|
89 | 100 | string ns = null; |
|
90 | 101 | for(var ctx = this; ctx != null; ctx = ctx.ParentContext) { |
|
91 |
if (ctx.m_prefix2ns |
|
|
92 | if (ctx != this) // cache for the future use | |
|
93 | DefinePrefixNoCheck(ns, prefix); | |
|
102 | if (ctx.m_prefix2ns != null && ctx.m_prefix2ns.TryGetValue(prefix, out ns) == true) | |
|
94 | 103 | return ns; |
|
95 | 104 |
|
|
96 | } | |
|
97 | 105 | return null; |
|
98 | 106 | } |
|
99 | 107 |
General Comments 3
ok, latest stable version should be in default
You need to be logged in to leave comments.
Login now