]>
Commit | Line | Data |
---|---|---|
20effc67 TL |
1 | // |
2 | // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) | |
3 | // | |
4 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | |
5 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
6 | // | |
7 | // Official repository: https://github.com/boostorg/json | |
8 | // | |
9 | ||
10 | #include <boost/json/monotonic_resource.hpp> | |
11 | #include <boost/json/null_resource.hpp> | |
12 | #include <boost/json/parse.hpp> | |
13 | #include <boost/json/parser.hpp> | |
14 | #include <boost/json/static_resource.hpp> | |
15 | #include <boost/json/stream_parser.hpp> | |
16 | ||
17 | #include <iostream> | |
18 | #include <string> | |
19 | ||
20 | #include "test_suite.hpp" | |
21 | ||
22 | BOOST_JSON_NS_BEGIN | |
23 | ||
24 | //---------------------------------------------------------- | |
25 | ||
26 | static void set1() { | |
27 | ||
28 | //---------------------------------------------------------- | |
29 | { | |
30 | //[doc_parsing_1 | |
31 | value jv = parse( "[1,2,3,4,5]" ); | |
32 | //] | |
33 | } | |
34 | //---------------------------------------------------------- | |
35 | { | |
36 | //[doc_parsing_2 | |
37 | error_code ec; | |
38 | value jv = parse( "[1,2,3,4,5]", ec ); | |
39 | if( ec ) | |
40 | std::cout << "Parsing failed: " << ec.message() << "\n"; | |
41 | //] | |
42 | } | |
43 | //---------------------------------------------------------- | |
44 | { | |
45 | //[doc_parsing_3 | |
46 | try | |
47 | { | |
48 | error_code ec; | |
49 | value jv = parse( "[1,2,3,4,5]", ec ); | |
50 | if( ec ) | |
51 | std::cout << "Parsing failed: " << ec.message() << "\n"; | |
52 | } | |
53 | catch( std::bad_alloc const& e) | |
54 | { | |
55 | std::cout << "Parsing failed: " << e.what() << "\n"; | |
56 | } | |
57 | //] | |
58 | } | |
59 | //---------------------------------------------------------- | |
60 | { | |
61 | //[doc_parsing_4 | |
62 | { | |
63 | monotonic_resource mr; | |
64 | ||
65 | value const jv = parse( "[1,2,3,4,5]", &mr ); | |
66 | } | |
67 | //] | |
68 | } | |
69 | //---------------------------------------------------------- | |
70 | { | |
71 | //[doc_parsing_5 | |
72 | parse_options opt; // all extensions default to off | |
73 | opt.allow_comments = true; // permit C and C++ style comments to appear in whitespace | |
74 | opt.allow_trailing_commas = true; // allow an additional trailing comma in object and array element lists | |
75 | opt.allow_invalid_utf8 = true; // skip utf-8 validation of keys and strings | |
76 | ||
77 | value jv = parse( "[1,2,3,] // comment ", storage_ptr(), opt ); | |
78 | //] | |
79 | } | |
80 | //---------------------------------------------------------- | |
81 | { | |
82 | #if __cpp_designated_initializers >= 201707L | |
83 | //[doc_parsing_6 | |
84 | value jv = parse( "[1,2,3,] // comment ", storage_ptr(), | |
1e59de90 | 85 | { |
20effc67 TL |
86 | .allow_comments = true, // permit C and C++ style comments to appear in whitespace |
87 | .allow_trailing_commas = true, // allow a trailing comma in object and array lists | |
88 | .allow_invalid_utf8 = true // skip utf-8 validation of keys and strings | |
89 | }); | |
90 | //] | |
91 | #endif | |
92 | } | |
93 | //---------------------------------------------------------- | |
94 | ||
95 | } // set1 | |
96 | ||
97 | //---------------------------------------------------------- | |
98 | //[doc_parsing_7 | |
99 | class connection | |
100 | { | |
101 | parser p_; // persistent data member | |
102 | ||
103 | public: | |
104 | void do_read( string_view s ) // called for each complete message from the network | |
105 | { | |
106 | p_.reset(); // start parsing a new JSON using the default resource | |
107 | p_.write( s ); // parse the buffer, using exceptions to indicate error | |
108 | do_rpc( p_.release() ); // process the command | |
109 | } | |
110 | ||
111 | void do_rpc( value jv ); | |
112 | }; | |
113 | //] | |
114 | ||
115 | //---------------------------------------------------------- | |
116 | ||
117 | static void set2() { | |
118 | ||
119 | //---------------------------------------------------------- | |
120 | { | |
121 | //[doc_parsing_8 | |
122 | stream_parser p; | |
123 | error_code ec; | |
124 | string_view s = "[1,2,3] %HOME%"; | |
125 | std::size_t n = p.write_some( s, ec ); | |
126 | assert( ! ec && p.done() && n == 8 ); | |
127 | s = s.substr( n ); | |
128 | value jv = p.release(); | |
129 | assert( s == "%HOME%" ); | |
130 | //] | |
131 | } | |
132 | //---------------------------------------------------------- | |
133 | { | |
134 | //[doc_parsing_9 | |
135 | parse_options opt; // All extensions default to off | |
136 | opt.allow_comments = true; // Permit C and C++ style comments to appear in whitespace | |
137 | opt.allow_trailing_commas = true; // Allow an additional trailing comma in object and array element lists | |
138 | opt.allow_invalid_utf8 = true; // Skip utf-8 validation of keys and strings | |
1e59de90 | 139 | stream_parser p( storage_ptr(), opt ); // The stream_parser will use the options |
20effc67 TL |
140 | //] |
141 | } | |
142 | //---------------------------------------------------------- | |
143 | ||
144 | } // set2 | |
145 | ||
146 | //---------------------------------------------------------- | |
147 | //[doc_parsing_10 | |
148 | value read_json( std::istream& is, error_code& ec ) | |
149 | { | |
150 | stream_parser p; | |
151 | std::string line; | |
152 | while( std::getline( is, line ) ) | |
153 | { | |
154 | p.write( line, ec ); | |
155 | if( ec ) | |
156 | return nullptr; | |
157 | } | |
158 | p.finish( ec ); | |
159 | if( ec ) | |
160 | return nullptr; | |
161 | return p.release(); | |
162 | } | |
163 | //] | |
164 | ||
165 | //---------------------------------------------------------- | |
166 | ||
167 | static void set3() { | |
168 | ||
169 | //---------------------------------------------------------- | |
170 | { | |
171 | //[doc_parsing_11 | |
172 | { | |
173 | monotonic_resource mr; | |
174 | ||
175 | stream_parser p; | |
176 | p.reset( &mr ); // Use mr for the resulting value | |
177 | p.write( "[1,2,3,4,5]" ); // Parse the input JSON | |
178 | value const jv = p.release(); // Retrieve the result | |
179 | assert( *jv.storage() == mr ); // Same memory resource | |
180 | } | |
181 | //] | |
182 | } | |
183 | //---------------------------------------------------------- | |
184 | { | |
185 | //[doc_parsing_12 | |
186 | unsigned char temp[ 4096 ]; // Declare our buffer | |
187 | stream_parser p( | |
188 | storage_ptr(), // Default memory resource | |
189 | parse_options{}, // Default parse options (strict parsing) | |
190 | temp); // Use our buffer for temporary storage | |
191 | //] | |
192 | } | |
193 | //---------------------------------------------------------- | |
194 | ||
195 | } // set3 | |
196 | ||
197 | //---------------------------------------------------------- | |
198 | ||
199 | //[doc_parsing_13 | |
200 | /* Parse JSON and invoke the handler | |
201 | ||
202 | This function parses the JSON specified in `s` | |
203 | and invokes the handler, whose signature must | |
204 | be equivalent to: | |
205 | ||
206 | void( value const& jv ); | |
207 | ||
208 | The operation is guaranteed not to perform any | |
209 | dynamic memory allocations. However, some | |
210 | implementation-defined upper limits on the size | |
211 | of the input JSON and the size of the resulting | |
212 | value are imposed. | |
213 | ||
214 | Upon error, an exception is thrown. | |
215 | */ | |
216 | template< class Handler > | |
217 | void do_rpc( string_view s, Handler&& handler ) | |
218 | { | |
1e59de90 | 219 | unsigned char temp[ 4096 ]; // The parser will use this storage for its temporary needs |
20effc67 TL |
220 | parser p( // Construct a strict parser using the temp buffer and no dynamic memory |
221 | get_null_resource(), // The null resource never dynamically allocates memory | |
222 | parse_options(), // Default constructed parse options allow only standard JSON | |
223 | temp ); | |
224 | ||
225 | unsigned char buf[ 16384 ]; // Now we need a buffer to hold the actual JSON values | |
226 | static_resource mr2( buf ); // The static resource is monotonic, using only a caller-provided buffer | |
227 | p.reset( &mr2 ); // Use the static resource for producing the value | |
228 | p.write( s ); // Parse the entire string we received from the network client | |
229 | ||
230 | // Retrieve the value and invoke the handler with it. | |
231 | // The value will use `buf` for storage. The handler | |
232 | // must not take ownership, since monotonic resources | |
233 | // are inefficient with mutation. | |
234 | handler( p.release() ); | |
235 | } | |
236 | //] | |
237 | ||
238 | //---------------------------------------------------------- | |
239 | ||
240 | class doc_parsing_test | |
241 | { | |
242 | public: | |
243 | void | |
244 | run() | |
245 | { | |
246 | (void)&set1; | |
247 | (void)&set2; | |
248 | (void)&set3; | |
249 | } | |
250 | }; | |
251 | ||
252 | TEST_SUITE(doc_parsing_test, "boost.json.doc_parsing"); | |
253 | ||
254 | BOOST_JSON_NS_END |