/
reader.hpp
187 lines (156 loc) · 6.37 KB
/
reader.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
#ifndef TRIAL_PROTOCOL_JSON_READER_HPP
#define TRIAL_PROTOCOL_JSON_READER_HPP
///////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015 Bjorn Reese <breese@users.sourceforge.net>
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
///////////////////////////////////////////////////////////////////////////////
#include <string>
#include <stack>
#include <vector>
#include <trial/protocol/json/error.hpp>
#include <trial/protocol/json/token.hpp>
#include <trial/protocol/json/detail/decoder.hpp>
namespace trial
{
namespace protocol
{
namespace json
{
//! @brief Incremental JSON reader.
//!
//! Parse a JSON formatted input buffer incrementally. Incrementally means that
//! the reader only parses enough of the input to identify the next token.
//! The entire input has to be parsed by repeating parsing the next token until
//! the end of the input.
template <typename CharT>
class basic_reader
{
public:
using value_type = typename detail::basic_decoder<CharT>::value_type;
using size_type = typename detail::basic_decoder<CharT>::size_type;
using view_type = core::detail::basic_string_view<CharT, core::char_traits<CharT>>;
basic_reader();
//! @brief Construct an incremental JSON reader.
//!
//! The first token is automatically parsed.
//!
//! The reader does not assume ownership of the view.
//!
//! @param[in] view A string view of a JSON formatted buffer.
basic_reader(const view_type& view);
//! @brief Copy-construct an incremental JSON reader.
//!
//! Copies the internal parsing state from the input reader, and continues
//! parsing independently from where the input reader had reached.
//!
//! @param[in] other The reader that is copied.
basic_reader(const basic_reader& other) = default;
basic_reader(basic_reader&&) = default;
basic_reader& operator=(const basic_reader&) = default;
basic_reader& operator=(basic_reader&&) = default;
//! @brief Parse the next token.
//!
//! @returns false if an error occurred or end-of-input was reached, true otherwise.
bool next();
//! @brief Parse the next token if current token has a given value.
//!
//! @param[in] expect Expected value of current token.
//! @returns false if current token does not have the expected value.
bool next(token::code::value expect);
//! @brief Get the current nesting level.
//!
//! Keep track of the nesting level of containers.
//! The outermost root level is 0.
//!
//! @returns The current nesting level.
size_type level() const noexcept;
//! @brief Get the current token as a detailed code.
//!
//! @returns The code of the current token.
token::code::value code() const noexcept;
//! @brief Get the current token as a symbol.
//!
//! @returns The symbol of the current token.
token::symbol::value symbol() const noexcept;
//! @brief Get the current token as a category.
//!
//! @returns The category of the current token.
token::category::value category() const noexcept;
//! @brief Get the current error.
//!
//! The error code contains an error enumerator. If parsing did not result
//! in an error, the json::no_error enumerator is used.
//!
//! @returns The current error code.
std::error_code error() const noexcept;
//! @brief Converts the current value into ReturnType.
//!
//! The following conversions are valid:
//! -# Convert a symbol::boolean token into bool.
//! -# Convert a symbol::integer token into an integral C++ type (expect bool.)
//! -# Convert a symbol::real token into a floating-point C++ type.
//! -# Convert a symbol::string token into std::string.
//!
//! @returns The converted value.
//! @throws json::error if requested type is incompatible with the current token.
template <typename ReturnType> ReturnType value() const;
//! @brief Converts the current value into T.
//!
//! The following conversions are valid:
//! -# Convert a symbol::boolean token into bool.
//! -# Convert a symbol::integer token into an integral C++ type (expect bool.)
//! -# Convert a symbol::real token into a floating-point C++ type.
//! -# Convert a symbol::string token into std::string.
//!
//! @param[out] output The converted value if no error occurs.
//! @returns json::errc if requested type is incompatible with the current token.
template <typename T> json::errc value(T& output) const noexcept;
//! @brief Collects a converted string.
//!
//! The Collector must implement the following functions:
//! -# push_back(value_type)
//! -# append(const value_type *, size_type)
//!
//! @param[out] collector The object that receives the converted string.
//! @returns json::errc if requested type is incompatible with the current token.
template <typename Collector> json::errc string(Collector& collector) const noexcept;
//! @returns A view of the current value before it is converted into its type.
view_type literal() const noexcept;
//! @returns A view of the remaining buffer.
view_type tail() const noexcept;
#ifndef BOOST_DOXYGEN_INVOKED
protected:
template <typename ReturnType, typename Enable = void>
struct overloader;
bool next_frame();
protected:
using decoder_type = detail::basic_decoder<value_type>;
decoder_type decoder;
struct frame
{
frame(token::null) noexcept;
frame(token::begin_array) noexcept;
frame(token::begin_object) noexcept;
token::code::value (frame::*next)(decoder_type&) noexcept;
private:
token::code::value next_outer(decoder_type&) noexcept;
token::code::value next_array(decoder_type&) noexcept;
token::code::value next_array_value(decoder_type&) noexcept;
token::code::value next_object(decoder_type&) noexcept;
token::code::value next_object_key(decoder_type&) noexcept;
token::code::value next_object_value(decoder_type&) noexcept;
};
std::stack<frame, std::vector<frame>> stack;
#endif
};
using reader = basic_reader<char>;
} // namespace json
} // namespace protocol
} // namespace trial
#include <trial/protocol/json/detail/reader.ipp>
#endif // TRIAL_PROTOCOL_JSON_READER_HPP