diff --git a/Makefile b/Makefile index 844afedd..e6ceba29 100644 --- a/Makefile +++ b/Makefile @@ -92,10 +92,10 @@ ujdecode.o: $(UJSON4C_INCLUDE) $(CC) $(CFLAGS) -c dependencies/ujson4c/src/ujdecode.c parsingcompetition: benchmark/parsingcompetition.cpp $(HEADERS) $(LIBFILES) $(OBJECTS) - $(CXX) $(CXXFLAGS) -o parsingcompetition $(LIBFILES) benchmark/parsingcompetition.cpp ujdecode.o -I. $(LIBFLAGS) + $(CXX) $(CXXFLAGS) -o parsingcompetition $(LIBFILES) benchmark/parsingcompetition.cpp $(OBJECTS) -I. $(LIBFLAGS) -allparserscheckfile: tests/allparserscheckfile.cpp $(HEADERS) $(LIBFILES) - $(CXX) $(CXXFLAGS) -o allparserscheckfile $(LIBFILES) tests/allparserscheckfile.cpp -I. $(LIBFLAGS) +allparserscheckfile: tests/allparserscheckfile.cpp $(HEADERS) $(LIBFILES) $(OBJECTS) + $(CXX) $(CXXFLAGS) -o allparserscheckfile $(LIBFILES) tests/allparserscheckfile.cpp $(OBJECTS) -I. $(LIBFLAGS) parsehisto: benchmark/parse.cpp $(HEADERS) $(LIBFILES) $(CXX) $(CXXFLAGS) -o parsehisto benchmark/parse.cpp $(LIBFILES) $(LIBFLAGS) -DBUILDHISTOGRAM diff --git a/README.md b/README.md index 4ce59f53..0cf74366 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,9 @@ To simplify the engineering, we make some assumptions. ## Features - We parse integers and floating-point numbers as separate types which allows us to support large 64-bit integers. -- We do full UTF-8 validation as part of the parsing. +- We do full UTF-8 validation as part of the parsing. (Parsers like fastjson, gason and dropbox json11 do not do UTF-8 validation.) +- We fully validate the numbers. (Parsers like gason and ultranjson will accept `[0e+]` as valid JSON.) +- We validate string content for unescaped characters. (Parsers like fastjson and ultrajson accept unescaped line breaks and tags in strings.) ## Architecture diff --git a/benchmark/parsingcompetition.cpp b/benchmark/parsingcompetition.cpp index 39218eb8..b1ca42a3 100644 --- a/benchmark/parsingcompetition.cpp +++ b/benchmark/parsingcompetition.cpp @@ -1,4 +1,4 @@ - +#include #include "jsonparser/jsonparser.h" #include "benchmark.h" @@ -26,7 +26,7 @@ using namespace std; // fastjson has a tricky interface void on_json_error( void *, const fastjson::ErrorContext& ec) { - std::cerr<<"ERROR: "<= argc) { cerr << "Usage: " << argv[0] << " \n"; cerr << "Or " << argv[0] << " -v \n"; + cerr << "To enable parsers that are not standard compliant, use the -a flag\n"; exit(1); } - bool verbose = false; - if (argc > 2) { - if (strcmp(argv[1], "-v")) - verbose = true; + const char * filename = argv[optind]; + if(optind + 1 < argc) { + cerr << "warning: ignoring everything after " << argv[optind + 1] << endl; } - pair p = get_corpus(argv[argc - 1]); + pair p = get_corpus(filename); if (verbose) { std::cout << "Input has "; if (p.second > 1024 * 1024) @@ -88,15 +103,15 @@ int main(int argc, char *argv[]) { BEST_TIME("sajson (static alloc)", sajson::parse(sajson::bounded_allocation(ast_buffer, astbuffersize), sajson::mutable_string_view(p.second, buffer)).is_valid(), true, memcpy(buffer, p.first, p.second), repeat, volume, true); std::string json11err; - BEST_TIME("dropbox (json11) ", json11::Json::parse(buffer,json11err).is_null(), false, memcpy(buffer, p.first, p.second), repeat, volume, true); + if(all) BEST_TIME("dropbox (json11) ", (( json11::Json::parse(buffer,json11err).is_null() ) || ( ! json11err.empty() )), false, memcpy(buffer, p.first, p.second), repeat, volume, true); - BEST_TIME("fastjson ", fastjson_parse(buffer), true, memcpy(buffer, p.first, p.second), repeat, volume, true); + if(all) BEST_TIME("fastjson ", fastjson_parse(buffer), true, memcpy(buffer, p.first, p.second), repeat, volume, true); JsonValue value; JsonAllocator allocator; char *endptr; - BEST_TIME("gason ", jsonParse(buffer, &endptr, &value, allocator), JSON_OK, memcpy(buffer, p.first, p.second), repeat, volume, true); + if(all) BEST_TIME("gason ", jsonParse(buffer, &endptr, &value, allocator), JSON_OK, memcpy(buffer, p.first, p.second), repeat, volume, true); void *state; - BEST_TIME("ultrajson ", (UJDecode(buffer, p.second, NULL, &state) == NULL), false, memcpy(buffer, p.first, p.second), repeat, volume, true); + if(all) BEST_TIME("ultrajson ", (UJDecode(buffer, p.second, NULL, &state) == NULL), false, memcpy(buffer, p.first, p.second), repeat, volume, true); BEST_TIME("memcpy ", (memcpy(buffer, p.first, p.second) == buffer), true, , repeat, volume, true); free(p.first); free(ast_buffer); diff --git a/tests/allparserscheckfile.cpp b/tests/allparserscheckfile.cpp index dd9ff3d0..483c8756 100644 --- a/tests/allparserscheckfile.cpp +++ b/tests/allparserscheckfile.cpp @@ -8,9 +8,32 @@ #include "rapidjson/reader.h" // you have to check in the submodule #include "rapidjson/stringbuffer.h" #include "rapidjson/writer.h" - +#include "json11.cpp" #include "sajson.h" +#include "fastjson.cpp" +#include "fastjson_dom.cpp" +#include "gason.cpp" +extern "C" +{ +#include "ultrajsondec.c" +#include "ujdecode.h" +} +using namespace rapidjson; +using namespace std; + + +// fastjson has a tricky interface +void on_json_error( void *, const fastjson::ErrorContext& ec) { + //std::cerr<<"ERROR: "<((const char *)buffer).HasParseError() == false); bool sajson_correct = sajson::parse(sajson::dynamic_allocation(), sajson::mutable_string_view(p.second, buffer)).is_valid(); + std::string json11err; + bool dropbox_correct = (( json11::Json::parse(buffer,json11err).is_null() ) || ( ! json11err.empty() )) == false; + bool fastjson_correct = fastjson_parse(buffer); + JsonValue value; + JsonAllocator allocator; + char *endptr; + bool gason_correct = (jsonParse(buffer, &endptr, &value, allocator) == JSON_OK); + void *state; + bool ultrajson_correct = ((UJDecode(buffer, p.second, NULL, &state) == NULL) == false); printf("our parser : %s \n", ours_correct ? "correct":"invalid"); printf("rapid : %s \n", rapid_correct ? "correct":"invalid"); printf("rapid (check encoding) : %s \n", rapid_correct_checkencoding ? "correct":"invalid"); printf("sajson : %s \n", sajson_correct ? "correct":"invalid"); - + printf("dropbox : %s \n", dropbox_correct ? "correct":"invalid"); + printf("fastjson : %s \n", fastjson_correct ? "correct":"invalid"); + printf("gason : %s \n", gason_correct ? "correct":"invalid"); + printf("ultrajson : %s \n", ultrajson_correct ? "correct":"invalid"); + free(buffer); free(p.first); deallocate_ParsedJson(pj_ptr);