Commit 8ea70e3d authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook Github Bot

Export folly::json::parse_error

Summary:
[Folly] Export `folly::json::parse_error` v.s. having it be a hidden type.

* Move class body to `.h`.
* Leave helper function, previously the constructor, in anonymous namespace in `.cpp`.

Reviewed By: vitaut

Differential Revision: D17578773

fbshipit-source-id: 0d50fdf662bbf67e844ff0ec9ef24975cea92f62
parent a8d1fd8e
......@@ -37,8 +37,21 @@ namespace folly {
//////////////////////////////////////////////////////////////////////
namespace json {
namespace {
parse_error make_parse_error(
unsigned int line,
std::string const& context,
std::string const& expected) {
return parse_error(to<std::string>(
"json parse error on line ",
line,
!context.empty() ? to<std::string>(" near `", context, '\'') : "",
": ",
expected));
}
struct Printer {
explicit Printer(
std::string& out,
......@@ -51,7 +64,7 @@ struct Printer {
case dynamic::DOUBLE:
if (!opts_.allow_nan_inf &&
(std::isnan(v.asDouble()) || std::isinf(v.asDouble()))) {
throw std::runtime_error(
throw json::parse_error(
"folly::toJson: JSON object value was a "
"NaN or INF");
}
......@@ -91,7 +104,7 @@ struct Printer {
private:
void printKV(const std::pair<const dynamic, dynamic>& p) const {
if (!opts_.allow_non_string_keys && !p.first.isString()) {
throw std::runtime_error(
throw json::parse_error(
"folly::toJson: JSON object key was not a "
"string");
}
......@@ -193,19 +206,6 @@ struct Printer {
//////////////////////////////////////////////////////////////////////
struct FOLLY_EXPORT ParseError : std::runtime_error {
explicit ParseError(
unsigned int line,
std::string const& context,
std::string const& expected)
: std::runtime_error(to<std::string>(
"json parse error on line ",
line,
!context.empty() ? to<std::string>(" near `", context, '\'') : "",
": ",
expected)) {}
};
// Wraps our input buffer with some helper functions.
struct Input {
explicit Input(StringPiece range, json::serialization_opts const* opts)
......@@ -281,7 +281,7 @@ struct Input {
void expect(char c) {
if (**this != c) {
throw ParseError(
throw json::make_parse_error(
lineNum_, context(), to<std::string>("expected '", c, '\''));
}
++*this;
......@@ -323,7 +323,7 @@ struct Input {
}
dynamic error(char const* what) const {
throw ParseError(lineNum_, context(), what);
throw json::make_parse_error(lineNum_, context(), what);
}
json::serialization_opts const& getOpts() {
......
......@@ -166,6 +166,11 @@ void escapeString(
*/
std::string stripComments(StringPiece jsonC);
class FOLLY_EXPORT parse_error : public std::runtime_error {
public:
using std::runtime_error::runtime_error;
};
// may be extened in future to include offset, col, etc.
struct parse_location {
uint32_t line{}; // 0-indexed
......
......@@ -25,6 +25,7 @@ using folly::dynamic;
using folly::parseJson;
using folly::parseJsonWithMetadata;
using folly::toJson;
using folly::json::parse_error;
TEST(Json, Unicode) {
auto val = parseJson(u8"\"I \u2665 UTF-8\"");
......@@ -78,12 +79,12 @@ TEST(Json, Parse) {
EXPECT_TRUE(std::isnan(parseJson("NaN").asDouble()));
// case matters
EXPECT_THROW(parseJson("infinity"), std::runtime_error);
EXPECT_THROW(parseJson("inf"), std::runtime_error);
EXPECT_THROW(parseJson("Inf"), std::runtime_error);
EXPECT_THROW(parseJson("INF"), std::runtime_error);
EXPECT_THROW(parseJson("nan"), std::runtime_error);
EXPECT_THROW(parseJson("NAN"), std::runtime_error);
EXPECT_THROW(parseJson("infinity"), parse_error);
EXPECT_THROW(parseJson("inf"), parse_error);
EXPECT_THROW(parseJson("Inf"), parse_error);
EXPECT_THROW(parseJson("INF"), parse_error);
EXPECT_THROW(parseJson("nan"), parse_error);
EXPECT_THROW(parseJson("NAN"), parse_error);
auto array = parseJson("[12,false, false , null , [12e4,32, [], 12]]");
EXPECT_EQ(array.size(), 5);
......@@ -91,12 +92,11 @@ TEST(Json, Parse) {
EXPECT_EQ(std::prev(array.end())->size(), 4);
}
EXPECT_THROW(parseJson("\n[12,\n\nnotvalidjson"), std::runtime_error);
EXPECT_THROW(parseJson("\n[12,\n\nnotvalidjson"), parse_error);
EXPECT_THROW(parseJson("12e2e2"), std::runtime_error);
EXPECT_THROW(parseJson("12e2e2"), parse_error);
EXPECT_THROW(
parseJson("{\"foo\":12,\"bar\":42} \"something\""), std::runtime_error);
EXPECT_THROW(parseJson("{\"foo\":12,\"bar\":42} \"something\""), parse_error);
// clang-format off
dynamic value = dynamic::object
......@@ -353,7 +353,7 @@ TEST(Json, ParseTrailingComma) {
EXPECT_EQ(arr, parseJson("[1, 2, ]", on));
EXPECT_EQ(arr, parseJson("[1, 2 , ]", on));
EXPECT_EQ(arr, parseJson("[1, 2 ,]", on));
EXPECT_THROW(parseJson("[1, 2,]", off), std::runtime_error);
EXPECT_THROW(parseJson("[1, 2,]", off), parse_error);
dynamic obj = dynamic::object("a", 1);
EXPECT_EQ(obj, parseJson("{\"a\": 1}", on));
......@@ -361,7 +361,7 @@ TEST(Json, ParseTrailingComma) {
EXPECT_EQ(obj, parseJson("{\"a\": 1, }", on));
EXPECT_EQ(obj, parseJson("{\"a\": 1 , }", on));
EXPECT_EQ(obj, parseJson("{\"a\": 1 ,}", on));
EXPECT_THROW(parseJson("{\"a\":1,}", off), std::runtime_error);
EXPECT_THROW(parseJson("{\"a\":1,}", off), parse_error);
}
TEST(Json, BoolConversion) {
......@@ -389,7 +389,7 @@ TEST(Json, Produce) {
// We're not allowed to have non-string keys in json.
EXPECT_THROW(
toJson(dynamic::object("abc", "xyz")(42.33, "asd")), std::runtime_error);
toJson(dynamic::object("abc", "xyz")(42.33, "asd")), parse_error);
// Check Infinity/Nan
folly::json::serialization_opts opts;
......@@ -604,7 +604,7 @@ TEST(Json, ParseNonStringKeys) {
// check that we don't allow non-string keys as this violates the
// strict JSON spec (though it is emitted by the output of
// folly::dynamic with operator <<).
EXPECT_THROW(parseJson("{1:[]}"), std::runtime_error);
EXPECT_THROW(parseJson("{1:[]}"), parse_error);
// check that we can parse colloquial JSON if the option is set
folly::json::serialization_opts opts;
......@@ -713,14 +713,14 @@ TEST(Json, ParseNumbersAsStrings) {
EXPECT_EQ("-Infinity", parse("-Infinity"));
EXPECT_EQ("NaN", parse("NaN"));
EXPECT_THROW(parse("ThisIsWrong"), std::runtime_error);
EXPECT_THROW(parse("34-2"), std::runtime_error);
EXPECT_THROW(parse(""), std::runtime_error);
EXPECT_THROW(parse("-"), std::runtime_error);
EXPECT_THROW(parse("34-e2"), std::runtime_error);
EXPECT_THROW(parse("34e2.4"), std::runtime_error);
EXPECT_THROW(parse("infinity"), std::runtime_error);
EXPECT_THROW(parse("nan"), std::runtime_error);
EXPECT_THROW(parse("ThisIsWrong"), parse_error);
EXPECT_THROW(parse("34-2"), parse_error);
EXPECT_THROW(parse(""), parse_error);
EXPECT_THROW(parse("-"), parse_error);
EXPECT_THROW(parse("34-e2"), parse_error);
EXPECT_THROW(parse("34e2.4"), parse_error);
EXPECT_THROW(parse("infinity"), parse_error);
EXPECT_THROW(parse("nan"), parse_error);
}
TEST(Json, SortKeys) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment