Initial check-in.
This commit is contained in:
Родитель
2c661949e9
Коммит
8dba9a6f83
|
@ -0,0 +1,63 @@
|
|||
###############################################################################
|
||||
# Set default behavior to automatically normalize line endings.
|
||||
###############################################################################
|
||||
* text=auto
|
||||
|
||||
###############################################################################
|
||||
# Set default behavior for command prompt diff.
|
||||
#
|
||||
# This is need for earlier builds of msysgit that does not have it on by
|
||||
# default for csharp files.
|
||||
# Note: This is only used by command line
|
||||
###############################################################################
|
||||
#*.cs diff=csharp
|
||||
|
||||
###############################################################################
|
||||
# Set the merge driver for project and solution files
|
||||
#
|
||||
# Merging from the command prompt will add diff markers to the files if there
|
||||
# are conflicts (Merging from VS is not affected by the settings below, in VS
|
||||
# the diff markers are never inserted). Diff markers may cause the following
|
||||
# file extensions to fail to load in VS. An alternative would be to treat
|
||||
# these files as binary and thus will always conflict and require user
|
||||
# intervention with every merge. To do so, just uncomment the entries below
|
||||
###############################################################################
|
||||
#*.sln merge=binary
|
||||
#*.csproj merge=binary
|
||||
#*.vbproj merge=binary
|
||||
#*.vcxproj merge=binary
|
||||
#*.vcproj merge=binary
|
||||
#*.dbproj merge=binary
|
||||
#*.fsproj merge=binary
|
||||
#*.lsproj merge=binary
|
||||
#*.wixproj merge=binary
|
||||
#*.modelproj merge=binary
|
||||
#*.sqlproj merge=binary
|
||||
#*.wwaproj merge=binary
|
||||
|
||||
###############################################################################
|
||||
# behavior for image files
|
||||
#
|
||||
# image files are treated as binary by default.
|
||||
###############################################################################
|
||||
#*.jpg binary
|
||||
#*.png binary
|
||||
#*.gif binary
|
||||
|
||||
###############################################################################
|
||||
# diff behavior for common document formats
|
||||
#
|
||||
# Convert binary document formats to text before diffing them. This feature
|
||||
# is only available from the command line. Turn it on by uncommenting the
|
||||
# entries below.
|
||||
###############################################################################
|
||||
#*.doc diff=astextplain
|
||||
#*.DOC diff=astextplain
|
||||
#*.docx diff=astextplain
|
||||
#*.DOCX diff=astextplain
|
||||
#*.dot diff=astextplain
|
||||
#*.DOT diff=astextplain
|
||||
#*.pdf diff=astextplain
|
||||
#*.PDF diff=astextplain
|
||||
#*.rtf diff=astextplain
|
||||
#*.RTF diff=astextplain
|
|
@ -0,0 +1,193 @@
|
|||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
|
||||
# User-specific files
|
||||
*.suo
|
||||
*.user
|
||||
*.sln.docstates
|
||||
|
||||
# Build results
|
||||
[Dd]rop/
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
x64/
|
||||
build/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
|
||||
# Roslyn cache directories
|
||||
*.ide/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
#NUNIT
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_i.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
|
||||
# JustCode is a .NET coding addin-in
|
||||
.JustCode
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# NCrunch
|
||||
_NCrunch_*
|
||||
.*crunch*.local.xml
|
||||
|
||||
# MightyMoose
|
||||
*.mm.*
|
||||
AutoTest.Net/
|
||||
|
||||
# Web workbench (sass)
|
||||
.sass-cache/
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
## TODO: Comment the next line if you want to checkin your
|
||||
## web deploy settings but do note that will include unencrypted
|
||||
## passwords
|
||||
#*.pubxml
|
||||
|
||||
# NuGet Bootstrap Tools
|
||||
.tools/
|
||||
|
||||
# NuGet Packages Directory
|
||||
packages/*
|
||||
## TODO: If the tool you use requires repositories.config
|
||||
## uncomment the next line
|
||||
#!packages/repositories.config
|
||||
|
||||
# Enable "build/" folder in the NuGet Packages folder since
|
||||
# NuGet packages use it for MSBuild targets.
|
||||
# This line needs to be after the ignore of the build folder
|
||||
# (and the packages folder if the line above has been uncommented)
|
||||
!packages/build/
|
||||
|
||||
# Windows Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
|
||||
# Windows Store app package directory
|
||||
AppPackages/
|
||||
|
||||
# Others
|
||||
sql/
|
||||
*.Cache
|
||||
ClientBin/
|
||||
[Ss]tyle[Cc]op.*
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
node_modules/
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file
|
||||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
# because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
# LightSwitch generated files
|
||||
GeneratedArtifacts/
|
||||
_Pvt_Extensions/
|
||||
ModelManifest.xml
|
|
@ -0,0 +1,30 @@
|
|||
Contributing
|
||||
============
|
||||
There are many ways to contribute.
|
||||
|
||||
1. [Report defects and provide suggestions](https://github.com/Microsoft/Microsoft.Shared.Dna.Json/issues).
|
||||
If you believe you have found a security vulnerability in this project, please follow [these steps](https://technet.microsoft.com/en-us/security/ff852094.aspx) to report it. For more information on how vulnerabilities are disclosed, see [Coordinated Vulnerability Disclosure](https://technet.microsoft.com/en-us/security/dn467923).
|
||||
2. Review [pull requests](https://github.com/Microsoft/Microsoft.Shared.Dna.Json/pulls), even if it's just to verify that the defect was fixed or that the feature was implemented as intended.
|
||||
3. Contribute fixes and features:
|
||||
1. Fork this repository (https://github.com/Microsoft/Microsoft.Shared.Dna.Json/fork) and clone it.
|
||||
2. Create a feature branch (`git checkout -b my-new-feature`).
|
||||
3. Make small commits as you go along (`git commit -am 'Add helper method with test'`).
|
||||
4. Push your feature branch to your fork (`git push origin my-new-feature`).
|
||||
5. Create a new Pull Request (https://github.com/Microsoft/Microsoft.Shared.Dna.Json/pulls).
|
||||
|
||||
For source code contributions, you will need to complete a **Contributor License Agreement (CLA)**. Briefly, this agreement testifies that you grant us permission to use the submitted change according to the terms of the project's license, and that the work being submitted is under the appropriate copyright.
|
||||
|
||||
The Contributor License Agreement (CLA) process
|
||||
-----------------------------------------------
|
||||
The CLA process is automated on this GitHub repository. Here is what happens when you open a pull request:
|
||||
|
||||
1. The Microsoft Pull Request BOT (MSBOT) checks whether the change requires a CLA. For example, trivial typo fixes usually do not require a CLA. If no CLA is required, the pull request is labeled as **cla-not-required** and you are done.
|
||||
2. If the change requires a CLA, the system checks whether you have already signed a CLA. If you have, the pull request is labeled as **cla-signed** and you are done.
|
||||
3. If you need to sign a CLA, MSBOT will label the request as **cla-required** and post a comment to the pull request asking you to sign in to a website to sign the CLA (it is fully digital and no faxing is involved).
|
||||
4. Once you have signed a CLA, the pull request is labeled as **cla-signed** and you are done.
|
||||
|
||||
Only pull requests that are labeled as **cla-not-required**, **cla-signed**, or **cla-already-signed** can be accepted.
|
||||
|
||||
Code of Conduct
|
||||
---------------
|
||||
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
|
|
@ -0,0 +1,9 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Microsoft Corporation
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Dictionary>
|
||||
<Words>
|
||||
<Recognized>
|
||||
<Word>dna</Word>
|
||||
<Word>json</Word>
|
||||
</Recognized>
|
||||
</Words>
|
||||
</Dictionary>
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
|
||||
</startup>
|
||||
</configuration>
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -0,0 +1,24 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// <copyright file="IProfile.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license. See license file in the project root for full license information.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Shared.Dna.Json.Profile
|
||||
{
|
||||
using System.Diagnostics;
|
||||
|
||||
/// <summary>
|
||||
/// Profiler interface.
|
||||
/// </summary>
|
||||
public interface IProfile
|
||||
{
|
||||
/// <summary>
|
||||
/// Execute a single test iteration.
|
||||
/// </summary>
|
||||
/// <param name="watch">The stopwatch timing the iteration.</param>
|
||||
/// <returns>A value indicating whether or not the test is valid.</returns>
|
||||
bool Execute(Stopwatch watch);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,426 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// <copyright file="JsonDna.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license. See license file in the project root for full license information.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Shared.Dna.Json.Profile
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
/// <summary>
|
||||
/// OSG Data and Analytics JSON profilers.
|
||||
/// </summary>
|
||||
public static class JsonDna
|
||||
{
|
||||
/// <summary>
|
||||
/// Reusable reader.
|
||||
/// </summary>
|
||||
[ThreadStatic]
|
||||
private static JsonParser reader = null;
|
||||
|
||||
/// <summary>
|
||||
/// Reusable writer.
|
||||
/// </summary>
|
||||
[ThreadStatic]
|
||||
private static JsonBuilder writer = null;
|
||||
|
||||
/// <summary>
|
||||
/// Prepare the reader for use in a single iteration.
|
||||
/// </summary>
|
||||
/// <param name="payload">The JSON payload to use.</param>
|
||||
/// <returns>A prepared reader.</returns>
|
||||
private static JsonParser PrepareReader(string payload)
|
||||
{
|
||||
JsonParser result = JsonDna.reader;
|
||||
if (result == null)
|
||||
{
|
||||
result = new JsonParser();
|
||||
JsonDna.reader = result;
|
||||
}
|
||||
|
||||
result.Reset(payload);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Prepare the writer for use in a single iteration.
|
||||
/// </summary>
|
||||
/// <returns>A prepared writer.</returns>
|
||||
private static JsonBuilder PerpareWriter()
|
||||
{
|
||||
JsonBuilder result = JsonDna.writer;
|
||||
if (result == null)
|
||||
{
|
||||
result = new JsonBuilder();
|
||||
JsonDna.writer = result;
|
||||
}
|
||||
|
||||
result.Clear();
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Confirm the reader successfully parses the payload.
|
||||
/// </summary>
|
||||
/// <param name="reader">The reader to check.</param>
|
||||
/// <param name="watch">The stopwatch timing the iteration.</param>
|
||||
/// <returns>A value indicating whether or not the iteration is valid.</returns>
|
||||
private static bool ConfirmReader(JsonParser reader, Stopwatch watch)
|
||||
{
|
||||
bool valid = true;
|
||||
bool parsed = false;
|
||||
bool outcome = false;
|
||||
bool asLogical = false;
|
||||
long asIntegral = 0L;
|
||||
double asFloating = 0D;
|
||||
string asText = null;
|
||||
while (valid && reader.Next())
|
||||
{
|
||||
parsed = true;
|
||||
switch (reader.TokenType)
|
||||
{
|
||||
case JsonTokenType.Boolean:
|
||||
outcome = reader.TryParseToken(out asLogical);
|
||||
watch.Stop();
|
||||
valid = valid && outcome && asLogical == Constants.LogicalValue;
|
||||
watch.Start();
|
||||
break;
|
||||
case JsonTokenType.Integer:
|
||||
outcome = reader.TryParseToken(out asIntegral);
|
||||
watch.Stop();
|
||||
valid = valid && outcome && asIntegral == Constants.IntegralValue;
|
||||
watch.Start();
|
||||
break;
|
||||
case JsonTokenType.Float:
|
||||
outcome = reader.TryParseToken(out asFloating);
|
||||
watch.Stop();
|
||||
valid = valid && outcome && asFloating == Constants.FloatValue;
|
||||
watch.Start();
|
||||
break;
|
||||
case JsonTokenType.BeginProperty:
|
||||
outcome = reader.TryParseToken(out asText);
|
||||
watch.Stop();
|
||||
valid = valid && outcome && Constants.AnyProperty.ContainsKey(asText);
|
||||
watch.Start();
|
||||
break;
|
||||
case JsonTokenType.String:
|
||||
outcome = reader.TryParseToken(out asText);
|
||||
watch.Stop();
|
||||
valid = valid && outcome && string.CompareOrdinal(asText, Constants.TextValue) == 0;
|
||||
watch.Start();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return parsed && valid;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Confirm the writer successfully builds the payload.
|
||||
/// </summary>
|
||||
/// <param name="writer">The writer to check.</param>
|
||||
/// <param name="expected">The expected payload.</param>
|
||||
/// <param name="watch">The stopwatch timing the iteration.</param>
|
||||
/// <returns>A value indicating whether or not the iteration is valid.</returns>
|
||||
private static bool ConfirmWriter(JsonBuilder writer, string expected, Stopwatch watch)
|
||||
{
|
||||
bool result = false;
|
||||
string actual = writer.Finish();
|
||||
watch.Stop();
|
||||
result = string.CompareOrdinal(expected, actual) == 0;
|
||||
watch.Start();
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recursively build a complex object.
|
||||
/// </summary>
|
||||
/// <param name="writer">The writer to use.</param>
|
||||
/// <param name="width">The length of the recursive array.</param>
|
||||
/// <param name="depth">The depth of the recursive object.</param>
|
||||
private static void RecursiveObject(JsonBuilder writer, int width, int depth)
|
||||
{
|
||||
writer.OpenObject();
|
||||
writer.OpenProperty(Constants.LogicalProperty);
|
||||
writer.WriteValue(Constants.LogicalValue);
|
||||
writer.CloseToken();
|
||||
writer.OpenProperty(Constants.IntegralProperty);
|
||||
writer.WriteValue(Constants.IntegralValue);
|
||||
writer.CloseToken();
|
||||
writer.OpenProperty(Constants.FloatProperty);
|
||||
writer.WriteValue(Constants.FloatValue);
|
||||
writer.CloseToken();
|
||||
writer.OpenProperty(Constants.TextProperty);
|
||||
writer.WriteValue(Constants.TextValue);
|
||||
writer.CloseToken();
|
||||
if (depth > 0)
|
||||
{
|
||||
writer.OpenProperty(Constants.ArrayProperty);
|
||||
writer.OpenArray();
|
||||
for (int i = 0; i < width; i++)
|
||||
{
|
||||
int shallow = depth - 1;
|
||||
JsonDna.RecursiveObject(writer, width, shallow);
|
||||
}
|
||||
|
||||
writer.CloseToken();
|
||||
writer.CloseToken();
|
||||
}
|
||||
|
||||
writer.CloseToken();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read logical value.
|
||||
/// </summary>
|
||||
public sealed class ReadLogical : IProfile
|
||||
{
|
||||
/// <summary>
|
||||
/// Execute a single test iteration.
|
||||
/// </summary>
|
||||
/// <param name="watch">The stopwatch timing the iteration.</param>
|
||||
/// <returns>A value indicating whether or not the test is valid.</returns>
|
||||
public bool Execute(Stopwatch watch)
|
||||
{
|
||||
JsonParser reader = JsonDna.PrepareReader(Constants.LogicalJson);
|
||||
return JsonDna.ConfirmReader(reader, watch);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read integral value.
|
||||
/// </summary>
|
||||
public sealed class ReadIntegral : IProfile
|
||||
{
|
||||
/// <summary>
|
||||
/// Execute a single test iteration.
|
||||
/// </summary>
|
||||
/// <param name="watch">The stopwatch timing the iteration.</param>
|
||||
/// <returns>A value indicating whether or not the test is valid.</returns>
|
||||
public bool Execute(Stopwatch watch)
|
||||
{
|
||||
JsonParser reader = JsonDna.PrepareReader(Constants.IntegralJson);
|
||||
return JsonDna.ConfirmReader(reader, watch);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read floating point value.
|
||||
/// </summary>
|
||||
public sealed class ReadFloat : IProfile
|
||||
{
|
||||
/// <summary>
|
||||
/// Execute a single test iteration.
|
||||
/// </summary>
|
||||
/// <param name="watch">The stopwatch timing the iteration.</param>
|
||||
/// <returns>A value indicating whether or not the test is valid.</returns>
|
||||
public bool Execute(Stopwatch watch)
|
||||
{
|
||||
JsonParser reader = JsonDna.PrepareReader(Constants.FloatJson);
|
||||
return JsonDna.ConfirmReader(reader, watch);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read text value.
|
||||
/// </summary>
|
||||
public sealed class ReadText : IProfile
|
||||
{
|
||||
/// <summary>
|
||||
/// Execute a single test iteration.
|
||||
/// </summary>
|
||||
/// <param name="watch">The stopwatch timing the iteration.</param>
|
||||
/// <returns>A value indicating whether or not the test is valid.</returns>
|
||||
public bool Execute(Stopwatch watch)
|
||||
{
|
||||
JsonParser reader = JsonDna.PrepareReader(Constants.TextJson);
|
||||
return JsonDna.ConfirmReader(reader, watch);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read array.
|
||||
/// </summary>
|
||||
public sealed class ReadArray : IProfile
|
||||
{
|
||||
/// <summary>
|
||||
/// Execute a single test iteration.
|
||||
/// </summary>
|
||||
/// <param name="watch">The stopwatch timing the iteration.</param>
|
||||
/// <returns>A value indicating whether or not the test is valid.</returns>
|
||||
public bool Execute(Stopwatch watch)
|
||||
{
|
||||
JsonParser reader = JsonDna.PrepareReader(Constants.ArrayJson);
|
||||
return JsonDna.ConfirmReader(reader, watch);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read object.
|
||||
/// </summary>
|
||||
public sealed class ReadObject : IProfile
|
||||
{
|
||||
/// <summary>
|
||||
/// Execute a single test iteration.
|
||||
/// </summary>
|
||||
/// <param name="watch">The stopwatch timing the iteration.</param>
|
||||
/// <returns>A value indicating whether or not the test is valid.</returns>
|
||||
public bool Execute(Stopwatch watch)
|
||||
{
|
||||
JsonParser reader = JsonDna.PrepareReader(Constants.ObjectJson);
|
||||
return JsonDna.ConfirmReader(reader, watch);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read complex object.
|
||||
/// </summary>
|
||||
public sealed class ReadComplex : IProfile
|
||||
{
|
||||
/// <summary>
|
||||
/// Execute a single test iteration.
|
||||
/// </summary>
|
||||
/// <param name="watch">The stopwatch timing the iteration.</param>
|
||||
/// <returns>A value indicating whether or not the test is valid.</returns>
|
||||
public bool Execute(Stopwatch watch)
|
||||
{
|
||||
JsonParser reader = JsonDna.PrepareReader(Constants.ComplexJson);
|
||||
return JsonDna.ConfirmReader(reader, watch);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write logical value.
|
||||
/// </summary>
|
||||
public sealed class WriteLogical : IProfile
|
||||
{
|
||||
/// <summary>
|
||||
/// Execute a single test iteration.
|
||||
/// </summary>
|
||||
/// <param name="watch">The stopwatch timing the iteration.</param>
|
||||
/// <returns>A value indicating whether or not the test is valid.</returns>
|
||||
public bool Execute(Stopwatch watch)
|
||||
{
|
||||
JsonBuilder writer = JsonDna.PerpareWriter();
|
||||
writer.WriteValue(Constants.LogicalValue);
|
||||
return JsonDna.ConfirmWriter(writer, Constants.LogicalJson, watch);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write integral value.
|
||||
/// </summary>
|
||||
public sealed class WriteIntegral : IProfile
|
||||
{
|
||||
/// <summary>
|
||||
/// Execute a single test iteration.
|
||||
/// </summary>
|
||||
/// <param name="watch">The stopwatch timing the iteration.</param>
|
||||
/// <returns>A value indicating whether or not the test is valid.</returns>
|
||||
public bool Execute(Stopwatch watch)
|
||||
{
|
||||
JsonBuilder writer = JsonDna.PerpareWriter();
|
||||
writer.WriteValue(Constants.IntegralValue);
|
||||
return JsonDna.ConfirmWriter(writer, Constants.IntegralJson, watch);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write floating-point value.
|
||||
/// </summary>
|
||||
public sealed class WriteFloat : IProfile
|
||||
{
|
||||
/// <summary>
|
||||
/// Execute a single test iteration.
|
||||
/// </summary>
|
||||
/// <param name="watch">The stopwatch timing the iteration.</param>
|
||||
/// <returns>A value indicating whether or not the test is valid.</returns>
|
||||
public bool Execute(Stopwatch watch)
|
||||
{
|
||||
JsonBuilder writer = JsonDna.PerpareWriter();
|
||||
writer.WriteValue(Constants.FloatValue);
|
||||
return JsonDna.ConfirmWriter(writer, Constants.FloatJson, watch);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write text value.
|
||||
/// </summary>
|
||||
public sealed class WriteText : IProfile
|
||||
{
|
||||
/// <summary>
|
||||
/// Execute a single test iteration.
|
||||
/// </summary>
|
||||
/// <param name="watch">The stopwatch timing the iteration.</param>
|
||||
/// <returns>A value indicating whether or not the test is valid.</returns>
|
||||
public bool Execute(Stopwatch watch)
|
||||
{
|
||||
JsonBuilder writer = JsonDna.PerpareWriter();
|
||||
writer.WriteValue(Constants.TextValue);
|
||||
return JsonDna.ConfirmWriter(writer, Constants.TextJson, watch);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write array.
|
||||
/// </summary>
|
||||
public sealed class WriteArray : IProfile
|
||||
{
|
||||
/// <summary>
|
||||
/// Execute a single test iteration.
|
||||
/// </summary>
|
||||
/// <param name="watch">The stopwatch timing the iteration.</param>
|
||||
/// <returns>A value indicating whether or not the test is valid.</returns>
|
||||
public bool Execute(Stopwatch watch)
|
||||
{
|
||||
JsonBuilder writer = JsonDna.PerpareWriter();
|
||||
writer.OpenArray();
|
||||
writer.WriteValue(Constants.LogicalValue);
|
||||
writer.WriteValue(Constants.IntegralValue);
|
||||
writer.WriteValue(Constants.FloatValue);
|
||||
writer.WriteValue(Constants.TextValue);
|
||||
writer.CloseToken();
|
||||
return JsonDna.ConfirmWriter(writer, Constants.ArrayJson, watch);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write object.
|
||||
/// </summary>
|
||||
public sealed class WriteObject : IProfile
|
||||
{
|
||||
/// <summary>
|
||||
/// Execute a single test iteration.
|
||||
/// </summary>
|
||||
/// <param name="watch">The stopwatch timing the iteration.</param>
|
||||
/// <returns>A value indicating whether or not the test is valid.</returns>
|
||||
public bool Execute(Stopwatch watch)
|
||||
{
|
||||
JsonBuilder writer = JsonDna.PerpareWriter();
|
||||
JsonDna.RecursiveObject(writer, 0, 0);
|
||||
return JsonDna.ConfirmWriter(writer, Constants.ObjectJson, watch);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write complex object.
|
||||
/// </summary>
|
||||
public sealed class WriteComplex : IProfile
|
||||
{
|
||||
/// <summary>
|
||||
/// Execute a single test iteration.
|
||||
/// </summary>
|
||||
/// <param name="watch">The stopwatch timing the iteration.</param>
|
||||
/// <returns>A value indicating whether or not the test is valid.</returns>
|
||||
public bool Execute(Stopwatch watch)
|
||||
{
|
||||
JsonBuilder writer = JsonDna.PerpareWriter();
|
||||
JsonDna.RecursiveObject(writer, 3, 3);
|
||||
return JsonDna.ConfirmWriter(writer, Constants.ComplexJson, watch);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,179 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// <copyright file="JsonDnaPerformanceTests.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license. See license file in the project root for full license information.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Shared.Dna.Json.Profile
|
||||
{
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
/// <summary>
|
||||
/// Performance tests for OSG Data and Analytics JSON code.
|
||||
/// </summary>
|
||||
[TestClass]
|
||||
[ExcludeFromCodeCoverage]
|
||||
public class JsonDnaPerformanceTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the test context.
|
||||
/// </summary>
|
||||
public TestContext TestContext { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Read logical.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonDna_Read_Logical()
|
||||
{
|
||||
double meanExecutionMilliseconds = 0D;
|
||||
Assert.IsTrue(Profiler.Execute<JsonDna.ReadLogical>(Constants.PerformanceIterations, out meanExecutionMilliseconds));
|
||||
this.TestContext.WriteLine("Average execution time (ms): {0}", meanExecutionMilliseconds);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read integral.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonDna_Read_Integral()
|
||||
{
|
||||
double meanExecutionMilliseconds = 0D;
|
||||
Assert.IsTrue(Profiler.Execute<JsonDna.ReadIntegral>(Constants.PerformanceIterations, out meanExecutionMilliseconds));
|
||||
this.TestContext.WriteLine("Average execution time (ms): {0}", meanExecutionMilliseconds);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read float.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonDna_Read_Float()
|
||||
{
|
||||
double meanExecutionMilliseconds = 0D;
|
||||
Assert.IsTrue(Profiler.Execute<JsonDna.ReadFloat>(Constants.PerformanceIterations, out meanExecutionMilliseconds));
|
||||
this.TestContext.WriteLine("Average execution time (ms): {0}", meanExecutionMilliseconds);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read text.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonDna_Read_Text()
|
||||
{
|
||||
double meanExecutionMilliseconds = 0D;
|
||||
Assert.IsTrue(Profiler.Execute<JsonDna.ReadText>(Constants.PerformanceIterations, out meanExecutionMilliseconds));
|
||||
this.TestContext.WriteLine("Average execution time (ms): {0}", meanExecutionMilliseconds);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read array.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonDna_Read_Array()
|
||||
{
|
||||
double meanExecutionMilliseconds = 0D;
|
||||
Assert.IsTrue(Profiler.Execute<JsonDna.ReadArray>(Constants.PerformanceIterations, out meanExecutionMilliseconds));
|
||||
this.TestContext.WriteLine("Average execution time (ms): {0}", meanExecutionMilliseconds);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read object.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonDna_Read_Object()
|
||||
{
|
||||
double meanExecutionMilliseconds = 0D;
|
||||
Assert.IsTrue(Profiler.Execute<JsonDna.ReadObject>(Constants.PerformanceIterations, out meanExecutionMilliseconds));
|
||||
this.TestContext.WriteLine("Average execution time (ms): {0}", meanExecutionMilliseconds);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read complex.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonDna_Read_Complex()
|
||||
{
|
||||
double meanExecutionMilliseconds = 0D;
|
||||
Assert.IsTrue(Profiler.Execute<JsonDna.ReadComplex>(Constants.PerformanceIterations, out meanExecutionMilliseconds));
|
||||
this.TestContext.WriteLine("Average execution time (ms): {0}", meanExecutionMilliseconds);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write logical.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonDna_Write_Logical()
|
||||
{
|
||||
double meanExecutionMilliseconds = 0D;
|
||||
Assert.IsTrue(Profiler.Execute<JsonDna.WriteLogical>(Constants.PerformanceIterations, out meanExecutionMilliseconds));
|
||||
this.TestContext.WriteLine("Average execution time (ms): {0}", meanExecutionMilliseconds);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write integral.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonDna_Write_Integral()
|
||||
{
|
||||
double meanExecutionMilliseconds = 0D;
|
||||
Assert.IsTrue(Profiler.Execute<JsonDna.WriteIntegral>(Constants.PerformanceIterations, out meanExecutionMilliseconds));
|
||||
this.TestContext.WriteLine("Average execution time (ms): {0}", meanExecutionMilliseconds);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write float.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonDna_Write_Float()
|
||||
{
|
||||
double meanExecutionMilliseconds = 0D;
|
||||
Assert.IsTrue(Profiler.Execute<JsonDna.WriteFloat>(Constants.PerformanceIterations, out meanExecutionMilliseconds));
|
||||
this.TestContext.WriteLine("Average execution time (ms): {0}", meanExecutionMilliseconds);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write text.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonDna_Write_Text()
|
||||
{
|
||||
double meanExecutionMilliseconds = 0D;
|
||||
Assert.IsTrue(Profiler.Execute<JsonDna.WriteText>(Constants.PerformanceIterations, out meanExecutionMilliseconds));
|
||||
this.TestContext.WriteLine("Average execution time (ms): {0}", meanExecutionMilliseconds);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write array.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonDna_Write_Array()
|
||||
{
|
||||
double meanExecutionMilliseconds = 0D;
|
||||
Assert.IsTrue(Profiler.Execute<JsonDna.WriteArray>(Constants.PerformanceIterations, out meanExecutionMilliseconds));
|
||||
this.TestContext.WriteLine("Average execution time (ms): {0}", meanExecutionMilliseconds);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write object.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonDna_Write_Object()
|
||||
{
|
||||
double meanExecutionMilliseconds = 0D;
|
||||
Assert.IsTrue(Profiler.Execute<JsonDna.WriteObject>(Constants.PerformanceIterations, out meanExecutionMilliseconds));
|
||||
this.TestContext.WriteLine("Average execution time (ms): {0}", meanExecutionMilliseconds);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write complex.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonDna_Write_Complex()
|
||||
{
|
||||
double meanExecutionMilliseconds = 0D;
|
||||
Assert.IsTrue(Profiler.Execute<JsonDna.WriteComplex>(Constants.PerformanceIterations, out meanExecutionMilliseconds));
|
||||
this.TestContext.WriteLine("Average execution time (ms): {0}", meanExecutionMilliseconds);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{C338ACCE-9521-435A-9011-2D6DF981920A}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Microsoft.Shared.Dna.Json.Profile</RootNamespace>
|
||||
<AssemblyName>Microsoft.Shared.Dna.Json.Profile</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<RestorePackages>true</RestorePackages>
|
||||
<RunCodeAnalysis>true</RunCodeAnalysis>
|
||||
<CodeAnalysisRuleSet>..\Microsoft.Shared.Dna.Test.ruleset</CodeAnalysisRuleSet>
|
||||
<NuGetPackageImportStamp>
|
||||
</NuGetPackageImportStamp>
|
||||
<DontImportCodeContracts>true</DontImportCodeContracts>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="Microsoft.VisualStudio.QualityTools.LoadTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
</ItemGroup>
|
||||
<Choose>
|
||||
<When Condition="('$(VisualStudioVersion)' == '10.0' or '$(VisualStudioVersion)' == '') and '$(TargetFrameworkVersion)' == 'v3.5'">
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
|
||||
</ItemGroup>
|
||||
</When>
|
||||
<Otherwise>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework" />
|
||||
</ItemGroup>
|
||||
</Otherwise>
|
||||
</Choose>
|
||||
<ItemGroup>
|
||||
<Compile Include="..\Microsoft.Shared.Dna.Json\JsonBuilder.cs">
|
||||
<Link>Microsoft.Shared.Dna\JsonBuilder.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Microsoft.Shared.Dna.Json\JsonConstants.cs">
|
||||
<Link>Microsoft.Shared.Dna\JsonConstants.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Microsoft.Shared.Dna.Json\JsonParser.cs">
|
||||
<Link>Microsoft.Shared.Dna\JsonParser.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Microsoft.Shared.Dna.Json\JsonTokenTypeExtensions.cs">
|
||||
<Link>Microsoft.Shared.Dna\JsonTokenTypeExtensions.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Microsoft.Shared.Dna.Json\Microsoft.Shared.Dna\FixedStringBuilder.cs">
|
||||
<Link>Microsoft.Shared.Dna\FixedStringBuilder.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Microsoft.Shared.Dna.Json\Microsoft.Shared.Dna\StringSegment.cs">
|
||||
<Link>Microsoft.Shared.Dna\StringSegment.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="Constants.cs" />
|
||||
<Compile Include="IProfile.cs" />
|
||||
<Compile Include="JsonDna.cs" />
|
||||
<Compile Include="JsonDnaPerformanceTests.cs" />
|
||||
<Compile Include="Profiler.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
<Content Include="profile_all.cmd">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<None Include="packages.config">
|
||||
<SubType>Designer</SubType>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="..\Microsoft.Shared.Dna.targets" />
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
<Import Project="..\packages\StyleCop.MSBuild.4.7.54.0\build\StyleCop.MSBuild.Targets" Condition="Exists('..\packages\StyleCop.MSBuild.4.7.54.0\build\StyleCop.MSBuild.Targets')" />
|
||||
</Project>
|
|
@ -0,0 +1,163 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// <copyright file="Profiler.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license. See license file in the project root for full license information.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Shared.Dna.Json.Profile
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
|
||||
/// <summary>
|
||||
/// Performance profiler.
|
||||
/// </summary>
|
||||
public static class Profiler
|
||||
{
|
||||
/// <summary>
|
||||
/// Execute a profile.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The profile type.</typeparam>
|
||||
/// <param name="iterations">The number of iterations.</param>
|
||||
/// <param name="meanElapsedMilliseconds">
|
||||
/// The average elapsed time per iteration.
|
||||
/// </param>
|
||||
/// <returns>A value indicating whether or not the execution is valid.</returns>
|
||||
public static bool Execute<T>(int iterations, out double meanElapsedMilliseconds) where T : IProfile, new()
|
||||
{
|
||||
return Profiler.ExecuteGeneric<T>(iterations, out meanElapsedMilliseconds);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Execute a profile.
|
||||
/// </summary>
|
||||
/// <param name="type">The profile type.</param>
|
||||
/// <param name="iterations">The number of iterations.</param>
|
||||
/// <param name="meanElapsedMilliseconds">
|
||||
/// The average elapsed time per iteration.
|
||||
/// </param>
|
||||
/// <returns>A value indicating whether or not the execution is valid.</returns>
|
||||
public static bool Execute(Type type, int iterations, out double meanElapsedMilliseconds)
|
||||
{
|
||||
object[] parameters = new object[] { iterations, 0D };
|
||||
bool result = (bool)typeof(Profiler)
|
||||
.GetMethod("ExecuteGeneric", BindingFlags.NonPublic | BindingFlags.Static)
|
||||
.MakeGenericMethod(type)
|
||||
.Invoke(null, parameters);
|
||||
meanElapsedMilliseconds = (double)parameters[1];
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Execute a profile.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The profile type.</typeparam>
|
||||
/// <param name="iterations">The number of iterations.</param>
|
||||
/// <param name="meanElapsedMilliseconds">
|
||||
/// The average elapsed time per iteration.
|
||||
/// </param>
|
||||
/// <returns>A value indicating whether or not the execution is valid.</returns>
|
||||
private static bool ExecuteGeneric<T>(int iterations, out double meanElapsedMilliseconds) where T : IProfile, new()
|
||||
{
|
||||
bool result = true;
|
||||
int dop = Environment.ProcessorCount;
|
||||
Thread[] executors = new Thread[dop];
|
||||
ExecuteState[] states = new ExecuteState[dop];
|
||||
int perExecutor = iterations / dop;
|
||||
int remainder = iterations % dop;
|
||||
for (int i = 0; i < dop; i++)
|
||||
{
|
||||
states[i] = new ExecuteState
|
||||
{
|
||||
Iterations = perExecutor + (--remainder > 0 ? 1 : 0),
|
||||
Count = 0L,
|
||||
Total = 0L,
|
||||
Valid = true
|
||||
};
|
||||
executors[i] = new Thread(Profiler.ExecutePartial<T>);
|
||||
executors[i].Start(states[i]);
|
||||
}
|
||||
|
||||
long total = 0L;
|
||||
long count = 0L;
|
||||
for (int i = 0; i < dop; i++)
|
||||
{
|
||||
executors[i].Join();
|
||||
total += states[i].Total;
|
||||
count += states[i].Count;
|
||||
result = result && states[i].Valid;
|
||||
}
|
||||
|
||||
meanElapsedMilliseconds = (double)total / TimeSpan.TicksPerMillisecond / count;
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Execute a fraction of the iterations for a profile.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The profile type.</typeparam>
|
||||
/// <param name="state">The execution state.</param>
|
||||
private static void ExecutePartial<T>(object state) where T : IProfile, new()
|
||||
{
|
||||
ExecuteState asExecute = state as ExecuteState;
|
||||
T profile = new T();
|
||||
Stopwatch watch = new Stopwatch();
|
||||
for (int warmup = asExecute.Iterations / 10; warmup > 0; warmup--)
|
||||
{
|
||||
profile.Execute(watch);
|
||||
}
|
||||
|
||||
bool valid = false;
|
||||
for (int i = 0; i < asExecute.Iterations; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
watch.Restart();
|
||||
valid = profile.Execute(watch);
|
||||
watch.Stop();
|
||||
}
|
||||
catch
|
||||
{
|
||||
valid = false;
|
||||
}
|
||||
|
||||
if (valid)
|
||||
{
|
||||
asExecute.Total += watch.ElapsedTicks;
|
||||
asExecute.Count++;
|
||||
}
|
||||
|
||||
asExecute.Valid = asExecute.Valid && valid;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Profiler execution state.
|
||||
/// </summary>
|
||||
private sealed class ExecuteState
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the number of valid iterations.
|
||||
/// </summary>
|
||||
public long Count { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number of iterations to attempt.
|
||||
/// </summary>
|
||||
public int Iterations { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the total execution time of all iterations in ticks.
|
||||
/// </summary>
|
||||
public long Total { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether or not all iterations were valid.
|
||||
/// </summary>
|
||||
public bool Valid { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// <copyright file="Program.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license. See license file in the project root for full license information.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Shared.Dna.Json.Profile
|
||||
{
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
/// <summary>
|
||||
/// Entry point class.
|
||||
/// </summary>
|
||||
public static class Program
|
||||
{
|
||||
/// <summary>
|
||||
/// Entry point method.
|
||||
/// </summary>
|
||||
/// <param name="args">Command line arguments.</param>
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
try
|
||||
{
|
||||
string group = args[0];
|
||||
string profile = args[1];
|
||||
int iterations = int.Parse(args[2], CultureInfo.InvariantCulture);
|
||||
string typeName = string.Concat("Microsoft.Shared.Dna.Json.Profile." + group + "+" + profile);
|
||||
Type type = null;
|
||||
try
|
||||
{
|
||||
type = typeof(Program).Assembly.GetType(typeName);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
if (type == null)
|
||||
{
|
||||
Console.WriteLine("Couldn't find profile \"{0}\" in group \"{1}\".", profile, group);
|
||||
return;
|
||||
}
|
||||
|
||||
double meanExecutionMilliseconds = 0D;
|
||||
bool valid = Profiler.Execute(type, iterations, out meanExecutionMilliseconds);
|
||||
Console.WriteLine("{0},{1},{2},{3}", group, profile, meanExecutionMilliseconds, valid);
|
||||
}
|
||||
catch
|
||||
{
|
||||
Console.WriteLine("Usage: Microsoft.Shared.Dna.Json.Profile.exe (group) (profile) (iterations)");
|
||||
Console.WriteLine(" Groups:");
|
||||
Console.WriteLine(" JsonDna");
|
||||
Console.WriteLine(" Reading Profiles:");
|
||||
Console.WriteLine(" ReadLogical");
|
||||
Console.WriteLine(" ReadIntegral");
|
||||
Console.WriteLine(" ReadFloat");
|
||||
Console.WriteLine(" ReadText");
|
||||
Console.WriteLine(" ReadArray");
|
||||
Console.WriteLine(" ReadObject");
|
||||
Console.WriteLine(" ReadComplex");
|
||||
Console.WriteLine(" Writing Profiles:");
|
||||
Console.WriteLine(" WriteLogical");
|
||||
Console.WriteLine(" WriteIntegral");
|
||||
Console.WriteLine(" WriteFloat");
|
||||
Console.WriteLine(" WriteText");
|
||||
Console.WriteLine(" WriteArray");
|
||||
Console.WriteLine(" WriteObject");
|
||||
Console.WriteLine(" WriteComplex");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="StyleCop.MSBuild" version="4.7.54.0" targetFramework="net45" developmentDependency="true" />
|
||||
</packages>
|
|
@ -0,0 +1,7 @@
|
|||
@ECHO OFF
|
||||
ECHO Group,Profile,MeanElapsedMilliseconds,Valid
|
||||
FOR %%I IN (JsonDna) DO (
|
||||
FOR %%J IN (ReadLogical ReadIntegral ReadFloat ReadText ReadArray ReadObject ReadComplex WriteLogical WriteIntegral WriteFloat WriteText WriteArray WriteObject WriteComplex) DO (
|
||||
Microsoft.Shared.Dna.Json.Profile.exe %%I %%J 100000
|
||||
)
|
||||
)
|
|
@ -0,0 +1,146 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// <copyright file="AssertToken.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license. See license file in the project root for full license information.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Shared.Dna.Json.Test
|
||||
{
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
/// <summary>
|
||||
/// Parser token validation.
|
||||
/// </summary>
|
||||
internal static class AssertToken
|
||||
{
|
||||
/// <summary>
|
||||
/// Validates that the parser is complete.
|
||||
/// </summary>
|
||||
/// <param name="expectedPayload">The expected payload.</param>
|
||||
/// <param name="actualParser">The actual parser.</param>
|
||||
public static void IsComplete(string expectedPayload, JsonParser actualParser)
|
||||
{
|
||||
Assert.IsFalse(actualParser.Next());
|
||||
AssertToken.Matches(JsonTokenType.Complete, expectedPayload, 0, expectedPayload.Length, actualParser);
|
||||
Assert.IsFalse(actualParser.Next());
|
||||
AssertToken.Matches(JsonTokenType.Complete, expectedPayload, 0, expectedPayload.Length, actualParser);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates that the parser is on a property.
|
||||
/// </summary>
|
||||
/// <param name="expectedProperty">The expected property.</param>
|
||||
/// <param name="expectedPayload">The expected payload.</param>
|
||||
/// <param name="expectedOffset">The expected offset.</param>
|
||||
/// <param name="expectedCount">The expected count.</param>
|
||||
/// <param name="actualParser">The actual parser.</param>
|
||||
public static void IsProperty(string expectedProperty, string expectedPayload, int expectedOffset, int expectedCount, JsonParser actualParser)
|
||||
{
|
||||
AssertToken.Matches(JsonTokenType.BeginProperty, expectedPayload, expectedOffset, expectedCount, actualParser);
|
||||
string actualProperty = null;
|
||||
Assert.IsTrue(actualParser.TryParseToken(out actualProperty));
|
||||
Assert.AreEqual(expectedProperty, actualProperty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates that the parser is on a value.
|
||||
/// </summary>
|
||||
/// <param name="expectedValue">The expected value.</param>
|
||||
/// <param name="expectedPayload">The expected payload.</param>
|
||||
/// <param name="expectedOffset">The expected offset.</param>
|
||||
/// <param name="expectedCount">The expected count.</param>
|
||||
/// <param name="actualParser">The actual parser.</param>
|
||||
public static void IsValue(bool expectedValue, string expectedPayload, int expectedOffset, int expectedCount, JsonParser actualParser)
|
||||
{
|
||||
AssertToken.Matches(JsonTokenType.Boolean, expectedPayload, expectedOffset, expectedCount, actualParser);
|
||||
bool actualValue = false;
|
||||
Assert.IsTrue(actualParser.TryParseToken(out actualValue));
|
||||
Assert.AreEqual(expectedValue, actualValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates that the parser is on a value.
|
||||
/// </summary>
|
||||
/// <param name="expectedValue">The expected value.</param>
|
||||
/// <param name="expectedPayload">The expected payload.</param>
|
||||
/// <param name="expectedOffset">The expected offset.</param>
|
||||
/// <param name="expectedCount">The expected count.</param>
|
||||
/// <param name="actualParser">The actual parser.</param>
|
||||
public static void IsValue(long expectedValue, string expectedPayload, int expectedOffset, int expectedCount, JsonParser actualParser)
|
||||
{
|
||||
AssertToken.Matches(JsonTokenType.Integer, expectedPayload, expectedOffset, expectedCount, actualParser);
|
||||
long actualValue = 0L;
|
||||
Assert.IsTrue(actualParser.TryParseToken(out actualValue));
|
||||
Assert.AreEqual(expectedValue, actualValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates that the parser is on a value.
|
||||
/// </summary>
|
||||
/// <param name="expectedValue">The expected value.</param>
|
||||
/// <param name="expectedPayload">The expected payload.</param>
|
||||
/// <param name="expectedOffset">The expected offset.</param>
|
||||
/// <param name="expectedCount">The expected count.</param>
|
||||
/// <param name="actualParser">The actual parser.</param>
|
||||
public static void IsValue(ulong expectedValue, string expectedPayload, int expectedOffset, int expectedCount, JsonParser actualParser)
|
||||
{
|
||||
AssertToken.Matches(JsonTokenType.Integer, expectedPayload, expectedOffset, expectedCount, actualParser);
|
||||
ulong actualValue = 0UL;
|
||||
Assert.IsTrue(actualParser.TryParseToken(out actualValue));
|
||||
Assert.AreEqual(expectedValue, actualValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates that the parser is on a value.
|
||||
/// </summary>
|
||||
/// <param name="expectedValue">The expected value.</param>
|
||||
/// <param name="expectedPayload">The expected payload.</param>
|
||||
/// <param name="expectedOffset">The expected offset.</param>
|
||||
/// <param name="expectedCount">The expected count.</param>
|
||||
/// <param name="actualParser">The actual parser.</param>
|
||||
public static void IsValue(double expectedValue, string expectedPayload, int expectedOffset, int expectedCount, JsonParser actualParser)
|
||||
{
|
||||
AssertToken.Matches(JsonTokenType.Float, expectedPayload, expectedOffset, expectedCount, actualParser);
|
||||
double actualValue = 0D;
|
||||
Assert.IsTrue(actualParser.TryParseToken(out actualValue));
|
||||
Assert.AreEqual(expectedValue, actualValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates that the parser is on a value.
|
||||
/// </summary>
|
||||
/// <param name="expectedValue">The expected value.</param>
|
||||
/// <param name="expectedPayload">The expected payload.</param>
|
||||
/// <param name="expectedOffset">The expected offset.</param>
|
||||
/// <param name="expectedCount">The expected count.</param>
|
||||
/// <param name="actualParser">The actual parser.</param>
|
||||
public static void IsValue(string expectedValue, string expectedPayload, int expectedOffset, int expectedCount, JsonParser actualParser)
|
||||
{
|
||||
AssertToken.Matches(JsonTokenType.String, expectedPayload, expectedOffset, expectedCount, actualParser);
|
||||
string actualValue = null;
|
||||
Assert.IsTrue(actualParser.TryParseToken(out actualValue));
|
||||
Assert.AreEqual(expectedValue.Length, actualValue.Length);
|
||||
for (int i = 0; i < expectedValue.Length; i++)
|
||||
{
|
||||
Assert.AreEqual(expectedValue[i], actualValue[i], "index:{0}", i);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates that the parser is on a given token.
|
||||
/// </summary>
|
||||
/// <param name="expectedType">The expected token type.</param>
|
||||
/// <param name="expectedPayload">The expected payload.</param>
|
||||
/// <param name="expectedOffset">The expected offset.</param>
|
||||
/// <param name="expectedCount">The expected count.</param>
|
||||
/// <param name="actualParser">The actual parser.</param>
|
||||
public static void Matches(JsonTokenType expectedType, string expectedPayload, int expectedOffset, int expectedCount, JsonParser actualParser)
|
||||
{
|
||||
Assert.AreEqual(expectedType, actualParser.TokenType);
|
||||
Assert.AreSame(expectedPayload, actualParser.TokenSegment.String);
|
||||
Assert.AreEqual(expectedOffset, actualParser.TokenSegment.Offset);
|
||||
Assert.AreEqual(expectedCount, actualParser.TokenSegment.Count);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// <copyright file="Constants.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license. See license file in the project root for full license information.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Shared.Dna.Json.Test
|
||||
{
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
/// <summary>
|
||||
/// Test constants.
|
||||
/// </summary>
|
||||
public static class Constants
|
||||
{
|
||||
/// <summary>
|
||||
/// A string containing every unicode character.
|
||||
/// </summary>
|
||||
public static readonly string UnicodeRainbowDecoded = Constants.CreateUnicodeRainbowDecoded();
|
||||
|
||||
/// <summary>
|
||||
/// A string containing every unicode character encoded as a JSON escape sequence.
|
||||
/// </summary>
|
||||
public static readonly string UnicodeRainbowEncoded = Constants.CreateUnicodeRainbowEncoded();
|
||||
|
||||
/// <summary>
|
||||
/// Create the unicode rainbow.
|
||||
/// </summary>
|
||||
/// <returns>A string containing every unicode character.</returns>
|
||||
private static string CreateUnicodeRainbowDecoded()
|
||||
{
|
||||
char[] result = new char[char.MaxValue + 1];
|
||||
for (char c = char.MinValue; c < char.MaxValue; c++)
|
||||
{
|
||||
result[c] = c;
|
||||
}
|
||||
|
||||
result[char.MaxValue] = char.MaxValue;
|
||||
return new string(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a JSON-encoded version of the unicode rainbow.
|
||||
/// </summary>
|
||||
/// <returns>A string containing every unicode character encoded as a JSON escape sequence.</returns>
|
||||
private static string CreateUnicodeRainbowEncoded()
|
||||
{
|
||||
StringBuilder result = new StringBuilder(70000);
|
||||
result.Append("\"");
|
||||
for (char c = char.MinValue; c < char.MaxValue; c++)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '"':
|
||||
result.Append("\\\"");
|
||||
break;
|
||||
case '\\':
|
||||
result.Append("\\\\");
|
||||
break;
|
||||
case '\b':
|
||||
result.Append("\\b");
|
||||
break;
|
||||
case '\f':
|
||||
result.Append("\\f");
|
||||
break;
|
||||
case '\n':
|
||||
result.Append("\\n");
|
||||
break;
|
||||
case '\r':
|
||||
result.Append("\\r");
|
||||
break;
|
||||
case '\t':
|
||||
result.Append("\\t");
|
||||
break;
|
||||
default:
|
||||
if (char.IsControl(c))
|
||||
{
|
||||
result.Append("\\u");
|
||||
byte[] bytes = BitConverter.GetBytes(c);
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
Array.Reverse(bytes);
|
||||
}
|
||||
|
||||
for (int i = 0; i < bytes.Length; i++)
|
||||
{
|
||||
result.Append(BitConverter.ToString(bytes, i, 1));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Append(c);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
result.Append(char.MaxValue);
|
||||
result.Append("\"");
|
||||
return result.ToString();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,511 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// <copyright file="JsonBuilderTests.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license. See license file in the project root for full license information.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Shared.Dna.Json.Test
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Globalization;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
/// <summary>
|
||||
/// Tests for the <see cref="JsonBuilder"/> class.
|
||||
/// </summary>
|
||||
[TestClass]
|
||||
[ExcludeFromCodeCoverage]
|
||||
public class JsonBuilderTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor assigns minimum capacity.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonBuilder_Constructor_Assigns_Minimum_Capacity()
|
||||
{
|
||||
JsonBuilder target = new JsonBuilder(0, 1);
|
||||
Assert.IsFalse(target.WriteValue(null));
|
||||
Assert.AreEqual("{\"(truncated)\":true}", target.Finish());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor rejects non-positive depth.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonBuilder_Constructor_Rejects_Non_Positive_Depth()
|
||||
{
|
||||
try
|
||||
{
|
||||
JsonBuilder target = new JsonBuilder(0, 0);
|
||||
Assert.IsNull(target);
|
||||
}
|
||||
catch (ArgumentOutOfRangeException ex)
|
||||
{
|
||||
Assert.AreEqual(typeof(ArgumentOutOfRangeException), ex.GetType());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear causes Finish to return empty string.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonBuilder_Clear_Causes_Finish_To_Return_Empty_String()
|
||||
{
|
||||
JsonBuilder target = new JsonBuilder();
|
||||
Assert.IsTrue(target.WriteValue("Should not be returned"));
|
||||
target.Clear();
|
||||
Assert.AreEqual(string.Empty, target.Finish());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OpenArray creates empty array.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonBuilder_OpenArray_Creates_Empty_Array()
|
||||
{
|
||||
JsonBuilder target = new JsonBuilder();
|
||||
Assert.IsTrue(target.OpenArray());
|
||||
Assert.AreEqual("[]", target.Finish());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OpenArray can be nested in OpenArray.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonBuilder_OpenArray_Can_Be_Nested_In_OpenArray()
|
||||
{
|
||||
JsonBuilder target = new JsonBuilder();
|
||||
Assert.IsTrue(target.OpenArray());
|
||||
Assert.IsTrue(target.OpenArray());
|
||||
Assert.IsTrue(target.WriteValue(1));
|
||||
target.CloseToken();
|
||||
Assert.IsTrue(target.OpenArray());
|
||||
Assert.IsTrue(target.WriteValue(2));
|
||||
Assert.AreEqual("[[1],[2]]", target.Finish());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OpenArray can be nested in OpenProperty.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonBuilder_OpenArray_Can_Be_Nested_In_OpenProperty()
|
||||
{
|
||||
JsonBuilder target = new JsonBuilder();
|
||||
Assert.IsTrue(target.OpenObject());
|
||||
Assert.IsTrue(target.OpenProperty("first"));
|
||||
Assert.IsTrue(target.OpenArray());
|
||||
Assert.IsTrue(target.WriteValue(1));
|
||||
target.CloseToken();
|
||||
target.CloseToken();
|
||||
Assert.IsTrue(target.OpenProperty("second"));
|
||||
Assert.IsTrue(target.OpenArray());
|
||||
Assert.IsTrue(target.WriteValue(2));
|
||||
Assert.AreEqual("{\"first\":[1],\"second\":[2]}", target.Finish());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OpenObject creates empty object.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonBuilder_OpenObject_Creates_Empty_Object()
|
||||
{
|
||||
JsonBuilder target = new JsonBuilder();
|
||||
Assert.IsTrue(target.OpenObject());
|
||||
Assert.AreEqual("{}", target.Finish());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OpenObject can be nested in OpenArray.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonBuilder_OpenObject_Can_Be_Nested_In_OpenArray()
|
||||
{
|
||||
JsonBuilder target = new JsonBuilder();
|
||||
Assert.IsTrue(target.OpenArray());
|
||||
Assert.IsTrue(target.OpenObject());
|
||||
Assert.IsTrue(target.OpenProperty("value"));
|
||||
Assert.IsTrue(target.WriteValue(1));
|
||||
target.CloseToken();
|
||||
target.CloseToken();
|
||||
Assert.IsTrue(target.OpenObject());
|
||||
Assert.IsTrue(target.OpenProperty("value"));
|
||||
Assert.IsTrue(target.WriteValue(2));
|
||||
Assert.AreEqual("[{\"value\":1},{\"value\":2}]", target.Finish());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OpenObject can be nested in OpenProperty.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonBuilder_OpenObject_Can_Be_Nested_In_OpenProperty()
|
||||
{
|
||||
JsonBuilder target = new JsonBuilder();
|
||||
Assert.IsTrue(target.OpenObject());
|
||||
Assert.IsTrue(target.OpenProperty("first"));
|
||||
Assert.IsTrue(target.OpenObject());
|
||||
Assert.IsTrue(target.OpenProperty("value"));
|
||||
Assert.IsTrue(target.WriteValue(1));
|
||||
target.CloseToken();
|
||||
target.CloseToken();
|
||||
target.CloseToken();
|
||||
Assert.IsTrue(target.OpenProperty("second"));
|
||||
Assert.IsTrue(target.OpenObject());
|
||||
Assert.IsTrue(target.OpenProperty("value"));
|
||||
Assert.IsTrue(target.WriteValue(2));
|
||||
Assert.AreEqual("{\"first\":{\"value\":1},\"second\":{\"value\":2}}", target.Finish());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OpenProperty creates null property.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonBuilder_OpenProperty_Creates_Null_Property()
|
||||
{
|
||||
JsonBuilder target = new JsonBuilder();
|
||||
Assert.IsTrue(target.OpenObject());
|
||||
Assert.IsTrue(target.OpenProperty("isNull"));
|
||||
Assert.AreEqual("{\"isNull\":null}", target.Finish());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OpenProperty creates null property.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonBuilder_OpenProperty_Rejects_Null_Property_Name()
|
||||
{
|
||||
JsonBuilder target = new JsonBuilder();
|
||||
Assert.IsTrue(target.OpenObject());
|
||||
try
|
||||
{
|
||||
target.OpenProperty(null);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ArgumentNullException ex)
|
||||
{
|
||||
Assert.AreEqual(typeof(ArgumentNullException), ex.GetType());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// TryResize increases capacity and preserves current state.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonBuilder_TryResize_Increases_Capacity_And_Preserves_Current_State()
|
||||
{
|
||||
JsonBuilder target = new JsonBuilder(50, 2);
|
||||
Assert.IsTrue(target.OpenArray());
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
Assert.IsTrue(target.WriteValue(i), "index:{0}", i);
|
||||
}
|
||||
|
||||
Assert.IsTrue(target.TryResize(100));
|
||||
for (int i = 10; i < 20; i++)
|
||||
{
|
||||
Assert.IsTrue(target.WriteValue(i), "index:{0}", i);
|
||||
}
|
||||
|
||||
Assert.AreEqual("[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]", target.Finish());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// TryResize decreases capacity if state can be preserved.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonBuilder_TryResize_Decreases_Capacity_If_State_Can_Be_Preserved()
|
||||
{
|
||||
JsonBuilder target = new JsonBuilder(100, 2);
|
||||
Assert.IsTrue(target.OpenArray());
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
Assert.IsTrue(target.WriteValue(i), "index:{0}", i);
|
||||
}
|
||||
|
||||
Assert.IsTrue(target.TryResize(50));
|
||||
Assert.AreEqual("[0,1,2,3,4,5,6,7,8,9]", target.Finish());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// TryResize does nothing if capacity is below minimum.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonBuilder_TryResize_Does_Nothing_If_Capacity_Is_Below_Minimum()
|
||||
{
|
||||
JsonBuilder target = new JsonBuilder(100, 2);
|
||||
Assert.IsFalse(target.TryResize(0));
|
||||
Assert.IsTrue(target.OpenArray());
|
||||
for (int i = 0; i < 20; i++)
|
||||
{
|
||||
Assert.IsTrue(target.WriteValue(i), "index:{0}", i);
|
||||
}
|
||||
|
||||
Assert.AreEqual("[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]", target.Finish());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// TryResize does nothing if state cannot be preserved.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonBuilder_TryResize_Does_Nothing_If_State_Cannot_Be_Preserved()
|
||||
{
|
||||
JsonBuilder target = new JsonBuilder(100, 2);
|
||||
Assert.IsTrue(target.OpenArray());
|
||||
for (int i = 0; i < 20; i++)
|
||||
{
|
||||
Assert.IsTrue(target.WriteValue(i), "index:{0}", i);
|
||||
}
|
||||
|
||||
Assert.IsFalse(target.TryResize(50));
|
||||
Assert.AreEqual("[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]", target.Finish());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// WriteValue writes Boolean.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonBuilder_WriteValue_Writes_Boolean()
|
||||
{
|
||||
JsonBuilder target = new JsonBuilder();
|
||||
Assert.IsTrue(target.WriteValue(true));
|
||||
Assert.AreEqual("true", target.Finish());
|
||||
target.Clear();
|
||||
Assert.IsTrue(target.WriteValue(false));
|
||||
Assert.AreEqual("false", target.Finish());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// WriteValue writes Byte.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonBuilder_WriteValue_Writes_Byte()
|
||||
{
|
||||
JsonBuilder target = new JsonBuilder();
|
||||
Assert.IsTrue(target.WriteValue(byte.MinValue));
|
||||
Assert.AreEqual("0", target.Finish());
|
||||
target.Clear();
|
||||
Assert.IsTrue(target.WriteValue(byte.MaxValue));
|
||||
Assert.AreEqual("255", target.Finish());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// WriteValue writes SByte.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonBuilder_WriteValue_Writes_SByte()
|
||||
{
|
||||
JsonBuilder target = new JsonBuilder();
|
||||
Assert.IsTrue(target.WriteValue(sbyte.MinValue));
|
||||
Assert.AreEqual("-128", target.Finish());
|
||||
target.Clear();
|
||||
Assert.IsTrue(target.WriteValue(sbyte.MaxValue));
|
||||
Assert.AreEqual("127", target.Finish());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// WriteValue writes Int16.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonBuilder_WriteValue_Writes_Int16()
|
||||
{
|
||||
JsonBuilder target = new JsonBuilder();
|
||||
Assert.IsTrue(target.WriteValue(short.MinValue));
|
||||
Assert.AreEqual("-32768", target.Finish());
|
||||
target.Clear();
|
||||
Assert.IsTrue(target.WriteValue(short.MaxValue));
|
||||
Assert.AreEqual("32767", target.Finish());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// WriteValue writes UInt16.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonBuilder_WriteValue_Writes_UInt16()
|
||||
{
|
||||
JsonBuilder target = new JsonBuilder();
|
||||
Assert.IsTrue(target.WriteValue(ushort.MinValue));
|
||||
Assert.AreEqual("0", target.Finish());
|
||||
target.Clear();
|
||||
Assert.IsTrue(target.WriteValue(ushort.MaxValue));
|
||||
Assert.AreEqual("65535", target.Finish());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// WriteValue writes Int32.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonBuilder_WriteValue_Writes_Int32()
|
||||
{
|
||||
JsonBuilder target = new JsonBuilder();
|
||||
Assert.IsTrue(target.WriteValue(int.MinValue));
|
||||
Assert.AreEqual("-2147483648", target.Finish());
|
||||
target.Clear();
|
||||
Assert.IsTrue(target.WriteValue(int.MaxValue));
|
||||
Assert.AreEqual("2147483647", target.Finish());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// WriteValue writes UInt32.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonBuilder_WriteValue_Writes_UInt32()
|
||||
{
|
||||
JsonBuilder target = new JsonBuilder();
|
||||
Assert.IsTrue(target.WriteValue(uint.MinValue));
|
||||
Assert.AreEqual("0", target.Finish());
|
||||
target.Clear();
|
||||
Assert.IsTrue(target.WriteValue(uint.MaxValue));
|
||||
Assert.AreEqual("4294967295", target.Finish());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// WriteValue writes Int64.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonBuilder_WriteValue_Writes_Int64()
|
||||
{
|
||||
JsonBuilder target = new JsonBuilder();
|
||||
Assert.IsTrue(target.WriteValue(long.MinValue));
|
||||
Assert.AreEqual("-9223372036854775808", target.Finish());
|
||||
target.Clear();
|
||||
Assert.IsTrue(target.WriteValue(long.MaxValue));
|
||||
Assert.AreEqual("9223372036854775807", target.Finish());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// WriteValue writes UInt64.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonBuilder_WriteValue_Writes_UInt64()
|
||||
{
|
||||
JsonBuilder target = new JsonBuilder();
|
||||
Assert.IsTrue(target.WriteValue(ulong.MinValue));
|
||||
Assert.AreEqual("0", target.Finish());
|
||||
target.Clear();
|
||||
Assert.IsTrue(target.WriteValue(ulong.MaxValue));
|
||||
Assert.AreEqual("18446744073709551615", target.Finish());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// WriteValue writes Single.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonBuilder_WriteValue_Writes_Single()
|
||||
{
|
||||
JsonBuilder target = new JsonBuilder();
|
||||
Assert.IsTrue(target.WriteValue(float.MinValue));
|
||||
Assert.AreEqual("-3.40282347E+38", target.Finish());
|
||||
target.Clear();
|
||||
Assert.IsTrue(target.WriteValue(float.Epsilon));
|
||||
Assert.AreEqual("1.401298E-45", target.Finish());
|
||||
target.Clear();
|
||||
Assert.IsTrue(target.WriteValue(float.MaxValue));
|
||||
Assert.AreEqual("3.40282347E+38", target.Finish());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// WriteValue writes Double.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonBuilder_WriteValue_Writes_Double()
|
||||
{
|
||||
JsonBuilder target = new JsonBuilder();
|
||||
Assert.IsTrue(target.WriteValue(double.MinValue));
|
||||
Assert.AreEqual("-1.7976931348623157E+308", target.Finish());
|
||||
target.Clear();
|
||||
Assert.IsTrue(target.WriteValue(double.Epsilon));
|
||||
Assert.AreEqual("4.94065645841247E-324", target.Finish());
|
||||
target.Clear();
|
||||
Assert.IsTrue(target.WriteValue(double.MaxValue));
|
||||
Assert.AreEqual("1.7976931348623157E+308", target.Finish());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// WriteValue writes decimal.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonBuilder_WriteValue_Writes_Decimal()
|
||||
{
|
||||
JsonBuilder target = new JsonBuilder();
|
||||
Assert.IsTrue(target.WriteValue(decimal.MinValue));
|
||||
Assert.AreEqual("-79228162514264337593543950335", target.Finish());
|
||||
target.Clear();
|
||||
Assert.IsTrue(target.WriteValue(decimal.MaxValue));
|
||||
Assert.AreEqual("79228162514264337593543950335", target.Finish());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// WriteValue writes String.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonBuilder_WriteValue_Writes_String()
|
||||
{
|
||||
JsonBuilder target = new JsonBuilder(70000, 1);
|
||||
Assert.IsTrue(target.WriteValue(null));
|
||||
Assert.AreEqual("null", target.Finish());
|
||||
target.Clear();
|
||||
Assert.IsTrue(target.WriteValue(string.Empty));
|
||||
Assert.AreEqual("\"\"", target.Finish());
|
||||
target.Clear();
|
||||
Assert.IsTrue(target.WriteValue(Constants.UnicodeRainbowDecoded));
|
||||
string encoded = target.Finish();
|
||||
for (int i = 0; i < Constants.UnicodeRainbowEncoded.Length; i++)
|
||||
{
|
||||
Assert.AreEqual(Constants.UnicodeRainbowEncoded[i], encoded[i], "index:{0}", i);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writing truncates array when capacity is exceeded.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonBuilder_Writing_Truncates_Array_When_Capacity_Is_Exceeded()
|
||||
{
|
||||
JsonBuilder target = new JsonBuilder(50, 2);
|
||||
Assert.IsTrue(target.OpenArray());
|
||||
bool succeeded = true;
|
||||
for (int i = 0; succeeded; i++)
|
||||
{
|
||||
succeeded = target.WriteValue(i);
|
||||
}
|
||||
|
||||
Assert.AreEqual("[0,1,2,3,4,5,6,7,8,9,10,11,{\"(truncated)\":true}]", target.Finish());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writing truncates object when capacity is exceeded.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonBuilder_Writing_Truncates_Object_When_Capacity_Is_Exceeded()
|
||||
{
|
||||
JsonBuilder target = new JsonBuilder(50, 4);
|
||||
Assert.IsTrue(target.OpenObject());
|
||||
bool succeeded = true;
|
||||
for (int i = 0; succeeded; i++)
|
||||
{
|
||||
if (target.OpenProperty(i.ToString(CultureInfo.InvariantCulture)))
|
||||
{
|
||||
succeeded = target.WriteValue(i);
|
||||
target.CloseToken();
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
Assert.AreEqual("{\"0\":0,\"1\":1,\"2\":2,\"3\":3,\"(truncated)\":true}", target.Finish());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writing truncates value when capacity is exceeded.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonBuilder_Writing_Truncates_Value_When_Capacity_Is_Exceeded()
|
||||
{
|
||||
JsonBuilder target = new JsonBuilder(20, 1);
|
||||
target.WriteValue("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
|
||||
Assert.AreEqual("{\"(truncated)\":true}", target.Finish());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,461 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// <copyright file="JsonParserTests.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license. See license file in the project root for full license information.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Shared.Dna.Json.Test
|
||||
{
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
/// <summary>
|
||||
/// Tests for the <see cref="JsonParser"/> class.
|
||||
/// </summary>
|
||||
[TestClass]
|
||||
public class JsonParserTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor allows null payload.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonParser_Constructor_Allows_Null_Payload()
|
||||
{
|
||||
string payload = null;
|
||||
JsonParser target = new JsonParser(payload);
|
||||
Assert.IsFalse(target.Next());
|
||||
Assert.AreEqual(JsonTokenType.Invalid, target.TokenType);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor rejects non-positive depth.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonParser_Constructor_Rejects_Non_Positive_Depth()
|
||||
{
|
||||
try
|
||||
{
|
||||
JsonParser target = new JsonParser("null", 4, 0);
|
||||
Assert.IsNull(target);
|
||||
}
|
||||
catch (ArgumentOutOfRangeException ex)
|
||||
{
|
||||
Assert.AreEqual(typeof(ArgumentOutOfRangeException), ex.GetType());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Next parses empty array.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonParser_Next_Parses_Empty_Array()
|
||||
{
|
||||
string payload = "[]";
|
||||
JsonParser target = new JsonParser(payload);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.BeginArray, payload, 0, 1, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.EndArray, payload, 0, 2, target);
|
||||
AssertToken.IsComplete(payload, target);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Next parses array nested in array.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonParser_Next_Parses_Array_Nested_In_Array()
|
||||
{
|
||||
string payload = "[[1,2]]";
|
||||
JsonParser target = new JsonParser(payload);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.BeginArray, payload, 0, 1, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.BeginArray, payload, 1, 1, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.IsValue(1L, payload, 2, 1, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.IsValue(2L, payload, 4, 1, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.EndArray, payload, 1, 5, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.EndArray, payload, 0, 7, target);
|
||||
AssertToken.IsComplete(payload, target);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Next parses array nested in property.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonParser_Next_Parses_Array_Nested_In_Property()
|
||||
{
|
||||
string payload = "{\"array\":[1,2]}";
|
||||
JsonParser target = new JsonParser(payload);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.BeginObject, payload, 0, 1, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.IsProperty("array", payload, 1, 8, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.BeginArray, payload, 9, 1, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.IsValue(1L, payload, 10, 1, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.IsValue(2L, payload, 12, 1, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.EndArray, payload, 9, 5, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.EndProperty, payload, 1, 13, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.EndObject, payload, 0, 15, target);
|
||||
AssertToken.IsComplete(payload, target);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Next parses empty object.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonParser_Next_Parses_Empty_Object()
|
||||
{
|
||||
string payload = "{}";
|
||||
JsonParser target = new JsonParser(payload);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.BeginObject, payload, 0, 1, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.EndObject, payload, 0, 2, target);
|
||||
AssertToken.IsComplete(payload, target);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Next parses object nested in array.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonParser_Next_Parses_Object_Nested_In_Array()
|
||||
{
|
||||
string payload = "[{\"value\":1},{\"value\":2}]";
|
||||
JsonParser target = new JsonParser(payload);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.BeginArray, payload, 0, 1, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.BeginObject, payload, 1, 1, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.IsProperty("value", payload, 2, 8, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.IsValue(1L, payload, 10, 1, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.EndProperty, payload, 2, 9, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.EndObject, payload, 1, 11, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.BeginObject, payload, 13, 1, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.IsProperty("value", payload, 14, 8, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.IsValue(2L, payload, 22, 1, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.EndProperty, payload, 14, 9, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.EndObject, payload, 13, 11, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.EndArray, payload, 0, 25, target);
|
||||
AssertToken.IsComplete(payload, target);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Next parses object nested in property.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonParser_Next_Parses_Object_Nested_In_Property()
|
||||
{
|
||||
string payload = "{\"first\":{\"value\":1},\"second\":{\"value\":2}}";
|
||||
JsonParser target = new JsonParser(payload);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.BeginObject, payload, 0, 1, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.IsProperty("first", payload, 1, 8, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.BeginObject, payload, 9, 1, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.IsProperty("value", payload, 10, 8, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.IsValue(1L, payload, 18, 1, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.EndProperty, payload, 10, 9, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.EndObject, payload, 9, 11, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.EndProperty, payload, 1, 19, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.IsProperty("second", payload, 21, 9, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.BeginObject, payload, 30, 1, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.IsProperty("value", payload, 31, 8, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.IsValue(2L, payload, 39, 1, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.EndProperty, payload, 31, 9, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.EndObject, payload, 30, 11, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.EndProperty, payload, 21, 20, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.EndObject, payload, 0, 42, target);
|
||||
AssertToken.IsComplete(payload, target);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Next halts on empty element.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonParser_Next_Halts_On_Empty_Element()
|
||||
{
|
||||
string payload = "{\"array\":[0z0]}";
|
||||
JsonParser target = new JsonParser(payload);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.BeginObject, payload, 0, 1, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.IsProperty("array", payload, 1, 8, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.BeginArray, payload, 9, 1, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.IsValue(0L, payload, 10, 1, target);
|
||||
Assert.IsFalse(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.Invalid, payload, 11, 0, target);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Skip moves over containers.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonParser_Skip_Moves_Over_Containers()
|
||||
{
|
||||
string payload = "{\"first\":{\"value\":1},\"second\":[1,2],\"third\":123.45}";
|
||||
JsonParser target = new JsonParser(payload);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.BeginObject, payload, 0, 1, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.IsProperty("first", payload, 1, 8, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.BeginObject, payload, 9, 1, target);
|
||||
Assert.IsTrue(target.Skip());
|
||||
AssertToken.Matches(JsonTokenType.EndObject, payload, 9, 11, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.EndProperty, payload, 1, 19, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.IsProperty("second", payload, 21, 9, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.BeginArray, payload, 30, 1, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.IsValue(1, payload, 31, 1, target);
|
||||
Assert.IsTrue(target.Skip());
|
||||
AssertToken.Matches(JsonTokenType.EndArray, payload, 30, 5, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.EndProperty, payload, 21, 14, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.IsProperty("third", payload, 36, 8, target);
|
||||
Assert.IsTrue(target.Skip());
|
||||
AssertToken.Matches(JsonTokenType.EndProperty, payload, 36, 14, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.EndObject, payload, 0, 51, target);
|
||||
AssertToken.IsComplete(payload, target);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Next parses null property.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonParser_Next_Parses_Null_Property()
|
||||
{
|
||||
string payload = "{\"isNull\":null}";
|
||||
JsonParser target = new JsonParser(payload);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.BeginObject, payload, 0, 1, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.IsProperty("isNull", payload, 1, 9, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.Null, payload, 10, 4, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.EndProperty, payload, 1, 13, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.EndObject, payload, 0, 15, target);
|
||||
AssertToken.IsComplete(payload, target);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reset expands buffer.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonParser_Reset_Expands_Buffer()
|
||||
{
|
||||
string payload = "{\"text\":\"\\n\"}";
|
||||
JsonParser target = new JsonParser(payload);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.BeginObject, payload, 0, 1, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.IsProperty("text", payload, 1, 7, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.IsValue("\n", payload, 8, 4, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.EndProperty, payload, 1, 11, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.EndObject, payload, 0, 13, target);
|
||||
AssertToken.IsComplete(payload, target);
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.Append("{\"text\":\"");
|
||||
for (int i = 0; i < 100000; i++)
|
||||
{
|
||||
builder.Append("\\n");
|
||||
}
|
||||
|
||||
builder.Append("\"}");
|
||||
payload = builder.ToString();
|
||||
target.Reset(payload);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.BeginObject, payload, 0, 1, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.IsProperty("text", payload, 1, 7, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.IsValue(new string('\n', 100000), payload, 8, 200002, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.EndProperty, payload, 1, 200009, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.EndObject, payload, 0, 200011, target);
|
||||
AssertToken.IsComplete(payload, target);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// TryParseToken parses Boolean.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonParser_TryParseToken_Parses_Boolean()
|
||||
{
|
||||
string payload = "true";
|
||||
JsonParser target = new JsonParser(payload);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.IsValue(true, payload, 0, payload.Length, target);
|
||||
AssertToken.IsComplete(payload, target);
|
||||
payload = "false";
|
||||
target.Reset(payload);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.IsValue(false, payload, 0, payload.Length, target);
|
||||
AssertToken.IsComplete(payload, target);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// TryParseToken parses Int64.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonParser_TryParseToken_Parses_Int64()
|
||||
{
|
||||
string payload = long.MaxValue.ToString(CultureInfo.InvariantCulture);
|
||||
JsonParser target = new JsonParser(payload);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.IsValue(long.MaxValue, payload, 0, payload.Length, target);
|
||||
AssertToken.IsComplete(payload, target);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// TryParseToken parses UInt64.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonParser_TryParseToken_Parses_UInt64()
|
||||
{
|
||||
string payload = ulong.MaxValue.ToString(CultureInfo.InvariantCulture);
|
||||
JsonParser target = new JsonParser(payload);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.IsValue(ulong.MaxValue, payload, 0, payload.Length, target);
|
||||
AssertToken.IsComplete(payload, target);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// TryParseToken parses UInt64.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonParser_TryParseToken_Parses_Hexadecimal_UInt64()
|
||||
{
|
||||
string payload = "0x0123456789ABCDEF";
|
||||
JsonParser target = new JsonParser(payload);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.IsValue(81985529216486895UL, payload, 0, payload.Length, target);
|
||||
AssertToken.IsComplete(payload, target);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// TryParseToken parses Double.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonParser_TryParseToken_Parses_Double()
|
||||
{
|
||||
string payload = double.MinValue.ToString("R", CultureInfo.InvariantCulture);
|
||||
JsonParser target = new JsonParser(payload);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.IsValue(double.MinValue, payload, 0, payload.Length, target);
|
||||
AssertToken.IsComplete(payload, target);
|
||||
payload = double.Epsilon.ToString("R", CultureInfo.InvariantCulture);
|
||||
target.Reset(payload);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.IsValue(double.Epsilon, payload, 0, payload.Length, target);
|
||||
AssertToken.IsComplete(payload, target);
|
||||
payload = double.MaxValue.ToString("R", CultureInfo.InvariantCulture);
|
||||
target.Reset(payload);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.IsValue(double.MaxValue, payload, 0, payload.Length, target);
|
||||
AssertToken.IsComplete(payload, target);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// TryParseToken parses String.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonParser_TryParseToken_Parses_String()
|
||||
{
|
||||
string payload = Constants.UnicodeRainbowEncoded;
|
||||
JsonParser target = new JsonParser(payload);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.IsValue(Constants.UnicodeRainbowDecoded, payload, 0, payload.Length, target);
|
||||
AssertToken.IsComplete(payload, target);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// TryParseToken ignores array white space.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonParser_TryParseToken_Ignores_Array_White_Space()
|
||||
{
|
||||
string payload = " [ 1 , 2 ] ";
|
||||
JsonParser target = new JsonParser(payload);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.BeginArray, payload, 1, 1, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.IsValue(1, payload, 3, 1, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.IsValue(2, payload, 7, 1, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.EndArray, payload, 1, 9, target);
|
||||
AssertToken.IsComplete(payload, target);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// TryParseToken ignores object white space.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void JsonParser_TryParseToken_Ignores_Object_White_Space()
|
||||
{
|
||||
string payload = " { \"key\" : \"value\" } ";
|
||||
JsonParser target = new JsonParser(payload);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.BeginObject, payload, 1, 1, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.IsProperty("key", payload, 3, 7, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.IsValue("value", payload, 11, 7, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.EndProperty, payload, 3, 15, target);
|
||||
Assert.IsTrue(target.Next());
|
||||
AssertToken.Matches(JsonTokenType.EndObject, payload, 1, 19, target);
|
||||
AssertToken.IsComplete(payload, target);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,118 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{453C48C4-AA86-45A1-AEAE-A404EA3E0B94}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Microsoft.Shared.Dna.Json.Test</RootNamespace>
|
||||
<AssemblyName>Microsoft.Shared.Dna.Json.Test</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
<ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath>
|
||||
<IsCodedUITest>False</IsCodedUITest>
|
||||
<TestProjectType>UnitTest</TestProjectType>
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<RestorePackages>true</RestorePackages>
|
||||
<RunCodeAnalysis>true</RunCodeAnalysis>
|
||||
<CodeAnalysisRuleSet>..\Microsoft.Shared.Dna.Test.ruleset</CodeAnalysisRuleSet>
|
||||
<NuGetPackageImportStamp>
|
||||
</NuGetPackageImportStamp>
|
||||
<DontImportCodeContracts>true</DontImportCodeContracts>
|
||||
<CodeContractsInstallDir>$(MSBuildProjectDirectory)\..\packages\DotNet.Contracts.1.10.20606.1\</CodeContractsInstallDir>
|
||||
<CodeContractsAssemblyMode>1</CodeContractsAssemblyMode>
|
||||
<CodeContractsEnableRuntimeChecking>true</CodeContractsEnableRuntimeChecking>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="Microsoft.VisualStudio.QualityTools.LoadTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
</ItemGroup>
|
||||
<Choose>
|
||||
<When Condition="('$(VisualStudioVersion)' == '10.0' or '$(VisualStudioVersion)' == '') and '$(TargetFrameworkVersion)' == 'v3.5'">
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
|
||||
</ItemGroup>
|
||||
</When>
|
||||
<Otherwise>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework" />
|
||||
</ItemGroup>
|
||||
</Otherwise>
|
||||
</Choose>
|
||||
<ItemGroup>
|
||||
<Compile Include="..\Microsoft.Shared.Dna.Json\JsonBuilder.cs">
|
||||
<Link>Microsoft.Shared.Dna\JsonBuilder.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Microsoft.Shared.Dna.Json\JsonConstants.cs">
|
||||
<Link>Microsoft.Shared.Dna\JsonConstants.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Microsoft.Shared.Dna.Json\JsonParser.cs">
|
||||
<Link>Microsoft.Shared.Dna\JsonParser.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Microsoft.Shared.Dna.Json\JsonTokenTypeExtensions.cs">
|
||||
<Link>Microsoft.Shared.Dna\JsonTokenTypeExtensions.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Microsoft.Shared.Dna.Json\Microsoft.Shared.Dna\FixedStringBuilder.cs">
|
||||
<Link>Microsoft.Shared.Dna\FixedStringBuilder.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Microsoft.Shared.Dna.Json\Microsoft.Shared.Dna\StringSegment.cs">
|
||||
<Link>Microsoft.Shared.Dna\StringSegment.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="AssertToken.cs" />
|
||||
<Compile Include="Constants.cs" />
|
||||
<Compile Include="JsonBuilderTests.cs" />
|
||||
<Compile Include="JsonParserTests.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config">
|
||||
<SubType>Designer</SubType>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<Choose>
|
||||
<When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'">
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.VisualStudio.QualityTools.CodedUITestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualStudio.TestTools.UITest.Common, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualStudio.TestTools.UITest.Extension, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualStudio.TestTools.UITesting, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
</When>
|
||||
</Choose>
|
||||
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="..\Microsoft.Shared.Dna.targets" />
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
<Import Project="$(CodeContractsInstallDir)MsBuild\v14.0\Microsoft.CodeContracts.targets" Condition="Exists('$(CodeContractsInstallDir)MsBuild\v14.0\Microsoft.CodeContracts.targets')" />
|
||||
<Import Project="..\packages\StyleCop.MSBuild.4.7.54.0\build\StyleCop.MSBuild.Targets" Condition="Exists('..\packages\StyleCop.MSBuild.4.7.54.0\build\StyleCop.MSBuild.Targets')" />
|
||||
</Project>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="DotNet.Contracts" version="1.10.20606.1" targetFramework="net45" />
|
||||
<package id="StyleCop.MSBuild" version="4.7.54.0" targetFramework="net45" developmentDependency="true" />
|
||||
</packages>
|
|
@ -0,0 +1,46 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.25420.1
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Shared.Dna.Json", "Microsoft.Shared.Dna.Json\Microsoft.Shared.Dna.Json.csproj", "{90D59DA0-084B-4722-8F45-D742818F3D9A}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Shared.Dna.Json.Test", "Microsoft.Shared.Dna.Json.Test\Microsoft.Shared.Dna.Json.Test.csproj", "{453C48C4-AA86-45A1-AEAE-A404EA3E0B94}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Shared.Dna.Json.Profile", "Microsoft.Shared.Dna.Json.Profile\Microsoft.Shared.Dna.Json.Profile.csproj", "{C338ACCE-9521-435A-9011-2D6DF981920A}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{D5A0AB76-DA28-4961-A2BD-8E0EC7F30138}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
CONTRIBUTING.md = CONTRIBUTING.md
|
||||
LICENSE.txt = LICENSE.txt
|
||||
Microsoft.Shared.Dna.Dictionary.xml = Microsoft.Shared.Dna.Dictionary.xml
|
||||
Microsoft.Shared.Dna.ruleset = Microsoft.Shared.Dna.ruleset
|
||||
Microsoft.Shared.Dna.targets = Microsoft.Shared.Dna.targets
|
||||
Microsoft.Shared.Dna.Test.ruleset = Microsoft.Shared.Dna.Test.ruleset
|
||||
README.md = README.md
|
||||
Settings.StyleCop = Settings.StyleCop
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{90D59DA0-084B-4722-8F45-D742818F3D9A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{90D59DA0-084B-4722-8F45-D742818F3D9A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{90D59DA0-084B-4722-8F45-D742818F3D9A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{90D59DA0-084B-4722-8F45-D742818F3D9A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{453C48C4-AA86-45A1-AEAE-A404EA3E0B94}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{453C48C4-AA86-45A1-AEAE-A404EA3E0B94}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{453C48C4-AA86-45A1-AEAE-A404EA3E0B94}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{453C48C4-AA86-45A1-AEAE-A404EA3E0B94}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C338ACCE-9521-435A-9011-2D6DF981920A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C338ACCE-9521-435A-9011-2D6DF981920A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C338ACCE-9521-435A-9011-2D6DF981920A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C338ACCE-9521-435A-9011-2D6DF981920A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,233 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// <copyright file="JsonConstants.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license. See license file in the project root for full license information.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Shared.Dna.Json
|
||||
{
|
||||
/// <summary>
|
||||
/// Constant JSON values used by both <see cref="JsonBuilder"/> and
|
||||
/// <see cref="JsonParser"/>.
|
||||
/// </summary>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage(
|
||||
"Microsoft.Performance",
|
||||
"CA1812:AvoidUninstantiatedInternalClasses",
|
||||
Justification = "You don't have to use everything in an in-line code share.")]
|
||||
internal static class JsonConstants
|
||||
{
|
||||
/// <summary>
|
||||
/// The array header character.
|
||||
/// </summary>
|
||||
public const char ArrayHeader = '[';
|
||||
|
||||
/// <summary>
|
||||
/// The array footer character.
|
||||
/// </summary>
|
||||
public const char ArrayFooter = ']';
|
||||
|
||||
/// <summary>
|
||||
/// Maximum character length of a boolean value.
|
||||
/// </summary>
|
||||
public const int BooleanValueLength = 5;
|
||||
|
||||
/// <summary>
|
||||
/// The escape character.
|
||||
/// </summary>
|
||||
public const char CharacterEscape = '\\';
|
||||
|
||||
/// <summary>
|
||||
/// The decimal point character.
|
||||
/// </summary>
|
||||
public const char DecimalPoint = '.';
|
||||
|
||||
/// <summary>
|
||||
/// The base of a decimal number.
|
||||
/// </summary>
|
||||
public const byte DecimalRadix = 10;
|
||||
|
||||
/// <summary>
|
||||
/// The default capacity for all internal character buffers.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Keep this under the large object limit.
|
||||
/// </remarks>
|
||||
public const int DefaultCapacity = 40000;
|
||||
|
||||
/// <summary>
|
||||
/// The default depth for all internal context stacks.
|
||||
/// </summary>
|
||||
public const int DefaultDepth = 20;
|
||||
|
||||
/// <summary>
|
||||
/// The element separator character.
|
||||
/// </summary>
|
||||
public const char ElementSeparator = ',';
|
||||
|
||||
/// <summary>
|
||||
/// The lower-case exponent character.
|
||||
/// </summary>
|
||||
public const char ExponentLowercase = 'e';
|
||||
|
||||
/// <summary>
|
||||
/// The upper-case exponent character.
|
||||
/// </summary>
|
||||
public const char ExponentUppercase = 'E';
|
||||
|
||||
/// <summary>
|
||||
/// The first character of the false literal.
|
||||
/// </summary>
|
||||
public const char FalseLeadCharacter = 'f';
|
||||
|
||||
/// <summary>
|
||||
/// The false literal string.
|
||||
/// </summary>
|
||||
public const string FalseValue = "false";
|
||||
|
||||
/// <summary>
|
||||
/// The character length of the false literal string.
|
||||
/// </summary>
|
||||
public const int FalseValueLength = 5;
|
||||
|
||||
/// <summary>
|
||||
/// The lower-case hexadecimal indicator.
|
||||
/// </summary>
|
||||
public const char HexLowercase = 'x';
|
||||
|
||||
/// <summary>
|
||||
/// The base of a hexadecimal number.
|
||||
/// </summary>
|
||||
public const byte HexRadix = 16;
|
||||
|
||||
/// <summary>
|
||||
/// The upper-case hexadecimal indicator.
|
||||
/// </summary>
|
||||
public const char HexUppercase = 'X';
|
||||
|
||||
/// <summary>
|
||||
/// The name-value separator character.
|
||||
/// </summary>
|
||||
public const char NameValueSeparator = ':';
|
||||
|
||||
/// <summary>
|
||||
/// The negative sign character.
|
||||
/// </summary>
|
||||
public const char NegativeSign = '-';
|
||||
|
||||
/// <summary>
|
||||
/// The first character of the null literal.
|
||||
/// </summary>
|
||||
public const char NullLeadCharacter = 'n';
|
||||
|
||||
/// <summary>
|
||||
/// The null literal string.
|
||||
/// </summary>
|
||||
public const string NullValue = "null";
|
||||
|
||||
/// <summary>
|
||||
/// The character length of the null literal string.
|
||||
/// </summary>
|
||||
public const int NullValueLength = 4;
|
||||
|
||||
/// <summary>
|
||||
/// The object header character.
|
||||
/// </summary>
|
||||
public const char ObjectHeader = '{';
|
||||
|
||||
/// <summary>
|
||||
/// The object footer character.
|
||||
/// </summary>
|
||||
public const char ObjectFooter = '}';
|
||||
|
||||
/// <summary>
|
||||
/// The negative sign character.
|
||||
/// </summary>
|
||||
public const char PositiveSign = '+';
|
||||
|
||||
/// <summary>
|
||||
/// The string enclosure character.
|
||||
/// </summary>
|
||||
public const char StringEnclosure = '"';
|
||||
|
||||
/// <summary>
|
||||
/// The first character of the true literal.
|
||||
/// </summary>
|
||||
public const char TrueLeadCharacter = 't';
|
||||
|
||||
/// <summary>
|
||||
/// The true literal string.
|
||||
/// </summary>
|
||||
public const string TrueValue = "true";
|
||||
|
||||
/// <summary>
|
||||
/// The character length of the true literal string.
|
||||
/// </summary>
|
||||
public const int TrueValueLength = 4;
|
||||
|
||||
/// <summary>
|
||||
/// The truncated flag as an object.
|
||||
/// </summary>
|
||||
public const string TruncatedObject = "{\"(truncated)\":true}";
|
||||
|
||||
/// <summary>
|
||||
/// The character length of the truncated flag as an object.
|
||||
/// </summary>
|
||||
public const int TruncatedObjectLength = 20;
|
||||
|
||||
/// <summary>
|
||||
/// The truncated flag as a property.
|
||||
/// </summary>
|
||||
public const string TruncatedProperty = "\"(truncated)\":true";
|
||||
|
||||
/// <summary>
|
||||
/// The character length of the truncated flag as a property.
|
||||
/// </summary>
|
||||
public const int TruncatedPropertyLength = 18;
|
||||
|
||||
/// <summary>
|
||||
/// The zero character.
|
||||
/// </summary>
|
||||
public const char Zero = '0';
|
||||
|
||||
/// <summary>
|
||||
/// The decimal digit lookup table.
|
||||
/// </summary>
|
||||
public static readonly sbyte[] DecimalDigits = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
|
||||
|
||||
/// <summary>
|
||||
/// The element length of the decimal digit lookup table.
|
||||
/// </summary>
|
||||
public static readonly int DecimalDigitsLength = JsonConstants.DecimalDigits.Length;
|
||||
|
||||
/// <summary>
|
||||
/// The character escape sequences lookup table.
|
||||
/// </summary>
|
||||
public static readonly string[] EscapeSequences = { "\\u0000", "\\u0001", "\\u0002", "\\u0003", "\\u0004", "\\u0005", "\\u0006", "\\u0007", "\\b", "\\t", "\\n", "\\u000B", "\\f", "\\r", "\\u000E", "\\u000F", "\\u0010", "\\u0011", "\\u0012", "\\u0013", "\\u0014", "\\u0015", "\\u0016", "\\u0017", "\\u0018", "\\u0019", "\\u001A", "\\u001B", "\\u001C", "\\u001D", "\\u001E", "\\u001F", null, null, "\\\"", null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "\\\\", null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "\\u007F", "\\u0080", "\\u0081", "\\u0082", "\\u0083", "\\u0084", "\\u0085", "\\u0086", "\\u0087", "\\u0088", "\\u0089", "\\u008A", "\\u008B", "\\u008C", "\\u008D", "\\u008E", "\\u008F", "\\u0090", "\\u0091", "\\u0092", "\\u0093", "\\u0094", "\\u0095", "\\u0096", "\\u0097", "\\u0098", "\\u0099", "\\u009A", "\\u009B", "\\u009C", "\\u009D", "\\u009E", "\\u009F" };
|
||||
|
||||
/// <summary>
|
||||
/// The element length of the character escape sequences lookup table.
|
||||
/// </summary>
|
||||
public static readonly int EscapeSequencesLength = JsonConstants.EscapeSequences.Length;
|
||||
|
||||
/// <summary>
|
||||
/// The hexadecimal digit lookup table.
|
||||
/// </summary>
|
||||
public static readonly sbyte[] HexDigits = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15 };
|
||||
|
||||
/// <summary>
|
||||
/// The element length of the hexadecimal digit lookup table.
|
||||
/// </summary>
|
||||
public static readonly int HexDigitsLength = JsonConstants.HexDigits.Length;
|
||||
|
||||
/// <summary>
|
||||
/// The character un-escape sequences lookup table.
|
||||
/// </summary>
|
||||
public static readonly char[] UnescapeSequences = { '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\"', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '/', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\\', '\0', '\0', '\0', '\0', '\0', '\b', '\0', '\0', '\0', '\f', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\n', '\0', '\0', '\0', '\r', '\0', '\t' };
|
||||
|
||||
/// <summary>
|
||||
/// The element length of the character un-escape sequences lookup table.
|
||||
/// </summary>
|
||||
public static readonly int UnescapeSequencesLength = JsonConstants.UnescapeSequences.Length;
|
||||
}
|
||||
}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,221 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// <copyright file="JsonTokenTypeExtensions.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license. See license file in the project root for full license information.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Shared.Dna.Json
|
||||
{
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the various JSON token types that the parser can encounter.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
internal enum JsonTokenType : short
|
||||
{
|
||||
/// <summary>
|
||||
/// No token encountered yet.
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// The beginning of an array.
|
||||
/// </summary>
|
||||
BeginArray = 1,
|
||||
|
||||
/// <summary>
|
||||
/// The end of an array.
|
||||
/// </summary>
|
||||
EndArray = 2,
|
||||
|
||||
/// <summary>
|
||||
/// The beginning of an object.
|
||||
/// </summary>
|
||||
BeginObject = 4,
|
||||
|
||||
/// <summary>
|
||||
/// The end of an object.
|
||||
/// </summary>
|
||||
EndObject = 8,
|
||||
|
||||
/// <summary>
|
||||
/// The beginning of a property.
|
||||
/// </summary>
|
||||
BeginProperty = 16,
|
||||
|
||||
/// <summary>
|
||||
/// The end of a property.
|
||||
/// </summary>
|
||||
EndProperty = 32,
|
||||
|
||||
/// <summary>
|
||||
/// A null literal.
|
||||
/// </summary>
|
||||
Null = 64,
|
||||
|
||||
/// <summary>
|
||||
/// A boolean literal - true or false.
|
||||
/// </summary>
|
||||
Boolean = 128,
|
||||
|
||||
/// <summary>
|
||||
/// An integer value.
|
||||
/// </summary>
|
||||
Integer = 256,
|
||||
|
||||
/// <summary>
|
||||
/// A floating-point value.
|
||||
/// </summary>
|
||||
Float = 512,
|
||||
|
||||
/// <summary>
|
||||
/// A string value.
|
||||
/// </summary>
|
||||
String = 1024,
|
||||
|
||||
/// <summary>
|
||||
/// Parsing reached the end of the string with no errors.
|
||||
/// </summary>
|
||||
Complete = 2048,
|
||||
|
||||
/// <summary>
|
||||
/// Parsing encountered a malformed token in the string.
|
||||
/// </summary>
|
||||
Invalid = 4096,
|
||||
|
||||
/// <summary>
|
||||
/// Any open container type - arrays, objects or properties.
|
||||
/// </summary>
|
||||
OpenContainer = BeginArray | BeginObject | BeginProperty,
|
||||
|
||||
/// <summary>
|
||||
/// Any closed container type - arrays, objects or properties.
|
||||
/// </summary>
|
||||
ClosedContainer = EndArray | EndObject | EndProperty,
|
||||
|
||||
/// <summary>
|
||||
/// Any container type - arrays, objects or properties.
|
||||
/// </summary>
|
||||
Container = BeginArray | EndArray | BeginObject | EndObject | BeginProperty | EndProperty,
|
||||
|
||||
/// <summary>
|
||||
/// Any numeric type - integers or floating-point values.
|
||||
/// </summary>
|
||||
Number = Integer | Float,
|
||||
|
||||
/// <summary>
|
||||
/// Any value type - nulls, booleans, numbers, or strings.
|
||||
/// </summary>
|
||||
Value = Null | Boolean | Integer | Float | String,
|
||||
|
||||
/// <summary>
|
||||
/// Parsing is complete - either because the end of the string was reached or an
|
||||
/// invalid token was encountered.
|
||||
/// </summary>
|
||||
EndOfPayload = Complete | Invalid
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extension methods for <see cref="JsonTokenType"/>.
|
||||
/// </summary>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage(
|
||||
"Microsoft.Performance",
|
||||
"CA1812:AvoidUninstantiatedInternalClasses",
|
||||
Justification = "You don't have to use everything in an in-line code share.")]
|
||||
internal static class JsonTokenTypeExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Determines if a token type is a closed container.
|
||||
/// </summary>
|
||||
/// <param name="target">The token to check.</param>
|
||||
/// <returns>
|
||||
/// A value indicating whether or not the token is a closed container.
|
||||
/// </returns>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage(
|
||||
"Microsoft.Performance",
|
||||
"CA1811:AvoidUncalledPrivateCode",
|
||||
Justification = "You don't have to use everything in an in-line code share.")]
|
||||
public static bool IsClosedContainer(this JsonTokenType target)
|
||||
{
|
||||
return (target & JsonTokenType.ClosedContainer) != JsonTokenType.None;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if a token type is a container or not.
|
||||
/// </summary>
|
||||
/// <param name="target">The token to check.</param>
|
||||
/// <returns>A value indicating whether or not the token is a container.</returns>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage(
|
||||
"Microsoft.Performance",
|
||||
"CA1811:AvoidUncalledPrivateCode",
|
||||
Justification = "You don't have to use everything in an in-line code share.")]
|
||||
public static bool IsContainer(this JsonTokenType target)
|
||||
{
|
||||
return (target & JsonTokenType.Container) != JsonTokenType.None;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if a token is at the end of the payload.
|
||||
/// </summary>
|
||||
/// <param name="target">The token to check.</param>
|
||||
/// <returns>
|
||||
/// A value indicating whether or not the token is at the end of the payload.
|
||||
/// </returns>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage(
|
||||
"Microsoft.Performance",
|
||||
"CA1811:AvoidUncalledPrivateCode",
|
||||
Justification = "You don't have to use everything in an in-line code share.")]
|
||||
public static bool IsEndOfPayload(this JsonTokenType target)
|
||||
{
|
||||
return (target & JsonTokenType.EndOfPayload) != JsonTokenType.None;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if a token type is a null literal.
|
||||
/// </summary>
|
||||
/// <param name="target">The token to check.</param>
|
||||
/// <returns>
|
||||
/// A value indicating whether or not the token is a null literal.
|
||||
/// </returns>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage(
|
||||
"Microsoft.Performance",
|
||||
"CA1811:AvoidUncalledPrivateCode",
|
||||
Justification = "You don't have to use everything in an in-line code share.")]
|
||||
public static bool IsNull(this JsonTokenType target)
|
||||
{
|
||||
return target == JsonTokenType.Null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if a token type is an open container.
|
||||
/// </summary>
|
||||
/// <param name="target">The token to check.</param>
|
||||
/// <returns>
|
||||
/// A value indicating whether or not the token is an open container.
|
||||
/// </returns>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage(
|
||||
"Microsoft.Performance",
|
||||
"CA1811:AvoidUncalledPrivateCode",
|
||||
Justification = "You don't have to use everything in an in-line code share.")]
|
||||
public static bool IsOpenContainer(this JsonTokenType target)
|
||||
{
|
||||
return (target & JsonTokenType.OpenContainer) != JsonTokenType.None;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if a token type is a value or not.
|
||||
/// </summary>
|
||||
/// <param name="target">The token to check.</param>
|
||||
/// <returns>A value indicating whether or not the token is a value.</returns>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage(
|
||||
"Microsoft.Performance",
|
||||
"CA1811:AvoidUncalledPrivateCode",
|
||||
Justification = "You don't have to use everything in an in-line code share.")]
|
||||
public static bool IsValue(this JsonTokenType target)
|
||||
{
|
||||
return (target & JsonTokenType.Value) != JsonTokenType.None;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{90D59DA0-084B-4722-8F45-D742818F3D9A}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Microsoft.Shared.Dna.Json</RootNamespace>
|
||||
<AssemblyName>Microsoft.Shared.Dna.Json</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
|
||||
<RestorePackages>true</RestorePackages>
|
||||
<RunCodeAnalysis>true</RunCodeAnalysis>
|
||||
<CodeAnalysisRuleSet>..\Microsoft.Shared.Dna.ruleset</CodeAnalysisRuleSet>
|
||||
<NuGetPackageImportStamp>
|
||||
</NuGetPackageImportStamp>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="JsonBuilder.cs" />
|
||||
<Compile Include="JsonConstants.cs" />
|
||||
<Compile Include="JsonParser.cs" />
|
||||
<Compile Include="JsonTokenTypeExtensions.cs" />
|
||||
<Compile Include="Microsoft.Shared.Dna\FixedStringBuilder.cs" />
|
||||
<Compile Include="Microsoft.Shared.Dna\StringSegment.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Package Include="Microsoft.Shared.Dna.Json.nuspec" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config">
|
||||
<SubType>Designer</SubType>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="..\Microsoft.Shared.Dna.targets" />
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
<Import Project="..\packages\StyleCop.MSBuild.4.7.54.0\build\StyleCop.MSBuild.Targets" Condition="Exists('..\packages\StyleCop.MSBuild.4.7.54.0\build\StyleCop.MSBuild.Targets')" />
|
||||
</Project>
|
|
@ -0,0 +1,30 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<package>
|
||||
<metadata>
|
||||
<id>Microsoft.Shared.Dna.Json</id>
|
||||
<version>2.0.0</version>
|
||||
<title>Windows Data and Analytics Shared Code - JSON Processing</title>
|
||||
<authors>Microsoft,microsoft-shared-dna</authors>
|
||||
<owners>Microsoft,microsoft-shared-dna</owners>
|
||||
<description>Are you doing simple read and write tasks with JSON.NET (or even System.Runtime.Serialization.Json)? Do you want to partially process your JSON payload? Are you running it in a tight loop? Are you wondering why there's so much pressure on the garbage collector? Do you want something even faster? If so, then this package might be right for you.</description>
|
||||
<summary>Windows Data and Analytics shared code for reading and writing JSON in big data applications.</summary>
|
||||
<projectUrl>https://github.com/Microsoft/Microsoft.Shared.Dna.Json</projectUrl>
|
||||
<licenseUrl>https://github.com/Microsoft/Microsoft.Shared.Dna.Json/blob/master/LICENSE.txt</licenseUrl>
|
||||
<copyright>Microsoft Corporation</copyright>
|
||||
<requireLicenseAcceptance>true</requireLicenseAcceptance>
|
||||
<tags>microsoft telemetry map-reduce big data json</tags>
|
||||
<developmentDependency>true</developmentDependency>
|
||||
<dependencies>
|
||||
<dependency id="Microsoft.Shared.Dna.Text" version="2.0.0" />
|
||||
</dependencies>
|
||||
<frameworkAssemblies>
|
||||
<frameworkAssembly assemblyName="System" />
|
||||
</frameworkAssemblies>
|
||||
</metadata>
|
||||
<files>
|
||||
<file src="JsonBuilder.cs" target="content\net40\Microsoft.Shared.Dna" />
|
||||
<file src="JsonConstants.cs" target="content\net40\Microsoft.Shared.Dna" />
|
||||
<file src="JsonParser.cs" target="content\net40\Microsoft.Shared.Dna" />
|
||||
<file src="JsonTokenTypeExtensions.cs" target="content\net40\Microsoft.Shared.Dna" />
|
||||
</files>
|
||||
</package>
|
|
@ -0,0 +1,442 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// <copyright file="FixedStringBuilder.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license. See license file in the project root for full license information.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Shared.Dna.Text
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics.Contracts;
|
||||
|
||||
/// <summary>
|
||||
/// Fixed-length string builder.
|
||||
/// </summary>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage(
|
||||
"Microsoft.Performance",
|
||||
"CA1812:AvoidUninstantiatedInternalClasses",
|
||||
Justification = "You don't have to use everything in an in-line code share.")]
|
||||
internal sealed class FixedStringBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// Character buffer array.
|
||||
/// </summary>
|
||||
private char[] buffer = null;
|
||||
|
||||
/// <summary>
|
||||
/// Cached buffer capacity. Always equal to this.buffer.Length.
|
||||
/// </summary>
|
||||
private int bufferCapacity = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Current length of the characters in the buffer.
|
||||
/// </summary>
|
||||
private int length = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="FixedStringBuilder"/> class.
|
||||
/// </summary>
|
||||
/// <param name="capacity">
|
||||
/// The maximum number of characters that the builder can create a string for.
|
||||
/// </param>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage(
|
||||
"Microsoft.Performance",
|
||||
"CA1811:AvoidUncalledPrivateCode",
|
||||
Justification = "You don't have to use everything in an in-line code share.")]
|
||||
public FixedStringBuilder(int capacity)
|
||||
{
|
||||
#if CONTRACTS_FULL // Work around the implicit rewrite requirements of Contract.Requires<T>
|
||||
Contract.Requires<ArgumentOutOfRangeException>(capacity >= 0);
|
||||
#endif
|
||||
this.buffer = new char[capacity];
|
||||
this.bufferCapacity = capacity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the last character written to the builder, or the null character if nothing
|
||||
/// has been added.
|
||||
/// </summary>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage(
|
||||
"Microsoft.Performance",
|
||||
"CA1811:AvoidUncalledPrivateCode",
|
||||
Justification = "You don't have to use everything in an in-line code share.")]
|
||||
public char Last
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.length == 0)
|
||||
{
|
||||
return char.MinValue;
|
||||
}
|
||||
|
||||
return this.buffer[this.length - 1];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current number of characters that have been written to the builder.
|
||||
/// </summary>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage(
|
||||
"Microsoft.Performance",
|
||||
"CA1811:AvoidUncalledPrivateCode",
|
||||
Justification = "You don't have to use everything in an in-line code share.")]
|
||||
public int Length
|
||||
{
|
||||
get { return this.length; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears all the characters that have been written to the builder.
|
||||
/// </summary>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage(
|
||||
"Microsoft.Performance",
|
||||
"CA1811:AvoidUncalledPrivateCode",
|
||||
Justification = "You don't have to use everything in an in-line code share.")]
|
||||
public void Clear()
|
||||
{
|
||||
this.length = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts all the characters in the builder to a single string.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A string containing all the characters currently in the builder.
|
||||
/// </returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return new string(this.buffer, 0, this.length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to append a single character to the builder.
|
||||
/// </summary>
|
||||
/// <param name="value">The character to append.</param>
|
||||
/// <param name="reserve">
|
||||
/// The amount of capacity that must remain in the builder after the character has
|
||||
/// been added.
|
||||
/// </param>
|
||||
/// <returns>A value indicating whether or not the character was added.</returns>
|
||||
/// <remarks>
|
||||
/// You'll see a lot of repeated code in the TryAppend methods. This is deliberate.
|
||||
/// Since these methods are are usually on the hot path, you get a significant
|
||||
/// performance boost by manually in-lining the code.
|
||||
/// </remarks>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage(
|
||||
"Microsoft.Performance",
|
||||
"CA1811:AvoidUncalledPrivateCode",
|
||||
Justification = "You don't have to use everything in an in-line code share.")]
|
||||
public bool TryAppend(char value, int reserve)
|
||||
{
|
||||
#if CONTRACTS_FULL // Work around the implicit rewrite requirements of Contract.Requires<T>
|
||||
Contract.Requires<ArgumentOutOfRangeException>(reserve >= 0);
|
||||
#endif
|
||||
if (this.length + reserve < this.bufferCapacity)
|
||||
{
|
||||
this.buffer[this.length++] = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to append a single character to the builder.
|
||||
/// </summary>
|
||||
/// <param name="value">The character to append.</param>
|
||||
/// <param name="reserve">
|
||||
/// The amount of capacity that must remain in the builder after the character has
|
||||
/// been added.
|
||||
/// </param>
|
||||
/// <param name="rollback">
|
||||
/// The length to set the builder to if the append failed.
|
||||
/// </param>
|
||||
/// <returns>A value indicating whether or not the character was added.</returns>
|
||||
/// <remarks>
|
||||
/// You'll see a lot of repeated code in the TryAppend methods. This is deliberate.
|
||||
/// Since these methods are are usually on the hot path, you get a significant
|
||||
/// performance boost by manually in-lining the code.
|
||||
/// </remarks>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage(
|
||||
"Microsoft.Performance",
|
||||
"CA1811:AvoidUncalledPrivateCode",
|
||||
Justification = "You don't have to use everything in an in-line code share.")]
|
||||
public bool TryAppend(char value, int reserve, int rollback)
|
||||
{
|
||||
#if CONTRACTS_FULL // Work around the implicit rewrite requirements of Contract.Requires<T>
|
||||
Contract.Requires<ArgumentOutOfRangeException>(reserve >= 0);
|
||||
Contract.Requires<ArgumentOutOfRangeException>(rollback >= 0);
|
||||
#endif
|
||||
if (this.length + reserve < this.bufferCapacity)
|
||||
{
|
||||
this.buffer[this.length++] = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
this.length = rollback;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to append a single character to the builder.
|
||||
/// </summary>
|
||||
/// <param name="value">The character to append.</param>
|
||||
/// <param name="reserve">
|
||||
/// The amount of capacity that must remain in the builder after the character has
|
||||
/// been added.
|
||||
/// </param>
|
||||
/// <param name="rollback">
|
||||
/// The length of the builder before the character was added.
|
||||
/// </param>
|
||||
/// <returns>A value indicating whether or not the character was added.</returns>
|
||||
/// <remarks>
|
||||
/// You'll see a lot of repeated code in the TryAppend methods. This is deliberate.
|
||||
/// Since these methods are are usually on the hot path, you get a significant
|
||||
/// performance boost by manually in-lining the code.
|
||||
/// </remarks>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage(
|
||||
"Microsoft.Performance",
|
||||
"CA1811:AvoidUncalledPrivateCode",
|
||||
Justification = "You don't have to use everything in an in-line code share.")]
|
||||
public bool TryAppend(char value, int reserve, out int rollback)
|
||||
{
|
||||
#if CONTRACTS_FULL // Work around the implicit rewrite requirements of Contract.Requires<T>
|
||||
Contract.Requires<ArgumentOutOfRangeException>(reserve >= 0);
|
||||
#endif
|
||||
rollback = this.length;
|
||||
if (this.length + reserve < this.bufferCapacity)
|
||||
{
|
||||
this.buffer[this.length++] = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to append a string to the builder.
|
||||
/// </summary>
|
||||
/// <param name="value">The string to append.</param>
|
||||
/// <param name="reserve">
|
||||
/// The amount of capacity that must remain in the builder after the string has been
|
||||
/// added.
|
||||
/// </param>
|
||||
/// <returns>A value indicating whether or not the string was added.</returns>
|
||||
/// <remarks>
|
||||
/// You'll see a lot of repeated code in the TryAppend methods. This is deliberate.
|
||||
/// Since these methods are are usually on the hot path, you get a significant
|
||||
/// performance boost by manually in-lining the code.
|
||||
/// </remarks>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage(
|
||||
"Microsoft.Performance",
|
||||
"CA1811:AvoidUncalledPrivateCode",
|
||||
Justification = "You don't have to use everything in an in-line code share.")]
|
||||
public bool TryAppend(string value, int reserve)
|
||||
{
|
||||
#if CONTRACTS_FULL // Work around the implicit rewrite requirements of Contract.Requires<T>
|
||||
Contract.Requires<ArgumentOutOfRangeException>(reserve >= 0);
|
||||
#endif
|
||||
return this.TryAppendUnsafe(value, reserve);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to append a string to the builder.
|
||||
/// </summary>
|
||||
/// <param name="value">The string to append.</param>
|
||||
/// <param name="reserve">
|
||||
/// The amount of capacity that must remain in the builder after the string has been
|
||||
/// added.
|
||||
/// </param>
|
||||
/// <param name="rollback">
|
||||
/// The length to set the builder to if the append failed.
|
||||
/// </param>
|
||||
/// <returns>A value indicating whether or not the string was added.</returns>
|
||||
/// <remarks>
|
||||
/// You'll see a lot of repeated code in the TryAppend methods. This is deliberate.
|
||||
/// Since these methods are are usually on the hot path, you get a significant
|
||||
/// performance boost by manually in-lining the code.
|
||||
/// </remarks>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage(
|
||||
"Microsoft.Performance",
|
||||
"CA1811:AvoidUncalledPrivateCode",
|
||||
Justification = "You don't have to use everything in an in-line code share.")]
|
||||
public bool TryAppend(string value, int reserve, int rollback)
|
||||
{
|
||||
#if CONTRACTS_FULL // Work around the implicit rewrite requirements of Contract.Requires<T>
|
||||
Contract.Requires<ArgumentOutOfRangeException>(reserve >= 0);
|
||||
Contract.Requires<ArgumentOutOfRangeException>(rollback >= 0);
|
||||
#endif
|
||||
return this.TryAppendUnsafe(value, reserve, rollback);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to expand the capacity of the string builder.
|
||||
/// </summary>
|
||||
/// <param name="capacity">
|
||||
/// The new maximum number of characters that the builder can create a string for.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A value indicating whether the builder was expanded or the current capacity was
|
||||
/// sufficient.
|
||||
/// </returns>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage(
|
||||
"Microsoft.Performance",
|
||||
"CA1811:AvoidUncalledPrivateCode",
|
||||
Justification = "You don't have to use everything in an in-line code share.")]
|
||||
public bool TryExpand(int capacity)
|
||||
{
|
||||
#if CONTRACTS_FULL // Work around the implicit rewrite requirements of Contract.Requires<T>
|
||||
Contract.Requires<ArgumentOutOfRangeException>(capacity >= 0);
|
||||
#endif
|
||||
if (capacity > this.bufferCapacity)
|
||||
{
|
||||
this.Resize(capacity);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to change the capacity of the string builder.
|
||||
/// </summary>
|
||||
/// <param name="capacity">
|
||||
/// The new maximum number of characters that the builder can create a string for.
|
||||
/// </param>
|
||||
/// <param name="reserve">
|
||||
/// The amount of capacity that must remain in the builder after the builder has
|
||||
/// been resized.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A value indicating whether the builder was resized or the current content and
|
||||
/// reserve exceeded the new capacity.
|
||||
/// </returns>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage(
|
||||
"Microsoft.Performance",
|
||||
"CA1811:AvoidUncalledPrivateCode",
|
||||
Justification = "You don't have to use everything in an in-line code share.")]
|
||||
public bool TryResize(int capacity, int reserve)
|
||||
{
|
||||
#if CONTRACTS_FULL // Work around the implicit rewrite requirements of Contract.Requires<T>
|
||||
Contract.Requires<ArgumentOutOfRangeException>(capacity >= reserve);
|
||||
Contract.Requires<ArgumentOutOfRangeException>(reserve >= 0);
|
||||
#endif
|
||||
if (capacity - reserve >= this.length)
|
||||
{
|
||||
this.Resize(capacity);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes the capacity of the string builder.
|
||||
/// </summary>
|
||||
/// <param name="capacity">
|
||||
/// The new maximum number of characters that the builder can create a string for.
|
||||
/// </param>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage(
|
||||
"Microsoft.Performance",
|
||||
"CA1811:AvoidUncalledPrivateCode",
|
||||
Justification = "You don't have to use everything in an in-line code share.")]
|
||||
private void Resize(int capacity)
|
||||
{
|
||||
char[] resized = new char[capacity];
|
||||
for (int i = 0; i < this.length; i++)
|
||||
{
|
||||
resized[i] = this.buffer[i];
|
||||
}
|
||||
|
||||
this.buffer = resized;
|
||||
this.bufferCapacity = capacity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to append a string to the builder.
|
||||
/// </summary>
|
||||
/// <param name="value">The string to append.</param>
|
||||
/// <param name="reserve">
|
||||
/// The amount of capacity that must remain in the builder after the string has been
|
||||
/// added.
|
||||
/// </param>
|
||||
/// <returns>A value indicating whether or not the string was added.</returns>
|
||||
/// <remarks>
|
||||
/// This method uses character pointer arithmetic to iterate over the string because
|
||||
/// it is significantly faster than using the string indexer.
|
||||
/// </remarks>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage(
|
||||
"Microsoft.Performance",
|
||||
"CA1811:AvoidUncalledPrivateCode",
|
||||
Justification = "You don't have to use everything in an in-line code share.")]
|
||||
private unsafe bool TryAppendUnsafe(string value, int reserve)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int valueLength = value.Length;
|
||||
if (this.length + valueLength + reserve <= this.bufferCapacity)
|
||||
{
|
||||
fixed (char* valuePointer = value)
|
||||
{
|
||||
for (int i = 0; i < valueLength; i++)
|
||||
{
|
||||
this.buffer[this.length++] = *(valuePointer + i);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to append a string to the builder.
|
||||
/// </summary>
|
||||
/// <param name="value">The string to append.</param>
|
||||
/// <param name="reserve">
|
||||
/// The amount of capacity that must remain in the builder after the string has been
|
||||
/// added.
|
||||
/// </param>
|
||||
/// <param name="rollback">
|
||||
/// The length to set the builder to if the append failed.
|
||||
/// </param>
|
||||
/// <returns>A value indicating whether or not the string was added.</returns>
|
||||
/// <remarks>
|
||||
/// This method uses character pointer arithmetic to iterate over the string because
|
||||
/// it is significantly faster than using the string indexer.
|
||||
/// </remarks>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage(
|
||||
"Microsoft.Performance",
|
||||
"CA1811:AvoidUncalledPrivateCode",
|
||||
Justification = "You don't have to use everything in an in-line code share.")]
|
||||
private unsafe bool TryAppendUnsafe(string value, int reserve, int rollback)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int valueLength = value.Length;
|
||||
if (this.length + valueLength + reserve <= this.bufferCapacity)
|
||||
{
|
||||
fixed (char* valuePointer = value)
|
||||
{
|
||||
for (int i = 0; i < valueLength; i++)
|
||||
{
|
||||
this.buffer[this.length++] = *(valuePointer + i);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
this.length = rollback;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,123 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// <copyright file="StringSegment.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license. See license file in the project root for full license information.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Shared.Dna.Text
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics.Contracts;
|
||||
|
||||
/// <summary>
|
||||
/// Delimits a section of a string.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// It's surprising that this isn't in the .NET framework itself given the existence
|
||||
/// of <see cref="System.ArraySegment<T>"/>.
|
||||
/// </remarks>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage(
|
||||
"Microsoft.Performance",
|
||||
"CA1812:AvoidUninstantiatedInternalClasses",
|
||||
Justification = "You don't have to use everything in an in-line code share.")]
|
||||
internal struct StringSegment
|
||||
{
|
||||
/// <summary>
|
||||
/// The original string containing the substring.
|
||||
/// </summary>
|
||||
public readonly string String;
|
||||
|
||||
/// <summary>
|
||||
/// The position of the first character in the substring.
|
||||
/// </summary>
|
||||
public readonly int Offset;
|
||||
|
||||
/// <summary>
|
||||
/// The number of characters in the substring.
|
||||
/// </summary>
|
||||
public readonly int Count;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="StringSegment"/> struct.
|
||||
/// </summary>
|
||||
/// <param name="str">The string to delimit</param>
|
||||
/// <remarks>
|
||||
/// This creates a substring containing the entire string.
|
||||
/// </remarks>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage(
|
||||
"Microsoft.Performance",
|
||||
"CA1811:AvoidUncalledPrivateCode",
|
||||
Justification = "You don't have to use everything in an in-line code share.")]
|
||||
public StringSegment(string str)
|
||||
{
|
||||
#if CONTRACTS_FULL // Work around the implicit rewrite requirements of Contract.Requires<T>
|
||||
Contract.Requires<ArgumentNullException>(str != null);
|
||||
#endif
|
||||
this.String = str;
|
||||
this.Offset = 0;
|
||||
this.Count = str.Length;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="StringSegment"/> struct.
|
||||
/// </summary>
|
||||
/// <param name="str">The original string containing the substring.</param>
|
||||
/// <param name="offset">
|
||||
/// The position of the first character in the substring.
|
||||
/// </param>
|
||||
/// <remarks>
|
||||
/// The count is set to the remainder of the string.
|
||||
/// </remarks>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage(
|
||||
"Microsoft.Performance",
|
||||
"CA1811:AvoidUncalledPrivateCode",
|
||||
Justification = "You don't have to use everything in an in-line code share.")]
|
||||
public StringSegment(string str, int offset)
|
||||
{
|
||||
#if CONTRACTS_FULL // Work around the implicit rewrite requirements of Contract.Requires<T>
|
||||
Contract.Requires<ArgumentNullException>(str != null);
|
||||
Contract.Requires<ArgumentOutOfRangeException>(offset >= 0 && (offset == 0 || offset < str.Length));
|
||||
#endif
|
||||
this.String = str;
|
||||
this.Offset = offset;
|
||||
this.Count = str.Length - offset;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="StringSegment"/> struct.
|
||||
/// </summary>
|
||||
/// <param name="str">The original string containing the substring.</param>
|
||||
/// <param name="offset">
|
||||
/// The position of the first character in the substring.
|
||||
/// </param>
|
||||
/// <param name="count">The number of characters in the substring.</param>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage(
|
||||
"Microsoft.Performance",
|
||||
"CA1811:AvoidUncalledPrivateCode",
|
||||
Justification = "You don't have to use everything in an in-line code share.")]
|
||||
public StringSegment(string str, int offset, int count)
|
||||
{
|
||||
#if CONTRACTS_FULL // Work around the implicit rewrite requirements of Contract.Requires<T>
|
||||
Contract.Requires<ArgumentNullException>(str != null);
|
||||
Contract.Requires<ArgumentOutOfRangeException>(offset >= 0 && (offset == 0 || offset < str.Length));
|
||||
Contract.Requires<ArgumentOutOfRangeException>(count >= 0 && count <= str.Length - offset);
|
||||
#endif
|
||||
this.String = str;
|
||||
this.Offset = offset;
|
||||
this.Count = count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a substring from the original string.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A substring starting at the offset position and having a length equal to the
|
||||
/// count.
|
||||
/// </returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return this.String.Substring(this.Offset, this.Count);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Shared.Dna.Text" version="2.0.0" targetFramework="net40" developmentDependency="true" />
|
||||
<package id="StyleCop.MSBuild" version="4.7.54.0" targetFramework="net40" developmentDependency="true" />
|
||||
</packages>
|
|
@ -0,0 +1,23 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RuleSet Name="OSG DnA Shared Code Test Rules" Description="Rules for shared code tests used by OSG Data and Analytics" ToolsVersion="14.0">
|
||||
<IncludeAll Action="Warning" />
|
||||
<Rules AnalyzerId="Microsoft.Analyzers.ManagedCodeAnalysis" RuleNamespace="Microsoft.Rules.Managed">
|
||||
<Rule Id="CA1004" Action="None" />
|
||||
<Rule Id="CA1014" Action="None" />
|
||||
<Rule Id="CA1016" Action="None" />
|
||||
<Rule Id="CA1017" Action="None" />
|
||||
<Rule Id="CA1020" Action="None" />
|
||||
<Rule Id="CA1021" Action="None" />
|
||||
<Rule Id="CA1031" Action="None" />
|
||||
<Rule Id="CA1034" Action="None" />
|
||||
<Rule Id="CA1062" Action="None" />
|
||||
<Rule Id="CA1303" Action="None" />
|
||||
<Rule Id="CA1707" Action="None" />
|
||||
<Rule Id="CA1716" Action="None" />
|
||||
<Rule Id="CA1724" Action="None" />
|
||||
<Rule Id="CA1811" Action="None" />
|
||||
<Rule Id="CA2000" Action="None" />
|
||||
<Rule Id="CA2204" Action="None" />
|
||||
<Rule Id="CA2210" Action="None" />
|
||||
</Rules>
|
||||
</RuleSet>
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RuleSet Name="OSG DnA Shared Code Rules" Description="Rules for shared code packages used by OSG Data and Analytics" ToolsVersion="12.0">
|
||||
<IncludeAll Action="Warning" />
|
||||
<Rules AnalyzerId="Microsoft.Analyzers.ManagedCodeAnalysis" RuleNamespace="Microsoft.Rules.Managed">
|
||||
<Rule Id="CA1016" Action="None" />
|
||||
<Rule Id="CA2210" Action="None" />
|
||||
</Rules>
|
||||
</RuleSet>
|
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<CodeAnalysisDictionary Include="$(MSBuildThisFileDirectory)Microsoft.Shared.Dna.Dictionary.xml">
|
||||
<Visible>false</Visible>
|
||||
</CodeAnalysisDictionary>
|
||||
</ItemGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<Package />
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<AvailableItemName Include="Package" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<BuildDependsOn>$(BuildDependsOn);BuildNuSpec;</BuildDependsOn>
|
||||
</PropertyGroup>
|
||||
<Target Name="NuGetProperties">
|
||||
<PropertyGroup>
|
||||
<NonInteractiveSwitch Condition=" '$(VisualStudioVersion)' != '' And '$(OS)' == 'Windows_NT' ">-NonInteractive</NonInteractiveSwitch>
|
||||
<NuGetExePath Condition=" '$(NuGetExePath)' == '' ">$(MSBuildThisFileDirectory).tools\NuGet.exe</NuGetExePath>
|
||||
<PackageOutputDir Condition=" '$(PackageOutputDir)' == '' And '$(Configuration)' == 'Release' ">$(MSBuildThisFileDirectory)Drop</PackageOutputDir>
|
||||
<PackageOutputDir Condition=" '$(PackageOutputDir)' == '' ">$(TargetDir.Trim('\\'))</PackageOutputDir>
|
||||
</PropertyGroup>
|
||||
</Target>
|
||||
<Target Name="BuildNuSpec" DependsOnTargets="NuGetProperties" Inputs="@(Package)" Outputs="@(Package->'$(PackageOutputDir)\%(Filename).nupkg')">
|
||||
<PropertyGroup>
|
||||
<BuildNuSpecCommand>$(MSBuildThisFileDirectory).tools\NuGet.exe pack "%(Package.FullPath)" -Properties "Configuration=$(Configuration);Platform=$(Platform)" $(NonInteractiveSwitch) -OutputDirectory "$(PackageOutputDir)"</BuildNuSpecCommand>
|
||||
</PropertyGroup>
|
||||
<MakeDir Directories="$(PackageOutputDir)" Condition=" !Exists('$(PackageOutputDir)') "/>
|
||||
<Exec Command="$(BuildNuSpecCommand)" Condition=" '$(OS)' != 'Windows_NT' " />
|
||||
<Exec Command="$(BuildNuSpecCommand)" LogStandardErrorAsError="true" Condition=" '$(OS)' == 'Windows_NT' " />
|
||||
</Target>
|
||||
</Project>
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<config>
|
||||
<clear />
|
||||
<add key="repositoryPath" value="packages" />
|
||||
</config>
|
||||
<packageSources>
|
||||
<clear />
|
||||
<add key="vss-package-management" value="https://www.myget.org/F/vss-package-management/api/v2" />
|
||||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
|
||||
</packageSources>
|
||||
<activePackageSource>
|
||||
<add key="All" value="(Aggregate source)" />
|
||||
</activePackageSource>
|
||||
</configuration>
|
47
README.md
47
README.md
|
@ -1,2 +1,47 @@
|
|||
# Microsoft.Shared.Dna.Json
|
||||
Windows Data and Analytics Shared Code - JSON Processing
|
||||
========================================================
|
||||
Are you doing simple read and write tasks with JSON strings?
|
||||
Do you want to partially process your JSON payload?
|
||||
Are you running it in a tight loop?
|
||||
Are you wondering why there's so much pressure on the garbage collector?
|
||||
Do you want something even faster?
|
||||
|
||||
If so, then this package might be right for you.
|
||||
|
||||
The Windows team is building it's own high-performance, low-allocation JSON API for processing data in various "big data" systems. We've managed to squeeze some pretty astonishing performance out of our implementation. Since it wasn't tightly coupled to anything either, we thought we'd share the goodness with everyone.
|
||||
|
||||
We're sharing our code as NuGet "recipe" packages. That means that instead of adding a DLL reference to your code, we're adding the source files themselves. Everything we add is internal and therefore scoped only to that assembly. So, you can freely add this to as many projects as you like without fear of conflicts. We do this for a few reasons:
|
||||
|
||||
1. In this day and age, the JIT compiler is usually smart enough to optimize away annything you don't use and codegen overhead isn't typically concerning on beefy server machines.
|
||||
2. It helps avoid assembly versioning issues when several projects have a dependency on this and each other.
|
||||
3. It also -- to a lesser degree -- insulates us from framework versioning issues. We try to keep the syntax simple and therefore, in many cases, we're natually compatible all the way back to .NET 3.5.
|
||||
4. It gives the compiler a chance to inline our code in your project, thus giving us a boost in performance in some cases.
|
||||
5. Most importantly, it gives you the freedom to tweak and tinker without even necessarily having to wait for a pull request to be approved. Although, you can still do that (and we encourage it). You just don't have to necessarily wait for all the paperwork to go through if you're in a hurry.
|
||||
|
||||
License
|
||||
-------
|
||||
This source code and artifacts are released under the terms of the [MIT License](LICENSE.txt).
|
||||
|
||||
How do I install it?
|
||||
--------------------
|
||||
The package is available on [nuget.org](http://www.nuget.org/packages/Microsoft.Shared.Dna.Json).
|
||||
|
||||
How do I build it?
|
||||
------------------
|
||||
If you have Visual Studio 2015 installed, open an MSBuild command prompt and run:
|
||||
|
||||
build.cmd
|
||||
|
||||
This will download the dependencies, compile the code, run unit tests, and package everything. You should end up with a file named something like Microsoft.Shared.Dna.Json.{major}.{minor}.{patch}.nupkg under the Drop folder.
|
||||
|
||||
How can I contribute?
|
||||
---------------------
|
||||
Please refer to [CONTRIBUTING.md](CONTRIBUTING.md).
|
||||
|
||||
Reporting Security Vulnerabilities
|
||||
----------------------------------
|
||||
If you believe you have found a security vulnerability in this project, please follow [these steps](https://technet.microsoft.com/en-us/security/ff852094.aspx) to report it. For more information on how vulnerabilities are disclosed, see [Coordinated Vulnerability Disclosure](https://technet.microsoft.com/en-us/security/dn467923).
|
||||
|
||||
Code of Conduct
|
||||
---------------
|
||||
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
<StyleCopSettings Version="105">
|
||||
<GlobalSettings>
|
||||
<CollectionProperty Name="RecognizedWords">
|
||||
<Value>Int</Value>
|
||||
</CollectionProperty>
|
||||
</GlobalSettings>
|
||||
<Parsers>
|
||||
<Parser ParserId="StyleCop.CSharp.CsParser">
|
||||
<ParserSettings>
|
||||
<BooleanProperty Name="AnalyzeDesignerFiles">False</BooleanProperty>
|
||||
<CollectionProperty Name="GeneratedFileFilters">
|
||||
<Value>\.g\.cs$</Value>
|
||||
<Value>\.generated\.cs$</Value>
|
||||
<Value>\.g\.i\.cs$</Value>
|
||||
<Value>TemporaryGeneratedFile_.*\.cs$</Value>
|
||||
</CollectionProperty>
|
||||
</ParserSettings>
|
||||
</Parser>
|
||||
</Parsers>
|
||||
</StyleCopSettings>
|
|
@ -0,0 +1,14 @@
|
|||
@ECHO OFF
|
||||
PUSHD "%~dp0"
|
||||
IF NOT EXIST .tools CALL init.cmd
|
||||
.tools\nuget restore
|
||||
msbuild build.proj /verbosity:n /clp:ShowCommandLine /m:%NUMBER_OF_PROCESSORS% /nr:false /fl /flp:LogFile=MSBuild.log;Verbosity=diag;ShowTimestamp
|
||||
FOR %%I IN (Debug Release) DO (
|
||||
FOR /R %%J IN (bin\%%~I\*.Test.dll) DO (
|
||||
vstest.console "%%~J"
|
||||
)
|
||||
FOR /R %%J IN (bin\%%~I\*.Profile.exe) DO (
|
||||
vstest.console "%%~J"
|
||||
)
|
||||
)
|
||||
POPD
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Solution Include="$(MSBuildThisFileDirectory)**\*.sln">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Any CPU</Platform>
|
||||
</Solution>
|
||||
<Solution Include="$(MSBuildThisFileDirectory)**\*.sln">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Any CPU</Platform>
|
||||
</Solution>
|
||||
</ItemGroup>
|
||||
<Target Name="Clean">
|
||||
<MSBuild Targets="Clean" Projects="@(Solution)" Properties="$(ProjectProperties);Configuration=%(Configuration);Platform=%(Platform)" />
|
||||
</Target>
|
||||
<Target Name="Build">
|
||||
<MSBuild Targets="Build" Projects="@(Solution)" Properties="$(ProjectProperties);Configuration=%(Configuration);Platform=%(Platform)" />
|
||||
</Target>
|
||||
<Target Name="Rebuild">
|
||||
<MSBuild Targets="Rebuild" Projects="@(Solution)" Properties="$(ProjectProperties);Configuration=%(Configuration);Platform=%(Platform)" />
|
||||
</Target>
|
||||
</Project>
|
|
@ -0,0 +1,3 @@
|
|||
@echo off
|
||||
powershell -ExecutionPolicy Bypass -Command .\init.ps1
|
||||
set PATH=%~dp0.tools;%~dp0.tools\VSS.NuGet.AuthHelper;%PATH%
|
|
@ -0,0 +1 @@
|
|||
. "$PSScriptRoot\scripts\init\Initialize-Environment.ps1" -RepoRoot $PSScriptRoot
|
|
@ -0,0 +1 @@
|
|||
0.1.3
|
|
@ -0,0 +1,86 @@
|
|||
Param(
|
||||
[Parameter(Mandatory=$true)] [string] $outDir,
|
||||
[Parameter(Mandatory=$true)] [string] $downloadUrl,
|
||||
[Parameter(Mandatory=$true)] [string] $downloadName,
|
||||
[Parameter(Mandatory=$false)] [boolean] $unzip = $false
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
# Grab the VSS.NuGet toolset from VSO
|
||||
Add-Type -AssemblyName System.IO
|
||||
Add-Type -AssemblyName System.IO.Compression.FileSystem
|
||||
|
||||
$etagFile = Join-Path $outDir "$downloadName.ETag"
|
||||
$downloadPath = Join-Path $outDir "$downloadName.download"
|
||||
$downloadDest = Join-Path $outDir $downloadName
|
||||
$downloadDestTemp = Join-Path $outDir "$downloadName.tmp"
|
||||
$headers = @{}
|
||||
|
||||
Write-Host -NoNewLine "Ensuring that $downloadName is up to date..."
|
||||
|
||||
# If the destination folder doesn't exist, delete the ETag file if it exists
|
||||
if (!(Test-Path -PathType Container $downloadDest) -and (Test-Path -PathType Container $etagFile)) {
|
||||
Remove-Item -Force $etagFile
|
||||
}
|
||||
|
||||
if (Test-Path $etagFile)
|
||||
{
|
||||
$headers.Add("If-None-Match", [System.IO.File]::ReadAllText($etagFile))
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$response = Invoke-WebRequest -Headers $headers -Uri $downloadUrl -PassThru -OutFile $downloadPath -UseBasicParsing
|
||||
}
|
||||
catch [System.Net.WebException]
|
||||
{
|
||||
$response = $_.Exception.Response
|
||||
}
|
||||
|
||||
if ($response.StatusCode -eq 200)
|
||||
{
|
||||
Unblock-File $downloadPath
|
||||
[System.IO.File]::WriteAllText($etagFile, $response.Headers["ETag"])
|
||||
|
||||
if($unzip)
|
||||
{
|
||||
# Extract to a temp folder
|
||||
if (Test-Path -PathType Container $downloadDestTemp)
|
||||
{
|
||||
[System.IO.Directory]::Delete($downloadDestTemp, $true)
|
||||
}
|
||||
|
||||
[System.IO.Compression.ZipFile]::ExtractToDirectory($downloadPath, $downloadDestTemp)
|
||||
Remove-Item $downloadPath
|
||||
}
|
||||
else
|
||||
{
|
||||
$downloadDestTemp = $downloadPath;
|
||||
}
|
||||
|
||||
# Delete and rename to final dest
|
||||
if (Test-Path -PathType Container $downloadDest)
|
||||
{
|
||||
[System.IO.Directory]::Delete($downloadDest, $true)
|
||||
}
|
||||
|
||||
Move-Item -Force $downloadDestTemp $downloadDest
|
||||
Write-Host "Updated $downloadName"
|
||||
}
|
||||
elseif ($response.StatusCode -eq 304)
|
||||
{
|
||||
Write-Host "Done"
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Host
|
||||
Write-Warning "Failed to fetch updated NuGet tools from $downloadUrl"
|
||||
if (!(Test-Path $downloadDest)) {
|
||||
throw "$downloadName was not found at $downloadDest"
|
||||
} else {
|
||||
Write-Warning "$downloadName may be out of date"
|
||||
}
|
||||
}
|
||||
|
||||
return $downloadDest
|
|
@ -0,0 +1,32 @@
|
|||
param(
|
||||
[Parameter(Mandatory=$true)] [string] $repoRoot
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$scriptsDir = $PSScriptRoot
|
||||
$customScriptsDir = "$repoRoot\scripts\"
|
||||
$preInitScript = "$customScriptsDir\PreInit.ps1"
|
||||
$preRestoreToolsScript = "$customScriptsDir\PreRestoreTools.ps1"
|
||||
$postInitScript = "$customScriptsDir\PostInit.ps1"
|
||||
|
||||
# Run PreInit.ps1 if it exists
|
||||
if (Test-Path $preInitScript) {
|
||||
. $preInitScript -RepoRoot $repoRoot
|
||||
}
|
||||
|
||||
# Download the NuGet tools if necessary
|
||||
. "$scriptsDir\Initialize-NuGet.ps1" -RepoRoot $repoRoot
|
||||
|
||||
# Run PreRestoreTools.ps1 if it exists
|
||||
if (Test-Path $preRestoreToolsScript) {
|
||||
. $preRestoreToolsScript -RepoRoot $repoRoot
|
||||
}
|
||||
|
||||
# Restores tool packages (if .nuget\tools\packages.config exists)
|
||||
. "$scriptsDir\Restore-ToolPackages.ps1" -RepoRoot $repoRoot
|
||||
|
||||
# Run PostInit.ps1 if it exists
|
||||
if (Test-Path $postInitScript) {
|
||||
. $postInitScript -RepoRoot $repoRoot
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
Param(
|
||||
[Parameter(Mandatory=$true)] [string] $outDir,
|
||||
[Parameter(Mandatory=$true)] [string] $downloadFeed,
|
||||
[Parameter(Mandatory=$true)] [string] $packageName,
|
||||
[Parameter(Mandatory=$true)] [string] $targetFileName
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$downloadDest = Join-Path $outDir $targetFileName
|
||||
|
||||
$tempFolder = "$env:temp\Package-$(Get-Date -format 'yyyy-MM-dd_hh-mm-ss')"
|
||||
New-Item $tempFolder -ItemType Directory
|
||||
|
||||
& "$outDir\nuget.exe" install $packageName -source $downloadFeed -OutputDirectory `"$tempFolder`" -Prerelease -NonInteractive
|
||||
|
||||
$authHelper = Get-ChildItem -Filter $targetFileName -Path $tempFolder -Recurse
|
||||
|
||||
if(-not $authHelper)
|
||||
{
|
||||
Write-Warning "Failed to fetch updated $targetFileName from $downloadFeed"
|
||||
if (!(Test-Path $downloadDest)) {
|
||||
throw "$packageName was not found at $downloadFeed"
|
||||
} else {
|
||||
Write-Warning "$targetFileName may be out of date"
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Copy-Item -Path $authHelper.FullName -Destination $outDir
|
||||
}
|
||||
|
||||
Remove-Item $tempFolder -Force -Recurse
|
|
@ -0,0 +1,26 @@
|
|||
Param(
|
||||
[Parameter(Mandatory=$true)] [string] $repoRoot
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
# Create the .tools directory
|
||||
New-Item -ItemType Directory -Force -Path "$repoRoot\.tools" | Out-Null
|
||||
$toolsDir = Join-Path -Resolve $repoRoot ".tools"
|
||||
|
||||
# Ensure nuget.exe is up-to-date
|
||||
$nugetDownloadName = "nuget.exe"
|
||||
. "$PSScriptRoot\Initialize-DownloadLatest.ps1" -OutDir $toolsDir -DownloadUrl "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe" -DownloadName $nugetDownloadName -Unzip $false
|
||||
|
||||
# Ensure VSS.NuGet.AuthHelper is up-to-date
|
||||
$credProviderDownloadFeed = "https://nuget.org/api/v2/"
|
||||
$credProviderPackageName = "Microsoft.VisualStudio.Services.NuGet.CredentialProvider"
|
||||
$credProviderExeName = "CredentialProvider.VSS.exe"
|
||||
|
||||
. "$PSScriptRoot\Initialize-InstallFromNuget.ps1" -OutDir $toolsDir -DownloadFeed $credProviderDownloadFeed -PackageName $credProviderPackageName -targetFileName $credProviderExeName
|
||||
|
||||
# Add the tools dir to the path which directly contains NuGet.exe and VSS.NuGet.AuthHelper.exe
|
||||
if (!($env:Path -like "*$toolsDir;*"))
|
||||
{
|
||||
$env:Path = "$toolsDir;" + $env:Path
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
Param(
|
||||
[Parameter(Mandatory=$true)] [string] $repoRoot
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$toolsPackagesConfigPath = "$repoRoot\.nuget\tools\packages.config"
|
||||
$packagesDirectory = "$repoRoot\packages"
|
||||
|
||||
# Restore NuGet tools packages, unless we're on a build machine
|
||||
if((Test-Path env:\BUILD_BUILDNUMBER) -eq $true)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (Test-Path $toolsPackagesConfigPath) {
|
||||
Write-Host "Restoring tool packages..."
|
||||
nuget restore -PackagesDirectory $packagesDirectory $toolsPackagesConfigPath
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Error "Failed to restore tool packages."
|
||||
} else {
|
||||
Write-Host "Restored tool packages"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
param(
|
||||
[string] $repoRoot
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
if (!$repoRoot -or !(Test-Path $repoRoot)) {
|
||||
Write-Host "The option -repoRoot was not specified or was not found, assuming current working directory"
|
||||
$repoRoot = (Resolve-Path .\).Path
|
||||
}
|
||||
|
||||
$packagesDir = "$repoRoot\packages"
|
||||
|
||||
# Prefer the absolute path of the environment's nuget.exe if it exists, otherwise use nuget.exe on the path
|
||||
$nugetExe = "$repoRoot\.tools\VSS.NuGet\nuget.exe"
|
||||
if(!(Test-Path $nugetExe)) {
|
||||
# Check if there's one on the path\
|
||||
$nugetExe = (Get-Command -ErrorAction SilentlyContinue -Name nuget).Path
|
||||
if (! $nugetExe) {
|
||||
Write-Error "Failed to find nuget.exe. Please ensure a nuget.exe is on the path."
|
||||
}
|
||||
}
|
||||
|
||||
# Get current version
|
||||
$packageName = "Microsoft.VisualStudio.Services.NuGet.Bootstrap"
|
||||
$versionMarkFilePath = "$repoRoot\scripts\init\.version"
|
||||
$currentVersion = (Get-Content $versionMarkFilePath)
|
||||
$nugetSource = "https://nuget.org/api/v2/"
|
||||
Write-Host "Current version is $currentVersion"
|
||||
|
||||
# Get newest available version
|
||||
$listOutput = & $nugetExe list -source $nugetSource -NonInteractive $packageName
|
||||
|
||||
if ($LastExitCode -ne 0 -or (! $listOutput)) {
|
||||
Write-Error "Unable to find $packageName"
|
||||
}
|
||||
|
||||
$latestLine = $listOutput | Select-String -Pattern $packageName | Select-Object -First 1
|
||||
if ((! $latestLine) ) {
|
||||
Write-Error "Error parsing available versions of $packageName"
|
||||
}
|
||||
|
||||
$newestVersion = ($latestLine -split ' ')[1]
|
||||
Write-Host "Newest version is $newestVersion"
|
||||
|
||||
# Note: Doesn't actually check that it's newer.
|
||||
# Instead of implementing a semver check here, just leave it up to the user to confirm they actually want to "update"
|
||||
if ($currentVersion -ne $newestVersion) {
|
||||
$confirmation = Read-Host "Update from $currentVersion to $($newestVersion)? [y/n]"
|
||||
if ($confirmation -eq "y") {
|
||||
|
||||
# Download the newest version
|
||||
& $nugetExe install $packageName -Version $newestVersion -OutputDirectory $packagesDir -source $nugetSource
|
||||
|
||||
# Bootstrap
|
||||
$bootstrapPath = Resolve-Path "$repoRoot\packages\$packageName.$newestVersion\tools\Bootstrap.ps1"
|
||||
& $bootstrapPath -RepoRoot $repoRoot
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче