Skip to content

Commit 26ce3ed

Browse files
committed
Added ability to download json file from an http or https url
1 parent 76d5979 commit 26ce3ed

3 files changed

Lines changed: 109 additions & 14 deletions

File tree

CMakeLists.txt

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ include( ExternalProject )
66

77
find_package( Boost 1.58.0 COMPONENTS system date_time iostreams program_options filesystem regex unit_test_framework REQUIRED )
88

9+
find_package( CURL )
10+
911
enable_testing( )
1012
add_definitions( -DBOOST_TEST_DYN_LINK )
1113

@@ -57,14 +59,23 @@ externalproject_add(
5759
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/install
5860
)
5961

62+
externalproject_add(
63+
temp_file_prj
64+
GIT_REPOSITORY "https://github.com/beached/libtemp_file.git"
65+
SOURCE_DIR "${CMAKE_BINARY_DIR}/dependencies/temp_file"
66+
GIT_TAG "master"
67+
INSTALL_DIR "${CMAKE_BINARY_DIR}/install"
68+
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/install
69+
)
70+
6071
set( HEADER_FOLDER "include" )
6172
set( SOURCE_FOLDER "src" )
6273
set( TEST_FOLDER "tests" )
6374

6475
include_directories( SYSTEM "${CMAKE_BINARY_DIR}/install/include" )
6576
include_directories( ${HEADER_FOLDER} )
6677
include_directories( SYSTEM ${OPENSSL_INCLUDE_DIR} )
67-
78+
include_directories( SYSTEM ${CURL_INCLUDE_DIRS} )
6879
include_directories( SYSTEM ${Boost_INCLUDE_DIRS} )
6980

7081
link_directories( "${CMAKE_BINARY_DIR}/install/lib" )
@@ -83,7 +94,8 @@ add_dependencies( json_to_cpp header_libraries_prj parse_json_prj char_range_prj
8394
target_link_libraries( json_to_cpp parse_json tz char_range ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} )
8495

8596
add_executable( json_to_cpp_bin ${HEADER_FILES} ${SOURCE_FOLDER}/main.cpp )
86-
target_link_libraries( json_to_cpp_bin json_to_cpp parse_json char_range ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} )
97+
add_dependencies( json_to_cpp_bin temp_file_prj )
98+
target_link_libraries( json_to_cpp_bin json_to_cpp parse_json char_range temp_file ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${CURL_LIBRARIES} )
8799

88100
install( TARGETS json_to_cpp DESTINATION lib )
89101
install( TARGETS json_to_cpp_bin DESTINATION bin )

src/json_to_cpp.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,11 @@ namespace daw {
191191
val_info_t val_info;
192192
val_info.name = "element_" + cur_obj.name;
193193
auto const & arry = cur_item.get_array( );
194-
val_info.type = arry.front( ).type( );
194+
if( arry.empty( ) ) {
195+
val_info.type = daw::json::impl::value_t::value_types::null;
196+
} else {
197+
val_info.type = arry.front( ).type( );
198+
}
195199
switch( val_info.type ) {
196200
case value_t::value_types::array: {
197201
obj_state.has_arrays = true;

src/main.cpp

Lines changed: 90 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
// The MIT License (MIT)
1+
// The MIT License ( MIT )
22
//
3-
// Copyright (c) 2016 Darrell Wright
3+
// Copyright ( c ) 2016 Darrell Wright
44
//
55
// Permission is hereby granted, free of charge, to any person obtaining a copy
66
// of this software and associated documentation files( the "Software" ), to deal
@@ -20,26 +20,105 @@
2020
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2121
// SOFTWARE.
2222

23+
#include <boost/algorithm/string/predicate.hpp>
24+
#include <boost/optional.hpp>
25+
#include <boost/utility/string_view.hpp>
2326
#include <cstdlib>
27+
#include <curl/curl.h>
2428
#include <fstream>
29+
#include <string>
30+
#include <memory>
2531
#include <iostream>
2632

2733
#include "json_to_cpp.h"
34+
namespace {
35+
size_t callback( char const * in, size_t const size, size_t const num, std::string * const out ) {
36+
assert( out );
37+
size_t totalBytes = size * num;
38+
out->append( in, totalBytes );
39+
return totalBytes;
40+
}
41+
42+
boost::optional<std::string> download( boost::string_view url ) {
43+
struct curl_slist *headers = nullptr;
44+
curl_slist_append( headers, "Accept: application/json" );
45+
curl_slist_append( headers, "Content-Type: application/json" );
46+
curl_slist_append( headers, "charsets: utf-8" );
47+
48+
CURL* curl = curl_easy_init( );
49+
if( !curl ) {
50+
return boost::none;
51+
}
52+
curl_easy_setopt( curl, CURLOPT_HTTPHEADER, headers );
53+
curl_easy_setopt( curl, CURLOPT_HTTPGET, 1 );
54+
curl_easy_setopt( curl, CURLOPT_HTTPHEADER, headers);
55+
// Set remote URL.
56+
curl_easy_setopt( curl, CURLOPT_URL, url.data( ) );
57+
58+
// Don't wait forever, time out after 10 seconds.
59+
curl_easy_setopt( curl, CURLOPT_TIMEOUT, 15 );
60+
61+
// Follow HTTP redirects if necessary.
62+
curl_easy_setopt( curl, CURLOPT_FOLLOWLOCATION, 1L );
63+
64+
// Response information.
65+
int httpCode = 0;
66+
std::string httpData;
67+
68+
// Hook up data handling function.
69+
curl_easy_setopt( curl, CURLOPT_WRITEFUNCTION, callback );
70+
71+
// Hook up data container ( will be passed as the last parameter to the
72+
// callback handling function ). Can be any pointer type, since it will
73+
// internally be passed as a void pointer.
74+
curl_easy_setopt( curl, CURLOPT_WRITEDATA, &httpData );
75+
76+
// Run our HTTP GET command, capture the HTTP response code, and clean up.
77+
curl_easy_perform( curl );
78+
curl_easy_getinfo( curl, CURLINFO_RESPONSE_CODE, &httpCode );
79+
curl_easy_cleanup( curl );
80+
81+
if( httpCode != 200 ) {
82+
std::cerr << "Couldn't GET from " << url << '\n';
83+
return boost::none;
84+
}
85+
86+
return httpData;
87+
}
88+
89+
bool is_url( boost::string_view path ) {
90+
return boost::starts_with( path.data( ), "http://" ) || boost::starts_with( path.data( ), "https://" );
91+
}
92+
} // namespace anonymous
2893

2994
int main( int argc, char ** argv ) {
3095
using namespace daw::json_to_cpp;
31-
32-
std::ifstream in_file;
33-
in_file.open( argv[1] );
34-
if( !in_file ) {
35-
std::cerr << "Must supply valid json file on commandline\n";
96+
if( argc != 2 ) {
97+
std::cerr << "Must supply a url or a file as the json source\n";
3698
exit( EXIT_FAILURE );
3799
}
38-
std::string json_blob;
39-
std::copy( std::istream_iterator<char>{ in_file }, std::istream_iterator<char>{ }, std::back_inserter( json_blob ) );
40-
in_file.close( );
100+
std::string const uri{ argv[1] };
101+
std::string json_str;
102+
if( is_url( uri ) ) {
103+
auto tmp = download( uri );
104+
if( tmp ) {
105+
json_str = *tmp;
106+
} else {
107+
std::cerr << "Could not download json data from '" << uri << "'\n";
108+
exit( EXIT_FAILURE );
109+
}
110+
} else {
111+
std::ifstream in_file;
112+
in_file.open( argv[1] );
113+
if( !in_file ) {
114+
std::cerr << "Must supply valid json file on commandline\n";
115+
exit( EXIT_FAILURE );
116+
}
117+
std::copy( std::istream_iterator<char>{ in_file }, std::istream_iterator<char>{ }, std::back_inserter( json_str ) );
118+
in_file.close( );
119+
}
41120
config_t config{ };
42-
generate_cpp( json_blob, std::cout, config );
121+
generate_cpp( json_str, std::cout, config );
43122
std::cout << std::endl;
44123

45124
return EXIT_SUCCESS;

0 commit comments

Comments
 (0)