7 #ifndef CPPWAMP_INTERNAL_VARIANTDECODING_HPP
8 #define CPPWAMP_INTERNAL_VARIANTDECODING_HPP
15 #include <jsoncons/byte_string.hpp>
16 #include <jsoncons/config/version.hpp>
17 #include <jsoncons/json_visitor.hpp>
18 #include <jsoncons/json_visitor2.hpp>
19 #include <jsoncons/ser_context.hpp>
20 #include <jsoncons/source.hpp>
21 #include <jsoncons/tag_type.hpp>
22 #include "../codec.hpp"
23 #include "../variant.hpp"
26 #define CPPWAMP_JSONCONS_VERSION \
27 (JSONCONS_VERSION_MAJOR * 10000000u + \
28 JSONCONS_VERSION_MINOR * 1000u + \
29 JSONCONS_VERSION_PATCH)
31 #define CPPWAMP_JSONCONS_CURSOR_PROVIDES_SIZE (CPPWAMP_JSONCONS_VERSION > 168007)
40 template <
typename TVisitor>
41 class VariantDecodingVisitorBase :
public TVisitor
44 using string_view_type =
typename TVisitor::string_view_type;
48 contextStack_.clear();
54 const Variant& variant() const & {
return variant_;}
56 Variant&& variant() && {
return std::move(variant_);}
58 bool empty()
const {
return !hasRoot_;}
61 using Tag = jsoncons::semantic_tag;
62 using Where = jsoncons::ser_context;
65 std::error_code put(T&& value,
const Where& where,
bool isComposite =
false)
67 if (contextStack_.empty())
68 return addRoot(std::forward<T>(value), isComposite);
70 switch (context().variant().typeId())
73 return addArrayElement(std::forward<T>(value), isComposite);
75 return addObjectElement(std::forward<T>(value), isComposite, where);
86 key_ = std::move(key);
87 context().setKeyIsDone();
90 void putStringOrKey(
String&& str,
const Where& where)
92 if (!contextStack_.empty() && context().expectsKey())
93 putKey(std::move(str));
95 put(std::move(str), where);
100 assert(!contextStack_.empty());
101 contextStack_.pop_back();
105 using Base = TVisitor;
106 using ByteStringView = jsoncons::byte_string_view;
117 Variant& variant() {
return *variant_;}
119 bool expectsKey()
const
121 return variant_->is<
Object>() && !keyIsDone_;
124 bool keyIsDone()
const {
return keyIsDone_;}
126 void setKeyIsDone(
bool done =
true) {keyIsDone_ = done;}
129 Variant* variant_ =
nullptr;
130 bool keyIsDone_ =
false;
133 static std::string makeErrorMessage(std::string what,
const Where& where)
135 what +=
" at column ";
136 what += std::to_string(where.column());
138 what += std::to_string(where.line());
139 what +=
", position ";
140 what += std::to_string(where.position());
144 template <
typename T>
145 std::error_code putInteger(T integer,
const Where& where)
150 template <
typename T>
151 std::error_code addRoot(T&& value,
bool isComposite)
153 variant_ = std::forward<T>(value);
156 contextStack_.push_back(variant_);
160 template <
typename T>
161 std::error_code addArrayElement(T&& value,
bool isComposite)
163 auto&
array = context().variant().template as<TypeId::array>();
164 array.push_back(std::forward<T>(value));
166 contextStack_.push_back(
array.back());
170 template <
typename T>
171 std::error_code addObjectElement(T&& value,
bool isComposite,
174 auto& ctx = context();
175 if (!ctx.keyIsDone())
178 Variant* newElement =
nullptr;
179 auto&
object = ctx.variant().template as<TypeId::object>();
180 auto found =
object.find(key_);
181 if (found ==
object.end())
183 auto result =
object.emplace(std::move(key_),
184 std::forward<T>(value));
185 newElement = &(result.first->second);
189 found->second = std::forward<T>(value);
190 newElement = &(found->second);
192 ctx.setKeyIsDone(
false);
194 contextStack_.push_back(*newElement);
201 assert(!contextStack_.empty());
202 return contextStack_.back();
209 void visit_flush()
override {}
211 bool visit_begin_object(Tag,
const Where& where, std::error_code&)
override
213 put(
Object{}, where,
true);
217 bool visit_end_object(
const Where&, std::error_code&)
override
223 bool visit_begin_array(Tag,
const Where& where, std::error_code&)
override
225 put(
Array{}, where,
true);
229 bool visit_begin_array(std::size_t length, Tag,
const Where& where,
230 std::error_code&)
override
235 put(std::move(a), where,
true);
239 bool visit_end_array(
const Where&, std::error_code&)
override
245 bool visit_null(Tag,
const Where& where, std::error_code& ec)
override
247 ec = put(
null, where);
251 bool visit_bool(
bool value, Tag,
const Where& where,
252 std::error_code& ec)
override
254 ec = put(value, where);
258 bool visit_byte_string(
const ByteStringView& bsv, Tag,
const Where& where,
259 std::error_code& ec)
override
261 ec = put(Blob(
Blob::Data(bsv.begin(), bsv.end())), where);
265 bool visit_uint64(uint64_t n, Tag,
const Where& where,
266 std::error_code& ec)
override
268 if (n <= std::numeric_limits<Variant::Int>::max())
269 ec = putInteger(n, where);
275 bool visit_int64(int64_t n, Tag,
const Where& where,
276 std::error_code& ec)
override
278 ec = putInteger(n, where);
282 bool visit_double(
double x, Tag,
const Where& where,
283 std::error_code& ec)
override
289 std::vector<Context> contextStack_;
292 bool hasRoot_ =
false;
296 class VariantJsonDecodingVisitor :
297 public VariantDecodingVisitorBase<jsoncons::json_visitor>
300 bool visit_key(
const string_view_type& name,
const Where&,
301 std::error_code&)
override
303 putKey(
String(name.data(), name.size()));
307 bool visit_string(
const string_view_type& sv, Tag,
const Where& where,
308 std::error_code& ec)
override
310 if ( (sv.size() > 0) && (sv[0] ==
'\0') )
315 put(Blob(std::move(bytes)), where);
318 put(
String(sv.data(), sv.size()), where);
324 class VariantDecodingVisitor :
325 public VariantDecodingVisitorBase<jsoncons::json_visitor2>
328 bool visit_string(
const string_view_type& sv, Tag,
const Where& where,
329 std::error_code&)
override
331 putStringOrKey(
String(sv.data(), sv.size()), where);
337 template <
typename TConfig>
341 template <
typename... TArgs>
342 explicit GenericDecoder(std::string codecName, TArgs&&... inputStubArgs)
343 : inputStub_(std::forward<TArgs>(inputStubArgs)...),
345 codecName_(std::move(codecName))
348 template <
typename TSourceable>
349 std::error_code
decode(TSourceable&& input, Variant& variant)
351 Source source(std::forward<TSourceable>(input));
352 parser_.reset(std::move(source));
355 parser_.parse(visitor_, ec);
357 variant = std::move(visitor_).variant();
363 using Input =
typename TConfig::Input;
364 using Source =
typename TConfig::Source;
365 using Parser =
typename TConfig::Parser;
366 using Visitor = internal::VariantDecodingVisitor;
377 std::string codecName_;
384 #endif // CPPWAMP_INTERNAL_VARIANTDECODING_HPP