- reorganized repository to match standard layout
diff --git a/src/jsontestrunner/jsontest.vcproj b/src/jsontestrunner/jsontest.vcproj
new file mode 100644
index 0000000..f86b27e
--- /dev/null
+++ b/src/jsontestrunner/jsontest.vcproj
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="Windows-1252"?>

+<VisualStudioProject

+	ProjectType="Visual C++"

+	Version="7.10"

+	Name="jsontest"

+	ProjectGUID="{25AF2DD2-D396-4668-B188-488C33B8E620}"

+	Keyword="Win32Proj">

+	<Platforms>

+		<Platform

+			Name="Win32"/>

+	</Platforms>

+	<Configurations>

+		<Configuration

+			Name="Debug|Win32"

+			OutputDirectory="../../build/vs71/debug/jsontest"

+			IntermediateDirectory="../../build/vs71/debug/jsontest"

+			ConfigurationType="1"

+			CharacterSet="2">

+			<Tool

+				Name="VCCLCompilerTool"

+				Optimization="0"

+				AdditionalIncludeDirectories="../../include"

+				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"

+				MinimalRebuild="TRUE"

+				BasicRuntimeChecks="3"

+				RuntimeLibrary="1"

+				UsePrecompiledHeader="0"

+				WarningLevel="3"

+				Detect64BitPortabilityProblems="TRUE"

+				DebugInformationFormat="4"/>

+			<Tool

+				Name="VCCustomBuildTool"/>

+			<Tool

+				Name="VCLinkerTool"

+				OutputFile="$(OutDir)/jsontest.exe"

+				LinkIncremental="2"

+				GenerateDebugInformation="TRUE"

+				ProgramDatabaseFile="$(OutDir)/jsontest.pdb"

+				SubSystem="1"

+				TargetMachine="1"/>

+			<Tool

+				Name="VCMIDLTool"/>

+			<Tool

+				Name="VCPostBuildEventTool"/>

+			<Tool

+				Name="VCPreBuildEventTool"/>

+			<Tool

+				Name="VCPreLinkEventTool"/>

+			<Tool

+				Name="VCResourceCompilerTool"/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"/>

+			<Tool

+				Name="VCXMLDataGeneratorTool"/>

+			<Tool

+				Name="VCWebDeploymentTool"/>

+			<Tool

+				Name="VCManagedWrapperGeneratorTool"/>

+			<Tool

+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>

+		</Configuration>

+		<Configuration

+			Name="Release|Win32"

+			OutputDirectory="../../build/vs71/release/jsontest"

+			IntermediateDirectory="../../build/vs71/release/jsontest"

+			ConfigurationType="1"

+			CharacterSet="2">

+			<Tool

+				Name="VCCLCompilerTool"

+				AdditionalIncludeDirectories="../../include"

+				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"

+				RuntimeLibrary="0"

+				UsePrecompiledHeader="0"

+				WarningLevel="3"

+				Detect64BitPortabilityProblems="TRUE"

+				DebugInformationFormat="3"/>

+			<Tool

+				Name="VCCustomBuildTool"/>

+			<Tool

+				Name="VCLinkerTool"

+				OutputFile="$(OutDir)/jsontest.exe"

+				LinkIncremental="1"

+				GenerateDebugInformation="TRUE"

+				SubSystem="1"

+				OptimizeReferences="2"

+				EnableCOMDATFolding="2"

+				TargetMachine="1"/>

+			<Tool

+				Name="VCMIDLTool"/>

+			<Tool

+				Name="VCPostBuildEventTool"/>

+			<Tool

+				Name="VCPreBuildEventTool"/>

+			<Tool

+				Name="VCPreLinkEventTool"/>

+			<Tool

+				Name="VCResourceCompilerTool"/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"/>

+			<Tool

+				Name="VCXMLDataGeneratorTool"/>

+			<Tool

+				Name="VCWebDeploymentTool"/>

+			<Tool

+				Name="VCManagedWrapperGeneratorTool"/>

+			<Tool

+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>

+		</Configuration>

+	</Configurations>

+	<References>

+	</References>

+	<Files>

+		<File

+			RelativePath=".\main.cpp">

+		</File>

+	</Files>

+	<Globals>

+	</Globals>

+</VisualStudioProject>

diff --git a/src/jsontestrunner/main.cpp b/src/jsontestrunner/main.cpp
new file mode 100644
index 0000000..1d43720
--- /dev/null
+++ b/src/jsontestrunner/main.cpp
@@ -0,0 +1,185 @@
+#include <json/json.h>

+#include <algorithm> // sort

+#include <stdio.h>

+

+#if defined(_MSC_VER)  &&  _MSC_VER >= 1310

+# pragma warning( disable: 4996 )     // disable fopen deprecation warning

+#endif

+

+static std::string

+readInputTestFile( const char *path )

+{

+   FILE *file = fopen( path, "rb" );

+   if ( !file )

+      return std::string("");

+   fseek( file, 0, SEEK_END );

+   int size = ftell( file );

+   fseek( file, 0, SEEK_SET );

+   std::string text;

+   char *buffer = new char[size+1];

+   buffer[size] = 0;

+   if ( fread( buffer, 1, size, file ) == size )

+      text = buffer;

+   fclose( file );

+   delete[] buffer;

+   return text;

+}

+

+

+static void

+printValueTree( FILE *fout, Json::Value &value, const std::string &path = "." )

+{

+   switch ( value.type() )

+   {

+   case Json::nullValue:

+      fprintf( fout, "%s=null\n", path.c_str() );

+      break;

+   case Json::intValue:

+      fprintf( fout, "%s=%d\n", path.c_str(), value.asInt() );

+      break;

+   case Json::uintValue:

+      fprintf( fout, "%s=%u\n", path.c_str(), value.asUInt() );

+      break;

+   case Json::realValue:

+      fprintf( fout, "%s=%.16g\n", path.c_str(), value.asDouble() );

+      break;

+   case Json::stringValue:

+      fprintf( fout, "%s=\"%s\"\n", path.c_str(), value.asString().c_str() );

+      break;

+   case Json::booleanValue:

+      fprintf( fout, "%s=%s\n", path.c_str(), value.asBool() ? "true" : "false" );

+      break;

+   case Json::arrayValue:

+      {

+         fprintf( fout, "%s=[]\n", path.c_str() );

+         int size = value.size();

+         for ( int index =0; index < size; ++index )

+         {

+            static char buffer[16];

+            sprintf( buffer, "[%d]", index );

+            printValueTree( fout, value[index], path + buffer );

+         }

+      }

+      break;

+   case Json::objectValue:

+      {

+         fprintf( fout, "%s={}\n", path.c_str() );

+         Json::Value::Members members( value.getMemberNames() );

+         std::sort( members.begin(), members.end() );

+         std::string suffix = *(path.end()-1) == '.' ? "" : ".";

+         for ( Json::Value::Members::iterator it = members.begin(); 

+               it != members.end(); 

+               ++it )

+         {

+            const std::string &name = *it;

+            printValueTree( fout, value[name], path + suffix + name );

+         }

+      }

+      break;

+   default:

+      break;

+   }

+}

+

+

+static int

+parseAndSaveValueTree( const std::string &input, 

+                       const std::string &actual,

+                       const std::string &kind,

+                       Json::Value &root )

+{

+   Json::Reader reader;

+   bool parsingSuccessful = reader.parse( input, root );

+   if ( !parsingSuccessful )

+   {

+      printf( "Failed to parse %s file: \n%s\n", 

+              kind.c_str(),

+              reader.getFormatedErrorMessages().c_str() );

+      return 1;

+   }

+

+   FILE *factual = fopen( actual.c_str(), "wt" );

+   if ( !factual )

+   {

+      printf( "Failed to create %s actual file.\n", kind.c_str() );

+      return 2;

+   }

+   printValueTree( factual, root );

+   fclose( factual );

+   return 0;

+}

+

+

+static int

+rewriteValueTree( const std::string &rewritePath, 

+                  const Json::Value &root, 

+                  std::string &rewrite )

+{

+//   Json::FastWriter writer;

+   Json::StyledWriter writer;

+   rewrite = writer.write( root );

+   FILE *fout = fopen( rewritePath.c_str(), "wt" );

+   if ( !fout )

+   {

+      printf( "Failed to create rewrite file: %s\n", rewritePath.c_str() );

+      return 2;

+   }

+   fprintf( fout, "%s\n", rewrite.c_str() );

+   fclose( fout );

+   return 0;

+}

+

+

+static std::string

+removeSuffix( const std::string &path, 

+              const std::string &extension )

+{

+   if ( extension.length() >= path.length() )

+      return std::string("");

+   std::string suffix = path.substr( path.length() - extension.length() );

+   if ( suffix != extension )

+      return std::string("");

+   return path.substr( 0, path.length() - extension.length() );

+}

+

+int main( int argc, const char *argv[] )

+{

+   if ( argc != 2 )

+   {

+      printf( "Usage: %s input-json-file", argv[0] );

+      return 3;

+   }

+

+   std::string input = readInputTestFile( argv[1] );

+   if ( input.empty() )

+   {

+      printf( "Failed to read input or empty input: %s\n", argv[1] );

+      return 3;

+   }

+

+   std::string basePath = removeSuffix( argv[1], ".json" );

+   if ( basePath.empty() )

+   {

+      printf( "Bad input path. Path does not end with '.expected':\n%s\n", argv[1] );

+      return 3;

+   }

+

+   std::string actualPath = basePath + ".actual";

+   std::string rewritePath = basePath + ".rewrite";

+   std::string rewriteActualPath = basePath + ".actual-rewrite";

+

+   Json::Value root;

+   int exitCode = parseAndSaveValueTree( input, actualPath, "input", root );

+   if ( exitCode == 0 )

+   {

+      std::string rewrite;

+      exitCode = rewriteValueTree( rewritePath, root, rewrite );

+      if ( exitCode == 0 )

+      {

+         Json::Value rewriteRoot;

+         exitCode = parseAndSaveValueTree( rewrite, rewriteActualPath, "rewrite", rewriteRoot );

+      }

+   }

+

+   return exitCode;

+}
\ No newline at end of file
diff --git a/src/jsontestrunner/sconscript b/src/jsontestrunner/sconscript
new file mode 100644
index 0000000..f81a2dc
--- /dev/null
+++ b/src/jsontestrunner/sconscript
@@ -0,0 +1,6 @@
+Import( 'env_testing buildJSONTests' )

+

+buildJSONTests( env_testing, Split( """

+    main.cpp

+     """ ),

+    'jsontestrunner' )