13 #ifndef __STOUT_JSON__
14 #define __STOUT_JSON__
21 #undef __STDC_FORMAT_MACROS
23 #define __STDC_FORMAT_MACROS
30 #include <type_traits>
33 #include <boost/variant.hpp>
96 typename std::enable_if<std::is_floating_point<T>::value,
int>::
type = 0)
102 typename std::enable_if<
103 std::is_integral<T>::value && std::is_signed<T>::value,
107 template <
typename T>
110 typename std::enable_if<
111 std::is_integral<T>::value && std::is_unsigned<T>::value,
115 template <
typename T>
120 return static_cast<T
>(
value);
158 Object(std::initializer_list<std::pair<const std::string, Value>> values_)
178 template <
typename T>
187 template <
typename T>
233 typedef boost::variant<
Null,
236 boost::recursive_wrapper<Object>,
237 boost::recursive_wrapper<Array>,
256 template <
typename T>
259 typename std::enable_if<std::is_arithmetic<T>::value,
int>::
type = 0)
264 template <
typename T>
267 typename std::enable_if<!std::is_arithmetic<T>::value,
int>::
type = 0)
270 template <
typename T>
273 template <
typename T>
306 struct ContainmentComparator :
public boost::static_visitor<bool>
308 explicit ContainmentComparator(
const Value& _self)
311 bool operator()(
const Object& other)
const;
312 bool operator()(
const Array& other)
const;
313 bool operator()(
const String& other)
const;
314 bool operator()(
const Number& other)
const;
315 bool operator()(
const Boolean& other)
const;
316 bool operator()(
const Null&)
const;
324 template <
typename T>
327 const T* t = boost::get<T>(
this);
333 inline bool Value::is<Value>()
const
339 template <
typename T>
342 return *CHECK_NOTNULL(boost::get<T>(
this));
347 inline const Value& Value::as<Value>()
const
353 template <
typename T>
356 const std::vector<std::string> names =
strings::split(path,
".", 2);
362 std::string
name = names[0];
367 size_t index = name.find(
'[');
368 if (index != std::string::npos) {
370 if (name.at(name.length() - 1) !=
']') {
371 return Error(
"Malformed array subscript, expecting ']'");
376 std::string s = name.substr(index + 1, name.length() - index - 2);
382 return Error(
"Failed to numify array subscript '" + s +
"'");
383 }
else if (i.
get() < 0) {
384 return Error(
"Array subscript '" + s +
"' must be >= 0");
390 name = name.substr(0, index);
393 std::map<std::string, Value>::const_iterator entry =
values.find(name);
395 if (entry ==
values.end()) {
399 Value value = entry->second;
404 if (subscript.
get() >= array.
values.size()) {
408 }
else if (value.
is<
Null>()) {
412 return Error(
"Intermediate JSON value not an array");
416 if (names.size() == 1) {
418 return value.
as<T>();
419 }
else if (value.
is<
Null>()) {
423 return Error(
"Found JSON value of wrong type");
429 return Error(
"Intermediate JSON value not an object");
432 return value.
as<
Object>().find<T>(names[1]);
436 template <
typename T>
443 std::map<std::string, Value>::const_iterator entry =
values.find(key);
445 if (entry ==
values.end()) {
449 Value value = entry->second;
451 if (!value.
is<T>()) {
453 return Error(
"Found JSON value of wrong type");
456 return value.
as<T>();
462 return boost::apply_visitor(Value::ContainmentComparator(*
this), other);
466 inline bool Value::ContainmentComparator::operator()(
const Object& other)
const
468 if (!
self.is<Object>()) {
473 if (other.
values.empty()) {
477 const Object& _self =
self.as<Object>();
481 if (other.
values.size() > _self.values.size()) {
486 auto _selfIterator = _self.values.find(key);
488 if (_selfIterator == _self.values.end()) {
492 if (!_selfIterator->second.contains(value)) {
501 inline bool Value::ContainmentComparator::operator()(
const String& other)
const
503 if (!
self.is<String>()) {
506 return self.as<String>().value == other.value;
510 inline bool Value::ContainmentComparator::operator()(
const Number& other)
const
512 if (!
self.is<Number>()) {
526 const Number& number =
self.as<Number>();
527 switch (number.type) {
529 switch (other.type) {
531 return number.value == other.value;
533 return number.value == other.signed_integer;
535 return number.value == other.unsigned_integer;
539 switch (other.type) {
541 return number.signed_integer == other.value;
543 return number.signed_integer == other.signed_integer;
546 return number.signed_integer >= 0 &&
547 number.as<uint64_t>() == other.unsigned_integer;
551 switch (other.type) {
553 return number.unsigned_integer == other.value;
556 return other.signed_integer >= 0 &&
557 number.unsigned_integer == other.as<uint64_t>();
559 return number.unsigned_integer == other.unsigned_integer;
567 inline bool Value::ContainmentComparator::operator()(
const Array& other)
const
569 if (!
self.is<Array>()) {
573 const Array& _self =
self.as<Array>();
575 if (_self.values.size() != other.values.size()) {
579 for (
unsigned i = 0; i < other.values.size(); ++i) {
580 if (!_self.values[i].contains(other.values[i])) {
589 inline bool Value::ContainmentComparator::operator()(
const Boolean& other)
const
591 if (!
self.is<Boolean>()) {
594 return self.as<Boolean>().value == other.value;
598 inline bool Value::ContainmentComparator::operator()(
const Null&)
const
600 return self.is<Null>();
612 return value.as<
Object>().values ==
object.values;
620 return value.as<
String>().value ==
string.value;
629 return Value::ContainmentComparator(value)(other);
634 if (value.is<
Array>()) {
643 return value.as<
Boolean>().value ==
boolean.value;
650 return value.is<
Null>();
660 return boost::apply_visitor(
Comparator(lhs), rhs);
666 return !(lhs == rhs);
696 json(writer,
boolean.value);
702 json(writer,
string.value);
708 switch (number.
type) {
724 json(writer,
object.values);
776 typename std::enable_if<std::is_same<T, Value>::value,
int>
::type = 0>
781 using result_type = void;
783 void operator()(
const Boolean& value)
const
785 json(std::move(writer_), value);
787 void operator()(
const String& value)
const
789 json(std::move(writer_), value);
791 void operator()(
const Number& value)
const
793 json(std::move(writer_), value);
795 void operator()(
const Object& value)
const
797 json(std::move(writer_), value);
799 void operator()(
const Array& value)
const
801 json(std::move(writer_), value);
803 void operator()(
const Null& value)
const
805 json(std::move(writer_), value);
809 } visitor{std::move(writer)};
810 boost::apply_visitor(visitor, value);
816 return stream <<
jsonify(
boolean);
822 return stream <<
jsonify(
string);
828 return stream <<
jsonify(number);
834 return stream <<
jsonify(
object);
840 return stream <<
jsonify(array);
846 return stream <<
jsonify(null);
853 if (value.is<picojson::null>()) {
855 }
else if (value.is<
bool>()) {
856 return Boolean(value.get<
bool>());
857 }
else if (value.is<picojson::value::object>()) {
860 const picojson::value& v,
861 value.get<picojson::value::object>()) {
865 }
else if (value.is<picojson::value::array>()) {
867 foreach (
const picojson::value& v, value.get<picojson::value::array>()) {
871 }
else if (value.is<int64_t>()) {
872 return Number(value.get<int64_t>());
873 }
else if (value.is<
double>()) {
874 return Number(value.get<
double>());
875 }
else if (value.is<std::string>()) {
876 return String(value.get<std::string>());
886 const char* parseBegin = s.c_str();
887 picojson::value value;
893 const char* lastVisibleChar =
898 const char* parseEnd =
901 if (!error.empty()) {
903 }
else if (parseEnd != lastVisibleChar + 1) {
905 "Parsed JSON included non-whitespace trailing characters: "
906 + s.substr(parseEnd - parseBegin, lastVisibleChar + 1 - parseEnd));
913 template <
typename T>
922 if (!value.
get().
is<T>()) {
923 return Error(
"Unexpected JSON type parsed");
926 return value.
get().
as<T>();
938 #endif // __STOUT_JSON__
T as() const
Definition: json.hpp:116
int64_t signed_integer
Definition: json.hpp:148
Value(const T &value, typename std::enable_if< std::is_arithmetic< T >::value, int >::type=0)
Definition: json.hpp:257
const T & as() const
Definition: json.hpp:340
bool operator()(const Null &) const
Definition: json.hpp:648
bool value
Definition: json.hpp:207
Definition: errorbase.hpp:35
bool operator()(const Number &other) const
Definition: json.hpp:625
Boolean()
Definition: json.hpp:205
friend void json(NumberWriter *writer, const Number &number)
Definition: json.hpp:706
Value(char *value)
Definition: json.hpp:250
Definition: jsonify.hpp:450
Definition: jsonify.hpp:179
Type
Definition: json.hpp:134
std::map< std::string, Value > values
Definition: json.hpp:190
Definition: jsonify.hpp:329
Definition: result.hpp:40
Value()
Definition: json.hpp:246
bool isSome() const
Definition: option.hpp:115
Value(bool value)
Definition: json.hpp:248
bool is() const
Definition: json.hpp:325
Result< T > at(const std::string &key) const
Definition: json.hpp:437
double value
Definition: json.hpp:147
void json(BooleanWriter *writer, const Boolean &boolean)
Definition: json.hpp:694
Result< int > index(const std::string &link)
Number(T _value, typename std::enable_if< std::is_integral< T >::value &&std::is_signed< T >::value, int >::type=0)
Definition: json.hpp:100
String(const char *_value)
Definition: json.hpp:78
Array(std::initializer_list< Value > values_)
Definition: json.hpp:197
Number(T _value, typename std::enable_if< std::is_floating_point< T >::value, int >::type=0)
Definition: json.hpp:94
bool operator!=(const Value &lhs, const Value &rhs)
Definition: json.hpp:664
String()
Definition: json.hpp:77
Definition: variant.hpp:47
const std::string WHITESPACE
Definition: strings.hpp:29
Try< ImageManifest > parse(const std::string &value)
Definition: parse.hpp:36
Definition: jsonify.hpp:418
const T & get() const &
Definition: option.hpp:118
#define foreachpair(KEY, VALUE, ELEMS)
Definition: foreach.hpp:51
String(const std::string &_value)
Definition: json.hpp:79
Try< Value > parse(const std::string &s)
Returns the OCI v1 descriptor, image index, image manifest and image configuration from the given str...
Definition: json.hpp:884
std::vector< Value > values
Definition: json.hpp:199
Definition: jsonify.hpp:202
std::ostream & operator<<(std::ostream &stream, const Boolean &boolean)
Definition: json.hpp:814
static Try error(const E &e)
Definition: try.hpp:42
bool operator()(const Object &object) const
Definition: json.hpp:609
JSON::Proxy jsonify(const T &)
Definition: jsonify.hpp:779
#define UNREACHABLE()
Definition: unreachable.hpp:22
Value(const T &value, typename std::enable_if<!std::is_arithmetic< T >::value, int >::type=0)
Definition: json.hpp:265
bool operator==(const Value &lhs, const Value &rhs)
Definition: json.hpp:658
bool isError() const
Definition: try.hpp:71
Number(T _value, typename std::enable_if< std::is_integral< T >::value &&std::is_unsigned< T >::value, int >::type=0)
Definition: json.hpp:108
std::string error(const std::string &msg, uint32_t code)
bool contains(const Value &other) const
Definition: json.hpp:460
Value(const char *value)
Definition: json.hpp:251
False()
Definition: json.hpp:223
Try< uint32_t > type(const std::string &path)
Comparator(const Value &_value)
Definition: json.hpp:606
std::vector< std::string > split(const std::string &s, const std::string &delims, const Option< size_t > &maxTokens=None())
Definition: strings.hpp:183
bool operator()(const Array &array) const
Definition: json.hpp:632
bool operator()(const Boolean &boolean) const
Definition: json.hpp:640
bool operator()(const String &string) const
Definition: json.hpp:617
boost::variant< Null, String, Number, boost::recursive_wrapper< Object >, boost::recursive_wrapper< Array >, Boolean > Variant
Definition: json.hpp:238
Number()
Definition: json.hpp:91
uint64_t unsigned_integer
Definition: json.hpp:149
enum JSON::Number::Type type
Result< T > find(const std::string &path) const
Definition: json.hpp:354
Value convert(const picojson::value &value)
Definition: json.hpp:851
const T & get() const
Definition: try.hpp:73
constexpr const char * name
Definition: shell.hpp:41
Boolean(bool _value)
Definition: json.hpp:206
Definition: jsonify.hpp:642
std::string value
Definition: json.hpp:80
True()
Definition: json.hpp:215
Definition: jsonify.hpp:384
Object(std::initializer_list< std::pair< const std::string, Value >> values_)
Definition: json.hpp:158