JSON Voorhees
Killer JSON for C++
Loading...
Searching...
No Matches
parse.hpp
Go to the documentation of this file.
1/// \file jsonv/parse.hpp
2///
3/// Copyright (c) 2012-2020 by Travis Gockel. All rights reserved.
4///
5/// This program is free software: you can redistribute it and/or modify it under the terms of the Apache License
6/// as published by the Apache Software Foundation, either version 2 of the License, or (at your option) any later
7/// version.
8///
9/// \author Travis Gockel (travis@gockelhut.com)
10#pragma once
11
12#include <jsonv/config.hpp>
13#include <optional>
14#include <string_view>
15#include <jsonv/value.hpp>
16
17#include <cstddef>
18#include <stdexcept>
19
20namespace jsonv
21{
22
23class deserialize_options;
24
25/// An error encountered when parsing.
26///
27/// \see parse
29 public std::runtime_error
30{
31public:
32 /// \{
33
34 /// Create an error with the given \a message and optional \a character location.
35 explicit parse_error(const char* message, std::optional<std::size_t> character) noexcept;
36 explicit parse_error(const char* message) noexcept;
37 /// \}
38
39 virtual ~parse_error() noexcept;
40
41 /// Get the character location of the encountered error.
43 const std::optional<std::size_t>& character() const { return _character; }
44
45private:
46 std::optional<std::size_t> _character;
47};
48
49/// Get a string representation of a \c parse_error.
50JSONV_PUBLIC std::ostream& operator<<(std::ostream& os, const parse_error& p);
51
52/// Get a string representation of a \c parse_error.
54
55/// Configuration for various parsing options. All parse functions should take in a \c parse_options as a parameter and
56/// should respect your settings.
58{
59public:
60 using size_type = value::size_type;
61
62 /** The encoding format for strings. **/
63 enum class encoding
64 {
65 /// Default UTF-8 encoding scheme. Strings must be well-formed UTF-8 as Unicode defines it, which is the same
66 /// as RFC 3629: every sequence is at most 4 bytes long and is the shortest encoding of its codepoint, and no
67 /// codepoint is a UTF-16 surrogate (U+D800 through U+DFFF) or above U+10FFFF. A string which breaks any of
68 /// these is a \c parse_error, as is an escape sequence naming an unpaired surrogate.
69 ///
70 /// \see http://www.unicode.org/versions/Unicode6.2.0/ch03.pdf#G7404
71 utf8,
72 /// Like \c utf8, but also reject unprintable ASCII characters in strings (see \c std::isprint). Where \c utf8
73 /// accepts a raw \c tab or \c newline character inside a string, this mode rejects it. UTF-8 validation is
74 /// identical in both modes -- the extra strictness is about ASCII control characters only.
75 utf8_strict,
76 };
77
78 struct k final
79 {
80 /// The absolute maximum structure depth to parse, which is the upper allowable limit for
81 /// \c parse_options::max_structure_depth(). This is a fixed limit of the library: the parser keeps its stack
82 /// of open structures at this size, so it is written into the header rather than left for a consumer to
83 /// define differently from the library it links. Use \c parse_options::max_structure_depth() to lower the
84 /// limit for a single parse.
85 static constexpr size_type max_structure_depth = 128;
86 };
87
88public:
89 /// Create an instance with the default options.
91
92 /// Create a parser with the default options -- this is the same result as the default constructor, but might be
93 /// helpful if you like to be more explicit.
96
97 /// Create a strict parser. In general, these options are meant to fail on anything that is not a 100% valid JSON
98 /// document. More specifically:
99 ///
100 /// \code
101 /// string_encoding() == encoding::utf8_strict
102 /// max_structure_depth() == 20
103 /// require_document() == true
104 /// comments() == false
105 /// \endcode
108
109 /// \{
110
111 /// The output encoding for multi-byte characters in strings. The default value is \c encoding::utf8.
113 encoding string_encoding() const { return _string_encoding; }
115 /// \}
116
117 /// \{
118
119 /// The maximum allowed nesting depth of any structure in the JSON document. RFC 8259 lets each implementation
120 /// choose its own nesting limit, so a document that is valid JSON can still be rejected by a low value. By default,
121 /// the value is \c nullopt, which means implementations should limit structure depth to
122 /// \c k::max_structure_depth. Setting \a depth to a value above \c k::max_structure_depth will cause
123 /// \c std::invalid_argument to be thrown from \c parse functions.
125 std::optional<size_type> max_structure_depth() const { return _max_struct_depth; }
126 parse_options& max_structure_depth(std::optional<size_type> depth);
127 /// \}
128
129 /// \{
130
131 /// If set to true, the result of a parse is required to have \c kind of \c kind::object or \c kind::array. By
132 /// default, this is turned off, which will allow \c parse to return values with \c kind::string or
133 /// \c kind::integer.
135 bool require_document() const { return _require_document; }
137 /// \}
138
139 /// \{
140
141 /// Are JSON comments allowed? While there is no official syntax for JSON comments, this uses the de-facto standard
142 /// of ECMAScript-style block comments: `/* comment */`. If this is enabled, comments are treated exactly like
143 /// whitespace. This is off by default, since RFC 8259 has no comments and a conforming parser rejects them; turn
144 /// it on for configuration files and other input written in that dialect.
146 bool comments() const { return _comments; }
148 /// \}
149
150private:
151 // For the purposes of ABI compliance, most modifications to the variables in this class should bump the minor
152 // version number.
153 encoding _string_encoding = encoding::utf8;
154 std::optional<size_type> _max_struct_depth = std::nullopt;
155 bool _require_document = false;
156 bool _comments = false;
157};
158
159/// \{
160
161/// Construct a JSON value from the given \a input.
162///
163/// \code
164/// jsonv::value out = jsonv::parse(R"( { "a": 1, "b": [ 2, 3, 4 ] } )");
165/// \endcode
166///
167/// \a parse_options controls parsing -- the indexing of source text into an AST -- and is \c
168/// parse_options::create_default() where not given. \a deserialize_options controls extraction -- transforming the AST
169/// into a \c jsonv::value -- and is \c deserialize_options::create_default() where not given.
170///
171/// An integer literal beyond the range of 64 bits is read as the nearest \c double, so it is a \c kind::decimal. One
172/// from 2^63 through 2^64-1 keeps its bits and reads back as a negative \c kind::integer (see
173/// \c ast_node::integer::value).
174///
175/// \throws parse_error if the source text is invalid JSON. This is thrown for errors like unterminated strings, arrays,
176/// or stray literals. Errors of this category are described as an offset into \a input. Input which holds no value
177/// is an error of this category, too: empty input, input of only whitespace and -- with \c parse_options::comments --
178/// input of only comments all report the input ending unexpectedly, at its end.
179/// \throws deserialization_error if the AST can not be transformed into a \c jsonv::value. This is thrown for errors
180/// like an object with duplicate keys (note that \c replace, the default \c
181/// deserialize_options::on_duplicate_key, does not throw for this case).
182/// \throws std::invalid_argument if a number literal has no finite \c double to round to, such as \c 1e400.
184value parse(std::string_view input,
187 );
188
189JSONV_NODISCARD JSONV_PUBLIC value parse(std::string_view input);
192/// \}
193
194/// \{
195
196/// Reads a JSON value from the \a input stream. For example, to parse JSON from a file:
197///
198/// \code
199/// std::ifstream file("file.json");
200/// jsonv::value out = parse(file);
201/// \endcode
202///
203/// \a parse_options controls parsing -- the indexing of source text into an AST -- and is \c
204/// parse_options::create_default() where not given. \a deserialize_options controls extraction -- transforming the AST
205/// into a \c jsonv::value -- and is \c deserialize_options::create_default() where not given.
206///
207/// An integer literal beyond the range of 64 bits is read as the nearest \c double, so it is a \c kind::decimal. One
208/// from 2^63 through 2^64-1 keeps its bits and reads back as a negative \c kind::integer (see
209/// \c ast_node::integer::value).
210///
211/// \throws parse_error if the source text is invalid JSON. This is thrown for errors like unterminated strings, arrays,
212/// or stray literals. Errors of this category are described as an offset into \a input. Input which holds no value
213/// is an error of this category, too: empty input, input of only whitespace and -- with \c parse_options::comments --
214/// input of only comments all report the input ending unexpectedly, at its end.
215/// \throws deserialization_error if the AST can not be transformed into a \c jsonv::value. This is thrown for errors
216/// like an object with duplicate keys (note that \c replace, the default \c
217/// deserialize_options::on_duplicate_key, does not throw for this case).
218/// \throws std::invalid_argument if a number literal has no finite \c double to round to, such as \c 1e400.
220value parse(std::istream& input,
223 );
224
228/// \}
229
230/// \{
231
232/// Read a JSON value from the string bound by `[begin, end)`.
234value parse(const char* begin,
235 const char* end,
238 );
239JSONV_NODISCARD JSONV_PUBLIC value parse(const char* begin, const char* end, const parse_options& parse_options);
241 const char* end,
243 );
244JSONV_NODISCARD JSONV_PUBLIC value parse(const char* begin, const char* end);
245/// \}
246
247}
Configuration for various deserialization options. This becomes part of the deserialization_context.
An error encountered when parsing.
Definition parse.hpp:30
parse_error(const char *message) noexcept
Create an error with the given message and optional character location.
parse_error(const char *message, std::optional< std::size_t > character) noexcept
Create an error with the given message and optional character location.
Configuration for various parsing options.
Definition parse.hpp:58
encoding string_encoding() const
The output encoding for multi-byte characters in strings. The default value is encoding::utf8.
Definition parse.hpp:113
bool require_document() const
If set to true, the result of a parse is required to have kind of kind::object or kind::array.
Definition parse.hpp:135
static parse_options create_strict()
Create a strict parser.
bool comments() const
Are JSON comments allowed? While there is no official syntax for JSON comments, this uses the de-fact...
Definition parse.hpp:146
parse_options & max_structure_depth(std::optional< size_type > depth)
The maximum allowed nesting depth of any structure in the JSON document.
parse_options & comments(bool)
Are JSON comments allowed? While there is no official syntax for JSON comments, this uses the de-fact...
std::optional< size_type > max_structure_depth() const
The maximum allowed nesting depth of any structure in the JSON document.
Definition parse.hpp:125
parse_options()
Create an instance with the default options.
static parse_options create_default()
Create a parser with the default options – this is the same result as the default constructor,...
parse_options & string_encoding(encoding)
The output encoding for multi-byte characters in strings. The default value is encoding::utf8.
encoding
The encoding format for strings.
Definition parse.hpp:64
parse_options & require_document(bool)
If set to true, the result of a parse is required to have kind of kind::object or kind::array.
Represents a single JSON value, which can be any one of a potential kind, each behaving slightly diff...
Definition value.hpp:113
Copyright (c) 2014-2020 by Travis Gockel.
#define JSONV_NODISCARD
Warn if the caller discards the result of this function.
Definition config.hpp:143
#define JSONV_PUBLIC
This function or class is part of the public API for JSON Voorhees.
Definition config.hpp:124
JSONV_PUBLIC std::string to_string(const ast_node_type &type)
Get what operator<< writes for type as a std::string.
STL namespace.
typename detail::optional_type< T >::type optional
Represents a value that may or may not be present.
Definition optional.hpp:239
JSONV_PUBLIC value parse(std::string_view input, const parse_options &parse_options, const deserialize_options &deserialize_options)
Construct a JSON value from the given input.
Copyright (c) 2012-2020 by Travis Gockel.