Skip to content

Commit

Permalink
fable: Accept // comments in JSON files
Browse files Browse the repository at this point in the history
This can be configured by a Conan package option named
"allow_comments", which is set to True by default.
  • Loading branch information
cassava committed Jul 25, 2022
1 parent 1a390ac commit b891da9
Show file tree
Hide file tree
Showing 8 changed files with 68 additions and 13 deletions.
3 changes: 3 additions & 0 deletions engine/conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ class CloeEngine(ConanFile):
"pedantic": [True, False],
}
default_options = {
"fable:allow_comments": True,

# These don't change the output.
"test": True,
"pedantic": True,
}
Expand Down
7 changes: 7 additions & 0 deletions fable/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ target_link_libraries(${target}
CONAN_PKG::nlohmann_json
)

option(AllowComments "Allow comments when parsing JSON?" ON)
if(AllowComments)
target_compile_definitions(${target} PRIVATE PARSE_JSON_WITH_COMMENTS=true)
else()
target_compile_definitions(${target} PRIVATE PARSE_JSON_WITH_COMMENTS=false)
endif()

# Testing ------------------------------------------------------------
option(BuildTests "Build tests?" ON)
if(BuildTests)
Expand Down
3 changes: 3 additions & 0 deletions fable/conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ class Fable(ConanFile):
description = "JSON schema and configuration library"
settings = "os", "compiler", "build_type", "arch"
options = {
"allow_comments": [True, False],
"shared": [True, False],
"fPIC": [True, False],
"test": [True, False],
}
default_options = {
"allow_comments": True,
"shared": False,
"fPIC": True,
"test": True,
Expand Down Expand Up @@ -53,6 +55,7 @@ def _configure_cmake(self):
self._cmake = CMake(self)
self._cmake.definitions["CMAKE_EXPORT_COMPILE_COMMANDS"] = True
self._cmake.definitions["FABLE_VERSION"] = self.version
self._cmake.definitions["AllowComments"] = self.options.allow_comments
self._cmake.definitions["BuildTests"] = self.options.test
self._cmake.configure()
return self._cmake
Expand Down
32 changes: 32 additions & 0 deletions fable/include/fable/json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,25 @@

namespace fable {

/**
* When parsing JSON from fable, should comments be allowed or lead to an
* exception? Value is controlled by `PARSE_JSON_WITH_COMMENTS` define.
* Default value is true.
*
* This does not automatically apply to use of `Json::parse`. Instead you
* should use the parse_json helper function defined in this file.
*/
extern bool NLOHMANN_JSON_ALLOW_COMMENTS;

/**
* When parsing JSON from fable, should exceptions be used?
* Default value is set by `PARSE_JSON_WITH_COMMENTS` define.
*
* This is here for completeness. The fable library will not work
* correctly if exceptions are disabled, so this should always be set to true.
*/
extern bool NLOHMANN_JSON_USE_EXCEPTIONS;

/**
* The Json type maps to nlohmann::json.
*
Expand Down Expand Up @@ -75,6 +94,19 @@ using JsonType = Json::value_t;
*/
std::string to_string(JsonType);

/**
* Return the result of Json::parse, with the options to use exceptions and
* allow comments as set in this library, from NLOHMANN_JSON_USE_EXCEPTIONS and
* NLOHMANN_JSON_ALLOW_COMMENTS.
*
* See the documentation on each of these global variables for more details.
*/
template <typename InputType>
inline Json parse_json(InputType&& input) {
return Json::parse(std::forward<InputType>(input), nullptr, NLOHMANN_JSON_USE_EXCEPTIONS,
NLOHMANN_JSON_ALLOW_COMMENTS);
}

} // namespace fable

#endif // FABLE_JSON_HPP_
14 changes: 7 additions & 7 deletions fable/include/fable/utility/gtest.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ inline void assert_schema_eq(const Confable& x, const Json& expect) {
}

inline void assert_schema_eq(const Confable& x, const char expect[]) {
assert_eq(x.schema().json_schema(), Json::parse(expect));
assert_eq(x.schema().json_schema(), parse_json(expect));
}

inline void assert_validate(const Confable& x, const Conf& input) {
Expand All @@ -60,15 +60,15 @@ inline void assert_validate(const Confable& x, const Conf& input) {
}

inline void assert_validate(const Confable& x, const char json_input[]) {
assert_validate(x, Conf{Json::parse(json_input)});
assert_validate(x, Conf{parse_json(json_input)});
}

inline void assert_invalidate(const Confable& x, const Conf& input) {
ASSERT_THROW(x.schema().validate(input), SchemaError);
}

inline void assert_invalidate(const Confable& x, const char json_input[]) {
assert_invalidate(x, Conf{Json::parse(json_input)});
assert_invalidate(x, Conf{parse_json(json_input)});
}

template <typename T>
Expand All @@ -78,7 +78,7 @@ inline void assert_to_json(const T& x, const Json& expect) {

template <typename T>
inline void assert_to_json(const T& x, const char json_expect[]) {
assert_to_json(x, Json::parse(json_expect));
assert_to_json(x, parse_json(json_expect));
}

inline void assert_from_conf_throw(Confable& x, const Conf& input) {
Expand All @@ -88,7 +88,7 @@ inline void assert_from_conf_throw(Confable& x, const Conf& input) {
}

inline void assert_from_conf_throw(Confable& x, const char json_input[]) {
assert_from_conf_throw(x, Conf{Json::parse(json_input)});
assert_from_conf_throw(x, Conf{parse_json(json_input)});
}

template <typename T>
Expand All @@ -98,7 +98,7 @@ inline void assert_from_conf(T& x, const Conf& input) {

template <typename T>
inline void assert_from_conf(T& x, const char json_input[]) {
assert_from_conf(x, Conf{Json::parse(json_input)});
assert_from_conf(x, Conf{parse_json(json_input)});
}

template <typename T>
Expand All @@ -109,7 +109,7 @@ inline void assert_from_eq_to(T& x, const Json& identity) {

template <typename T>
inline void assert_from_eq_to(T& x, const char json_input[]) {
assert_from_eq_to(x, Json::parse(json_input));
assert_from_eq_to(x, parse_json(json_input));
}

} // namespace fable
Expand Down
3 changes: 2 additions & 1 deletion fable/src/fable/conf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include <boost/filesystem.hpp> // for path

#include <fable/error.hpp> // for ConfError, WrongType, MissingProperty
#include <fable/json.hpp> // for NLOHMANN_JSON_ALLOW_COMMENTS

namespace fable {

Expand All @@ -39,7 +40,7 @@ Conf::Conf(const std::string& file) : file_(file) {
throw Error("could not open file {}: {}", file, strerror(errno));
}
try {
ifs >> data_;
data_ = parse_json(ifs);
} catch (std::exception& e) {
throw Error("unable to parse file {}: {}", file, e.what());
}
Expand Down
11 changes: 11 additions & 0 deletions fable/src/fable/json.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,23 @@
* \see fable/json.hpp
*/

#ifndef PARSE_JSON_USE_EXCEPTIONS
#define PARSE_JSON_USE_EXCEPTIONS true
#endif

#ifndef PARSE_JSON_WITH_COMMENTS
#define PARSE_JSON_WITH_COMMENTS true
#endif

#include <fable/json.hpp>

#include <string> // for string

namespace fable {

bool NLOHMANN_JSON_USE_EXCEPTIONS = PARSE_JSON_USE_EXCEPTIONS;
bool NLOHMANN_JSON_ALLOW_COMMENTS = PARSE_JSON_WITH_COMMENTS;

std::string to_string(JsonType type) {
switch (type) {
case JsonType::null:
Expand Down
8 changes: 3 additions & 5 deletions fable/src/fable/utility.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,7 @@ Json read_json_from_file(const char* filepath) {
throw std::runtime_error(std::string("could not open file: ") + filepath);
}

Json j;
ifs >> j;
return j;
return parse_json(ifs);
}

Json read_json_from_stdin() {
Expand All @@ -64,7 +62,7 @@ Json read_json_with_interpolation(const std::string& filepath_or_stdin, const En
std::istreambuf_iterator<char> begin(std::cin), end;
std::string s(begin, end);
s = interpolate_vars(s, env);
return Json::parse(s);
return parse_json(s);
} else {
std::ifstream ifs(filepath_or_stdin);
if (ifs.fail()) {
Expand All @@ -73,7 +71,7 @@ Json read_json_with_interpolation(const std::string& filepath_or_stdin, const En
std::istreambuf_iterator<char> begin(ifs), end;
std::string s(begin, end);
s = interpolate_vars(s, env);
return Json::parse(s);
return parse_json(s);
}
}

Expand Down

0 comments on commit b891da9

Please sign in to comment.