1f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III// Copyright 2007-2010 Baptiste Lepilleur
2f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III// Distributed under MIT license, or public domain if desired and
3f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III// recognized in your jurisdiction.
4f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
5f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
6f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III/* This executable is used for testing parser/writer using real JSON files.
7f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III */
8f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
9f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
10f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III#include <json/json.h>
11f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III#include <algorithm> // sort
12f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III#include <stdio.h>
13f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
14f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III#if defined(_MSC_VER)  &&  _MSC_VER >= 1310
15f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III# pragma warning( disable: 4996 )     // disable fopen deprecation warning
16f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III#endif
17f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
18f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins IIIstatic std::string
19f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins IIInormalizeFloatingPointStr( double value )
20f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III{
21f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III    char buffer[32];
22f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III    sprintf( buffer, "%.16g", value );
23f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III    buffer[sizeof(buffer)-1] = 0;
24f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III    std::string s( buffer );
25f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III    std::string::size_type index = s.find_last_of( "eE" );
26f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III    if ( index != std::string::npos )
27f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III    {
28f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III        std::string::size_type hasSign = (s[index+1] == '+' || s[index+1] == '-') ? 1 : 0;
29f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III        std::string::size_type exponentStartIndex = index + 1 + hasSign;
30f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III        std::string normalized = s.substr( 0, exponentStartIndex );
31f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III        std::string::size_type indexDigit = s.find_first_not_of( '0', exponentStartIndex );
32f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III        std::string exponent = "0";
33f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III        if ( indexDigit != std::string::npos ) // There is an exponent different from 0
34f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III        {
35f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III            exponent = s.substr( indexDigit );
36f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III        }
37f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III        return normalized + exponent;
38f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III    }
39f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III    return s;
40f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III}
41f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
42f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
43f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins IIIstatic std::string
44f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins IIIreadInputTestFile( const char *path )
45f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III{
46f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   FILE *file = fopen( path, "rb" );
47f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   if ( !file )
48f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      return std::string("");
49f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   fseek( file, 0, SEEK_END );
50f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   long size = ftell( file );
51f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   fseek( file, 0, SEEK_SET );
52f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   std::string text;
53f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   char *buffer = new char[size+1];
54f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   buffer[size] = 0;
55f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   if ( fread( buffer, 1, size, file ) == (unsigned long)size )
56f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      text = buffer;
57f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   fclose( file );
58f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   delete[] buffer;
59f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   return text;
60f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III}
61f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
62f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins IIIstatic void
63f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins IIIprintValueTree( FILE *fout, Json::Value &value, const std::string &path = "." )
64f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III{
65f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   switch ( value.type() )
66f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   {
67f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   case Json::nullValue:
68f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      fprintf( fout, "%s=null\n", path.c_str() );
69f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      break;
70f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   case Json::intValue:
71f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      fprintf( fout, "%s=%s\n", path.c_str(), Json::valueToString( value.asLargestInt() ).c_str() );
72f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      break;
73f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   case Json::uintValue:
74f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      fprintf( fout, "%s=%s\n", path.c_str(), Json::valueToString( value.asLargestUInt() ).c_str() );
75f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      break;
76f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   case Json::realValue:
77f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III       fprintf( fout, "%s=%s\n", path.c_str(), normalizeFloatingPointStr(value.asDouble()).c_str() );
78f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      break;
79f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   case Json::stringValue:
80f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      fprintf( fout, "%s=\"%s\"\n", path.c_str(), value.asString().c_str() );
81f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      break;
82f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   case Json::booleanValue:
83f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      fprintf( fout, "%s=%s\n", path.c_str(), value.asBool() ? "true" : "false" );
84f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      break;
85f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   case Json::arrayValue:
86f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      {
87f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III         fprintf( fout, "%s=[]\n", path.c_str() );
88f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III         int size = value.size();
89f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III         for ( int index =0; index < size; ++index )
90f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III         {
91f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III            static char buffer[16];
92f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III            sprintf( buffer, "[%d]", index );
93f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III            printValueTree( fout, value[index], path + buffer );
94f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III         }
95f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      }
96f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      break;
97f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   case Json::objectValue:
98f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      {
99f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III         fprintf( fout, "%s={}\n", path.c_str() );
100f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III         Json::Value::Members members( value.getMemberNames() );
101f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III         std::sort( members.begin(), members.end() );
102f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III         std::string suffix = *(path.end()-1) == '.' ? "" : ".";
103f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III         for ( Json::Value::Members::iterator it = members.begin();
104f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III               it != members.end();
105f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III               ++it )
106f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III         {
107f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III            const std::string &name = *it;
108f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III            printValueTree( fout, value[name], path + suffix + name );
109f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III         }
110f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      }
111f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      break;
112f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   default:
113f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      break;
114f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   }
115f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III}
116f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
117f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
118f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins IIIstatic int
119f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins IIIparseAndSaveValueTree( const std::string &input,
120f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III                       const std::string &actual,
121f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III                       const std::string &kind,
122f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III                       Json::Value &root,
123f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III                       const Json::Features &features,
124f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III                       bool parseOnly )
125f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III{
126f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   Json::Reader reader( features );
127f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   bool parsingSuccessful = reader.parse( input, root );
128f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   if ( !parsingSuccessful )
129f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   {
130f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      printf( "Failed to parse %s file: \n%s\n",
131f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III              kind.c_str(),
132f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III              reader.getFormattedErrorMessages().c_str() );
133f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      return 1;
134f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   }
135f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
136f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   if ( !parseOnly )
137f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   {
138f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      FILE *factual = fopen( actual.c_str(), "wt" );
139f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      if ( !factual )
140f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      {
141f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III         printf( "Failed to create %s actual file.\n", kind.c_str() );
142f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III         return 2;
143f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      }
144f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      printValueTree( factual, root );
145f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      fclose( factual );
146f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   }
147f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   return 0;
148f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III}
149f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
150f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
151f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins IIIstatic int
152f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins IIIrewriteValueTree( const std::string &rewritePath,
153f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III                  const Json::Value &root,
154f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III                  std::string &rewrite )
155f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III{
156f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   //Json::FastWriter writer;
157f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   //writer.enableYAMLCompatibility();
158f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   Json::StyledWriter writer;
159f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   rewrite = writer.write( root );
160f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   FILE *fout = fopen( rewritePath.c_str(), "wt" );
161f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   if ( !fout )
162f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   {
163f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      printf( "Failed to create rewrite file: %s\n", rewritePath.c_str() );
164f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      return 2;
165f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   }
166f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   fprintf( fout, "%s\n", rewrite.c_str() );
167f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   fclose( fout );
168f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   return 0;
169f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III}
170f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
171f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
172f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins IIIstatic std::string
173f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins IIIremoveSuffix( const std::string &path,
174f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III              const std::string &extension )
175f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III{
176f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   if ( extension.length() >= path.length() )
177f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      return std::string("");
178f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   std::string suffix = path.substr( path.length() - extension.length() );
179f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   if ( suffix != extension )
180f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      return std::string("");
181f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   return path.substr( 0, path.length() - extension.length() );
182f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III}
183f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
184f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
185f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins IIIstatic void
186f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins IIIprintConfig()
187f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III{
188f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   // Print the configuration used to compile JsonCpp
189f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III#if defined(JSON_NO_INT64)
190f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   printf( "JSON_NO_INT64=1\n" );
191f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III#else
192f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   printf( "JSON_NO_INT64=0\n" );
193f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III#endif
194f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III}
195f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
196f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
197f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins IIIstatic int
198f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins IIIprintUsage( const char *argv[] )
199f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III{
200f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   printf( "Usage: %s [--strict] input-json-file", argv[0] );
201f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   return 3;
202f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III}
203f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
204f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
205f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins IIIint
206f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins IIIparseCommandLine( int argc, const char *argv[],
207f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III                  Json::Features &features, std::string &path,
208f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III                  bool &parseOnly )
209f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III{
210f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   parseOnly = false;
211f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   if ( argc < 2 )
212f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   {
213f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      return printUsage( argv );
214f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   }
215f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
216f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   int index = 1;
217f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   if ( std::string(argv[1]) == "--json-checker" )
218f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   {
219f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      features = Json::Features::strictMode();
220f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      parseOnly = true;
221f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      ++index;
222f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   }
223f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
224f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   if ( std::string(argv[1]) == "--json-config" )
225f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   {
226f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      printConfig();
227f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      return 3;
228f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   }
229f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
230f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   if ( index == argc  ||  index + 1 < argc )
231f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   {
232f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      return printUsage( argv );
233f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   }
234f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
235f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   path = argv[index];
236f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   return 0;
237f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III}
238f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
239f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
240f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins IIIint main( int argc, const char *argv[] )
241f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III{
242f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   std::string path;
243f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   Json::Features features;
244f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   bool parseOnly;
245f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   int exitCode = parseCommandLine( argc, argv, features, path, parseOnly );
246f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   if ( exitCode != 0 )
247f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   {
248f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      return exitCode;
249f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   }
250f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
251f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   try
252f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   {
253f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      std::string input = readInputTestFile( path.c_str() );
254f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      if ( input.empty() )
255f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      {
256f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III         printf( "Failed to read input or empty input: %s\n", path.c_str() );
257f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III         return 3;
258f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      }
259f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
260f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      std::string basePath = removeSuffix( argv[1], ".json" );
261f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      if ( !parseOnly  &&  basePath.empty() )
262f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      {
263f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III         printf( "Bad input path. Path does not end with '.expected':\n%s\n", path.c_str() );
264f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III         return 3;
265f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      }
266f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
267f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      std::string actualPath = basePath + ".actual";
268f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      std::string rewritePath = basePath + ".rewrite";
269f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      std::string rewriteActualPath = basePath + ".actual-rewrite";
270f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
271f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      Json::Value root;
272f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      exitCode = parseAndSaveValueTree( input, actualPath, "input", root, features, parseOnly );
273f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      if ( exitCode == 0  &&  !parseOnly )
274f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      {
275f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III         std::string rewrite;
276f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III         exitCode = rewriteValueTree( rewritePath, root, rewrite );
277f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III         if ( exitCode == 0 )
278f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III         {
279f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III            Json::Value rewriteRoot;
280f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III            exitCode = parseAndSaveValueTree( rewrite, rewriteActualPath,
281f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III               "rewrite", rewriteRoot, features, parseOnly );
282f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III         }
283f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      }
284f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   }
285f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   catch ( const std::exception &e )
286f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   {
287f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      printf( "Unhandled exception:\n%s\n", e.what() );
288f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III      exitCode = 1;
289f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   }
290f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
291f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III   return exitCode;
292f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III}
293f59fb0e83fd0a4b41700d3f5eebdc8d21b173c2eLeon Scroggins III
294