Skip to content

Commit

Permalink
Finished json array's so that they are complete
Browse files Browse the repository at this point in the history
  • Loading branch information
beached committed Mar 17, 2019
1 parent 713b1d5 commit d190278
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 52 deletions.
2 changes: 1 addition & 1 deletion include/json_to_cpp.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ namespace daw {
boost::filesystem::path header_path;
boost::filesystem::path json_path;
bool separate_files;

bool hide_null_only;
std::ostream &header_file( );
std::ostream &cpp_file( );
}; // config_t
Expand Down
74 changes: 53 additions & 21 deletions src/json_to_cpp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ namespace daw {

std::string name( ) const noexcept;
std::string json_name( std::string member_name ) const noexcept;
std::string array_member_info( ) const;
daw::ordered_map<std::string, ti_value> const &children( ) const;
daw::ordered_map<std::string, ti_value> &children( );
bool &is_optional( ) noexcept;
Expand Down Expand Up @@ -167,6 +168,7 @@ namespace daw {
virtual std::string name( ) const = 0;
virtual std::string json_name( std::string member_name ) const = 0;
virtual type_info_t *clone( ) const = 0;
virtual std::string array_member_info( ) const = 0;
}; // type_info_t

type_info_t::~type_info_t( ) {}
Expand All @@ -180,6 +182,10 @@ namespace daw {
return value->json_name( std::move( member_name ) );
}

std::string ti_value::array_member_info( ) const {
return value->array_member_info( );
}

size_t ti_value::type( ) const {
return value->type( );
}
Expand Down Expand Up @@ -222,6 +228,10 @@ namespace daw {
return "json_custom<" + member_name + ">";
}

virtual std::string array_member_info( ) const override {
return "json_custom<no_name>";
}

ti_null( )
: type_info_t{} {
is_optional = true;
Expand All @@ -242,6 +252,10 @@ namespace daw {
return "int64_t";
}

virtual std::string array_member_info( ) const override {
return "json_number<no_name, int64_t>";
}

std::string json_name( std::string member_name ) const override {
return "json_number<" + member_name + ", intmax_t>";
}
Expand All @@ -261,6 +275,10 @@ namespace daw {
return "double";
}

virtual std::string array_member_info( ) const override {
return "json_number<no_name>";
}

std::string json_name( std::string member_name ) const override {
return "json_number<" + member_name + ">";
}
Expand All @@ -280,6 +298,10 @@ namespace daw {
return "bool";
}

virtual std::string array_member_info( ) const override {
return "json_bool<no_name>";
}

std::string json_name( std::string member_name ) const override {
return "json_bool<" + member_name + ">";
}
Expand All @@ -299,6 +321,10 @@ namespace daw {
return "std::string";
}

virtual std::string array_member_info( ) const override {
return "json_string<no_name>";
}

std::string json_name( std::string member_name ) const override {
return "json_string<" + member_name + ">";
}
Expand All @@ -319,6 +345,7 @@ namespace daw {
std::string name( ) const override {
return object_name;
}

ti_object( std::string obj_name )
: type_info_t{}
, object_name{std::move( obj_name )} {}
Expand All @@ -327,31 +354,15 @@ namespace daw {
return new ti_object( *this );
}

virtual std::string array_member_info( ) const override {
return "json_class<no_name, " + name( ) + ">";
}

std::string json_name( std::string member_name ) const override {
return "json_class<" + member_name + ", " + name( ) + ">";
}
};

std::string make_json_type( std::string name, size_t id ) {
switch( id ) {
case json::json_value_t::index_of<json::json_value_t::string_t>( ):
return "json_string<" + name;
case json::json_value_t::index_of<json::json_value_t::boolean_t>( ):
return "json_bool<" + name;
case json::json_value_t::index_of<json::json_value_t::integer_t>( ):
return "json_number<" + name + ", intmax_t";
case json::json_value_t::index_of<json::json_value_t::real_t>( ):
return "json_number<" + name;
case json::json_value_t::index_of<json::json_value_t::null_t>( ):
return "json_custom<" + name;
case json::json_value_t::index_of<json::json_value_t::array_t>( ):
return "json_array<" + name;
case json::json_value_t::index_of<json::json_value_t::object_t>( ):
return "json_class<" + name;
}
std::terminate( );
}

struct ti_array : public type_info_t {
size_t type( ) const override {
return daw::json::json_value_t::index_of<
Expand All @@ -363,7 +374,13 @@ namespace daw {
}

std::string json_name( std::string member_name ) const override {
return "json_array<" + member_name + ", " + name( ) + "," + +">";
return "json_array<" + member_name + ", " + name( ) + ", " +
children.begin( )->second.array_member_info( ) + ">";
}

std::string array_member_info( ) const override {
return "json_array<no_name, " + name( ) + ", " +
children.begin( )->second.array_member_info( ) + ">";
}

type_info_t *clone( ) const override {
Expand Down Expand Up @@ -517,6 +534,9 @@ namespace daw {
config.cpp_file( )
<< "void " << cur_obj.object_name << "::json_link_map( ) {\n";
for( auto const &child : cur_obj.children ) {
if( config.hide_null_only and child.second.is_null( ) ) {
continue;
}
config.cpp_file( )
<< "\tlink_" << daw::json::to_string( child.second.type( ) );
config.cpp_file( )
Expand All @@ -540,6 +560,9 @@ namespace daw {
<< "inline auto describe_json_class( " << cur_obj.object_name
<< " ) {\n\tusing namespace daw::json;\n";
for( auto const &child : cur_obj.children ) {
if( config.hide_null_only and child.second.is_null( ) ) {
continue;
}
config.cpp_file( )
<< "\tstatic constexpr char const " << child.first << "[] = \"";
if( daw::string_view( child.first.data( ), child.first.size( ) )
Expand All @@ -558,6 +581,9 @@ namespace daw {
bool is_first = true;

for( auto const &child : cur_obj.children ) {
if( config.hide_null_only and child.second.is_null( ) ) {
continue;
}
config.cpp_file( ) << "\t\t";
if( !is_first ) {
config.cpp_file( ) << ",";
Expand All @@ -581,6 +607,9 @@ namespace daw {
config.cpp_file( ) << "\treturn std::forward_as_tuple( ";
is_first = true;
for( auto const &child : cur_obj.children ) {
if( config.hide_null_only and child.second.is_null( ) ) {
continue;
}
if( !is_first ) {
config.cpp_file( ) << ", ";
} else {
Expand Down Expand Up @@ -643,6 +672,9 @@ namespace daw {
auto const obj_type = cur_obj.name( );
config.header_file( ) << "struct " << obj_type << " {\n";
for( auto const &child : cur_obj.children ) {
if( config.hide_null_only and child.second.is_null( ) ) {
continue;
}
auto const &member_name = child.first;
auto const &member_type = child.second.name( );
config.header_file( ) << "\t";
Expand Down
87 changes: 57 additions & 30 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
// Copyright ( c ) 2016 Darrell Wright
//
// 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
// 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 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,
Expand All @@ -27,40 +27,54 @@
#include <curl/curl.h>
#include <fstream>
#include <iostream>
#include <optional>
#include <memory>
#include <optional>
#include <string>

#include <daw/daw_string_view.h>

#include "json_to_cpp.h"

namespace {
std::optional<std::string> download( daw::string_view url, daw::string_view user_agent );
std::optional<std::string> download( daw::string_view url,
daw::string_view user_agent );
bool is_url( daw::string_view path );
} // namespace

int main( int argc, char **argv ) {
using namespace daw::json_to_cpp;
static std::string const default_user_agent =
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.100 Safari/537.36";
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/54.0.2840.100 Safari/537.36";

boost::program_options::options_description desc{"Options"};
desc.add_options( )( "help", "print option descriptions" )(
"in_file", boost::program_options::value<boost::filesystem::path>( ),
"json source file path or url" )( "use_jsonlink", boost::program_options::value<bool>( )->default_value( true ),
"Use JsonLink serializaion/deserialization" )(
"cpp_file", boost::program_options::value<boost::filesystem::path>( ), "output c++ file" )(
"json source file path or url" )(
"use_jsonlink",
boost::program_options::value<bool>( )->default_value( true ),
"Use JsonLink serializaion/deserialization" )(
"cpp_file", boost::program_options::value<boost::filesystem::path>( ),
"output c++ file" )(
"header_file", boost::program_options::value<boost::filesystem::path>( ),
"output c++ header file. If not specified uses cpp_file. Only valid when use_jsonlink=true" )(
"allow_overwrite", boost::program_options::value<bool>( )->default_value( true ),
"output c++ header file. If not specified uses cpp_file. Only valid when "
"use_jsonlink=true" )(
"allow_overwrite",
boost::program_options::value<bool>( )->default_value( true ),

"Overwrite existing output files" )(
"user_agent", boost::program_options::value<std::string>( )->default_value( default_user_agent ),
"hide_null_only",
boost::program_options::value<bool>( )->default_value( true ),
"Do not output json entries that are only ever null" )(
"user_agent",
boost::program_options::value<std::string>( )->default_value(
default_user_agent ),
"User agent to use when downloading via URL" );

boost::program_options::variables_map vm;
try {
boost::program_options::store( boost::program_options::parse_command_line( argc, argv, desc ), vm );
boost::program_options::store(
boost::program_options::parse_command_line( argc, argv, desc ), vm );
if( vm.count( "help" ) ) {
std::cout << "Command line options\n" << desc << std::endl;
return EXIT_SUCCESS;
Expand All @@ -81,11 +95,13 @@ int main( int argc, char **argv ) {

std::string json_str;
if( is_url( config.json_path.string( ) ) ) {
auto tmp = download( config.json_path.string( ), vm["user_agent"].as<std::string>( ) );
auto tmp = download( config.json_path.string( ),
vm["user_agent"].as<std::string>( ) );
if( tmp ) {
json_str = *tmp;
} else {
std::cerr << "Could not download json data from '" << canonical( config.json_path ) << "'\n";
std::cerr << "Could not download json data from '"
<< canonical( config.json_path ) << "'\n";
exit( EXIT_FAILURE );
}
} else {
Expand All @@ -98,42 +114,51 @@ int main( int argc, char **argv ) {
std::ifstream in_file;
in_file.open( config.json_path.string( ) );
if( !in_file ) {
std::cerr << "Could not open json in_file '" << canonical( config.json_path ) << "'\n";
std::cerr << "Could not open json in_file '"
<< canonical( config.json_path ) << "'\n";
exit( EXIT_FAILURE );
}
std::copy( std::istream_iterator<char>{in_file}, std::istream_iterator<char>{}, std::back_inserter( json_str ) );
std::copy( std::istream_iterator<char>{in_file},
std::istream_iterator<char>{}, std::back_inserter( json_str ) );
in_file.close( );
}

config.cpp_stream = &std::cout;
config.header_stream = &std::cout;
config.enable_jsonlink = vm["use_jsonlink"].as<bool>( );
config.hide_null_only = vm["allow_overwrite"].as<bool>( );
std::ofstream cpp_file;
std::ofstream header_file;

if( vm.count( "cpp_file" ) > 0 ) {
bool const allow_overwrite = vm["allow_overwrite"].as<bool>( );
config.cpp_path = canonical( vm["cpp_file"].as<boost::filesystem::path>( ) );
config.cpp_path =
canonical( vm["cpp_file"].as<boost::filesystem::path>( ) );
if( exists( config.cpp_path ) && !allow_overwrite ) {
std::cerr << "cpp_file '" << config.cpp_path << "' already exists\n";
exit( EXIT_FAILURE );
}
cpp_file.open( config.cpp_path.string( ), std::ios::out | std::ios::trunc );
if( !cpp_file ) {
std::cerr << "Could not open cpp_file '" << config.cpp_path << "' for writing\n";
std::cerr << "Could not open cpp_file '" << config.cpp_path
<< "' for writing\n";
exit( EXIT_FAILURE );
}
config.cpp_stream = &cpp_file;

if( config.enable_jsonlink && vm.count( "header_file" ) > 0 ) {
config.header_path = canonical( vm["header_file"].as<boost::filesystem::path>( ) );
config.header_path =
canonical( vm["header_file"].as<boost::filesystem::path>( ) );
if( exists( config.header_path ) && !allow_overwrite ) {
std::cerr << "header_file '" << config.header_path << "' already exists\n";
std::cerr << "header_file '" << config.header_path
<< "' already exists\n";
exit( EXIT_FAILURE );
}
header_file.open( config.header_path.string( ), std::ios::out | std::ios::trunc );
header_file.open( config.header_path.string( ),
std::ios::out | std::ios::trunc );
if( !header_file ) {
std::cerr << "Could not open header_file '" << config.header_path << "' for writing\n";
std::cerr << "Could not open header_file '" << config.header_path
<< "' for writing\n";
exit( EXIT_FAILURE );
}
config.header_stream = &header_file;
Expand All @@ -149,14 +174,16 @@ int main( int argc, char **argv ) {
}

namespace {
size_t callback( char const *in, size_t const size, size_t const num, std::string *const out ) {
size_t callback( char const *in, size_t const size, size_t const num,
std::string *const out ) {
assert( out );
size_t totalBytes = size * num;
out->append( in, totalBytes );
return totalBytes;
}

std::optional<std::string> download( daw::string_view url, daw::string_view user_agent ) {
std::optional<std::string> download( daw::string_view url,
daw::string_view user_agent ) {
struct curl_slist *headers = nullptr;
curl_slist_append( headers, "Accept: application/json" );
curl_slist_append( headers, "Content-Type: application/json" );
Expand Down Expand Up @@ -206,7 +233,7 @@ namespace {
}

bool is_url( daw::string_view path ) {
return boost::starts_with( path.data( ), "http://" ) || boost::starts_with( path.data( ), "https://" );
return boost::starts_with( path.data( ), "http://" ) ||
boost::starts_with( path.data( ), "https://" );
}
} // namespace

0 comments on commit d190278

Please sign in to comment.