Commit c5bb6a65 authored by Dominik Charousset's avatar Dominik Charousset

Allow parsing JSON directly from file

parent edfc54f2
......@@ -682,7 +682,19 @@ const array* empty_array() noexcept;
// -- parsing ------------------------------------------------------------------
// Parses the input and makes a deep copy of all strings.
// Specialization for parsers operating on mutable character sequences.
using mutable_string_parser_state = parser_state<char*>;
// Specialization for parsers operating on files.
using file_parser_state = parser_state<std::istreambuf_iterator<char>>;
// Parses the input string and makes a deep copy of all strings.
value* parse(string_parser_state& ps, monotonic_buffer_resource* storage);
// Parses the input string and makes a deep copy of all strings.
value* parse(file_parser_state& ps, monotonic_buffer_resource* storage);
// Parses the input file and makes a deep copy of all strings.
value* parse(string_parser_state& ps, monotonic_buffer_resource* storage);
// Parses the input and makes a shallow copy of strings whenever possible.
......
......@@ -123,6 +123,17 @@ public:
/// @note Implicitly calls `reset`.
bool load(std::string_view json_text);
/// Parses the content of the file under the given @p path. After loading the
/// content of the JSON file, the reader is ready for attempting to
/// deserialize inspectable objects.
/// @note Implicitly calls `reset`.
bool load_file(const char* path);
/// @copydoc load_file
bool load_file(const std::string& path) {
return load_file(path.c_str());
}
/// Reverts the state of the reader back to where it was after calling `load`.
/// @post The reader is ready for attempting to deserialize another
/// inspectable object.
......
......@@ -134,6 +134,13 @@ public:
/// objects created from that value.
static expected<json_value> parse_in_situ(std::string& str);
/// Attempts to parse the content of the file at @p path as JSON input into a
/// self-contained value.
static expected<json_value> parse_file(const char* path);
/// @copydoc parse_file
static expected<json_value> parse_file(const std::string& path);
// -- printing ---------------------------------------------------------------
template <class Buffer>
......
......@@ -141,7 +141,4 @@ auto make_error(const parser_state<Iterator, Sentinel>& ps, Ts&&... xs)
/// Specialization for parsers operating on string views.
using string_parser_state = parser_state<std::string_view::iterator>;
/// Specialization for parsers operating on mutable character sequences.
using mutable_string_parser_state = parser_state<char*>;
} // namespace caf
This diff is collapsed.
......@@ -8,6 +8,8 @@
#include "caf/detail/print.hpp"
#include "caf/string_algorithms.hpp"
#include <fstream>
namespace {
static constexpr const char class_name[] = "caf::json_reader";
......@@ -150,14 +152,36 @@ bool json_reader::load(std::string_view json_text) {
set_error(make_error(ps));
st_ = nullptr;
return false;
} else {
err_.reset();
detail::monotonic_buffer_resource::allocator<stack_type> alloc{&buf_};
st_ = new (alloc.allocate(1)) stack_type(stack_allocator{&buf_});
st_->reserve(16);
st_->emplace_back(root_);
return true;
}
err_.reset();
detail::monotonic_buffer_resource::allocator<stack_type> alloc{&buf_};
st_ = new (alloc.allocate(1)) stack_type(stack_allocator{&buf_});
st_->reserve(16);
st_->emplace_back(root_);
return true;
}
bool json_reader::load_file(const char* path) {
using iterator_t = std::istreambuf_iterator<char>;
reset();
std::ifstream input{path};
if (!input.is_open()) {
emplace_error(sec::cannot_open_file);
return false;
}
detail::json::file_parser_state ps{iterator_t{input}, iterator_t{}};
root_ = detail::json::parse(ps, &buf_);
if (ps.code != pec::success) {
set_error(make_error(ps));
st_ = nullptr;
return false;
}
err_.reset();
detail::monotonic_buffer_resource::allocator<stack_type> alloc{&buf_};
st_ = new (alloc.allocate(1)) stack_type(stack_allocator{&buf_});
st_->reserve(16);
st_->emplace_back(root_);
return true;
}
void json_reader::revert() {
......
......@@ -10,6 +10,8 @@
#include "caf/make_counted.hpp"
#include "caf/parser_state.hpp"
#include <fstream>
namespace caf {
// -- conversion ---------------------------------------------------------------
......@@ -92,35 +94,49 @@ expected<json_value> json_value::parse(std::string_view str) {
auto storage = make_counted<detail::json::storage>();
string_parser_state ps{str.begin(), str.end()};
auto root = detail::json::parse(ps, &storage->buf);
if (ps.code != pec::success) {
return {make_error(ps)};
} else {
if (ps.code == pec::success)
return {json_value{root, std::move(storage)}};
}
return {make_error(ps)};
}
expected<json_value> json_value::parse_shallow(std::string_view str) {
auto storage = make_counted<detail::json::storage>();
string_parser_state ps{str.begin(), str.end()};
auto root = detail::json::parse_shallow(ps, &storage->buf);
if (ps.code != pec::success) {
return {make_error(ps)};
} else {
if (ps.code == pec::success)
return {json_value{root, std::move(storage)}};
}
return {make_error(ps)};
}
expected<json_value> json_value::parse_in_situ(std::string& str) {
auto storage = make_counted<detail::json::storage>();
mutable_string_parser_state ps{str.data(), str.data() + str.size()};
detail::json::mutable_string_parser_state ps{str.data(),
str.data() + str.size()};
auto root = detail::json::parse_in_situ(ps, &storage->buf);
if (ps.code != pec::success) {
return {make_error(ps)};
} else {
if (ps.code == pec::success)
return {json_value{root, std::move(storage)}};
}
return {make_error(ps)};
}
expected<json_value> json_value::parse_file(const char* path) {
using iterator_t = std::istreambuf_iterator<char>;
std::ifstream input{path};
if (!input.is_open())
return make_error(sec::cannot_open_file);
auto storage = make_counted<detail::json::storage>();
detail::json::file_parser_state ps{iterator_t{input}, iterator_t{}};
auto root = detail::json::parse(ps, &storage->buf);
if (ps.code == pec::success)
return {json_value{root, std::move(storage)}};
return {make_error(ps)};
}
expected<json_value> json_value::parse_file(const std::string& path) {
return parse_file(path.c_str());
}
// -- free functions -----------------------------------------------------------
std::string to_string(const json_value& val) {
std::string result;
val.print_to(result);
......
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