From 5583a3c89b72847ce176e437b769d9da3f60223b Mon Sep 17 00:00:00 2001 From: John Keiser Date: Mon, 4 Jan 2021 13:05:08 -0800 Subject: [PATCH] Add error handling to yyjson --- benchmark/distinct_user_id/yyjson.h | 9 ++++++++- benchmark/find_tweet/yyjson.h | 5 +++++ benchmark/kostya/yyjson.h | 8 ++++++-- benchmark/large_random/yyjson.h | 7 +++++-- benchmark/partial_tweets/yyjson.h | 9 +++++++++ 5 files changed, 33 insertions(+), 5 deletions(-) diff --git a/benchmark/distinct_user_id/yyjson.h b/benchmark/distinct_user_id/yyjson.h index 16e5ba20..938e580a 100644 --- a/benchmark/distinct_user_id/yyjson.h +++ b/benchmark/distinct_user_id/yyjson.h @@ -13,21 +13,28 @@ public: yyjson_doc *doc = yyjson_read(json.data(), json.size(), 0); if (!doc) { return false; } yyjson_val *root = yyjson_doc_get_root(doc); + if (!yyjson_is_obj(root)) { return false; } yyjson_val *statuses = yyjson_obj_get(root, "statuses"); + if (!yyjson_is_arr(statuses)) { return "Statuses is not an array!"; } size_t tweet_idx, tweets_max; yyjson_val *tweet; yyjson_arr_foreach(statuses, tweet_idx, tweets_max, tweet) { auto user = yyjson_obj_get(tweet, "user"); + if (!yyjson_is_obj(user)) { return false; } auto id = yyjson_obj_get(user, "id"); - ids.push_back(yyjson_get_sint(id)); + if (!yyjson_is_uint(id)) { return false; } + ids.push_back(yyjson_get_uint(id)); // Not all tweets have a "retweeted_status", but when they do // we want to go and find the user within. auto retweet = yyjson_obj_get(tweet, "retweeted_status"); if (retweet) { + if (!yyjson_is_obj(retweet)) { return false; } user = yyjson_obj_get(retweet, "user"); + if (!yyjson_is_obj(user)) { return false; } id = yyjson_obj_get(user, "id"); + if (!yyjson_is_uint(id)) { return false; } ids.push_back(yyjson_get_sint(id)); } } diff --git a/benchmark/find_tweet/yyjson.h b/benchmark/find_tweet/yyjson.h index cf1ea7c8..4734cd19 100644 --- a/benchmark/find_tweet/yyjson.h +++ b/benchmark/find_tweet/yyjson.h @@ -20,14 +20,19 @@ public: yyjson_doc *doc = yyjson_read(json.data(), json.size(), 0); if (!doc) { return false; } yyjson_val *root = yyjson_doc_get_root(doc); + if (!yyjson_is_obj(root)) { return false; } yyjson_val *statuses = yyjson_obj_get(root, "statuses"); + if (!yyjson_is_arr(statuses)) { return "Statuses is not an array!"; } size_t tweet_idx, tweets_max; yyjson_val *tweet; yyjson_arr_foreach(statuses, tweet_idx, tweets_max, tweet) { + if (!yyjson_is_obj(tweet)) { return false; } auto id = yyjson_obj_get(tweet, "id"); + if (!yyjson_is_uint(id)) { return false; } if (yyjson_get_uint(id) == find_id) { auto _text = yyjson_obj_get(tweet, "text"); + if (yyjson_is_str(id)) { return false; } text = yyjson_get_str(_text); return true; } diff --git a/benchmark/kostya/yyjson.h b/benchmark/kostya/yyjson.h index 3c9c20f1..5a5c6700 100644 --- a/benchmark/kostya/yyjson.h +++ b/benchmark/kostya/yyjson.h @@ -9,7 +9,8 @@ namespace kostya { class yyjson { simdjson_really_inline double get_double(yyjson_val *obj, std::string_view key) { yyjson_val *val = yyjson_obj_getn(obj, key.data(), key.length()); - if (yyjson_get_type(val) != YYJSON_TYPE_NUM) { return 0; } + if (!val){ throw "missing point field!"; } + if (yyjson_get_type(val) != YYJSON_TYPE_NUM) { throw "Number is not a type!"; } switch (yyjson_get_subtype(val)) { case YYJSON_SUBTYPE_UINT: @@ -19,7 +20,7 @@ class yyjson { case YYJSON_SUBTYPE_REAL: return yyjson_get_real(val); default: - return 0; + SIMDJSON_UNREACHABLE(); } } @@ -28,11 +29,14 @@ public: yyjson_doc *doc = yyjson_read(json.data(), json.size(), 0); if (!doc) { return false; } yyjson_val *root = yyjson_doc_get_root(doc); + if (!yyjson_is_obj(root)) { return false; } yyjson_val *coords = yyjson_obj_get(root, "coordinates"); + if (!yyjson_is_obj(coords)) { return false; } size_t idx, max; yyjson_val *coord; yyjson_arr_foreach(coords, idx, max, coord) { + if (!yyjson_is_obj(coord)) { return false; } points.emplace_back(point{get_double(coord, "x"), get_double(coord, "y"), get_double(coord, "z")}); } diff --git a/benchmark/large_random/yyjson.h b/benchmark/large_random/yyjson.h index add25a4a..e5142136 100644 --- a/benchmark/large_random/yyjson.h +++ b/benchmark/large_random/yyjson.h @@ -11,7 +11,8 @@ class yyjson { simdjson_really_inline double get_double(yyjson_val *obj, std::string_view key) { yyjson_val *val = yyjson_obj_getn(obj, key.data(), key.length()); - if (yyjson_get_type(val) != YYJSON_TYPE_NUM) { return 0; } + if (!val){ throw "missing point field!"; } + if (yyjson_get_type(val) != YYJSON_TYPE_NUM) { throw "Number is not a type!"; } switch (yyjson_get_subtype(val)) { case YYJSON_SUBTYPE_UINT: @@ -21,7 +22,7 @@ class yyjson { case YYJSON_SUBTYPE_REAL: return yyjson_get_real(val); default: - return 0; + SIMDJSON_UNREACHABLE(); } } @@ -31,10 +32,12 @@ public: yyjson_doc *doc = yyjson_read(json.data(), json.size(), 0); if (!doc) { return false; } yyjson_val *coords = yyjson_doc_get_root(doc); + if (!yyjson_is_arr(coords)) { return false; } size_t idx, max; yyjson_val *coord; yyjson_arr_foreach(coords, idx, max, coord) { + if (!yyjson_is_obj(coord)) { return false; } points.emplace_back(point{get_double(coord, "x"), get_double(coord, "y"), get_double(coord, "z")}); } return true; diff --git a/benchmark/partial_tweets/yyjson.h b/benchmark/partial_tweets/yyjson.h index 23edb2e2..1dfb0075 100644 --- a/benchmark/partial_tweets/yyjson.h +++ b/benchmark/partial_tweets/yyjson.h @@ -11,18 +11,24 @@ class yyjson { simdjson_really_inline std::string_view get_string_view(yyjson_val *obj, std::string_view key) { auto val = yyjson_obj_getn(obj, key.data(), key.length()); + if (!yyjson_is_str(val)) { throw "field is not uint64 or null!"; } return { yyjson_get_str(val), yyjson_get_len(val) }; } simdjson_really_inline uint64_t get_uint64(yyjson_val *obj, std::string_view key) { auto val = yyjson_obj_getn(obj, key.data(), key.length()); + if (!yyjson_is_uint(val)) { throw "field is not uint64 or null!"; } return yyjson_get_uint(val); } simdjson_really_inline uint64_t get_nullable_uint64(yyjson_val *obj, std::string_view key) { auto val = yyjson_obj_getn(obj, key.data(), key.length()); + if (!yyjson_is_uint(val)) { } + auto type = yyjson_get_type(val); + if (type != YYJSON_TYPE_NUM && type != YYJSON_TYPE_NULL ) { throw "field is not uint64 or null!"; } return yyjson_get_uint(val); } simdjson_really_inline partial_tweets::twitter_user get_user(yyjson_val *obj, std::string_view key) { auto user = yyjson_obj_getn(obj, key.data(), key.length()); + if (!yyjson_is_obj(user)) { throw "missing twitter user field!"; } return { get_uint64(user, "id"), get_string_view(user, "screen_name") }; } @@ -32,11 +38,14 @@ public: yyjson_doc *doc = yyjson_read(json.data(), json.size(), 0); if (!doc) { return false; } yyjson_val *root = yyjson_doc_get_root(doc); + if (!yyjson_is_obj(root)) { return false; } yyjson_val *statuses = yyjson_obj_get(root, "statuses"); + if (!yyjson_is_arr(statuses)) { return "Statuses is not an array!"; } size_t tweet_idx, tweets_max; yyjson_val *tweet; yyjson_arr_foreach(statuses, tweet_idx, tweets_max, tweet) { + if (!yyjson_is_obj(tweet)) { return false; } // TODO these can't actually handle errors tweets.emplace_back(partial_tweets::tweet{ get_string_view(tweet, "created_at"),