mirror of
https://github.com/simdjson/simdjson
synced 2026-06-08 17:27:07 +00:00
Port tools to cxxopts (#904)
* Port tools to cxxopts * Fix minify tool architecture argument * Fix wrong return code in json2json * Change return codes * Better handling of the errors. * Updating to latest version. * cxxopts outside of SIMDJSON_COMPETITION Co-authored-by: Daniel Lemire <lemire@gmail.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
link_libraries(simdjson simdjson-internal-flags simdjson-windows-headers)
|
||||
link_libraries(simdjson simdjson-internal-flags simdjson-windows-headers cxxopts)
|
||||
|
||||
add_executable(json2json json2json.cpp)
|
||||
add_executable(jsonstats jsonstats.cpp)
|
||||
|
||||
+46
-27
@@ -1,40 +1,53 @@
|
||||
#include <iostream>
|
||||
#include <unistd.h>
|
||||
#include "simdjson.h"
|
||||
#ifndef __cpp_exceptions
|
||||
#define CXXOPTS_NO_EXCEPTIONS
|
||||
#endif
|
||||
#include "cxxopts.hpp"
|
||||
|
||||
void usage(const char *exe) {
|
||||
std::cerr << exe << " v" << STRINGIFY(SIMDJSON_VERSION) << " (" << simdjson::active_implementation->name() << ")" << std::endl;
|
||||
std::cerr << std::endl;
|
||||
std::cerr << "Reads json in, out the result of the parsing. " << std::endl;
|
||||
std::cerr << "Usage: " << exe << " <jsonfile>" << std::endl;
|
||||
std::cerr << "The -d flag dumps the raw content of the tape." << std::endl;
|
||||
}
|
||||
int main(int argc, char *argv[]) {
|
||||
bool rawdump = false;
|
||||
#ifdef __cpp_exceptions
|
||||
try {
|
||||
#endif
|
||||
std::string progName = "json2json";
|
||||
|
||||
int c;
|
||||
std::string progUsage = "json2json version ";
|
||||
progUsage += STRINGIFY(SIMDJSON_VERSION);
|
||||
progUsage += " (";
|
||||
progUsage += simdjson::active_implementation->name();
|
||||
progUsage += ")\n";
|
||||
progUsage += "Reads json in, out the result of the parsing.\n";
|
||||
progUsage += argv[0];
|
||||
progUsage += " <jsonfile>\n";
|
||||
|
||||
while ((c = getopt(argc, argv, "dh")) != -1) {
|
||||
switch (c) {
|
||||
case 'd':
|
||||
rawdump = true;
|
||||
break;
|
||||
case 'h':
|
||||
usage(argv[0]);
|
||||
return EXIT_SUCCESS;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
cxxopts::Options options(progName, progUsage);
|
||||
|
||||
options.add_options()
|
||||
("d,rawdump", "Dumps the raw content of the tape.", cxxopts::value<bool>()->default_value("false"))
|
||||
("f,file", "File name.", cxxopts::value<std::string>())
|
||||
("h,help", "Print usage.")
|
||||
;
|
||||
|
||||
// the first argument without an option name will be parsed into file
|
||||
options.parse_positional({"file"});
|
||||
auto result = options.parse(argc, argv);
|
||||
|
||||
if(result.count("help")) {
|
||||
std::cerr << options.help() << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
if (optind >= argc) {
|
||||
usage(argv[0]);
|
||||
|
||||
bool rawdump = result["rawdump"].as<bool>();
|
||||
|
||||
if(!result.count("file")) {
|
||||
std::cerr << "No filename specified." << std::endl;
|
||||
std::cerr << options.help() << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
const char *filename = argv[optind];
|
||||
if (optind + 1 < argc) {
|
||||
std::cerr << "warning: ignoring everything after " << argv[optind + 1]
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
const char *filename = result["file"].as<std::string>().c_str();
|
||||
|
||||
simdjson::dom::parser parser;
|
||||
auto [doc, error] = parser.load(filename); // do the parsing, return false on error
|
||||
if (error != simdjson::SUCCESS) {
|
||||
@@ -48,4 +61,10 @@ int main(int argc, char *argv[]) {
|
||||
std::cout << doc;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
#ifdef __cpp_exceptions
|
||||
} catch (const cxxopts::OptionException& e) {
|
||||
std::cout << "error parsing options: " << e.what() << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
+65
-36
@@ -2,6 +2,10 @@
|
||||
#include <set>
|
||||
|
||||
#include "simdjson.h"
|
||||
#ifndef __cpp_exceptions
|
||||
#define CXXOPTS_NO_EXCEPTIONS
|
||||
#endif
|
||||
#include "cxxopts.hpp"
|
||||
|
||||
size_t count_nonasciibytes(const uint8_t *input, size_t length) {
|
||||
size_t count = 0;
|
||||
@@ -180,18 +184,37 @@ stat_t simdjson_compute_stats(const simdjson::padded_string &p) {
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int myoptind = 1;
|
||||
if (myoptind >= argc) {
|
||||
std::cerr << "Reads json, prints stats. " << std::endl;
|
||||
std::cerr << "Usage: " << argv[0] << " <jsonfile>" << std::endl;
|
||||
exit(1);
|
||||
#ifdef __cpp_exceptions
|
||||
try {
|
||||
#endif
|
||||
std::string progName = "jsonstat";
|
||||
std::string progUsage = "Reads json, prints stats.\n";
|
||||
progUsage += argv[0];
|
||||
progUsage += " <jsonfile>";
|
||||
|
||||
cxxopts::Options options(progName, progUsage);
|
||||
|
||||
options.add_options()
|
||||
("h,help", "Print usage.")
|
||||
("f,file", "File name.", cxxopts::value<std::string>())
|
||||
;
|
||||
|
||||
options.parse_positional({"file"});
|
||||
auto result = options.parse(argc, argv);
|
||||
|
||||
if(result.count("help")) {
|
||||
std::cerr << options.help() << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
const char *filename = argv[myoptind];
|
||||
if (myoptind + 1 < argc) {
|
||||
std::cerr << "warning: ignoring everything after " << argv[myoptind + 1]
|
||||
<< std::endl;
|
||||
|
||||
if(!result.count("file")) {
|
||||
std::cerr << "No filename specified." << std::endl;
|
||||
std::cerr << options.help() << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
const char *filename = result["file"].as<std::string>().c_str();
|
||||
|
||||
auto [p, error] = simdjson::padded_string::load(filename);
|
||||
if (error) {
|
||||
std::cerr << "Could not load the file " << filename << std::endl;
|
||||
@@ -206,33 +229,33 @@ int main(int argc, char *argv[]) {
|
||||
// a JSON object and then to serialize it.
|
||||
|
||||
printf(R"({
|
||||
"integer_count" = %10zu,
|
||||
"integer32_count" = %10zu,
|
||||
"unsigned_integer32_count" = %10zu,
|
||||
"unsigned_integer_count" = %10zu,
|
||||
"float_count" = %10zu,
|
||||
"string_count" = %10zu,
|
||||
"string_byte_count" = %10zu,
|
||||
"ascii_string_count" = %10zu,
|
||||
"string_maximum_length" = %10zu,
|
||||
"backslash_count" = %10zu,
|
||||
"non_ascii_byte_count" = %10zu,
|
||||
"object_count" = %10zu,
|
||||
"maximum_object_size" = %10zu,
|
||||
"array_count" = %10zu,
|
||||
"maximum_array_size" = %10zu,
|
||||
"null_count" = %10zu,
|
||||
"true_count" = %10zu,
|
||||
"false_count" = %10zu,
|
||||
"byte_count" = %10zu,
|
||||
"structural_indexes_count" = %10zu,
|
||||
"key_count" = %10zu,
|
||||
"ascii_key_count" = %10zu,
|
||||
"key_maximum_length" = %10zu,
|
||||
"key_distinct_count" = %10zu,
|
||||
"integer_count" = %10zu,
|
||||
"integer32_count" = %10zu,
|
||||
"unsigned_integer32_count" = %10zu,
|
||||
"unsigned_integer_count" = %10zu,
|
||||
"float_count" = %10zu,
|
||||
"string_count" = %10zu,
|
||||
"string_byte_count" = %10zu,
|
||||
"ascii_string_count" = %10zu,
|
||||
"string_maximum_length" = %10zu,
|
||||
"backslash_count" = %10zu,
|
||||
"non_ascii_byte_count" = %10zu,
|
||||
"object_count" = %10zu,
|
||||
"maximum_object_size" = %10zu,
|
||||
"array_count" = %10zu,
|
||||
"maximum_array_size" = %10zu,
|
||||
"null_count" = %10zu,
|
||||
"true_count" = %10zu,
|
||||
"false_count" = %10zu,
|
||||
"byte_count" = %10zu,
|
||||
"structural_indexes_count" = %10zu,
|
||||
"key_count" = %10zu,
|
||||
"ascii_key_count" = %10zu,
|
||||
"key_maximum_length" = %10zu,
|
||||
"key_distinct_count" = %10zu,
|
||||
"repeated_key_distinct_count"= %10zu,
|
||||
"repeated_key_byte_count" = %10zu;
|
||||
"maximum_depth" = %10zu
|
||||
"repeated_key_byte_count" = %10zu;
|
||||
"maximum_depth" = %10zu
|
||||
}
|
||||
)",
|
||||
s.integer_count,s.integer32_count,s.unsigned_integer32_count,s.unsigned_integer_count,
|
||||
@@ -244,4 +267,10 @@ int main(int argc, char *argv[]) {
|
||||
s.ascii_key_count, s.key_maximum_length, s.all_keys.size(), s.repeated_keys.size(),
|
||||
s.repeated_key_byte_count, s.maximum_depth);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
#ifdef __cpp_exceptions
|
||||
} catch (const cxxopts::OptionException& e) {
|
||||
std::cout << "error parsing options: " << e.what() << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
+51
-62
@@ -5,74 +5,57 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include "simdjson.h"
|
||||
#ifndef __cpp_exceptions
|
||||
#define CXXOPTS_NO_EXCEPTIONS
|
||||
#endif
|
||||
#include "cxxopts.hpp"
|
||||
|
||||
// Stash the exe_name in main() for functions to use
|
||||
char* exe_name;
|
||||
cxxopts::Options options("minify", "Runs the parser against the given json files in a loop, measuring speed and other statistics.");
|
||||
|
||||
void print_usage(std::ostream& out) {
|
||||
out << "Usage: " << exe_name << " [-a ARCH] <jsonfile>" << std::endl;
|
||||
out << std::endl;
|
||||
out << "Runs the parser against the given json files in a loop, measuring speed and other statistics." << std::endl;
|
||||
out << std::endl;
|
||||
out << "Options:" << std::endl;
|
||||
out << std::endl;
|
||||
out << "-a IMPL - Use the given parser implementation. By default, detects the most advanced" << std::endl;
|
||||
out << " implementation supported on the host machine." << std::endl;
|
||||
for (auto impl : simdjson::available_implementations) {
|
||||
out << "-a " << std::left << std::setw(9) << impl->name() << " - Use the " << impl->description() << " parser implementation." << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void exit_usage(std::string message) {
|
||||
void usage(std::string message) {
|
||||
std::cerr << message << std::endl;
|
||||
std::cerr << std::endl;
|
||||
print_usage(std::cerr);
|
||||
exit(EXIT_FAILURE);
|
||||
std::cerr << options.help() << std::endl;
|
||||
}
|
||||
|
||||
|
||||
struct option_struct {
|
||||
char* filename{};
|
||||
|
||||
option_struct(int argc, char **argv) {
|
||||
int c;
|
||||
|
||||
while ((c = getopt(argc, argv, "a:")) != -1) {
|
||||
switch (c) {
|
||||
case 'a': {
|
||||
const simdjson::implementation *impl = simdjson::available_implementations[optarg];
|
||||
if (!impl) {
|
||||
std::string exit_message = std::string("Unsupported option value -a ") + optarg + ": expected -a with one of ";
|
||||
for (auto imple : simdjson::available_implementations) {
|
||||
exit_message += imple->name();
|
||||
exit_message += " ";
|
||||
}
|
||||
exit_usage(exit_message);
|
||||
}
|
||||
simdjson::active_implementation = impl;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// reaching here means an argument was given to getopt() which did not have a case label
|
||||
exit_usage("Unexpected argument - missing case for option "+
|
||||
std::string(1,static_cast<char>(c))+
|
||||
" (programming error)");
|
||||
}
|
||||
}
|
||||
|
||||
// All remaining arguments are considered to be files
|
||||
if(optind + 1 == argc) {
|
||||
filename = argv[optind];
|
||||
} else {
|
||||
exit_usage("Please specify exactly one input file.");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
exe_name = argv[0];
|
||||
option_struct options(argc, argv);
|
||||
std::string filename = options.filename;
|
||||
#ifdef __cpp_exceptions
|
||||
try {
|
||||
#endif
|
||||
std::stringstream ss;
|
||||
ss << "Parser implementation (by default, detects the most advanced implementation supported on the host machine)." << std::endl;
|
||||
ss << "Available parser implementations:" << std::endl;
|
||||
for (auto impl : simdjson::available_implementations) {
|
||||
ss << "-a " << std::left << std::setw(9) << impl->name() << " - Use the " << impl->description() << " parser implementation." << std::endl;
|
||||
}
|
||||
options.add_options()
|
||||
("a,arch", ss.str(), cxxopts::value<std::string>())
|
||||
("f,file", "File name.", cxxopts::value<std::string>())
|
||||
("h,help", "Print usage.")
|
||||
;
|
||||
|
||||
options.parse_positional({"file"});
|
||||
auto result = options.parse(argc, argv);
|
||||
|
||||
if(result.count("help")) {
|
||||
usage("");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
if(!result.count("file")) {
|
||||
usage("No filename specified.");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if(result.count("arch")) {
|
||||
const simdjson::implementation *impl = simdjson::available_implementations[result["arch"].as<std::string>().c_str()];
|
||||
if(!impl) {
|
||||
usage("Unsupported implementation.");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
simdjson::active_implementation = impl;
|
||||
}
|
||||
|
||||
std::string filename = result["file"].as<std::string>();
|
||||
|
||||
auto [p, error] = simdjson::padded_string::load(filename);
|
||||
if (error) {
|
||||
std::cerr << "Could not load the file " << filename << std::endl;
|
||||
@@ -83,4 +66,10 @@ int main(int argc, char *argv[]) {
|
||||
error = simdjson::active_implementation->minify((const uint8_t*)p.data(), p.length(), (uint8_t*)copy.data(), copy_len);
|
||||
if (error) { std::cerr << error << std::endl; return 1; }
|
||||
printf("%s", copy.data());
|
||||
#ifdef __cpp_exceptions
|
||||
} catch (const cxxopts::OptionException& e) {
|
||||
std::cout << "error parsing options: " << e.what() << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user