# HG changeset patch # User cin # Date 1507184689 -10800 # Node ID b49969a7043c62faf4f9ea95ce411a8144b17d53 # Parent 8dd666e6b6bf2232c63e1ba3c282bd92c13d919b# Parent 133ba4444accbdff9ad910c2052121a2f8e31968 Слияние diff -r 8dd666e6b6bf -r b49969a7043c Implab.mono.sln --- a/Implab.mono.sln Thu Oct 05 09:21:23 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,301 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Implab", "Implab\Implab.csproj", "{F550F1F8-8746-4AD0-9614-855F4C4B7F05}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{CE8D8D18-437A-445C-B662-4C2CE79A76F6}" - ProjectSection(SolutionItems) = preProject - Implab.vsmdi = Implab.vsmdi - Local.testsettings = Local.testsettings - TraceAndTestImpact.testsettings = TraceAndTestImpact.testsettings - EndProjectSection -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Implab.Fx", "Implab.Fx\Implab.Fx.csproj", "{06E706F8-6881-43EB-927E-FFC503AF6ABC}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{BCA337C3-BFDC-4825-BBDB-E6D467E4E452}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Implab.Test.mono", "Implab.Test\Implab.Test.mono.csproj", "{2BD05F84-E067-4B87-9477-FDC2676A21C6}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Implab.Format.Test", "Implab.Test\Implab.Format.Test\Implab.Format.Test.csproj", "{4D364996-7ECD-4193-8F90-F223FFEA49DA}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MonoPlay", "MonoPlay\MonoPlay.csproj", "{15DD7123-D504-4627-8B4F-D00C7F04D033}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - Debug 4.5|Any CPU = Debug 4.5|Any CPU - Release 4.5|Any CPU = Release 4.5|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Debug 4.5|Any CPU.ActiveCfg = Debug 4.5|Any CPU - {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Debug 4.5|Any CPU.Build.0 = Debug 4.5|Any CPU - {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Release 4.5|Any CPU.ActiveCfg = Release 4.5|Any CPU - {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Release 4.5|Any CPU.Build.0 = Release 4.5|Any CPU - {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {06E706F8-6881-43EB-927E-FFC503AF6ABC}.Release|Any CPU.Build.0 = Release|Any CPU - {15DD7123-D504-4627-8B4F-D00C7F04D033}.Debug 4.5|Any CPU.ActiveCfg = Debug|Any CPU - {15DD7123-D504-4627-8B4F-D00C7F04D033}.Debug 4.5|Any CPU.Build.0 = Debug|Any CPU - {15DD7123-D504-4627-8B4F-D00C7F04D033}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {15DD7123-D504-4627-8B4F-D00C7F04D033}.Debug|Any CPU.Build.0 = Debug|Any CPU - {15DD7123-D504-4627-8B4F-D00C7F04D033}.Release 4.5|Any CPU.ActiveCfg = Release|Any CPU - {15DD7123-D504-4627-8B4F-D00C7F04D033}.Release 4.5|Any CPU.Build.0 = Release|Any CPU - {15DD7123-D504-4627-8B4F-D00C7F04D033}.Release|Any CPU.ActiveCfg = Release|Any CPU - {15DD7123-D504-4627-8B4F-D00C7F04D033}.Release|Any CPU.Build.0 = Release|Any CPU - {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Debug 4.5|Any CPU.ActiveCfg = Debug 4.5|Any CPU - {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Debug 4.5|Any CPU.Build.0 = Debug 4.5|Any CPU - {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Release 4.5|Any CPU.ActiveCfg = Release 4.5|Any CPU - {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Release 4.5|Any CPU.Build.0 = Release 4.5|Any CPU - {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2BD05F84-E067-4B87-9477-FDC2676A21C6}.Release|Any CPU.Build.0 = Release|Any CPU - {4D364996-7ECD-4193-8F90-F223FFEA49DA}.Debug 4.5|Any CPU.ActiveCfg = Debug|Any CPU - {4D364996-7ECD-4193-8F90-F223FFEA49DA}.Debug 4.5|Any CPU.Build.0 = Debug|Any CPU - {4D364996-7ECD-4193-8F90-F223FFEA49DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4D364996-7ECD-4193-8F90-F223FFEA49DA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4D364996-7ECD-4193-8F90-F223FFEA49DA}.Release 4.5|Any CPU.ActiveCfg = Release|Any CPU - {4D364996-7ECD-4193-8F90-F223FFEA49DA}.Release 4.5|Any CPU.Build.0 = Release|Any CPU - {4D364996-7ECD-4193-8F90-F223FFEA49DA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4D364996-7ECD-4193-8F90-F223FFEA49DA}.Release|Any CPU.Build.0 = Release|Any CPU - {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Debug 4.5|Any CPU.ActiveCfg = Debug 4.5|Any CPU - {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Debug 4.5|Any CPU.Build.0 = Debug 4.5|Any CPU - {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Release 4.5|Any CPU.ActiveCfg = Release 4.5|Any CPU - {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Release 4.5|Any CPU.Build.0 = Release 4.5|Any CPU - {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Release|Any CPU.Build.0 = Release|Any CPU - {2F31E405-E267-4195-A05D-574093C21209}.Debug 4.5|Any CPU.ActiveCfg = Debug 4.5|Any CPU - {2F31E405-E267-4195-A05D-574093C21209}.Debug 4.5|Any CPU.Build.0 = Debug 4.5|Any CPU - {2F31E405-E267-4195-A05D-574093C21209}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2F31E405-E267-4195-A05D-574093C21209}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2F31E405-E267-4195-A05D-574093C21209}.Release 4.5|Any CPU.ActiveCfg = Release 4.5|Any CPU - {2F31E405-E267-4195-A05D-574093C21209}.Release 4.5|Any CPU.Build.0 = Release 4.5|Any CPU - {2F31E405-E267-4195-A05D-574093C21209}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2F31E405-E267-4195-A05D-574093C21209}.Release|Any CPU.Build.0 = Release|Any CPU - {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Debug 4.5|Any CPU.ActiveCfg = Debug 4.5|Any CPU - {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Debug 4.5|Any CPU.Build.0 = Debug 4.5|Any CPU - {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Release 4.5|Any CPU.ActiveCfg = Release 4.5|Any CPU - {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Release 4.5|Any CPU.Build.0 = Release 4.5|Any CPU - {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {2BD05F84-E067-4B87-9477-FDC2676A21C6} = {BCA337C3-BFDC-4825-BBDB-E6D467E4E452} - {4D364996-7ECD-4193-8F90-F223FFEA49DA} = {BCA337C3-BFDC-4825-BBDB-E6D467E4E452} - EndGlobalSection - GlobalSection(MonoDevelopProperties) = preSolution - Policies = $0 - $0.CSharpFormattingPolicy = $1 - $1.IndentSwitchBody = True - $1.NamespaceBraceStyle = EndOfLine - $1.ClassBraceStyle = EndOfLine - $1.InterfaceBraceStyle = EndOfLine - $1.StructBraceStyle = EndOfLine - $1.EnumBraceStyle = EndOfLine - $1.MethodBraceStyle = EndOfLine - $1.ConstructorBraceStyle = EndOfLine - $1.DestructorBraceStyle = EndOfLine - $1.BeforeMethodDeclarationParentheses = False - $1.BeforeMethodCallParentheses = False - $1.BeforeConstructorDeclarationParentheses = False - $1.NewLineBeforeConstructorInitializerColon = NewLine - $1.NewLineAfterConstructorInitializerColon = SameLine - $1.BeforeIndexerDeclarationBracket = False - $1.BeforeDelegateDeclarationParentheses = False - $1.NewParentheses = False - $1.SpacesBeforeBrackets = False - $1.inheritsSet = Mono - $1.inheritsScope = text/x-csharp - $1.scope = text/x-csharp - $0.TextStylePolicy = $2 - $2.FileWidth = 120 - $2.EolMarker = Unix - $2.inheritsSet = VisualStudio - $2.inheritsScope = text/plain - $2.scope = text/x-csharp - $0.DotNetNamingPolicy = $3 - $3.DirectoryNamespaceAssociation = PrefixedHierarchical - $3.ResourceNamePolicy = MSBuild - $0.TextStylePolicy = $4 - $4.FileWidth = 120 - $4.TabsToSpaces = False - $4.inheritsSet = VisualStudio - $4.inheritsScope = text/plain - $4.scope = application/xml - $0.XmlFormattingPolicy = $5 - $5.inheritsSet = Mono - $5.inheritsScope = application/xml - $5.scope = application/xml - $0.TextStylePolicy = $6 - $6.FileWidth = 120 - $6.TabsToSpaces = False - $6.inheritsSet = VisualStudio - $6.inheritsScope = text/plain - $6.scope = text/plain - $0.NameConventionPolicy = $7 - $7.Rules = $8 - $8.NamingRule = $9 - $9.Name = Namespaces - $9.AffectedEntity = Namespace - $9.VisibilityMask = VisibilityMask - $9.NamingStyle = PascalCase - $9.IncludeInstanceMembers = True - $9.IncludeStaticEntities = True - $8.NamingRule = $10 - $10.Name = Types - $10.AffectedEntity = Class, Struct, Enum, Delegate - $10.VisibilityMask = VisibilityMask - $10.NamingStyle = PascalCase - $10.IncludeInstanceMembers = True - $10.IncludeStaticEntities = True - $8.NamingRule = $11 - $11.Name = Interfaces - $11.RequiredPrefixes = $12 - $12.String = I - $11.AffectedEntity = Interface - $11.VisibilityMask = VisibilityMask - $11.NamingStyle = PascalCase - $11.IncludeInstanceMembers = True - $11.IncludeStaticEntities = True - $8.NamingRule = $13 - $13.Name = Attributes - $13.RequiredSuffixes = $14 - $14.String = Attribute - $13.AffectedEntity = CustomAttributes - $13.VisibilityMask = VisibilityMask - $13.NamingStyle = PascalCase - $13.IncludeInstanceMembers = True - $13.IncludeStaticEntities = True - $8.NamingRule = $15 - $15.Name = Event Arguments - $15.RequiredSuffixes = $16 - $16.String = EventArgs - $15.AffectedEntity = CustomEventArgs - $15.VisibilityMask = VisibilityMask - $15.NamingStyle = PascalCase - $15.IncludeInstanceMembers = True - $15.IncludeStaticEntities = True - $8.NamingRule = $17 - $17.Name = Exceptions - $17.RequiredSuffixes = $18 - $18.String = Exception - $17.AffectedEntity = CustomExceptions - $17.VisibilityMask = VisibilityMask - $17.NamingStyle = PascalCase - $17.IncludeInstanceMembers = True - $17.IncludeStaticEntities = True - $8.NamingRule = $19 - $19.Name = Methods - $19.AffectedEntity = Methods - $19.VisibilityMask = VisibilityMask - $19.NamingStyle = PascalCase - $19.IncludeInstanceMembers = True - $19.IncludeStaticEntities = True - $8.NamingRule = $20 - $20.Name = Static Readonly Fields - $20.AffectedEntity = ReadonlyField - $20.VisibilityMask = Internal, Protected, Public - $20.NamingStyle = PascalCase - $20.IncludeInstanceMembers = False - $20.IncludeStaticEntities = True - $8.NamingRule = $21 - $21.Name = Fields (Non Private) - $21.AffectedEntity = Field - $21.VisibilityMask = Internal, Public - $21.NamingStyle = CamelCase - $21.IncludeInstanceMembers = True - $21.IncludeStaticEntities = True - $8.NamingRule = $22 - $22.Name = ReadOnly Fields (Non Private) - $22.AffectedEntity = ReadonlyField - $22.VisibilityMask = Internal, Public - $22.NamingStyle = CamelCase - $22.IncludeInstanceMembers = True - $22.IncludeStaticEntities = False - $8.NamingRule = $23 - $23.Name = Fields (Private) - $23.RequiredPrefixes = $24 - $24.String = m_ - $23.AffectedEntity = Field, ReadonlyField - $23.VisibilityMask = Private, Protected - $23.NamingStyle = CamelCase - $23.IncludeInstanceMembers = True - $23.IncludeStaticEntities = False - $8.NamingRule = $25 - $25.Name = Static Fields (Private) - $25.RequiredPrefixes = $26 - $26.String = _ - $25.AffectedEntity = Field - $25.VisibilityMask = Private - $25.NamingStyle = CamelCase - $25.IncludeInstanceMembers = False - $25.IncludeStaticEntities = True - $8.NamingRule = $27 - $27.Name = ReadOnly Fields (Private) - $27.RequiredPrefixes = $28 - $28.String = m_ - $27.AffectedEntity = ReadonlyField - $27.VisibilityMask = Private, Protected - $27.NamingStyle = CamelCase - $27.IncludeInstanceMembers = True - $27.IncludeStaticEntities = False - $8.NamingRule = $29 - $29.Name = Constant Fields - $29.AffectedEntity = ConstantField - $29.VisibilityMask = VisibilityMask - $29.NamingStyle = AllUpper - $29.IncludeInstanceMembers = True - $29.IncludeStaticEntities = True - $8.NamingRule = $30 - $30.Name = Properties - $30.AffectedEntity = Property - $30.VisibilityMask = VisibilityMask - $30.NamingStyle = PascalCase - $30.IncludeInstanceMembers = True - $30.IncludeStaticEntities = True - $8.NamingRule = $31 - $31.Name = Events - $31.AffectedEntity = Event - $31.VisibilityMask = VisibilityMask - $31.NamingStyle = PascalCase - $31.IncludeInstanceMembers = True - $31.IncludeStaticEntities = True - $8.NamingRule = $32 - $32.Name = Enum Members - $32.AffectedEntity = EnumMember - $32.VisibilityMask = VisibilityMask - $32.NamingStyle = PascalCase - $32.IncludeInstanceMembers = True - $32.IncludeStaticEntities = True - $8.NamingRule = $33 - $33.Name = Parameters - $33.AffectedEntity = Parameter, LocalVariable - $33.VisibilityMask = VisibilityMask - $33.NamingStyle = CamelCase - $33.IncludeInstanceMembers = True - $33.IncludeStaticEntities = True - $8.NamingRule = $34 - $34.Name = Type Parameters - $34.RequiredPrefixes = $35 - $35.String = T - $34.AffectedEntity = TypeParameter - $34.VisibilityMask = VisibilityMask - $34.NamingStyle = PascalCase - $34.IncludeInstanceMembers = True - $34.IncludeStaticEntities = True - version = 0.2 - StartupItem = MonoPlay\MonoPlay.csproj - EndGlobalSection - GlobalSection(TestCaseManagementSettings) = postSolution - CategoryFile = Implab.vsmdi - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff -r 8dd666e6b6bf -r b49969a7043c Implab.sln --- a/Implab.sln Thu Oct 05 09:21:23 2017 +0300 +++ b/Implab.sln Thu Oct 05 09:24:49 2017 +0300 @@ -29,12 +29,12 @@ Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Debug 4.5|Any CPU.ActiveCfg = Debug 4.5|Any CPU - {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Debug 4.5|Any CPU.Build.0 = Debug 4.5|Any CPU + {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Debug 4.5|Any CPU.ActiveCfg = Debug|Any CPU + {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Debug 4.5|Any CPU.Build.0 = Debug|Any CPU {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Release 4.5|Any CPU.ActiveCfg = Release 4.5|Any CPU - {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Release 4.5|Any CPU.Build.0 = Release 4.5|Any CPU + {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Release 4.5|Any CPU.ActiveCfg = Release|Any CPU + {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Release 4.5|Any CPU.Build.0 = Release|Any CPU {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Release|Any CPU.ActiveCfg = Release|Any CPU {F550F1F8-8746-4AD0-9614-855F4C4B7F05}.Release|Any CPU.Build.0 = Release|Any CPU {63F92C0C-61BF-48C0-A377-8D67C3C661D0}.Debug 4.5|Any CPU.ActiveCfg = Debug 4.5|Any CPU @@ -65,188 +65,6 @@ GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection - GlobalSection(MonoDevelopProperties) = preSolution - StartupItem = Implab\Implab.csproj - Policies = $0 - $0.CSharpFormattingPolicy = $1 - $1.IndentSwitchBody = True - $1.NamespaceBraceStyle = EndOfLine - $1.ClassBraceStyle = EndOfLine - $1.InterfaceBraceStyle = EndOfLine - $1.StructBraceStyle = EndOfLine - $1.EnumBraceStyle = EndOfLine - $1.MethodBraceStyle = EndOfLine - $1.ConstructorBraceStyle = EndOfLine - $1.DestructorBraceStyle = EndOfLine - $1.BeforeMethodDeclarationParentheses = False - $1.BeforeMethodCallParentheses = False - $1.BeforeConstructorDeclarationParentheses = False - $1.NewLineBeforeConstructorInitializerColon = NewLine - $1.NewLineAfterConstructorInitializerColon = SameLine - $1.BeforeIndexerDeclarationBracket = False - $1.BeforeDelegateDeclarationParentheses = False - $1.NewParentheses = False - $1.SpacesBeforeBrackets = False - $1.inheritsSet = Mono - $1.inheritsScope = text/x-csharp - $1.scope = text/x-csharp - $0.TextStylePolicy = $6 - $2.FileWidth = 120 - $2.EolMarker = Unix - $2.inheritsSet = VisualStudio - $2.inheritsScope = text/plain - $2.scope = text/x-csharp - $0.DotNetNamingPolicy = $3 - $3.DirectoryNamespaceAssociation = PrefixedHierarchical - $3.ResourceNamePolicy = MSBuild - $4.FileWidth = 120 - $4.TabsToSpaces = False - $4.inheritsSet = VisualStudio - $4.inheritsScope = text/plain - $4.scope = application/xml - $0.XmlFormattingPolicy = $5 - $5.inheritsSet = Mono - $5.inheritsScope = application/xml - $5.scope = application/xml - $6.FileWidth = 120 - $6.TabsToSpaces = False - $6.inheritsSet = VisualStudio - $6.inheritsScope = text/plain - $6.scope = text/plain - $0.NameConventionPolicy = $7 - $7.Rules = $8 - $8.NamingRule = $34 - $9.Name = Namespaces - $9.AffectedEntity = Namespace - $9.VisibilityMask = VisibilityMask - $9.NamingStyle = PascalCase - $9.IncludeInstanceMembers = True - $9.IncludeStaticEntities = True - $10.Name = Types - $10.AffectedEntity = Class, Struct, Enum, Delegate - $10.VisibilityMask = VisibilityMask - $10.NamingStyle = PascalCase - $10.IncludeInstanceMembers = True - $10.IncludeStaticEntities = True - $11.Name = Interfaces - $11.RequiredPrefixes = $12 - $12.String = I - $11.AffectedEntity = Interface - $11.VisibilityMask = VisibilityMask - $11.NamingStyle = PascalCase - $11.IncludeInstanceMembers = True - $11.IncludeStaticEntities = True - $13.Name = Attributes - $13.RequiredSuffixes = $14 - $14.String = Attribute - $13.AffectedEntity = CustomAttributes - $13.VisibilityMask = VisibilityMask - $13.NamingStyle = PascalCase - $13.IncludeInstanceMembers = True - $13.IncludeStaticEntities = True - $15.Name = Event Arguments - $15.RequiredSuffixes = $16 - $16.String = EventArgs - $15.AffectedEntity = CustomEventArgs - $15.VisibilityMask = VisibilityMask - $15.NamingStyle = PascalCase - $15.IncludeInstanceMembers = True - $15.IncludeStaticEntities = True - $17.Name = Exceptions - $17.RequiredSuffixes = $18 - $18.String = Exception - $17.AffectedEntity = CustomExceptions - $17.VisibilityMask = VisibilityMask - $17.NamingStyle = PascalCase - $17.IncludeInstanceMembers = True - $17.IncludeStaticEntities = True - $19.Name = Methods - $19.AffectedEntity = Methods - $19.VisibilityMask = VisibilityMask - $19.NamingStyle = PascalCase - $19.IncludeInstanceMembers = True - $19.IncludeStaticEntities = True - $20.Name = Static Readonly Fields - $20.AffectedEntity = ReadonlyField - $20.VisibilityMask = Internal, Protected, Public - $20.NamingStyle = CamelCase - $20.IncludeInstanceMembers = False - $20.IncludeStaticEntities = True - $21.Name = Fields (Non Private) - $21.AffectedEntity = Field - $21.VisibilityMask = Internal, Public - $21.NamingStyle = CamelCase - $21.IncludeInstanceMembers = True - $21.IncludeStaticEntities = True - $22.Name = ReadOnly Fields (Non Private) - $22.AffectedEntity = ReadonlyField - $22.VisibilityMask = Internal, Public - $22.NamingStyle = CamelCase - $22.IncludeInstanceMembers = True - $22.IncludeStaticEntities = False - $23.Name = Fields (Private) - $23.RequiredPrefixes = $24 - $24.String = m_ - $23.AffectedEntity = Field, ReadonlyField - $23.VisibilityMask = Private, Protected - $23.NamingStyle = CamelCase - $23.IncludeInstanceMembers = True - $23.IncludeStaticEntities = False - $25.Name = Static Fields (Private) - $25.RequiredPrefixes = $26 - $26.String = _ - $25.AffectedEntity = Field - $25.VisibilityMask = Private - $25.NamingStyle = CamelCase - $25.IncludeInstanceMembers = False - $25.IncludeStaticEntities = True - $27.Name = ReadOnly Fields (Private) - $27.RequiredPrefixes = $28 - $28.String = m_ - $27.AffectedEntity = ReadonlyField - $27.VisibilityMask = Private, Protected - $27.NamingStyle = CamelCase - $27.IncludeInstanceMembers = True - $27.IncludeStaticEntities = False - $29.Name = Constant Fields - $29.AffectedEntity = ConstantField - $29.VisibilityMask = VisibilityMask - $29.NamingStyle = AllUpper - $29.IncludeInstanceMembers = True - $29.IncludeStaticEntities = True - $30.Name = Properties - $30.AffectedEntity = Property - $30.VisibilityMask = VisibilityMask - $30.NamingStyle = PascalCase - $30.IncludeInstanceMembers = True - $30.IncludeStaticEntities = True - $31.Name = Events - $31.AffectedEntity = Event - $31.VisibilityMask = VisibilityMask - $31.NamingStyle = PascalCase - $31.IncludeInstanceMembers = True - $31.IncludeStaticEntities = True - $32.Name = Enum Members - $32.AffectedEntity = EnumMember - $32.VisibilityMask = VisibilityMask - $32.NamingStyle = PascalCase - $32.IncludeInstanceMembers = True - $32.IncludeStaticEntities = True - $33.Name = Parameters - $33.AffectedEntity = Parameter, LocalVariable - $33.VisibilityMask = VisibilityMask - $33.NamingStyle = CamelCase - $33.IncludeInstanceMembers = True - $33.IncludeStaticEntities = True - $34.Name = Type Parameters - $34.RequiredPrefixes = $35 - $35.String = T - $34.AffectedEntity = TypeParameter - $34.VisibilityMask = VisibilityMask - $34.NamingStyle = PascalCase - $34.IncludeInstanceMembers = True - $34.IncludeStaticEntities = True - EndGlobalSection GlobalSection(TestCaseManagementSettings) = postSolution CategoryFile = Implab.vsmdi EndGlobalSection diff -r 8dd666e6b6bf -r b49969a7043c Implab/Formats/JSON/JsonElementContext.cs --- a/Implab/Formats/JSON/JsonElementContext.cs Thu Oct 05 09:21:23 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -namespace Implab.Formats.Json { - /// - /// internal - /// - enum JsonElementContext { - None, - Object, - Array, - Closed - } -} diff -r 8dd666e6b6bf -r b49969a7043c Implab/Formats/JSON/JsonElementType.cs --- a/Implab/Formats/JSON/JsonElementType.cs Thu Oct 05 09:21:23 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ -namespace Implab.Formats.Json { - /// - /// Тип элемента на котором находится парсер - /// - public enum JsonElementType { - None, - /// - /// Начало объекта - /// - BeginObject, - /// - /// Конец объекта - /// - EndObject, - /// - /// Начало массива - /// - BeginArray, - /// - /// Конец массива - /// - EndArray, - /// - /// Простое значение - /// - Value - } -} diff -r 8dd666e6b6bf -r b49969a7043c Implab/Formats/JSON/JsonGrammar.cs --- a/Implab/Formats/JSON/JsonGrammar.cs Thu Oct 05 09:21:23 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,148 +0,0 @@ -using System.Linq; -using Implab.Automaton.RegularExpressions; -using System; -using Implab.Automaton; -using Implab.Components; - -namespace Implab.Formats.Json { - public class JsonGrammar : Grammar { - public enum TokenType { - None, - BeginObject, - EndObject, - BeginArray, - EndArray, - String, - Number, - Literal, - NameSeparator, - ValueSeparator, - Whitespace, - - StringBound, - EscapedChar, - UnescapedChar, - EscapedUnicode - } - - static LazyAndWeak _instance = new LazyAndWeak(() => new JsonGrammar()); - - public static JsonGrammar Instance { - get { return _instance.Value; } - } - - readonly InputScanner m_jsonExpression; - readonly InputScanner m_stringExpression; - readonly CharAlphabet m_defaultAlphabet = new CharAlphabet(); - - public CharAlphabet DefaultAlphabet { get { return m_defaultAlphabet; } } - - public JsonGrammar() { - DefineAlphabet(Enumerable.Range(0, 0x20).Select(x => (char)x)); - var hexDigit = SymbolRangeToken('a','f').Or(SymbolRangeToken('A','F')).Or(SymbolRangeToken('0','9')); - var digit9 = SymbolRangeToken('1', '9'); - var zero = SymbolToken('0'); - var digit = zero.Or(digit9); - var dot = SymbolToken('.'); - var minus = SymbolToken('-'); - var sign = SymbolSetToken('-', '+'); - var expSign = SymbolSetToken('e', 'E'); - var letters = SymbolRangeToken('a', 'z'); - var integer = zero.Or(digit9.Cat(digit.EClosure())); - var frac = dot.Cat(digit.Closure()); - var exp = expSign.Cat(sign.Optional()).Cat(digit.Closure()); - var quote = SymbolToken('"'); - var backSlash = SymbolToken('\\'); - var specialEscapeChars = SymbolSetToken('\\', '"', '/', 'b', 'f', 't', 'n', 'r'); - var unicodeEspace = SymbolToken('u').Cat(hexDigit.Repeat(4)); - var whitespace = SymbolSetToken('\n', '\r', '\t', ' ').EClosure(); - var beginObject = whitespace.Cat(SymbolToken('{')).Cat(whitespace); - var endObject = whitespace.Cat(SymbolToken('}')).Cat(whitespace); - var beginArray = whitespace.Cat(SymbolToken('[')).Cat(whitespace); - var endArray = whitespace.Cat(SymbolToken(']')).Cat(whitespace); - var nameSep = whitespace.Cat(SymbolToken(':')).Cat(whitespace); - var valueSep = whitespace.Cat(SymbolToken(',')).Cat(whitespace); - - var number = minus.Optional().Cat(integer).Cat(frac.Optional()).Cat(exp.Optional()); - var literal = letters.Closure(); - var unescaped = SymbolTokenExcept(Enumerable.Range(0, 0x20).Union(new int[] { '\\', '"' }).Select(x => (char)x)); - - var jsonExpression = - number.Tag(TokenType.Number) - .Or(literal.Tag(TokenType.Literal)) - .Or(quote.Tag(TokenType.StringBound)) - .Or(beginObject.Tag(TokenType.BeginObject)) - .Or(endObject.Tag(TokenType.EndObject)) - .Or(beginArray.Tag(TokenType.BeginArray)) - .Or(endArray.Tag(TokenType.EndArray)) - .Or(nameSep.Tag(TokenType.NameSeparator)) - .Or(valueSep.Tag(TokenType.ValueSeparator)) - .Or(SymbolSetToken('\n', '\r', '\t', ' ').Closure().Tag(TokenType.Whitespace)); - - - var jsonStringExpression = - quote.Tag(TokenType.StringBound) - .Or(backSlash.Cat(specialEscapeChars).Tag(TokenType.EscapedChar)) - .Or(backSlash.Cat(unicodeEspace).Tag(TokenType.EscapedUnicode)) - .Or(unescaped.Closure().Tag(TokenType.UnescapedChar)); - - - m_jsonExpression = BuildScanner(jsonExpression); - m_stringExpression = BuildScanner(jsonStringExpression); - } - - public static InputScanner CreateJsonExpressionScanner() { - return Instance.m_jsonExpression.Clone(); - } - - public static InputScanner CreateStringExpressionScanner() { - return Instance.m_stringExpression.Clone(); - } - - protected override IAlphabetBuilder AlphabetBuilder { - get { - return m_defaultAlphabet; - } - } - - Token SymbolRangeToken(char start, char stop) { - return SymbolToken(Enumerable.Range(start, stop - start + 1).Select(x => (char)x)); - } - - public InputScanner BuildScanner(Token regexp) { - var dfa = new RegularDFA(AlphabetBuilder); - - var visitor = new RegularExpressionVisitor(dfa); - regexp.Accept(visitor); - visitor.BuildDFA(); - - if (dfa.IsFinalState(dfa.InitialState)) - throw new ApplicationException("The specified language contains empty token"); - - var ab = new CharAlphabet(); - var optimal = dfa.Optimize(ab); - - return new InputScanner( - optimal.CreateTransitionTable(), - optimal.CreateFinalStateTable(), - NormalizeTags(optimal.CreateTagTable()), - optimal.InitialState, - ab.CreateCharMap() - ); - } - - static TokenType[] NormalizeTags(TokenType[][] tags) { - var result = new TokenType[tags.Length]; - for(var i = 0; i< tags.Length; i++) { - if (tags[i] == null || tags[i].Length == 0) - result[i] = default(TokenType); - else if (tags[i].Length == 1) - result[i] = tags[i][0]; - else - throw new Exception($"Ambigous state tags {string.Join(", ", tags[i])}"); - } - return result; - } - - } -} diff -r 8dd666e6b6bf -r b49969a7043c Implab/Formats/JSON/JsonReader.cs --- a/Implab/Formats/JSON/JsonReader.cs Thu Oct 05 09:21:23 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,318 +0,0 @@ -using System; -using System.Diagnostics; -using System.IO; -using Implab.Automaton; -using Implab.Automaton.RegularExpressions; -using System.Linq; -using Implab.Components; -using System.Collections.Generic; -using System.Text; -using System.Globalization; - -namespace Implab.Formats.Json { - /// - /// Pull парсер JSON данных. - /// - /// - /// Следует отметить отдельную интерпретацию свойства , - /// оно означает текущий уровень вложенности объектов, однако закрывающий - /// элемент объекта и массива имеет уровень меньше, чем сам объект. - /// - /// { // Level = 1 - /// "name" : "Peter", // Level = 1 - /// "address" : { // Level = 2 - /// city : "Stern" // Level = 2 - /// } // Level = 1 - /// } // Level = 0 - /// - /// - public class JsonReader : Disposable { - - enum MemberContext { - MemberName, - MemberValue - } - - #region Parser rules - struct ParserContext { - readonly int[,] m_dfa; - int m_state; - - readonly JsonElementContext m_elementContext; - - public ParserContext(int[,] dfa, int state, JsonElementContext context) { - m_dfa = dfa; - m_state = state; - m_elementContext = context; - } - - public bool Move(JsonTokenType token) { - var next = m_dfa[m_state, (int)token]; - if (next == AutomatonConst.UNREACHABLE_STATE) - return false; - m_state = next; - return true; - } - - public JsonElementContext ElementContext { - get { return m_elementContext; } - } - } - - static readonly ParserContext _jsonContext; - static readonly ParserContext _objectContext; - static readonly ParserContext _arrayContext; - - static JsonReader() { - - var valueExpression = MakeToken(JsonTokenType.BeginArray, JsonTokenType.BeginObject, JsonTokenType.Literal, JsonTokenType.Number, JsonTokenType.String); - var memberExpression = MakeToken(JsonTokenType.String).Cat(MakeToken(JsonTokenType.NameSeparator)).Cat(valueExpression); - - var objectExpression = memberExpression - .Cat( - MakeToken(JsonTokenType.ValueSeparator) - .Cat(memberExpression) - .EClosure() - ) - .Optional() - .Cat(MakeToken(JsonTokenType.EndObject)) - .End(); - - var arrayExpression = valueExpression - .Cat( - MakeToken(JsonTokenType.ValueSeparator) - .Cat(valueExpression) - .EClosure() - ) - .Optional() - .Cat(MakeToken(JsonTokenType.EndArray)) - .End(); - - var jsonExpression = valueExpression.End(); - - _jsonContext = CreateParserContext(jsonExpression, JsonElementContext.None); - _objectContext = CreateParserContext(objectExpression, JsonElementContext.Object); - _arrayContext = CreateParserContext(arrayExpression, JsonElementContext.Array); - } - - static Token MakeToken(params JsonTokenType[] input) { - return Token.New( input.Select(t => (int)t).ToArray() ); - } - - static ParserContext CreateParserContext(Token expr, JsonElementContext context) { - - var dfa = new DFATable(); - var builder = new RegularExpressionVisitor(dfa); - expr.Accept(builder); - builder.BuildDFA(); - - return new ParserContext(dfa.CreateTransitionTable(), dfa.InitialState, context); - } - - #endregion - - readonly JsonScanner m_scanner; - // json starts from the value context and may content even a single literal - MemberContext m_memberContext = MemberContext.MemberValue; - - JsonElementType m_elementType; - object m_elementValue; - string m_memberName = String.Empty; - - Stack m_stack = new Stack(); - ParserContext m_context = _jsonContext; - - /// - /// Создает новый парсер на основе строки, содержащей JSON - /// - /// - JsonReader(JsonScanner scanner) { - m_scanner = scanner; - } - - public int Level { - get { return m_stack.Count; } - } - - /// - /// Тип текущего элемента на котором стоит парсер. - /// - public JsonElementType ElementType { - get { return m_elementType; } - } - - /// - /// Имя элемента - имя свойства родительского контейнера. Для элементов массивов и корневого всегда - /// пустая строка. - /// - public string ElementName { - get { return m_memberName; } - } - - /// - /// Значение элемента. Только для элементов типа , для остальных null - /// - public object ElementValue { - get { return m_elementValue; } - } - - /// - /// Читает слеюудущий объект из потока - /// - /// true - операция чтения прошла успешно, false - конец данных - public bool Read() { - string tokenValue; - JsonTokenType tokenType; - - m_memberName = String.Empty; - - while (m_scanner.ReadToken(out tokenValue, out tokenType)) { - if(!m_context.Move(tokenType)) - UnexpectedToken(tokenValue, tokenType); - - switch (tokenType) { - case JsonTokenType.BeginObject: - m_stack.Push(m_context); - m_context = _objectContext; - - m_elementValue = null; - m_memberContext = MemberContext.MemberName; - m_elementType = JsonElementType.BeginObject; - return true; - case JsonTokenType.EndObject: - if (m_stack.Count == 0) - UnexpectedToken(tokenValue, tokenType); - m_context = m_stack.Pop(); - - m_elementValue = null; - m_elementType = JsonElementType.EndObject; - return true; - case JsonTokenType.BeginArray: - m_stack.Push(m_context); - m_context = _arrayContext; - - m_elementValue = null; - m_memberContext = MemberContext.MemberValue; - m_elementType = JsonElementType.BeginArray; - return true; - case JsonTokenType.EndArray: - if (m_stack.Count == 0) - UnexpectedToken(tokenValue, tokenType); - m_context = m_stack.Pop(); - - m_elementValue = null; - m_elementType = JsonElementType.EndArray; - return true; - case JsonTokenType.String: - if (m_memberContext == MemberContext.MemberName) { - m_memberName = tokenValue; - break; - } - m_elementType = JsonElementType.Value; - m_elementValue = tokenValue; - return true; - case JsonTokenType.Number: - m_elementType = JsonElementType.Value; - m_elementValue = double.Parse(tokenValue, CultureInfo.InvariantCulture); - return true; - case JsonTokenType.Literal: - m_elementType = JsonElementType.Value; - m_elementValue = ParseLiteral(tokenValue); - return true; - case JsonTokenType.NameSeparator: - m_memberContext = MemberContext.MemberValue; - break; - case JsonTokenType.ValueSeparator: - m_memberContext = m_context.ElementContext == JsonElementContext.Object ? MemberContext.MemberName : MemberContext.MemberValue; - break; - default: - UnexpectedToken(tokenValue, tokenType); - break; - } - } - if (m_context.ElementContext != JsonElementContext.None) - throw new ParserException("Unexpedted end of data"); - - Eof = true; - - return false; - } - - object ParseLiteral(string literal) { - switch (literal) { - case "null": - return null; - case "false": - return false; - case "true": - return true; - default: - UnexpectedToken(literal, JsonTokenType.Literal); - return null; // avoid compliler error - } - } - - void UnexpectedToken(object value, JsonTokenType tokenType) { - throw new ParserException(String.Format("Unexpected token {0}: '{1}'", tokenType, value)); - } - - - /// - /// Признак конца потока - /// - public bool Eof { - get; - private set; - } - - protected override void Dispose(bool disposing) { - if (disposing) - m_scanner.Dispose(); - } - - /// - /// Переходит в конец текущего объекта. - /// - public void SeekElementEnd() { - var level = Level - 1; - - Debug.Assert(level >= 0); - - while (Level != level) - Read(); - } - - public static JsonReader Create(string file, Encoding encoding) { - return new JsonReader(JsonTextScanner.Create(file, encoding)); - } - - public static JsonReader Create(string file) { - return new JsonReader(JsonTextScanner.Create(file)); - } - - public static JsonReader Create(Stream stream, Encoding encoding) { - return new JsonReader(JsonTextScanner.Create(stream, encoding)); - } - - public static JsonReader Create(Stream stream) { - return new JsonReader(JsonTextScanner.Create(stream)); - } - - public static JsonReader Create(TextReader reader) { - return new JsonReader(JsonTextScanner.Create(reader)); - } - - public static JsonReader ParseString(string data) { - return new JsonReader(JsonStringScanner.Create(data)); - } - - public static JsonReader ParseString(string data, int offset, int length) { - return new JsonReader(JsonStringScanner.Create(data, offset, length)); - } - - public static JsonReader ParseString(char[] data, int offset, int lenght) { - return new JsonReader(JsonStringScanner.Create(data, offset, lenght)); - } - } - -} diff -r 8dd666e6b6bf -r b49969a7043c Implab/Formats/JSON/JsonScanner.cs --- a/Implab/Formats/JSON/JsonScanner.cs Thu Oct 05 09:21:23 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,190 +0,0 @@ -using System; -using System.Globalization; -using Implab.Automaton; -using System.Text; -using Implab.Components; -using System.IO; - -namespace Implab.Formats.Json { - /// - /// Сканнер (лексер), разбивающий поток символов на токены JSON. - /// - public abstract class JsonScanner : Disposable { - readonly InputScanner m_jsonContext = JsonGrammar.CreateJsonExpressionScanner(); - readonly InputScanner m_stringContext = JsonGrammar.CreateStringExpressionScanner(); - - readonly char[] m_unescapeBuf = new char[4]; - readonly char[] m_buffer; - int m_length; - int m_pos; - readonly StringBuilder m_tokenBuilder = new StringBuilder(); - - protected JsonScanner(char[] buffer, int pos, int length) { - m_buffer = buffer; - m_pos = pos; - m_length = length; - } - - bool ReadChunk(InputScanner scanner, out JsonGrammar.TokenType tokenType) { - scanner.ResetState(); - - while(scanner.Scan(m_buffer, m_pos, m_length)) { - // scanner requests new data - - if (m_pos != m_length) // capture results for the future - m_tokenBuilder.Append(m_buffer, m_pos, m_length - m_pos); - - // read next data - m_length = Read(m_buffer, 0, m_buffer.Length); - - if (m_length == 0) { - // no data is read - if (scanner.Position == m_pos) { - // scanned hasn't moved, that's the end - m_pos = 0; - tokenType = JsonGrammar.TokenType.None; - return false; - } - - if (scanner.IsFinal) { - m_pos = 0; - tokenType = scanner.Tag; - return true; - } else { - throw new ParserException("Unexpected EOF"); - } - } - - m_pos = 0; - } - var scannerPos = scanner.Position; - - // scanner stops as scannerPos - if (!scanner.IsFinal) - throw new ParserException($"Unexpected character '{m_buffer[scannerPos + 1]}'"); - - tokenType = scanner.Tag; - if (scannerPos != m_pos && tokenType == JsonGrammar.TokenType.Number || tokenType == JsonGrammar.TokenType.Literal) - m_tokenBuilder.Append(m_buffer, m_pos, scannerPos - m_pos); - - m_pos = scannerPos; - return true; - } - - bool ReadStringChunk(InputScanner scanner, out JsonGrammar.TokenType tokenType) { - scanner.ResetState(); - - while (scanner.Scan(m_buffer, m_pos, m_length)) { - // scanner requests new data - - if (m_pos != m_length) // capture results for the future - m_tokenBuilder.Append(m_buffer, m_pos, m_length - m_pos); - - // read next data - m_length = Read(m_buffer, 0, m_buffer.Length); - - if (m_length == 0) { - // no data is read - if (scanner.Position == m_pos) { - // scanned hasn't moved, that's the end - m_pos = 0; - tokenType = JsonGrammar.TokenType.None; - return false; - } - - if (scanner.IsFinal) { - m_pos = 0; - tokenType = scanner.Tag; - return true; - } else { - throw new ParserException("Unexpected EOF"); - } - } - - m_pos = 0; - } - var scannerPos = scanner.Position; - - // scanner stops as scannerPos - if (!scanner.IsFinal) - throw new ParserException($"Unexpected character '{m_buffer[scannerPos + 1]}'"); - - if (scannerPos != m_pos) { - m_tokenBuilder.Append(m_buffer, m_pos, scannerPos - m_pos); - m_pos = scannerPos; - } - tokenType = scanner.Tag; - return true; - } - - protected abstract int Read(char[] buffer, int offset, int size); - - - /// - /// Читает следующий лексический элемент из входных данных. - /// - /// Возвращает значение прочитанного токена. - /// Возвращает тип прочитанного токена. - /// true - чтение произведено успешно. false - достигнут конец входных данных - /// В случе если токен не распознается, возникает исключение. Значения токенов обрабатываются, т.е. - /// в строках обрабатываются экранированные символы, числа становтся типа double. - public bool ReadToken(out string tokenValue, out JsonTokenType tokenType) { - JsonGrammar.TokenType tag; - m_tokenBuilder.Clear(); - while (ReadChunk(m_jsonContext, out tag)) { - switch (tag) { - case JsonGrammar.TokenType.StringBound: - tokenValue = ReadString(); - tokenType = JsonTokenType.String; - break; - case JsonGrammar.TokenType.Number: - tokenValue = m_tokenBuilder.ToString(); - tokenType = JsonTokenType.Number; - break; - case JsonGrammar.TokenType.Literal: - tokenType = JsonTokenType.Literal; - tokenValue = m_tokenBuilder.ToString(); - break; - case JsonGrammar.TokenType.Whitespace: - m_tokenBuilder.Clear(); - continue; - default: - tokenType = (JsonTokenType)tag; - tokenValue = null; - break; - } - return true; - } - tokenValue = null; - tokenType = JsonTokenType.None; - return false; - } - - string ReadString() { - JsonGrammar.TokenType tag; - m_tokenBuilder.Clear(); - - while (ReadStringChunk(m_stringContext, out tag)) { - switch (tag) { - case JsonGrammar.TokenType.StringBound: - m_tokenBuilder.Length--; - return m_tokenBuilder.ToString(); - case JsonGrammar.TokenType.UnescapedChar: - break; - case JsonGrammar.TokenType.EscapedUnicode: // \xXXXX - unicode escape sequence - m_tokenBuilder.CopyTo(m_tokenBuilder.Length - 4, m_unescapeBuf, 0, 4); - m_tokenBuilder.Length -= 6; - m_tokenBuilder.Append(StringTranslator.TranslateHexUnicode(m_unescapeBuf, 0)); - break; - case JsonGrammar.TokenType.EscapedChar: // \t - escape sequence - var ch = m_tokenBuilder[m_tokenBuilder.Length-1]; - m_tokenBuilder.Length -= 2; - m_tokenBuilder.Append(StringTranslator.TranslateEscapedChar(ch)); - break; - } - } - - throw new ParserException("Unexpected end of data"); - } - } -} diff -r 8dd666e6b6bf -r b49969a7043c Implab/Formats/JSON/JsonStringScanner.cs --- a/Implab/Formats/JSON/JsonStringScanner.cs Thu Oct 05 09:21:23 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,76 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Implab.Formats.Json { - public class JsonStringScanner : JsonScanner { - const int _defaultBuffer = 64; - - readonly string m_data; - int m_offset; - - JsonStringScanner(string data, char[] buffer, int pos, int length, int offset) : base(buffer, pos, length) { - m_data = data; - m_offset = offset; - } - - protected override int Read(char[] buffer, int offset, int size) { - if (m_data == null) - return 0; - if (m_offset >= m_data.Length) - return 0; - - var count = Math.Min(size, m_data.Length - m_offset); - - m_data.CopyTo(m_offset, buffer, offset, count); - m_offset += count; - - return count; - } - - public static JsonStringScanner Create(string data) { - Safe.ArgumentNotNull(data, nameof(data)); - - if (data.Length <= _defaultBuffer) - return new JsonStringScanner(null, data.ToCharArray(), 0, data.Length, data.Length); - - var buffer = new char[_defaultBuffer]; - data.CopyTo(0, buffer, 0, _defaultBuffer); - return new JsonStringScanner(data, buffer, 0, _defaultBuffer, _defaultBuffer); - } - - public static JsonStringScanner Create(string data, int offset, int length) { - Safe.ArgumentNotNull(data, nameof(data)); - Safe.ArgumentGreaterThan(offset, 0, nameof(offset)); - Safe.ArgumentGreaterThan(length, 0, nameof(length)); - - if (offset + length > data.Length) - throw new ArgumentOutOfRangeException("Specified offset and length are out of the string bounds"); - - if (length <= _defaultBuffer) { - var buffer = new char[length]; - data.CopyTo(offset, buffer, 0, length); - - return new JsonStringScanner(null, buffer, 0, length, length); - } else { - var buffer = new char[_defaultBuffer]; - data.CopyTo(offset, buffer, 0, _defaultBuffer); - return new JsonStringScanner(data, buffer, 0, _defaultBuffer, offset + _defaultBuffer); - } - } - - public static JsonStringScanner Create(char[] data, int offset, int length) { - Safe.ArgumentNotNull(data, nameof(data)); - Safe.ArgumentGreaterThan(offset, 0, nameof(offset)); - Safe.ArgumentGreaterThan(length, 0, nameof(length)); - - if (offset + length > data.Length) - throw new ArgumentOutOfRangeException("Specified offset and length are out of the array bounds"); - - return new JsonStringScanner(null, data, offset, offset + length, offset + length); - - } - } -} diff -r 8dd666e6b6bf -r b49969a7043c Implab/Formats/JSON/JsonTextScanner.cs --- a/Implab/Formats/JSON/JsonTextScanner.cs Thu Oct 05 09:21:23 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Implab.Formats.Json { - public class JsonTextScanner : JsonScanner { - const int _bufferSize = 16*4096; - readonly TextReader m_reader; - - JsonTextScanner(TextReader reader, char[] buffer) : base(buffer, 0, 0) { - m_reader = reader; - } - - protected override int Read(char[] buffer, int offset, int size) { - return m_reader.Read(buffer, offset, size); - } - - public static JsonTextScanner Create(string file, Encoding encoding) { - return new JsonTextScanner(new StreamReader(file, encoding), new char[_bufferSize]); - } - - public static JsonTextScanner Create(string file) { - return new JsonTextScanner(new StreamReader(file), new char[_bufferSize]); - } - - public static JsonTextScanner Create(Stream stream, Encoding encoding) { - return new JsonTextScanner(new StreamReader(stream, encoding), new char[_bufferSize]); - } - - public static JsonTextScanner Create(Stream stream) { - return new JsonTextScanner(new StreamReader(stream), new char[_bufferSize]); - } - - public static JsonTextScanner Create(TextReader reader) { - Safe.ArgumentNotNull(reader, nameof(reader)); - return new JsonTextScanner(reader, new char[_bufferSize]); - } - - protected override void Dispose(bool disposing) { - if (disposing) - Safe.Dispose(m_reader); - - base.Dispose(disposing); - } - } -} diff -r 8dd666e6b6bf -r b49969a7043c Implab/Formats/JSON/JsonTokenType.cs --- a/Implab/Formats/JSON/JsonTokenType.cs Thu Oct 05 09:21:23 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -namespace Implab.Formats.Json { - /// - /// Тип токенов, возвращаемых . - /// - public enum JsonTokenType : int { - None = 0, - /// - /// Начало объекта - /// - BeginObject, - /// - /// Конец объекта - /// - EndObject, - /// - /// Начало массива - /// - BeginArray, - /// - /// Конец массива - /// - EndArray, - /// - /// Строка - /// - String, - /// - /// Число - /// - Number, - /// - /// Литерал - /// - Literal, - /// - /// Разделитель имени : - /// - NameSeparator, - /// - /// Разделитель имени , - /// - ValueSeparator - } -} diff -r 8dd666e6b6bf -r b49969a7043c Implab/Formats/JSON/JsonWriter.cs --- a/Implab/Formats/JSON/JsonWriter.cs Thu Oct 05 09:21:23 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,319 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Globalization; -using System.Diagnostics; - -namespace Implab.Formats.Json { - public class JsonWriter { - struct Context { - public bool needComma; - public JsonElementContext element; - } - Stack m_contextStack = new Stack(); - Context m_context; - - const int BUFFER_SIZE = 64; - - TextWriter m_writer; - readonly bool m_indent = true; - readonly int m_indentSize = 4; - readonly char[] m_buffer = new char[BUFFER_SIZE]; - int m_bufferPos; - - static readonly char [] _hex = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; - static readonly char [] _escapeBKS, - _escapeFWD, - _escapeCR, - _escapeNL, - _escapeTAB, - _escapeBSLASH, - _escapeQ; - - static JsonWriter() { - _escapeBKS = "\\b".ToCharArray(); - _escapeFWD = "\\f".ToCharArray(); - _escapeCR = "\\r".ToCharArray(); - _escapeNL = "\\n".ToCharArray(); - _escapeTAB = "\\t".ToCharArray(); - _escapeBSLASH = "\\\\".ToCharArray(); - _escapeQ = "\\\"".ToCharArray(); - } - - public JsonWriter(TextWriter writer) { - Safe.ArgumentNotNull(writer, "writer"); - m_writer = writer; - } - - public JsonWriter(TextWriter writer, bool indent) { - Safe.ArgumentNotNull(writer, "writer"); - - m_writer = writer; - m_indent = indent; - } - - void WriteIndent() { - if (m_indent) { - var indent = new char[m_contextStack.Count * m_indentSize + 1]; - indent[0] = '\n'; - for (int i = 1; i < indent.Length; i++) - indent[i] = ' '; - m_writer.Write(new String(indent)); - } else { - m_writer.Write(' '); - } - } - - void WriteMemberName(string name) { - Safe.ArgumentNotEmpty(name, "name"); - if (m_context.element != JsonElementContext.Object) - OperationNotApplicable("WriteMember"); - if (m_context.needComma) - m_writer.Write(","); - - WriteIndent(); - m_context.needComma = true; - Write(name); - m_writer.Write(" : "); - } - - public void WriteValue(string name, string value) { - WriteMemberName(name); - Write(value); - } - - public void WriteValue(string name, bool value) { - WriteMemberName(name); - Write(value); - } - - public void WriteValue(string name, double value) { - WriteMemberName(name); - Write(value); - } - - public void WriteValue(string value) { - if (m_context.element == JsonElementContext.Array) { - - if (m_context.needComma) - m_writer.Write(","); - WriteIndent(); - m_context.needComma = true; - - Write(value); - } else if (m_context.element == JsonElementContext.None) { - Write(value); - m_context.element = JsonElementContext.Closed; - } else { - OperationNotApplicable("WriteValue"); - } - } - - public void WriteValue(bool value) { - if (m_context.element == JsonElementContext.Array) { - - if (m_context.needComma) - m_writer.Write(","); - WriteIndent(); - m_context.needComma = true; - - Write(value); - } else if (m_context.element == JsonElementContext.None) { - Write(value); - m_context.element = JsonElementContext.Closed; - } else { - OperationNotApplicable("WriteValue"); - } - } - - public void WriteValue(double value) { - if (m_context.element == JsonElementContext.Array) { - - if (m_context.needComma) - m_writer.Write(","); - WriteIndent(); - m_context.needComma = true; - - Write(value); - } else if (m_context.element == JsonElementContext.None) { - Write(value); - m_context.element = JsonElementContext.Closed; - } else { - OperationNotApplicable("WriteValue"); - } - } - - public void BeginObject() { - if (m_context.element != JsonElementContext.None && m_context.element != JsonElementContext.Array) - OperationNotApplicable("BeginObject"); - if (m_context.needComma) - m_writer.Write(","); - - WriteIndent(); - - m_context.needComma = true; - - m_contextStack.Push(m_context); - - m_context = new Context { element = JsonElementContext.Object, needComma = false }; - m_writer.Write("{"); - } - - public void BeginObject(string name) { - WriteMemberName(name); - - m_contextStack.Push(m_context); - - m_context = new Context { element = JsonElementContext.Object, needComma = false }; - m_writer.Write("{"); - } - - public void EndObject() { - if (m_context.element != JsonElementContext.Object) - OperationNotApplicable("EndObject"); - - m_context = m_contextStack.Pop(); - if (m_contextStack.Count == 0) - m_context.element = JsonElementContext.Closed; - WriteIndent(); - m_writer.Write("}"); - } - - public void BeginArray() { - if (m_context.element != JsonElementContext.None && m_context.element != JsonElementContext.Array) - throw new InvalidOperationException(); - if (m_context.needComma) { - m_writer.Write(","); - - } - m_context.needComma = true; - - WriteIndent(); - m_contextStack.Push(m_context); - m_context = new Context { element = JsonElementContext.Array, needComma = false }; - m_writer.Write("["); - } - - public void BeginArray(string name) { - WriteMemberName(name); - - m_contextStack.Push(m_context); - - m_context = new Context { element = JsonElementContext.Array, needComma = false }; - m_writer.Write("["); - } - - public void EndArray() { - if (m_context.element != JsonElementContext.Array) - OperationNotApplicable("EndArray"); - - m_context = m_contextStack.Pop(); - if (m_contextStack.Count == 0) - m_context.element = JsonElementContext.Closed; - WriteIndent(); - m_writer.Write("]"); - } - - void Write(bool value) { - m_writer.Write(value ? "true" : "false"); - } - - void FlushBuffer() { - if (m_bufferPos > 0) { - m_writer.Write(m_buffer, 0, m_bufferPos); - m_bufferPos = 0; - } - } - - void Write(string value) { - if (value == null) { - m_writer.Write("null"); - return; - } - - Debug.Assert(m_bufferPos == 0); - - var chars = value.ToCharArray(); - m_buffer[m_bufferPos++] = '"'; - - // Analysis disable once ForCanBeConvertedToForeach - for (int i = 0; i < chars.Length; i++) { - var ch = chars[i]; - - char[] escapeSeq; - - switch (ch) { - case '\b': - escapeSeq = _escapeBKS; - break; - case '\f': - escapeSeq = _escapeFWD; - break; - case '\r': - escapeSeq = _escapeCR; - break; - case '\n': - escapeSeq = _escapeNL; - break; - case '\t': - escapeSeq = _escapeTAB; - break; - case '\\': - escapeSeq = _escapeBSLASH; - break; - case '"': - escapeSeq = _escapeQ; - break; - default: - if (ch < 0x20) { - if (m_bufferPos + 6 > BUFFER_SIZE) - FlushBuffer(); - - m_buffer[m_bufferPos++] = '\\'; - m_buffer[m_bufferPos++] = 'u'; - m_buffer[m_bufferPos++] = '0'; - m_buffer[m_bufferPos++] = '0'; - m_buffer[m_bufferPos++] = _hex[ch >> 4 & 0xf]; - m_buffer[m_bufferPos++] = _hex[ch & 0xf]; - - } else { - if (m_bufferPos >= BUFFER_SIZE) - FlushBuffer(); - m_buffer[m_bufferPos++] = ch; - } - continue; - } - - if (m_bufferPos + escapeSeq.Length > BUFFER_SIZE) - FlushBuffer(); - - Array.Copy(escapeSeq, 0, m_buffer, m_bufferPos, escapeSeq.Length); - m_bufferPos += escapeSeq.Length; - - } - - if (m_bufferPos >= BUFFER_SIZE) - FlushBuffer(); - - m_buffer[m_bufferPos++] = '"'; - - FlushBuffer(); - } - - void Write(double value) { - if (double.IsNaN(value)) - Write("NaN"); - else if (double.IsNegativeInfinity(value)) - Write("-Infinity"); - else if (double.IsPositiveInfinity(value)) - Write("Infinity"); - else - m_writer.Write(value.ToString(CultureInfo.InvariantCulture)); - } - - void OperationNotApplicable(string opName) { - throw new InvalidOperationException(String.Format("The operation '{0}' isn't applicable in the context of '{1}'", opName, m_context.element )); - } - - } -} diff -r 8dd666e6b6bf -r b49969a7043c Implab/Formats/JSON/StringTranslator.cs --- a/Implab/Formats/JSON/StringTranslator.cs Thu Oct 05 09:21:23 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,52 +0,0 @@ -using Implab; -using Implab.Formats; -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Implab.Formats.Json { - /// - /// Класс для преобразования экранированной строки JSON - /// - static class StringTranslator { - static readonly char[] _escMap; - static readonly int[] _hexMap; - - static StringTranslator() { - var chars = new char[] { 'b', 'f', 't', 'r', 'n', '\\', '/', '"' }; - var vals = new char[] { '\b', '\f', '\t', '\r', '\n', '\\', '/', '"' }; - - _escMap = new char[chars.Max() + 1]; - - for (int i = 0; i < chars.Length; i++) - _escMap[chars[i]] = vals[i]; - - var hexs = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'A', 'B', 'C', 'D', 'E', 'F' }; - var ints = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 10, 11, 12, 13, 14, 15 }; - - _hexMap = new int[hexs.Max() + 1]; - - for (int i = 0; i < hexs.Length; i++) - _hexMap[hexs[i]] = ints[i]; - - } - - internal static char TranslateEscapedChar(char symbol) { - return _escMap[symbol]; - } - - internal static char TranslateHexUnicode(char[] symbols, int offset) { - Debug.Assert(symbols != null); - Debug.Assert(symbols.Length - offset >= 4); - - int value = (_hexMap[symbols[offset]] << 12) - | (_hexMap[symbols[offset + 1]] << 8) - | (_hexMap[symbols[offset + 2]] << 4) - | (_hexMap[symbols[offset + 3]]); - return (char)value; - } - } -} diff -r 8dd666e6b6bf -r b49969a7043c Implab/Formats/Json/JsonElementContext.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Formats/Json/JsonElementContext.cs Thu Oct 05 09:24:49 2017 +0300 @@ -0,0 +1,11 @@ +namespace Implab.Formats.Json { + /// + /// internal + /// + enum JsonElementContext { + None, + Object, + Array, + Closed + } +} diff -r 8dd666e6b6bf -r b49969a7043c Implab/Formats/Json/JsonElementType.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Formats/Json/JsonElementType.cs Thu Oct 05 09:24:49 2017 +0300 @@ -0,0 +1,28 @@ +namespace Implab.Formats.Json { + /// + /// Тип элемента на котором находится парсер + /// + public enum JsonElementType { + None, + /// + /// Начало объекта + /// + BeginObject, + /// + /// Конец объекта + /// + EndObject, + /// + /// Начало массива + /// + BeginArray, + /// + /// Конец массива + /// + EndArray, + /// + /// Простое значение + /// + Value + } +} diff -r 8dd666e6b6bf -r b49969a7043c Implab/Formats/Json/JsonGrammar.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Formats/Json/JsonGrammar.cs Thu Oct 05 09:24:49 2017 +0300 @@ -0,0 +1,148 @@ +using System.Linq; +using Implab.Automaton.RegularExpressions; +using System; +using Implab.Automaton; +using Implab.Components; + +namespace Implab.Formats.Json { + public class JsonGrammar : Grammar { + public enum TokenType { + None, + BeginObject, + EndObject, + BeginArray, + EndArray, + String, + Number, + Literal, + NameSeparator, + ValueSeparator, + Whitespace, + + StringBound, + EscapedChar, + UnescapedChar, + EscapedUnicode + } + + static LazyAndWeak _instance = new LazyAndWeak(() => new JsonGrammar()); + + public static JsonGrammar Instance { + get { return _instance.Value; } + } + + readonly InputScanner m_jsonExpression; + readonly InputScanner m_stringExpression; + readonly CharAlphabet m_defaultAlphabet = new CharAlphabet(); + + public CharAlphabet DefaultAlphabet { get { return m_defaultAlphabet; } } + + public JsonGrammar() { + DefineAlphabet(Enumerable.Range(0, 0x20).Select(x => (char)x)); + var hexDigit = SymbolRangeToken('a','f').Or(SymbolRangeToken('A','F')).Or(SymbolRangeToken('0','9')); + var digit9 = SymbolRangeToken('1', '9'); + var zero = SymbolToken('0'); + var digit = zero.Or(digit9); + var dot = SymbolToken('.'); + var minus = SymbolToken('-'); + var sign = SymbolSetToken('-', '+'); + var expSign = SymbolSetToken('e', 'E'); + var letters = SymbolRangeToken('a', 'z'); + var integer = zero.Or(digit9.Cat(digit.EClosure())); + var frac = dot.Cat(digit.Closure()); + var exp = expSign.Cat(sign.Optional()).Cat(digit.Closure()); + var quote = SymbolToken('"'); + var backSlash = SymbolToken('\\'); + var specialEscapeChars = SymbolSetToken('\\', '"', '/', 'b', 'f', 't', 'n', 'r'); + var unicodeEspace = SymbolToken('u').Cat(hexDigit.Repeat(4)); + var whitespace = SymbolSetToken('\n', '\r', '\t', ' ').EClosure(); + var beginObject = whitespace.Cat(SymbolToken('{')).Cat(whitespace); + var endObject = whitespace.Cat(SymbolToken('}')).Cat(whitespace); + var beginArray = whitespace.Cat(SymbolToken('[')).Cat(whitespace); + var endArray = whitespace.Cat(SymbolToken(']')).Cat(whitespace); + var nameSep = whitespace.Cat(SymbolToken(':')).Cat(whitespace); + var valueSep = whitespace.Cat(SymbolToken(',')).Cat(whitespace); + + var number = minus.Optional().Cat(integer).Cat(frac.Optional()).Cat(exp.Optional()); + var literal = letters.Closure(); + var unescaped = SymbolTokenExcept(Enumerable.Range(0, 0x20).Union(new int[] { '\\', '"' }).Select(x => (char)x)); + + var jsonExpression = + number.Tag(TokenType.Number) + .Or(literal.Tag(TokenType.Literal)) + .Or(quote.Tag(TokenType.StringBound)) + .Or(beginObject.Tag(TokenType.BeginObject)) + .Or(endObject.Tag(TokenType.EndObject)) + .Or(beginArray.Tag(TokenType.BeginArray)) + .Or(endArray.Tag(TokenType.EndArray)) + .Or(nameSep.Tag(TokenType.NameSeparator)) + .Or(valueSep.Tag(TokenType.ValueSeparator)) + .Or(SymbolSetToken('\n', '\r', '\t', ' ').Closure().Tag(TokenType.Whitespace)); + + + var jsonStringExpression = + quote.Tag(TokenType.StringBound) + .Or(backSlash.Cat(specialEscapeChars).Tag(TokenType.EscapedChar)) + .Or(backSlash.Cat(unicodeEspace).Tag(TokenType.EscapedUnicode)) + .Or(unescaped.Closure().Tag(TokenType.UnescapedChar)); + + + m_jsonExpression = BuildScanner(jsonExpression); + m_stringExpression = BuildScanner(jsonStringExpression); + } + + public static InputScanner CreateJsonExpressionScanner() { + return Instance.m_jsonExpression.Clone(); + } + + public static InputScanner CreateStringExpressionScanner() { + return Instance.m_stringExpression.Clone(); + } + + protected override IAlphabetBuilder AlphabetBuilder { + get { + return m_defaultAlphabet; + } + } + + Token SymbolRangeToken(char start, char stop) { + return SymbolToken(Enumerable.Range(start, stop - start + 1).Select(x => (char)x)); + } + + public InputScanner BuildScanner(Token regexp) { + var dfa = new RegularDFA(AlphabetBuilder); + + var visitor = new RegularExpressionVisitor(dfa); + regexp.Accept(visitor); + visitor.BuildDFA(); + + if (dfa.IsFinalState(dfa.InitialState)) + throw new ApplicationException("The specified language contains empty token"); + + var ab = new CharAlphabet(); + var optimal = dfa.Optimize(ab); + + return new InputScanner( + optimal.CreateTransitionTable(), + optimal.CreateFinalStateTable(), + NormalizeTags(optimal.CreateTagTable()), + optimal.InitialState, + ab.CreateCharMap() + ); + } + + static TokenType[] NormalizeTags(TokenType[][] tags) { + var result = new TokenType[tags.Length]; + for(var i = 0; i< tags.Length; i++) { + if (tags[i] == null || tags[i].Length == 0) + result[i] = default(TokenType); + else if (tags[i].Length == 1) + result[i] = tags[i][0]; + else + throw new Exception($"Ambigous state tags {string.Join(", ", tags[i])}"); + } + return result; + } + + } +} diff -r 8dd666e6b6bf -r b49969a7043c Implab/Formats/Json/JsonReader.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Formats/Json/JsonReader.cs Thu Oct 05 09:24:49 2017 +0300 @@ -0,0 +1,318 @@ +using System; +using System.Diagnostics; +using System.IO; +using Implab.Automaton; +using Implab.Automaton.RegularExpressions; +using System.Linq; +using Implab.Components; +using System.Collections.Generic; +using System.Text; +using System.Globalization; + +namespace Implab.Formats.Json { + /// + /// Pull парсер JSON данных. + /// + /// + /// Следует отметить отдельную интерпретацию свойства , + /// оно означает текущий уровень вложенности объектов, однако закрывающий + /// элемент объекта и массива имеет уровень меньше, чем сам объект. + /// + /// { // Level = 1 + /// "name" : "Peter", // Level = 1 + /// "address" : { // Level = 2 + /// city : "Stern" // Level = 2 + /// } // Level = 1 + /// } // Level = 0 + /// + /// + public class JsonReader : Disposable { + + enum MemberContext { + MemberName, + MemberValue + } + + #region Parser rules + struct ParserContext { + readonly int[,] m_dfa; + int m_state; + + readonly JsonElementContext m_elementContext; + + public ParserContext(int[,] dfa, int state, JsonElementContext context) { + m_dfa = dfa; + m_state = state; + m_elementContext = context; + } + + public bool Move(JsonTokenType token) { + var next = m_dfa[m_state, (int)token]; + if (next == AutomatonConst.UNREACHABLE_STATE) + return false; + m_state = next; + return true; + } + + public JsonElementContext ElementContext { + get { return m_elementContext; } + } + } + + static readonly ParserContext _jsonContext; + static readonly ParserContext _objectContext; + static readonly ParserContext _arrayContext; + + static JsonReader() { + + var valueExpression = MakeToken(JsonTokenType.BeginArray, JsonTokenType.BeginObject, JsonTokenType.Literal, JsonTokenType.Number, JsonTokenType.String); + var memberExpression = MakeToken(JsonTokenType.String).Cat(MakeToken(JsonTokenType.NameSeparator)).Cat(valueExpression); + + var objectExpression = memberExpression + .Cat( + MakeToken(JsonTokenType.ValueSeparator) + .Cat(memberExpression) + .EClosure() + ) + .Optional() + .Cat(MakeToken(JsonTokenType.EndObject)) + .End(); + + var arrayExpression = valueExpression + .Cat( + MakeToken(JsonTokenType.ValueSeparator) + .Cat(valueExpression) + .EClosure() + ) + .Optional() + .Cat(MakeToken(JsonTokenType.EndArray)) + .End(); + + var jsonExpression = valueExpression.End(); + + _jsonContext = CreateParserContext(jsonExpression, JsonElementContext.None); + _objectContext = CreateParserContext(objectExpression, JsonElementContext.Object); + _arrayContext = CreateParserContext(arrayExpression, JsonElementContext.Array); + } + + static Token MakeToken(params JsonTokenType[] input) { + return Token.New( input.Select(t => (int)t).ToArray() ); + } + + static ParserContext CreateParserContext(Token expr, JsonElementContext context) { + + var dfa = new DFATable(); + var builder = new RegularExpressionVisitor(dfa); + expr.Accept(builder); + builder.BuildDFA(); + + return new ParserContext(dfa.CreateTransitionTable(), dfa.InitialState, context); + } + + #endregion + + readonly JsonScanner m_scanner; + // json starts from the value context and may content even a single literal + MemberContext m_memberContext = MemberContext.MemberValue; + + JsonElementType m_elementType; + object m_elementValue; + string m_memberName = String.Empty; + + Stack m_stack = new Stack(); + ParserContext m_context = _jsonContext; + + /// + /// Создает новый парсер на основе строки, содержащей JSON + /// + /// + JsonReader(JsonScanner scanner) { + m_scanner = scanner; + } + + public int Level { + get { return m_stack.Count; } + } + + /// + /// Тип текущего элемента на котором стоит парсер. + /// + public JsonElementType ElementType { + get { return m_elementType; } + } + + /// + /// Имя элемента - имя свойства родительского контейнера. Для элементов массивов и корневого всегда + /// пустая строка. + /// + public string ElementName { + get { return m_memberName; } + } + + /// + /// Значение элемента. Только для элементов типа , для остальных null + /// + public object ElementValue { + get { return m_elementValue; } + } + + /// + /// Читает слеюудущий объект из потока + /// + /// true - операция чтения прошла успешно, false - конец данных + public bool Read() { + string tokenValue; + JsonTokenType tokenType; + + m_memberName = String.Empty; + + while (m_scanner.ReadToken(out tokenValue, out tokenType)) { + if(!m_context.Move(tokenType)) + UnexpectedToken(tokenValue, tokenType); + + switch (tokenType) { + case JsonTokenType.BeginObject: + m_stack.Push(m_context); + m_context = _objectContext; + + m_elementValue = null; + m_memberContext = MemberContext.MemberName; + m_elementType = JsonElementType.BeginObject; + return true; + case JsonTokenType.EndObject: + if (m_stack.Count == 0) + UnexpectedToken(tokenValue, tokenType); + m_context = m_stack.Pop(); + + m_elementValue = null; + m_elementType = JsonElementType.EndObject; + return true; + case JsonTokenType.BeginArray: + m_stack.Push(m_context); + m_context = _arrayContext; + + m_elementValue = null; + m_memberContext = MemberContext.MemberValue; + m_elementType = JsonElementType.BeginArray; + return true; + case JsonTokenType.EndArray: + if (m_stack.Count == 0) + UnexpectedToken(tokenValue, tokenType); + m_context = m_stack.Pop(); + + m_elementValue = null; + m_elementType = JsonElementType.EndArray; + return true; + case JsonTokenType.String: + if (m_memberContext == MemberContext.MemberName) { + m_memberName = tokenValue; + break; + } + m_elementType = JsonElementType.Value; + m_elementValue = tokenValue; + return true; + case JsonTokenType.Number: + m_elementType = JsonElementType.Value; + m_elementValue = double.Parse(tokenValue, CultureInfo.InvariantCulture); + return true; + case JsonTokenType.Literal: + m_elementType = JsonElementType.Value; + m_elementValue = ParseLiteral(tokenValue); + return true; + case JsonTokenType.NameSeparator: + m_memberContext = MemberContext.MemberValue; + break; + case JsonTokenType.ValueSeparator: + m_memberContext = m_context.ElementContext == JsonElementContext.Object ? MemberContext.MemberName : MemberContext.MemberValue; + break; + default: + UnexpectedToken(tokenValue, tokenType); + break; + } + } + if (m_context.ElementContext != JsonElementContext.None) + throw new ParserException("Unexpedted end of data"); + + Eof = true; + + return false; + } + + object ParseLiteral(string literal) { + switch (literal) { + case "null": + return null; + case "false": + return false; + case "true": + return true; + default: + UnexpectedToken(literal, JsonTokenType.Literal); + return null; // avoid compliler error + } + } + + void UnexpectedToken(object value, JsonTokenType tokenType) { + throw new ParserException(String.Format("Unexpected token {0}: '{1}'", tokenType, value)); + } + + + /// + /// Признак конца потока + /// + public bool Eof { + get; + private set; + } + + protected override void Dispose(bool disposing) { + if (disposing) + m_scanner.Dispose(); + } + + /// + /// Переходит в конец текущего объекта. + /// + public void SeekElementEnd() { + var level = Level - 1; + + Debug.Assert(level >= 0); + + while (Level != level) + Read(); + } + + public static JsonReader Create(string file, Encoding encoding) { + return new JsonReader(JsonTextScanner.Create(file, encoding)); + } + + public static JsonReader Create(string file) { + return new JsonReader(JsonTextScanner.Create(file)); + } + + public static JsonReader Create(Stream stream, Encoding encoding) { + return new JsonReader(JsonTextScanner.Create(stream, encoding)); + } + + public static JsonReader Create(Stream stream) { + return new JsonReader(JsonTextScanner.Create(stream)); + } + + public static JsonReader Create(TextReader reader) { + return new JsonReader(JsonTextScanner.Create(reader)); + } + + public static JsonReader ParseString(string data) { + return new JsonReader(JsonStringScanner.Create(data)); + } + + public static JsonReader ParseString(string data, int offset, int length) { + return new JsonReader(JsonStringScanner.Create(data, offset, length)); + } + + public static JsonReader ParseString(char[] data, int offset, int lenght) { + return new JsonReader(JsonStringScanner.Create(data, offset, lenght)); + } + } + +} diff -r 8dd666e6b6bf -r b49969a7043c Implab/Formats/Json/JsonScanner.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Formats/Json/JsonScanner.cs Thu Oct 05 09:24:49 2017 +0300 @@ -0,0 +1,190 @@ +using System; +using System.Globalization; +using Implab.Automaton; +using System.Text; +using Implab.Components; +using System.IO; + +namespace Implab.Formats.Json { + /// + /// Сканнер (лексер), разбивающий поток символов на токены JSON. + /// + public abstract class JsonScanner : Disposable { + readonly InputScanner m_jsonContext = JsonGrammar.CreateJsonExpressionScanner(); + readonly InputScanner m_stringContext = JsonGrammar.CreateStringExpressionScanner(); + + readonly char[] m_unescapeBuf = new char[4]; + readonly char[] m_buffer; + int m_length; + int m_pos; + readonly StringBuilder m_tokenBuilder = new StringBuilder(); + + protected JsonScanner(char[] buffer, int pos, int length) { + m_buffer = buffer; + m_pos = pos; + m_length = length; + } + + bool ReadChunk(InputScanner scanner, out JsonGrammar.TokenType tokenType) { + scanner.ResetState(); + + while(scanner.Scan(m_buffer, m_pos, m_length)) { + // scanner requests new data + + if (m_pos != m_length) // capture results for the future + m_tokenBuilder.Append(m_buffer, m_pos, m_length - m_pos); + + // read next data + m_length = Read(m_buffer, 0, m_buffer.Length); + + if (m_length == 0) { + // no data is read + if (scanner.Position == m_pos) { + // scanned hasn't moved, that's the end + m_pos = 0; + tokenType = JsonGrammar.TokenType.None; + return false; + } + + if (scanner.IsFinal) { + m_pos = 0; + tokenType = scanner.Tag; + return true; + } else { + throw new ParserException("Unexpected EOF"); + } + } + + m_pos = 0; + } + var scannerPos = scanner.Position; + + // scanner stops as scannerPos + if (!scanner.IsFinal) + throw new ParserException($"Unexpected character '{m_buffer[scannerPos + 1]}'"); + + tokenType = scanner.Tag; + if (scannerPos != m_pos && tokenType == JsonGrammar.TokenType.Number || tokenType == JsonGrammar.TokenType.Literal) + m_tokenBuilder.Append(m_buffer, m_pos, scannerPos - m_pos); + + m_pos = scannerPos; + return true; + } + + bool ReadStringChunk(InputScanner scanner, out JsonGrammar.TokenType tokenType) { + scanner.ResetState(); + + while (scanner.Scan(m_buffer, m_pos, m_length)) { + // scanner requests new data + + if (m_pos != m_length) // capture results for the future + m_tokenBuilder.Append(m_buffer, m_pos, m_length - m_pos); + + // read next data + m_length = Read(m_buffer, 0, m_buffer.Length); + + if (m_length == 0) { + // no data is read + if (scanner.Position == m_pos) { + // scanned hasn't moved, that's the end + m_pos = 0; + tokenType = JsonGrammar.TokenType.None; + return false; + } + + if (scanner.IsFinal) { + m_pos = 0; + tokenType = scanner.Tag; + return true; + } else { + throw new ParserException("Unexpected EOF"); + } + } + + m_pos = 0; + } + var scannerPos = scanner.Position; + + // scanner stops as scannerPos + if (!scanner.IsFinal) + throw new ParserException($"Unexpected character '{m_buffer[scannerPos + 1]}'"); + + if (scannerPos != m_pos) { + m_tokenBuilder.Append(m_buffer, m_pos, scannerPos - m_pos); + m_pos = scannerPos; + } + tokenType = scanner.Tag; + return true; + } + + protected abstract int Read(char[] buffer, int offset, int size); + + + /// + /// Читает следующий лексический элемент из входных данных. + /// + /// Возвращает значение прочитанного токена. + /// Возвращает тип прочитанного токена. + /// true - чтение произведено успешно. false - достигнут конец входных данных + /// В случе если токен не распознается, возникает исключение. Значения токенов обрабатываются, т.е. + /// в строках обрабатываются экранированные символы, числа становтся типа double. + public bool ReadToken(out string tokenValue, out JsonTokenType tokenType) { + JsonGrammar.TokenType tag; + m_tokenBuilder.Clear(); + while (ReadChunk(m_jsonContext, out tag)) { + switch (tag) { + case JsonGrammar.TokenType.StringBound: + tokenValue = ReadString(); + tokenType = JsonTokenType.String; + break; + case JsonGrammar.TokenType.Number: + tokenValue = m_tokenBuilder.ToString(); + tokenType = JsonTokenType.Number; + break; + case JsonGrammar.TokenType.Literal: + tokenType = JsonTokenType.Literal; + tokenValue = m_tokenBuilder.ToString(); + break; + case JsonGrammar.TokenType.Whitespace: + m_tokenBuilder.Clear(); + continue; + default: + tokenType = (JsonTokenType)tag; + tokenValue = null; + break; + } + return true; + } + tokenValue = null; + tokenType = JsonTokenType.None; + return false; + } + + string ReadString() { + JsonGrammar.TokenType tag; + m_tokenBuilder.Clear(); + + while (ReadStringChunk(m_stringContext, out tag)) { + switch (tag) { + case JsonGrammar.TokenType.StringBound: + m_tokenBuilder.Length--; + return m_tokenBuilder.ToString(); + case JsonGrammar.TokenType.UnescapedChar: + break; + case JsonGrammar.TokenType.EscapedUnicode: // \xXXXX - unicode escape sequence + m_tokenBuilder.CopyTo(m_tokenBuilder.Length - 4, m_unescapeBuf, 0, 4); + m_tokenBuilder.Length -= 6; + m_tokenBuilder.Append(StringTranslator.TranslateHexUnicode(m_unescapeBuf, 0)); + break; + case JsonGrammar.TokenType.EscapedChar: // \t - escape sequence + var ch = m_tokenBuilder[m_tokenBuilder.Length-1]; + m_tokenBuilder.Length -= 2; + m_tokenBuilder.Append(StringTranslator.TranslateEscapedChar(ch)); + break; + } + } + + throw new ParserException("Unexpected end of data"); + } + } +} diff -r 8dd666e6b6bf -r b49969a7043c Implab/Formats/Json/JsonStringScanner.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Formats/Json/JsonStringScanner.cs Thu Oct 05 09:24:49 2017 +0300 @@ -0,0 +1,76 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Implab.Formats.Json { + public class JsonStringScanner : JsonScanner { + const int _defaultBuffer = 64; + + readonly string m_data; + int m_offset; + + JsonStringScanner(string data, char[] buffer, int pos, int length, int offset) : base(buffer, pos, length) { + m_data = data; + m_offset = offset; + } + + protected override int Read(char[] buffer, int offset, int size) { + if (m_data == null) + return 0; + if (m_offset >= m_data.Length) + return 0; + + var count = Math.Min(size, m_data.Length - m_offset); + + m_data.CopyTo(m_offset, buffer, offset, count); + m_offset += count; + + return count; + } + + public static JsonStringScanner Create(string data) { + Safe.ArgumentNotNull(data, nameof(data)); + + if (data.Length <= _defaultBuffer) + return new JsonStringScanner(null, data.ToCharArray(), 0, data.Length, data.Length); + + var buffer = new char[_defaultBuffer]; + data.CopyTo(0, buffer, 0, _defaultBuffer); + return new JsonStringScanner(data, buffer, 0, _defaultBuffer, _defaultBuffer); + } + + public static JsonStringScanner Create(string data, int offset, int length) { + Safe.ArgumentNotNull(data, nameof(data)); + Safe.ArgumentGreaterThan(offset, 0, nameof(offset)); + Safe.ArgumentGreaterThan(length, 0, nameof(length)); + + if (offset + length > data.Length) + throw new ArgumentOutOfRangeException("Specified offset and length are out of the string bounds"); + + if (length <= _defaultBuffer) { + var buffer = new char[length]; + data.CopyTo(offset, buffer, 0, length); + + return new JsonStringScanner(null, buffer, 0, length, length); + } else { + var buffer = new char[_defaultBuffer]; + data.CopyTo(offset, buffer, 0, _defaultBuffer); + return new JsonStringScanner(data, buffer, 0, _defaultBuffer, offset + _defaultBuffer); + } + } + + public static JsonStringScanner Create(char[] data, int offset, int length) { + Safe.ArgumentNotNull(data, nameof(data)); + Safe.ArgumentGreaterThan(offset, 0, nameof(offset)); + Safe.ArgumentGreaterThan(length, 0, nameof(length)); + + if (offset + length > data.Length) + throw new ArgumentOutOfRangeException("Specified offset and length are out of the array bounds"); + + return new JsonStringScanner(null, data, offset, offset + length, offset + length); + + } + } +} diff -r 8dd666e6b6bf -r b49969a7043c Implab/Formats/Json/JsonTextScanner.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Formats/Json/JsonTextScanner.cs Thu Oct 05 09:24:49 2017 +0300 @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Implab.Formats.Json { + public class JsonTextScanner : JsonScanner { + const int _bufferSize = 16*4096; + readonly TextReader m_reader; + + JsonTextScanner(TextReader reader, char[] buffer) : base(buffer, 0, 0) { + m_reader = reader; + } + + protected override int Read(char[] buffer, int offset, int size) { + return m_reader.Read(buffer, offset, size); + } + + public static JsonTextScanner Create(string file, Encoding encoding) { + return new JsonTextScanner(new StreamReader(file, encoding), new char[_bufferSize]); + } + + public static JsonTextScanner Create(string file) { + return new JsonTextScanner(new StreamReader(file), new char[_bufferSize]); + } + + public static JsonTextScanner Create(Stream stream, Encoding encoding) { + return new JsonTextScanner(new StreamReader(stream, encoding), new char[_bufferSize]); + } + + public static JsonTextScanner Create(Stream stream) { + return new JsonTextScanner(new StreamReader(stream), new char[_bufferSize]); + } + + public static JsonTextScanner Create(TextReader reader) { + Safe.ArgumentNotNull(reader, nameof(reader)); + return new JsonTextScanner(reader, new char[_bufferSize]); + } + + protected override void Dispose(bool disposing) { + if (disposing) + Safe.Dispose(m_reader); + + base.Dispose(disposing); + } + } +} diff -r 8dd666e6b6bf -r b49969a7043c Implab/Formats/Json/JsonTokenType.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Formats/Json/JsonTokenType.cs Thu Oct 05 09:24:49 2017 +0300 @@ -0,0 +1,44 @@ +namespace Implab.Formats.Json { + /// + /// Тип токенов, возвращаемых . + /// + public enum JsonTokenType : int { + None = 0, + /// + /// Начало объекта + /// + BeginObject, + /// + /// Конец объекта + /// + EndObject, + /// + /// Начало массива + /// + BeginArray, + /// + /// Конец массива + /// + EndArray, + /// + /// Строка + /// + String, + /// + /// Число + /// + Number, + /// + /// Литерал + /// + Literal, + /// + /// Разделитель имени : + /// + NameSeparator, + /// + /// Разделитель имени , + /// + ValueSeparator + } +} diff -r 8dd666e6b6bf -r b49969a7043c Implab/Formats/Json/JsonWriter.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Formats/Json/JsonWriter.cs Thu Oct 05 09:24:49 2017 +0300 @@ -0,0 +1,319 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Globalization; +using System.Diagnostics; + +namespace Implab.Formats.Json { + public class JsonWriter { + struct Context { + public bool needComma; + public JsonElementContext element; + } + Stack m_contextStack = new Stack(); + Context m_context; + + const int BUFFER_SIZE = 64; + + TextWriter m_writer; + readonly bool m_indent = true; + readonly int m_indentSize = 4; + readonly char[] m_buffer = new char[BUFFER_SIZE]; + int m_bufferPos; + + static readonly char [] _hex = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; + static readonly char [] _escapeBKS, + _escapeFWD, + _escapeCR, + _escapeNL, + _escapeTAB, + _escapeBSLASH, + _escapeQ; + + static JsonWriter() { + _escapeBKS = "\\b".ToCharArray(); + _escapeFWD = "\\f".ToCharArray(); + _escapeCR = "\\r".ToCharArray(); + _escapeNL = "\\n".ToCharArray(); + _escapeTAB = "\\t".ToCharArray(); + _escapeBSLASH = "\\\\".ToCharArray(); + _escapeQ = "\\\"".ToCharArray(); + } + + public JsonWriter(TextWriter writer) { + Safe.ArgumentNotNull(writer, "writer"); + m_writer = writer; + } + + public JsonWriter(TextWriter writer, bool indent) { + Safe.ArgumentNotNull(writer, "writer"); + + m_writer = writer; + m_indent = indent; + } + + void WriteIndent() { + if (m_indent) { + var indent = new char[m_contextStack.Count * m_indentSize + 1]; + indent[0] = '\n'; + for (int i = 1; i < indent.Length; i++) + indent[i] = ' '; + m_writer.Write(new String(indent)); + } else { + m_writer.Write(' '); + } + } + + void WriteMemberName(string name) { + Safe.ArgumentNotEmpty(name, "name"); + if (m_context.element != JsonElementContext.Object) + OperationNotApplicable("WriteMember"); + if (m_context.needComma) + m_writer.Write(","); + + WriteIndent(); + m_context.needComma = true; + Write(name); + m_writer.Write(" : "); + } + + public void WriteValue(string name, string value) { + WriteMemberName(name); + Write(value); + } + + public void WriteValue(string name, bool value) { + WriteMemberName(name); + Write(value); + } + + public void WriteValue(string name, double value) { + WriteMemberName(name); + Write(value); + } + + public void WriteValue(string value) { + if (m_context.element == JsonElementContext.Array) { + + if (m_context.needComma) + m_writer.Write(","); + WriteIndent(); + m_context.needComma = true; + + Write(value); + } else if (m_context.element == JsonElementContext.None) { + Write(value); + m_context.element = JsonElementContext.Closed; + } else { + OperationNotApplicable("WriteValue"); + } + } + + public void WriteValue(bool value) { + if (m_context.element == JsonElementContext.Array) { + + if (m_context.needComma) + m_writer.Write(","); + WriteIndent(); + m_context.needComma = true; + + Write(value); + } else if (m_context.element == JsonElementContext.None) { + Write(value); + m_context.element = JsonElementContext.Closed; + } else { + OperationNotApplicable("WriteValue"); + } + } + + public void WriteValue(double value) { + if (m_context.element == JsonElementContext.Array) { + + if (m_context.needComma) + m_writer.Write(","); + WriteIndent(); + m_context.needComma = true; + + Write(value); + } else if (m_context.element == JsonElementContext.None) { + Write(value); + m_context.element = JsonElementContext.Closed; + } else { + OperationNotApplicable("WriteValue"); + } + } + + public void BeginObject() { + if (m_context.element != JsonElementContext.None && m_context.element != JsonElementContext.Array) + OperationNotApplicable("BeginObject"); + if (m_context.needComma) + m_writer.Write(","); + + WriteIndent(); + + m_context.needComma = true; + + m_contextStack.Push(m_context); + + m_context = new Context { element = JsonElementContext.Object, needComma = false }; + m_writer.Write("{"); + } + + public void BeginObject(string name) { + WriteMemberName(name); + + m_contextStack.Push(m_context); + + m_context = new Context { element = JsonElementContext.Object, needComma = false }; + m_writer.Write("{"); + } + + public void EndObject() { + if (m_context.element != JsonElementContext.Object) + OperationNotApplicable("EndObject"); + + m_context = m_contextStack.Pop(); + if (m_contextStack.Count == 0) + m_context.element = JsonElementContext.Closed; + WriteIndent(); + m_writer.Write("}"); + } + + public void BeginArray() { + if (m_context.element != JsonElementContext.None && m_context.element != JsonElementContext.Array) + throw new InvalidOperationException(); + if (m_context.needComma) { + m_writer.Write(","); + + } + m_context.needComma = true; + + WriteIndent(); + m_contextStack.Push(m_context); + m_context = new Context { element = JsonElementContext.Array, needComma = false }; + m_writer.Write("["); + } + + public void BeginArray(string name) { + WriteMemberName(name); + + m_contextStack.Push(m_context); + + m_context = new Context { element = JsonElementContext.Array, needComma = false }; + m_writer.Write("["); + } + + public void EndArray() { + if (m_context.element != JsonElementContext.Array) + OperationNotApplicable("EndArray"); + + m_context = m_contextStack.Pop(); + if (m_contextStack.Count == 0) + m_context.element = JsonElementContext.Closed; + WriteIndent(); + m_writer.Write("]"); + } + + void Write(bool value) { + m_writer.Write(value ? "true" : "false"); + } + + void FlushBuffer() { + if (m_bufferPos > 0) { + m_writer.Write(m_buffer, 0, m_bufferPos); + m_bufferPos = 0; + } + } + + void Write(string value) { + if (value == null) { + m_writer.Write("null"); + return; + } + + Debug.Assert(m_bufferPos == 0); + + var chars = value.ToCharArray(); + m_buffer[m_bufferPos++] = '"'; + + // Analysis disable once ForCanBeConvertedToForeach + for (int i = 0; i < chars.Length; i++) { + var ch = chars[i]; + + char[] escapeSeq; + + switch (ch) { + case '\b': + escapeSeq = _escapeBKS; + break; + case '\f': + escapeSeq = _escapeFWD; + break; + case '\r': + escapeSeq = _escapeCR; + break; + case '\n': + escapeSeq = _escapeNL; + break; + case '\t': + escapeSeq = _escapeTAB; + break; + case '\\': + escapeSeq = _escapeBSLASH; + break; + case '"': + escapeSeq = _escapeQ; + break; + default: + if (ch < 0x20) { + if (m_bufferPos + 6 > BUFFER_SIZE) + FlushBuffer(); + + m_buffer[m_bufferPos++] = '\\'; + m_buffer[m_bufferPos++] = 'u'; + m_buffer[m_bufferPos++] = '0'; + m_buffer[m_bufferPos++] = '0'; + m_buffer[m_bufferPos++] = _hex[ch >> 4 & 0xf]; + m_buffer[m_bufferPos++] = _hex[ch & 0xf]; + + } else { + if (m_bufferPos >= BUFFER_SIZE) + FlushBuffer(); + m_buffer[m_bufferPos++] = ch; + } + continue; + } + + if (m_bufferPos + escapeSeq.Length > BUFFER_SIZE) + FlushBuffer(); + + Array.Copy(escapeSeq, 0, m_buffer, m_bufferPos, escapeSeq.Length); + m_bufferPos += escapeSeq.Length; + + } + + if (m_bufferPos >= BUFFER_SIZE) + FlushBuffer(); + + m_buffer[m_bufferPos++] = '"'; + + FlushBuffer(); + } + + void Write(double value) { + if (double.IsNaN(value)) + Write("NaN"); + else if (double.IsNegativeInfinity(value)) + Write("-Infinity"); + else if (double.IsPositiveInfinity(value)) + Write("Infinity"); + else + m_writer.Write(value.ToString(CultureInfo.InvariantCulture)); + } + + void OperationNotApplicable(string opName) { + throw new InvalidOperationException(String.Format("The operation '{0}' isn't applicable in the context of '{1}'", opName, m_context.element )); + } + + } +} diff -r 8dd666e6b6bf -r b49969a7043c Implab/Formats/Json/StringTranslator.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Formats/Json/StringTranslator.cs Thu Oct 05 09:24:49 2017 +0300 @@ -0,0 +1,52 @@ +using Implab; +using Implab.Formats; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Implab.Formats.Json { + /// + /// Класс для преобразования экранированной строки JSON + /// + static class StringTranslator { + static readonly char[] _escMap; + static readonly int[] _hexMap; + + static StringTranslator() { + var chars = new char[] { 'b', 'f', 't', 'r', 'n', '\\', '/', '"' }; + var vals = new char[] { '\b', '\f', '\t', '\r', '\n', '\\', '/', '"' }; + + _escMap = new char[chars.Max() + 1]; + + for (int i = 0; i < chars.Length; i++) + _escMap[chars[i]] = vals[i]; + + var hexs = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'A', 'B', 'C', 'D', 'E', 'F' }; + var ints = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 10, 11, 12, 13, 14, 15 }; + + _hexMap = new int[hexs.Max() + 1]; + + for (int i = 0; i < hexs.Length; i++) + _hexMap[hexs[i]] = ints[i]; + + } + + internal static char TranslateEscapedChar(char symbol) { + return _escMap[symbol]; + } + + internal static char TranslateHexUnicode(char[] symbols, int offset) { + Debug.Assert(symbols != null); + Debug.Assert(symbols.Length - offset >= 4); + + int value = (_hexMap[symbols[offset]] << 12) + | (_hexMap[symbols[offset + 1]] << 8) + | (_hexMap[symbols[offset + 2]] << 4) + | (_hexMap[symbols[offset + 3]]); + return (char)value; + } + } +} diff -r 8dd666e6b6bf -r b49969a7043c Implab/Implab.csproj --- a/Implab/Implab.csproj Thu Oct 05 09:21:23 2017 +0300 +++ b/Implab/Implab.csproj Thu Oct 05 09:24:49 2017 +0300 @@ -15,7 +15,7 @@ full false bin\Debug - TRACE;DEBUG; + TRACE;DEBUG;NET_4_5 prompt 4 false @@ -25,44 +25,7 @@ full true bin\Release - prompt - 4 - false - - - true - full - false - bin\Debug - TRACE;DEBUG;NET_4_5 - prompt - 4 - true - false - - - true - bin\Release - prompt - 4 - false NET_4_5 - - - true - full - false - bin\Debug - TRACE;DEBUG;NET_4_5;MONO - prompt - 4 - true - false - - - true - bin\Release - NET_4_5;MONO; prompt 4 false @@ -219,77 +182,6 @@ - - - - - - - - - - - - - - - - - - - I - - - - - Attribute - - - - - EventArgs - - - - - Exception - - - - - - - - - m_ - - - - - _ - - - - - m_ - - - - - - - - - - T - - - - - - - - diff -r 8dd666e6b6bf -r b49969a7043c Implab/Xml/SerializationHelpers.cs --- a/Implab/Xml/SerializationHelpers.cs Thu Oct 05 09:21:23 2017 +0300 +++ b/Implab/Xml/SerializationHelpers.cs Thu Oct 05 09:24:49 2017 +0300 @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -32,6 +33,11 @@ return doc; } + public static void SerializeToFile(string file, T obj) { + using (var writer = File.CreateText(file)) + SerializersPool.Instance.Serialize(writer, obj); + } + public static T DeserializeFromString(string data) { return SerializersPool.Instance.DeserializeFromString(data); } diff -r 8dd666e6b6bf -r b49969a7043c MonoPlay/MonoPlay.csproj --- a/MonoPlay/MonoPlay.csproj Thu Oct 05 09:21:23 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,53 +0,0 @@ - - - - Debug - AnyCPU - 8.0.30703 - 2.0 - {15DD7123-D504-4627-8B4F-D00C7F04D033} - Exe - MonoPlay - MonoPlay - v4.5 - 0.2 - - - true - full - false - bin\Debug - DEBUG;TRACE; - prompt - 4 - false - - - full - true - bin\Release - prompt - 4 - false - - - - - ..\packages\System.Text.Json.2.0.0.11\lib\net40\System.Text.Json.dll - - - - - - - - - - {F550F1F8-8746-4AD0-9614-855F4C4B7F05} - Implab - - - - - - \ No newline at end of file diff -r 8dd666e6b6bf -r b49969a7043c MonoPlay/Program.cs --- a/MonoPlay/Program.cs Thu Oct 05 09:21:23 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -using Implab; -using Implab.Parallels; -using Implab.Diagnostics; -using System.Threading; - -namespace MonoPlay { - class MainClass { - - - public static void Main(string[] args) { - var pool = new WorkerPool(10); - - var listerner = new ConsoleTraceListener(); - listerner.Subscribe(); - - TraceLog.StartLogicalOperation("Main"); - - - var d = pool.Invoke(() => { - TraceLog.StartLogicalOperation("Worker"); - Thread.Sleep(100); - TraceLog.TraceInformation("worker done"); - TraceLog.EndLogicalOperation(); - }); - - var op = TraceContext.Instance.CurrentOperation; - ThreadPool.QueueUserWorkItem((o) => { - TraceContext.Instance.EnterLogicalOperation(op, false); - TraceLog.StartLogicalOperation("Thread"); - Thread.Sleep(100); - TraceLog.TraceInformation("thread done"); - TraceLog.EndLogicalOperation(); - }); - - TraceLog.TraceInformation("main done"); - TraceLog.EndLogicalOperation(); - - d.Join(); - - - - } - - } -} diff -r 8dd666e6b6bf -r b49969a7043c MonoPlay/Properties/AssemblyInfo.cs --- a/MonoPlay/Properties/AssemblyInfo.cs Thu Oct 05 09:21:23 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,27 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; - -// Information about this assembly is defined by the following attributes. -// Change them to the values specific to your project. - -[assembly: AssemblyTitle("MonoPlay")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("")] -[assembly: AssemblyCopyright("sergey")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". -// The form "{Major}.{Minor}.*" will automatically update the build and revision, -// and "{Major}.{Minor}.{Build}.*" will update just the revision. - -[assembly: AssemblyVersion("1.0.*")] - -// The following attributes are used to specify the signing key for the assembly, -// if desired. See the Mono documentation for more information about signing. - -//[assembly: AssemblyDelaySign(false)] -//[assembly: AssemblyKeyFile("")] - diff -r 8dd666e6b6bf -r b49969a7043c MonoPlay/packages.config --- a/MonoPlay/packages.config Thu Oct 05 09:21:23 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ - - - - \ No newline at end of file