12#ifndef GMP_SERIALIZATION_JSON_HPP_
13#define GMP_SERIALIZATION_JSON_HPP_
26#include <gmp/serialization/detail/text.hpp>
27#include <gmp/serialization/detail/write_value.hpp>
36 json_parser(std::string_view
input, json_read_options options)
37 : input_(
input), options_(options) {}
40 if (input_.size() > options_.max_input_size) {
42 "JSON input exceeds the configured size limit");
45 auto value = parse_value(0);
52 "unexpected characters after the JSON value");
59 return position_ >= input_.size();
63 return at_end() ?
'\0' : input_[position_];
72 const char c = peek();
73 if (
c !=
' ' &&
c !=
'\t' &&
c !=
'\n' &&
c !=
'\r') {
80 bool consume(
char expected)
noexcept {
88 bool consume_literal(std::string_view
literal)
noexcept {
98 const auto start = position_;
99 auto value = parse_value_impl(
depth);
101 value->source_offset(
start);
107 if (
depth > options_.max_depth) {
112 if (!consume_literal(
"null")) {
115 return serialization_value(
nullptr);
117 if (!consume_literal(
"true")) {
120 return serialization_value(
true);
122 if (!consume_literal(
"false")) {
125 return serialization_value(
false);
127 auto string = parse_string();
129 return string.error();
131 return serialization_value(std::move(*
string));
134 if (
depth >= options_.max_depth) {
136 "maximum JSON nesting depth exceeded");
138 return parse_array(
depth + 1);
140 if (
depth >= options_.max_depth) {
142 "maximum JSON nesting depth exceeded");
144 return parse_object(
depth + 1);
146 if (peek() ==
'-' || (peek() >=
'0' && peek() <=
'9')) {
147 return parse_number();
161 return serialization_value(std::move(
array));
164 if (
array.size() >= options_.max_container_size) {
166 "JSON array exceeds the configured size limit");
182 return serialization_value(std::move(
array));
190 return serialization_value(std::move(
object));
193 if (
object.size() >= options_.max_container_size) {
195 "JSON object exceeds the configured size limit");
200 auto key = parse_string();
208 auto value = parse_value(
depth);
210 return value.error();
212 object.emplace_back(std::move(*key), std::move(*value));
222 return serialization_value(std::move(
object));
226 if (input_.size() - position_ < 4) {
229 std::uint32_t value = 0;
230 for (
unsigned i = 0;
i < 4; ++
i) {
231 const char c = input_[position_++];
233 if (
c >=
'0' &&
c <=
'9') {
234 value |=
static_cast<std::uint32_t
>(
c -
'0');
235 }
else if (
c >=
'a' &&
c <=
'f') {
236 value |=
static_cast<std::uint32_t
>(
c -
'a' + 10);
237 }
else if (
c >=
'A' &&
c <=
'F') {
238 value |=
static_cast<std::uint32_t
>(
c -
'A' + 10);
250 const unsigned char c =
static_cast<unsigned char>(input_[position_++]);
261 output.push_back(
static_cast<char>(
c));
266 switch (input_[position_++]) {
292 auto first = parse_hex4();
294 return first.error();
298 if (!consume(
'\\') || !consume(
'u')) {
300 "high surrogate must be followed by a low surrogate");
302 auto second = parse_hex4();
320 if (
output.size() > options_.max_string_size) {
322 "JSON string exceeds the configured size limit");
329 const std::size_t
start = position_;
332 if (peek() >=
'0' && peek() <=
'9') {
336 if (peek() <
'1' || peek() >
'9') {
339 while (peek() >=
'0' && peek() <=
'9') {
346 if (peek() <
'0' || peek() >
'9') {
349 while (peek() >=
'0' && peek() <=
'9') {
353 if (peek() ==
'e' || peek() ==
'E') {
356 if (peek() ==
'+' || peek() ==
'-') {
359 if (peek() <
'0' || peek() >
'9') {
362 while (peek() >=
'0' && peek() <=
'9') {
373 return serialization_value(
integer);
379 return serialization_value(
integer);
386 std::chars_format::general);
388 !std::isfinite(number)) {
391 return serialization_value(number);
394 std::string_view input_;
395 json_read_options options_;
396 std::size_t position_ = 0;
399inline serialization_result<void> append_json_string(std::string &
output, std::string_view
string,
405 for (
const unsigned char c :
string) {
406 const std::size_t
width =
407 c ==
'"' ||
c ==
'\\' ||
c ==
'\b' ||
c ==
'\f' ||
c ==
'\n' ||
c ==
'\r' ||
c ==
'\t' ? 2
412 "JSON output exceeds configured limit");
418 "JSON output exceeds configured limit");
421 constexpr char hex[] =
"0123456789abcdef";
423 for (
const unsigned char c :
string) {
452 output.push_back(
static_cast<char>(
c));
462 explicit json_writer(json_write_options options = {}) : options_(options) {}
464 serialization_result<void> write_null() {
465 return scalar(
"null");
468 serialization_result<void> write_bool(
bool v) {
469 return scalar(
v ?
"true" :
"false");
472 serialization_result<void> write_signed(std::int64_t
v) {
476 serialization_result<void> write_unsigned(std::uint64_t
v) {
480 serialization_result<void> write_floating(
double v) {
481 if (!std::isfinite(
v)) {
483 "non-finite number cannot be represented");
486 auto c = std::to_chars(
b,
b +
sizeof(
b),
v, std::chars_format::general,
487 std::numeric_limits<double>::max_digits10);
488 if (
c.ec != std::errc{}) {
490 "failed to format floating point value");
492 auto s = before_value();
496 return append(std::string_view(
b,
static_cast<std::size_t
>(
c.ptr -
b)));
499 serialization_result<void> write_string(std::string_view
v) {
500 auto s = before_value();
504 return append_json_string(output_,
v, options_.max_output_size);
507 serialization_result<void> begin_array(std::size_t) {
511 serialization_result<void> end_array() {
515 serialization_result<void> begin_object(std::size_t) {
519 serialization_result<void> write_key(std::string_view key) {
520 if (stack_.empty() || !stack_.back().object || stack_.back().expecting_value) {
522 "object key in invalid archive state");
524 auto &
f = stack_.back();
525 serialization_result<void>
s;
526 if (
f.count && !(
s = append_char(
','))) {
529 if (options_.pretty) {
530 if (!(
s = append_char(
'\n')) || !(
s = append_indent(stack_.size()))) {
534 if (!(
s = append_json_string(output_, key, options_.max_output_size))) {
537 if (!(
s = append(options_.pretty ?
": " :
":"))) {
541 f.expecting_value =
true;
545 serialization_result<void> end_object() {
552 "JSON archive is already finished");
554 if (!stack_.empty() || !has_root_) {
558 return std::move(output_);
564 std::size_t count = 0;
565 bool expecting_value =
false;
568 serialization_result<void> before_value() {
571 "JSON archive is already finished");
573 if (stack_.empty()) {
580 auto &
f = stack_.back();
582 if (!
f.expecting_value) {
584 "object value without key");
586 f.expecting_value =
false;
588 serialization_result<void>
s;
589 if (
f.count && !(
s = append_char(
','))) {
592 if (options_.pretty) {
593 if (!(
s = append_char(
'\n')) || !(
s = append_indent(stack_.size()))) {
602 serialization_result<void> begin(
bool object) {
603 if (stack_.size() >= options_.max_depth) {
605 "maximum JSON output depth exceeded");
607 auto s = before_value();
611 if (!(
s = append_char(
object ?
'{' :
'['))) {
614 stack_.push_back({
object});
618 serialization_result<void> end(
bool object) {
619 if (stack_.empty() || stack_.back().object !=
object || stack_.back().expecting_value) {
621 "mismatched JSON archive end");
623 auto f = stack_.back();
625 serialization_result<void>
s;
626 if (options_.pretty &&
f.count) {
627 if (!(
s = append_char(
'\n')) || !(
s = append_indent(stack_.size()))) {
631 return append_char(
object ?
'}' :
']');
634 serialization_result<void> scalar(std::string_view
text) {
635 auto s = before_value();
642 template <
typename I> serialization_result<void> number(
I v) {
644 auto c = std::to_chars(
b,
b +
sizeof(
b),
v);
645 if (
c.ec != std::errc{}) {
647 "failed to format integer");
649 auto s = before_value();
653 return append(std::string_view(
b,
static_cast<std::size_t
>(
c.ptr -
b)));
656 serialization_result<void> append(std::string_view
text) {
657 if (output_.size() > options_.max_output_size ||
658 text.size() > options_.max_output_size - output_.size()) {
660 "JSON output exceeds configured limit");
662 output_.append(
text);
666 serialization_result<void> append_char(
char value) {
667 return append(std::string_view(&value, 1));
670 serialization_result<void> append_indent(std::size_t
depth) {
671 if (output_.size() > options_.max_output_size) {
673 "JSON output exceeds configured limit");
676 options_.max_output_size >= output_.size() ? options_.max_output_size - output_.size() : 0;
679 "JSON output exceeds configured limit");
681 output_.append(
depth * options_.indent_width,
' ');
685 json_write_options options_;
687 std::vector<frame> stack_;
688 bool has_root_ =
false;
689 bool finished_ =
false;
696 return detail::json_parser(
input, options).parse();
701 detail::json_writer
writer(options);
702 auto s = detail::write_serialization_value(
writer, value);
711 json_write_options
json = {}) {
724 json_read_options
json = {}) {
727 return value.error();
734 json_write_options
json = {}) {
737 throw serialization_exception(
r.error());
739 return std::move(*
r);
744 json_read_options
json = {}) {
747 throw serialization_exception(
r.error());
749 return std::move(*
r);
std::vector< std::pair< std::string, serialization_value > > object
std::vector< serialization_value > array
serialization_result< std::string > write_json(const serialization_value &value, json_write_options options={})
serialization_error make_serialization_error(serialization_errc code, std::string message, std::string path={}, std::size_t offset=serialization_error::unknown_offset)
std::string to_json_or_throw(const T &value, serialization_options serialization={}, json_write_options json={})
serialization_result< serialization_value > parse_json(std::string_view input, json_read_options options={})
serialization_result< T > from_json(std::string_view input, deserialization_options deserialization={}, json_read_options json={})
serialization_result< std::string > to_json(const T &value, serialization_options serialization={}, json_write_options json={})
T from_json_or_throw(std::string_view input, deserialization_options deserialization={}, json_read_options json={})