diff --git a/src/jansson-impl.hpp b/src/jansson-impl.hpp index dbf94df..de336dd 100644 --- a/src/jansson-impl.hpp +++ b/src/jansson-impl.hpp @@ -4,466 +4,466 @@ // it under the terms of the MIT license. See LICENSE for details. #if !defined(IN_JANSSON_HPP) -# error "jansson-impl.hpp may only by included from jansson.hpp" +#error "jansson-impl.hpp may only by included from jansson.hpp" #endif namespace json { - namespace _private { - // assignment operator - template - ValueBase<_Base>& ValueBase<_Base>::operator=(const Value& value) { - _Base::operator=(value); - return *this; - } - - // check value type - template - bool ValueBase<_Base>::is_undefined() const { - return _Base::as_json() == 0; - } - - template - bool ValueBase<_Base>::is_object() const { - return json_is_object(_Base::as_json()); - } - - template - bool ValueBase<_Base>::is_array() const { - return json_is_array(_Base::as_json()); - } - - template - bool ValueBase<_Base>::is_string() const { - return json_is_string(_Base::as_json()); - } - - template - bool ValueBase<_Base>::is_integer() const { - return json_is_integer(_Base::as_json()); - } - - template - bool ValueBase<_Base>::is_real() const { - return json_is_real(_Base::as_json()); - } - - template - bool ValueBase<_Base>::is_number() const { - return json_is_number(_Base::as_json()); - } - - template - bool ValueBase<_Base>::is_true() const { - return json_is_true(_Base::as_json()); - } - - template - bool ValueBase<_Base>::is_false() const { - return json_is_false(_Base::as_json()); - } - - template - bool ValueBase<_Base>::is_boolean() const { - return json_is_boolean(_Base::as_json()); - } - - template - bool ValueBase<_Base>::is_null() const { - return json_is_null(_Base::as_json()); - } - - // get size of array or object - template - unsigned int ValueBase<_Base>::size() const { - if (is_object()) - return json_object_size(_Base::as_json()); - else - return json_array_size(_Base::as_json()); - } - - // get value at array index (const version) - template - const Value ValueBase<_Base>::at(unsigned int index) const { - return Value(json_array_get(_Base::as_json(), index)); - } - - template - const Value ValueBase<_Base>::operator[](signed int index) const { return at(index); } - template - const Value ValueBase<_Base>::operator[](unsigned int index) const { return at(index); } - template - const Value ValueBase<_Base>::operator[](signed short index) const { return at(index); } - template - const Value ValueBase<_Base>::operator[](unsigned short index) const { return at(index); } - template - const Value ValueBase<_Base>::operator[](signed long index) const { return at(index); } - template - const Value ValueBase<_Base>::operator[](unsigned long index) const { return at(index); } - - // get value at array index (non-const version) - template - ValueBase ValueBase<_Base>::at(unsigned int index) { - return ElementProxy(_Base::as_json(), index); - } - - template - ValueBase ValueBase<_Base>::operator[](signed int index) { - return at(index); - } - - template - ValueBase ValueBase<_Base>::operator[](unsigned int index) { - return at(index); - } - - template - ValueBase ValueBase<_Base>::operator[](signed short index) { - return at(index); - } - - template - ValueBase ValueBase<_Base>::operator[](unsigned short index) { - return at(index); - } - - template - ValueBase ValueBase<_Base>::operator[](signed long index) { - return at(index); - } - - template - ValueBase ValueBase<_Base>::operator[](unsigned long index) { - return at(index); - } - - // get object property (const version) - template - const Value ValueBase<_Base>::get(const char* key) const { - return Value(json_object_get(_Base::as_json(), key)); - } - - template - const Value ValueBase<_Base>::get(const std::string& key) const { - return get(key.c_str()); - } - - template - const Value ValueBase<_Base>::operator[](const char* key) const { - return get(key); - } - - template - const Value ValueBase<_Base>::operator[](const std::string& key) const { - return get(key.c_str()); - } - - // get object property (non-const version) - template - ValueBase ValueBase<_Base>::get(const char* key) { - return PropertyProxy(_Base::as_json(), key); - } - - template - ValueBase ValueBase<_Base>::get(const std::string& key) { - return get(key.c_str()); - } - - template - ValueBase ValueBase<_Base>::operator[](const char* key) { - return get(key); - } - - template - ValueBase ValueBase<_Base>::operator[](const std::string& key) { - return get(key.c_str()); - } - - // clear all array/object values - template - void ValueBase<_Base>::clear() { - if (is_object()) - json_object_clear(_Base::as_json()); - else - json_array_clear(_Base::as_json()); - } - - // get value cast to specified type - template - const char* ValueBase<_Base>::as_cstring() const { - return json_string_value(_Base::as_json()); - } - - template - std::string ValueBase<_Base>::as_string() const { - const char* tmp = as_cstring(); - return tmp == 0 ? "" : tmp; - } - - template - int ValueBase<_Base>::as_integer() const { - return json_integer_value(_Base::as_json()); - } - - template - double ValueBase<_Base>::as_real() const { - return json_real_value(_Base::as_json()); - } - - template - double ValueBase<_Base>::as_number() const { - return json_number_value(_Base::as_json()); - } - - template - bool ValueBase<_Base>::as_boolean() const { - return is_true(); - } - - // set an object property (converts value to object is not one already) - template - _Base& ValueBase<_Base>::set_key(const char* key, const Value& value) { - json_object_set(_Base::as_json(), key, value._Base::as_json()); - return *this; - } - - template - _Base& ValueBase<_Base>::set_key(const std::string& key, const Value& value) { - return set_key(key.c_str(), value); - } - - // set an array index (converts value to object is not one already) - template - _Base& ValueBase<_Base>::set_at(unsigned int index, const Value& value) { - if (index == size()) - json_array_append(_Base::as_json(), value._Base::as_json()); - else - json_array_set(_Base::as_json(), index, value._Base::as_json()); - return *this; - } - - // delete an object key - template - _Base& ValueBase<_Base>::del_key(const char* key) { - json_object_del(_Base::as_json(), key); - return *this; - } - - template - _Base& ValueBase<_Base>::del_key(const std::string& key) { - return del_key(key.c_str()); - } - - // delete an item from an array by index - template - _Base& ValueBase<_Base>::del_at(unsigned int index) { - json_array_remove(_Base::as_json(), index); - return *this; - } - - // insert an item into an array at a given index - template - _Base& ValueBase<_Base>::insert_at(unsigned int index, const Value& value) { - json_array_insert(_Base::as_json(), index, value._Base::as_json()); - return *this; - } - - // write the value to a file - template - int ValueBase<_Base>::save_file(const char* path, int flags) const { - return json_dump_file(_Base::as_json(), path, flags); - } - - // write the value to a string (caller must deallocate with free()!) - template - char* ValueBase<_Base>::save_string(int flags) const { - return json_dumps(_Base::as_json(), flags); - } - - Basic::~Basic() { - json_decref(_value); - } - - // copy an existing Value - Basic& Basic::operator=(const Basic& e) { - if (&e != this) { - json_decref(_value); - _value = json_incref(e._value); - } - return *this; - } - - // get the underlying json_t - json_t* Basic::as_json() const { - return _value; - } - - // take ownership of a json_t (does not increase reference count) - Basic Basic::take_ownership(json_t* json) { - Basic v; - v._value = json; - return v; - } - - // assign value to proxied array element - ElementProxy& ElementProxy::operator=(const Value& value) { - json_array_set(_array, _index, value.as_json()); - return *this; - } - - // get the proxied element - json_t* ElementProxy::as_json() const { - return json_array_get(_array, _index); - } - - // assign value to proxied object property - PropertyProxy& PropertyProxy::operator=(const Value& value) { - json_object_set(_object, _key, value.as_json()); - return *this; - } - - json_t* PropertyProxy::as_json() const { - return json_object_get(_object, _key); - } - - } // namespace json::_private - - // construct Value::Value input - Value::Value(const char* value) { - _value = json_string(value); - } - - Value::Value(const std::string& value) { - _value = json_string(value.c_str()); - } - - Value::Value(bool value) { - _value = value ? json_true() : json_false(); - } - - Value::Value(signed int value) { - _value = json_integer(value); - } - - Value::Value(unsigned int value) { - _value = json_integer(value); - } - - Value::Value(signed short value) { - _value = json_integer(value); - } - - Value::Value(unsigned short value) { - _value = json_integer(value); - } - - Value::Value(signed long value) { - _value = json_integer(value); - } - - Value::Value(unsigned long value) { - _value = json_integer(value); - } - - Value::Value(float value) { - _value = json_real(value); - } - - Value::Value(double value) { - _value = json_real(value); - } - - // construct a new iterator for a given object - Iterator::Iterator(const Value& value) : _object(value), _iter(0) { - _iter = json_object_iter(_object.as_json()); - } - - // construct a new iterator for a given object - Iterator::Iterator(const _private::ValueBase<_private::PropertyProxy>& value) : - _object(value.as_json()), _iter(0) { - _iter = json_object_iter(_object.as_json()); - } - - // increment iterator - void Iterator::next() { - _iter = json_object_iter_next(_object.as_json(), _iter); - } - - Iterator& Iterator::operator++() { next(); return *this; } - - // test if iterator is still valid - bool Iterator::valid() const { - return _iter != 0; - } - - Iterator::operator bool() const { - return valid(); - } - - // get key - const char* Iterator::ckey() const { - return json_object_iter_key(_iter); - } - - std::string Iterator::key() const { - return ckey(); - } - - // get value - const Value Iterator::value() const { - return Value(json_object_iter_value(_iter)); - } - - // dereference value - const Value Iterator::operator*() const { - return value(); - } - - // create a new empty object - Value object() { - return Value::take_ownership(json_object()); - } - - // create a new empty array - Value array() { - return Value::take_ownership(json_array()); - } - - // create a new null value - Value null() { - return Value::take_ownership(json_null()); - } - - // load a file as a JSON value - Value load_file(const char* path, json_error_t* error) { - return Value::take_ownership(json_load_file(path, error)); - } - - // load a string as a JSON value - Value load_string(const char* string, json_error_t* error) { - return Value::take_ownership(json_loads(string, error)); - } + namespace _private { + // assignment operator + template + ValueBase<_Base>& ValueBase<_Base>::operator=(const Value& value) { + _Base::operator=(value); + return *this; + } + + // check value type + template + bool ValueBase<_Base>::is_undefined() const { + return _Base::as_json() == 0; + } + + template + bool ValueBase<_Base>::is_object() const { + return json_is_object(_Base::as_json()); + } + + template + bool ValueBase<_Base>::is_array() const { + return json_is_array(_Base::as_json()); + } + + template + bool ValueBase<_Base>::is_string() const { + return json_is_string(_Base::as_json()); + } + + template + bool ValueBase<_Base>::is_integer() const { + return json_is_integer(_Base::as_json()); + } + + template + bool ValueBase<_Base>::is_real() const { + return json_is_real(_Base::as_json()); + } + + template + bool ValueBase<_Base>::is_number() const { + return json_is_number(_Base::as_json()); + } + + template + bool ValueBase<_Base>::is_true() const { + return json_is_true(_Base::as_json()); + } + + template + bool ValueBase<_Base>::is_false() const { + return json_is_false(_Base::as_json()); + } + + template + bool ValueBase<_Base>::is_boolean() const { + return json_is_boolean(_Base::as_json()); + } + + template + bool ValueBase<_Base>::is_null() const { + return json_is_null(_Base::as_json()); + } + + // get size of array or object + template + unsigned int ValueBase<_Base>::size() const { + if (is_object()) + return json_object_size(_Base::as_json()); + else + return json_array_size(_Base::as_json()); + } + + // get value at array index (const version) + template + const Value ValueBase<_Base>::at(unsigned int index) const { + return Value(json_array_get(_Base::as_json(), index)); + } + + template + const Value ValueBase<_Base>::operator[](signed int index) const { return at(index); } + template + const Value ValueBase<_Base>::operator[](unsigned int index) const { return at(index); } + template + const Value ValueBase<_Base>::operator[](signed short index) const { return at(index); } + template + const Value ValueBase<_Base>::operator[](unsigned short index) const { return at(index); } + template + const Value ValueBase<_Base>::operator[](signed long index) const { return at(index); } + template + const Value ValueBase<_Base>::operator[](unsigned long index) const { return at(index); } + + // get value at array index (non-const version) + template + ValueBase ValueBase<_Base>::at(unsigned int index) { + return ElementProxy(_Base::as_json(), index); + } + + template + ValueBase ValueBase<_Base>::operator[](signed int index) { + return at(index); + } + + template + ValueBase ValueBase<_Base>::operator[](unsigned int index) { + return at(index); + } + + template + ValueBase ValueBase<_Base>::operator[](signed short index) { + return at(index); + } + + template + ValueBase ValueBase<_Base>::operator[](unsigned short index) { + return at(index); + } + + template + ValueBase ValueBase<_Base>::operator[](signed long index) { + return at(index); + } + + template + ValueBase ValueBase<_Base>::operator[](unsigned long index) { + return at(index); + } + + // get object property (const version) + template + const Value ValueBase<_Base>::get(const char* key) const { + return Value(json_object_get(_Base::as_json(), key)); + } + + template + const Value ValueBase<_Base>::get(const std::string& key) const { + return get(key.c_str()); + } + + template + const Value ValueBase<_Base>::operator[](const char* key) const { + return get(key); + } + + template + const Value ValueBase<_Base>::operator[](const std::string& key) const { + return get(key.c_str()); + } + + // get object property (non-const version) + template + ValueBase ValueBase<_Base>::get(const char* key) { + return PropertyProxy(_Base::as_json(), key); + } + + template + ValueBase ValueBase<_Base>::get(const std::string& key) { + return get(key.c_str()); + } + + template + ValueBase ValueBase<_Base>::operator[](const char* key) { + return get(key); + } + + template + ValueBase ValueBase<_Base>::operator[](const std::string& key) { + return get(key.c_str()); + } + + // clear all array/object values + template + void ValueBase<_Base>::clear() { + if (is_object()) + json_object_clear(_Base::as_json()); + else + json_array_clear(_Base::as_json()); + } + + // get value cast to specified type + template + const char* ValueBase<_Base>::as_cstring() const { + return json_string_value(_Base::as_json()); + } + + template + std::string ValueBase<_Base>::as_string() const { + const char* tmp = as_cstring(); + return tmp == 0 ? "" : tmp; + } + + template + int ValueBase<_Base>::as_integer() const { + return json_integer_value(_Base::as_json()); + } + + template + double ValueBase<_Base>::as_real() const { + return json_real_value(_Base::as_json()); + } + + template + double ValueBase<_Base>::as_number() const { + return json_number_value(_Base::as_json()); + } + + template + bool ValueBase<_Base>::as_boolean() const { + return is_true(); + } + + // set an object property (converts value to object is not one already) + template + _Base& ValueBase<_Base>::set_key(const char* key, const Value& value) { + json_object_set(_Base::as_json(), key, value._Base::as_json()); + return *this; + } + + template + _Base& ValueBase<_Base>::set_key(const std::string& key, const Value& value) { + return set_key(key.c_str(), value); + } + + // set an array index (converts value to object is not one already) + template + _Base& ValueBase<_Base>::set_at(unsigned int index, const Value& value) { + if (index == size()) + json_array_append(_Base::as_json(), value._Base::as_json()); + else + json_array_set(_Base::as_json(), index, value._Base::as_json()); + return *this; + } + + // delete an object key + template + _Base& ValueBase<_Base>::del_key(const char* key) { + json_object_del(_Base::as_json(), key); + return *this; + } + + template + _Base& ValueBase<_Base>::del_key(const std::string& key) { + return del_key(key.c_str()); + } + + // delete an item from an array by index + template + _Base& ValueBase<_Base>::del_at(unsigned int index) { + json_array_remove(_Base::as_json(), index); + return *this; + } + + // insert an item into an array at a given index + template + _Base& ValueBase<_Base>::insert_at(unsigned int index, const Value& value) { + json_array_insert(_Base::as_json(), index, value._Base::as_json()); + return *this; + } + + // write the value to a file + template + int ValueBase<_Base>::save_file(const char* path, int flags) const { + return json_dump_file(_Base::as_json(), path, flags); + } + + // write the value to a string (caller must deallocate with free()!) + template + char* ValueBase<_Base>::save_string(int flags) const { + return json_dumps(_Base::as_json(), flags); + } + + Basic::~Basic() { + json_decref(_value); + } + + // copy an existing Value + Basic& Basic::operator=(const Basic& e) { + if (&e != this) { + json_decref(_value); + _value = json_incref(e._value); + } + return *this; + } + + // get the underlying json_t + json_t* Basic::as_json() const { + return _value; + } + + // take ownership of a json_t (does not increase reference count) + Basic Basic::take_ownership(json_t* json) { + Basic v; + v._value = json; + return v; + } + + // assign value to proxied array element + ElementProxy& ElementProxy::operator=(const Value& value) { + json_array_set(_array, _index, value.as_json()); + return *this; + } + + // get the proxied element + json_t* ElementProxy::as_json() const { + return json_array_get(_array, _index); + } + + // assign value to proxied object property + PropertyProxy& PropertyProxy::operator=(const Value& value) { + json_object_set(_object, _key, value.as_json()); + return *this; + } + + json_t* PropertyProxy::as_json() const { + return json_object_get(_object, _key); + } + + } // namespace json::_private + + // construct Value::Value input + Value::Value(const char* value) { + _value = json_string(value); + } + + Value::Value(const std::string& value) { + _value = json_string(value.c_str()); + } + + Value::Value(bool value) { + _value = value ? json_true() : json_false(); + } + + Value::Value(signed int value) { + _value = json_integer(value); + } + + Value::Value(unsigned int value) { + _value = json_integer(value); + } + + Value::Value(signed short value) { + _value = json_integer(value); + } + + Value::Value(unsigned short value) { + _value = json_integer(value); + } + + Value::Value(signed long value) { + _value = json_integer(value); + } + + Value::Value(unsigned long value) { + _value = json_integer(value); + } + + Value::Value(float value) { + _value = json_real(value); + } + + Value::Value(double value) { + _value = json_real(value); + } + + // construct a new iterator for a given object + Iterator::Iterator(const Value& value) : _object(value), _iter(0) { + _iter = json_object_iter(_object.as_json()); + } + + // construct a new iterator for a given object + Iterator::Iterator(const _private::ValueBase<_private::PropertyProxy>& value) : + _object(value.as_json()), _iter(0) { + _iter = json_object_iter(_object.as_json()); + } + + // increment iterator + void Iterator::next() { + _iter = json_object_iter_next(_object.as_json(), _iter); + } + + Iterator& Iterator::operator++() { next(); return *this; } + + // test if iterator is still valid + bool Iterator::valid() const { + return _iter != 0; + } + + Iterator::operator bool() const { + return valid(); + } + + // get key + const char* Iterator::ckey() const { + return json_object_iter_key(_iter); + } + + std::string Iterator::key() const { + return ckey(); + } + + // get value + const Value Iterator::value() const { + return Value(json_object_iter_value(_iter)); + } + + // dereference value + const Value Iterator::operator*() const { + return value(); + } + + // create a new empty object + Value object() { + return Value::take_ownership(json_object()); + } + + // create a new empty array + Value array() { + return Value::take_ownership(json_array()); + } + + // create a new null value + Value null() { + return Value::take_ownership(json_null()); + } + + // load a file as a JSON value + Value load_file(const char* path, json_error_t* error) { + return Value::take_ownership(json_load_file(path, error)); + } + + // load a string as a JSON value + Value load_string(const char* string, json_error_t* error) { + return Value::take_ownership(json_loads(string, error)); + } } // namespace json // stream JSON value out std::ostream& operator<<(std::ostream& os, const json::Value& value) { - // get the temporary serialize string - char* tmp = value.save_string(); - if (tmp != 0) { - // stream temp string out and release it - os << tmp; - free(tmp); - } - return os; + // get the temporary serialize string + char* tmp = value.save_string(); + if (tmp != 0) { + // stream temp string out and release it + os << tmp; + free(tmp); + } + return os; } // read JSON value std::istream& operator>>(std::istream& is, json::Value& value) { - // buffer the remaining bytes into a single string for Jansson - std::stringstream tmp; - while (is) - tmp << static_cast(is.get()); - // parse the buffered string - value = json::load_string(tmp.str().c_str()); - return is; + // buffer the remaining bytes into a single string for Jansson + std::stringstream tmp; + while (is) + tmp << static_cast(is.get()); + // parse the buffered string + value = json::load_string(tmp.str().c_str()); + return is; } diff --git a/src/jansson.hpp b/src/jansson.hpp index 1bd18b1..020a277 100644 --- a/src/jansson.hpp +++ b/src/jansson.hpp @@ -13,281 +13,281 @@ #include namespace json { - // include Jansson C library into the json namespace - #include - - class Iterator; - class Value; - - // implementation details; do not use directly - namespace _private { - class ElementProxy; - class PropertyProxy; + // include Jansson C library into the json namespace +# include + + class Iterator; + class Value; + + // implementation details; do not use directly + namespace _private { + class ElementProxy; + class PropertyProxy; - // base class for JSON value interface - template - class ValueBase : public _Base { - public: - // empty constructor - ValueBase() : _Base() {} - - // copy constructor - ValueBase(const _Base& base) : _Base(base) {} - - // create reference to value - ValueBase(json_t* json) : _Base(json) {} - - // assignment operator - inline ValueBase& operator=(const Value& value); + // base class for JSON value interface + template + class ValueBase : public _Base { + public: + // empty constructor + ValueBase() : _Base() {} + + // copy constructor + ValueBase(const _Base& base) : _Base(base) {} + + // create reference to value + ValueBase(json_t* json) : _Base(json) {} + + // assignment operator + inline ValueBase& operator=(const Value& value); - // check value type - inline bool is_undefined() const; - inline bool is_object() const; - inline bool is_array() const; - inline bool is_string() const; - inline bool is_integer() const; - inline bool is_real() const; - inline bool is_number() const; - inline bool is_true() const; - inline bool is_false() const; - inline bool is_boolean() const; - inline bool is_null() const; + // check value type + inline bool is_undefined() const; + inline bool is_object() const; + inline bool is_array() const; + inline bool is_string() const; + inline bool is_integer() const; + inline bool is_real() const; + inline bool is_number() const; + inline bool is_true() const; + inline bool is_false() const; + inline bool is_boolean() const; + inline bool is_null() const; - // get size of array or object - inline unsigned int size() const; + // get size of array or object + inline unsigned int size() const; - // get value at array index (const version) - inline const Value at(unsigned int index) const; + // get value at array index (const version) + inline const Value at(unsigned int index) const; - inline const Value operator[](signed int index) const; - inline const Value operator[](unsigned int index) const; - inline const Value operator[](signed short index) const; - inline const Value operator[](unsigned short index) const; - inline const Value operator[](signed long index) const; - inline const Value operator[](unsigned long index) const; + inline const Value operator[](signed int index) const; + inline const Value operator[](unsigned int index) const; + inline const Value operator[](signed short index) const; + inline const Value operator[](unsigned short index) const; + inline const Value operator[](signed long index) const; + inline const Value operator[](unsigned long index) const; - // get value at array index (non-const version) - inline ValueBase at(unsigned int index); + // get value at array index (non-const version) + inline ValueBase at(unsigned int index); - inline ValueBase operator[](signed int index); - inline ValueBase operator[](unsigned int index); - inline ValueBase operator[](signed short index); - inline ValueBase operator[](unsigned short index); - inline ValueBase operator[](signed long index); - inline ValueBase operator[](unsigned long index); + inline ValueBase operator[](signed int index); + inline ValueBase operator[](unsigned int index); + inline ValueBase operator[](signed short index); + inline ValueBase operator[](unsigned short index); + inline ValueBase operator[](signed long index); + inline ValueBase operator[](unsigned long index); - // get object property (const version) - inline const Value get(const char* key) const; + // get object property (const version) + inline const Value get(const char* key) const; - inline const Value get(const std::string& key) const; - inline const Value operator[](const char* key) const; - inline const Value operator[](const std::string& key) const; + inline const Value get(const std::string& key) const; + inline const Value operator[](const char* key) const; + inline const Value operator[](const std::string& key) const; - // get object property (non-const version) - inline ValueBase get(const char* key); + // get object property (non-const version) + inline ValueBase get(const char* key); - inline ValueBase get(const std::string& key); - inline ValueBase operator[](const char* key); - inline ValueBase operator[](const std::string& key); + inline ValueBase get(const std::string& key); + inline ValueBase operator[](const char* key); + inline ValueBase operator[](const std::string& key); - // clear all array/object values - inline void clear(); + // clear all array/object values + inline void clear(); - // get value cast to specified type - inline const char* as_cstring() const; - inline std::string as_string() const; - inline int as_integer() const; - inline double as_real() const; - inline double as_number() const; - inline bool as_boolean() const; + // get value cast to specified type + inline const char* as_cstring() const; + inline std::string as_string() const; + inline int as_integer() const; + inline double as_real() const; + inline double as_number() const; + inline bool as_boolean() const; - // set an object property (converts value to object is not one already) - inline _Base& set_key(const char* key, const Value& value); + // set an object property (converts value to object is not one already) + inline _Base& set_key(const char* key, const Value& value); - inline _Base& set_key(const std::string& key, const Value& value); - - // set an array index (converts value to object is not one already) - inline _Base& set_at(unsigned int index, const Value& value); - - // delete an object key - inline _Base& del_key(const char* key); - - inline _Base& del_key(const std::string& key); - - // delete an item from an array by index - inline _Base& del_at(unsigned int index); - - // insert an item into an array at a given index - inline _Base& insert_at(unsigned int index, const Value& value); - - // write the value to a file - inline int save_file(const char* path, int flags = 0) const; - - // write the value to a string (caller must deallocate with free()!) - inline char* save_string(int flags = 0) const; - }; - - // represents any JSON value, private base - class Basic { - public: - // construct new Value with an undefined value - Basic() : _value(0) {} - - // copy constructor - Basic(const Basic& value) : _value(json_incref(value._value)) {} - - // make a reference to an existing json_t value - explicit Basic(json_t* value) : _value(json_incref(value)) {} - - // free Value resources - inline ~Basic(); - - // copy an existing Value - inline Basic& operator=(const Basic& e); - - // get the underlying json_t - inline json_t* as_json() const; + inline _Base& set_key(const std::string& key, const Value& value); + + // set an array index (converts value to object is not one already) + inline _Base& set_at(unsigned int index, const Value& value); + + // delete an object key + inline _Base& del_key(const char* key); + + inline _Base& del_key(const std::string& key); + + // delete an item from an array by index + inline _Base& del_at(unsigned int index); + + // insert an item into an array at a given index + inline _Base& insert_at(unsigned int index, const Value& value); + + // write the value to a file + inline int save_file(const char* path, int flags = 0) const; + + // write the value to a string (caller must deallocate with free()!) + inline char* save_string(int flags = 0) const; + }; + + // represents any JSON value, private base + class Basic { + public: + // construct new Value with an undefined value + Basic() : _value(0) {} + + // copy constructor + Basic(const Basic& value) : _value(json_incref(value._value)) {} + + // make a reference to an existing json_t value + explicit Basic(json_t* value) : _value(json_incref(value)) {} + + // free Value resources + inline ~Basic(); + + // copy an existing Value + inline Basic& operator=(const Basic& e); - // take ownership of a json_t (does not increase reference count) - inline static Basic take_ownership(json_t* json); + // get the underlying json_t + inline json_t* as_json() const; - protected: - // internal value pointer - json_t* _value; - }; + // take ownership of a json_t (does not increase reference count) + inline static Basic take_ownership(json_t* json); - // proxies an array element - class ElementProxy { - public: - // constructor - ElementProxy(json_t* array, unsigned int index) : _array(array), _index(index) {} + protected: + // internal value pointer + json_t* _value; + }; - // assign to the proxied element - inline ElementProxy& operator=(const Value& value); + // proxies an array element + class ElementProxy { + public: + // constructor + ElementProxy(json_t* array, unsigned int index) : _array(array), _index(index) {} - // get the proxied element - inline json_t* as_json() const; + // assign to the proxied element + inline ElementProxy& operator=(const Value& value); - private: - // array object we wrap - json_t* _array; + // get the proxied element + inline json_t* as_json() const; - // index of property - unsigned int _index; - }; + private: + // array object we wrap + json_t* _array; - // proxies an object property - class PropertyProxy { - public: - // constructor - PropertyProxy(json_t* array, const char* key) : _object(array), _key(key) {} + // index of property + unsigned int _index; + }; - // assign to the proxied element - inline PropertyProxy& operator=(const Value& value); + // proxies an object property + class PropertyProxy { + public: + // constructor + PropertyProxy(json_t* array, const char* key) : _object(array), _key(key) {} - // get the proxied element - inline json_t* as_json() const; + // assign to the proxied element + inline PropertyProxy& operator=(const Value& value); - private: - // array object we wrap - json_t* _object; + // get the proxied element + inline json_t* as_json() const; - // key of property - const char* _key; - }; + private: + // array object we wrap + json_t* _object; - } // namespace json::_private + // key of property + const char* _key; + }; - // represents any JSON value - class Value : public _private::ValueBase<_private::Basic> { - public: - // construct Value from input - explicit inline Value(const char* value); - explicit inline Value(const std::string& value); - explicit inline Value(bool value); - explicit inline Value(signed int value); - explicit inline Value(unsigned int value); - explicit inline Value(signed short value); - explicit inline Value(unsigned short value); - explicit inline Value(signed long value); - explicit inline Value(unsigned long value); - explicit inline Value(float value); - explicit inline Value(double value); + } // namespace json::_private - // empty constructor - Value() : _private::ValueBase<_private::Basic>() {} + // represents any JSON value + class Value : public _private::ValueBase<_private::Basic> { + public: + // construct Value from input + explicit inline Value(const char* value); + explicit inline Value(const std::string& value); + explicit inline Value(bool value); + explicit inline Value(signed int value); + explicit inline Value(unsigned int value); + explicit inline Value(signed short value); + explicit inline Value(unsigned short value); + explicit inline Value(signed long value); + explicit inline Value(unsigned long value); + explicit inline Value(float value); + explicit inline Value(double value); - // copy constructor for base - Value(const _private::Basic& value) : _private::ValueBase<_private::Basic>(value) {} - - // copy constructor for base - Value(const _private::ValueBase<_private::Basic>& value) : _private::ValueBase<_private::Basic>(value) {} + // empty constructor + Value() : _private::ValueBase<_private::Basic>() {} - // copy constructor - Value(const Value& value) : _private::ValueBase<_private::Basic>(value) {} + // copy constructor for base + Value(const _private::Basic& value) : _private::ValueBase<_private::Basic>(value) {} - // create reference to value - explicit Value(json_t* json) : _private::ValueBase<_private::Basic>(json) {} - }; + // copy constructor for base + Value(const _private::ValueBase<_private::Basic>& value) : _private::ValueBase<_private::Basic>(value) {} - // iterators over a JSON object - class Iterator { - public: - // construct a new iterator for a given object - inline Iterator(const Value& value); + // copy constructor + Value(const Value& value) : _private::ValueBase<_private::Basic>(value) {} - // construct a new iterator for a given object - inline Iterator(const _private::ValueBase<_private::PropertyProxy>& value); + // create reference to value + explicit Value(json_t* json) : _private::ValueBase<_private::Basic>(json) {} + }; - // increment iterator - inline void next(); + // iterators over a JSON object + class Iterator { + public: + // construct a new iterator for a given object + inline Iterator(const Value& value); - inline Iterator& operator++(); + // construct a new iterator for a given object + inline Iterator(const _private::ValueBase<_private::PropertyProxy>& value); - // test if iterator is still valid - inline bool valid() const; + // increment iterator + inline void next(); - inline operator bool() const; + inline Iterator& operator++(); - // get key - inline const char* ckey() const; + // test if iterator is still valid + inline bool valid() const; - inline std::string key() const; + inline operator bool() const; - // get value - inline const Value value() const; + // get key + inline const char* ckey() const; - // dereference value - inline const Value operator*() const; + inline std::string key() const; - private: - // disallow copying - Iterator(const Iterator&); - Iterator& operator=(const Iterator&); + // get value + inline const Value value() const; - // object being iterated over - Value _object; + // dereference value + inline const Value operator*() const; - // iterator value - void* _iter; - }; + private: + // disallow copying + Iterator(const Iterator&); + Iterator& operator=(const Iterator&); - // create a new empty object - inline Value object(); + // object being iterated over + Value _object; - // create a new empty array - inline Value array(); + // iterator value + void* _iter; + }; - // create a new null value - inline Value null(); + // create a new empty object + inline Value object(); - // load a file as a JSON value - inline Value load_file(const char* path, json_error_t* error = 0); + // create a new empty array + inline Value array(); - // load a string as a JSON value - inline Value load_string(const char* string, json_error_t* error = 0); + // create a new null value + inline Value null(); -} // namespace json + // load a file as a JSON value + inline Value load_file(const char* path, json_error_t* error = 0); + + // load a string as a JSON value + inline Value load_string(const char* string, json_error_t* error = 0); + +} // namespace json // stream JSON value out -- inefficient and not recommended for production use inline std::ostream& operator<<(std::ostream& os, const json::Value& value); diff --git a/test/suites/api/test_cpp.cpp b/test/suites/api/test_cpp.cpp index edcac77..5d3964a 100644 --- a/test/suites/api/test_cpp.cpp +++ b/test/suites/api/test_cpp.cpp @@ -4,156 +4,159 @@ #include "jansson.hpp" -#define ASSERT_OP(lhs, rhs, op, m) \ - do { \ - if(!((lhs) op (rhs))) { \ - std::cerr << std::boolalpha; \ - std::cerr << __FILE__ << '[' << __LINE__ << "]: ERROR: " << (m) << std::endl; \ - std::cerr << "\ttest: " << #lhs << ' ' << #op << ' ' << #rhs << std::endl; \ - std::cerr << "\tresult: " << (lhs) << ' ' << #op << ' ' << (rhs) << std::endl; \ - return 1; \ - } \ - } while(0) +#define ASSERT_OP(lhs, rhs, op, m) \ + do { \ + if(!((lhs) op (rhs))) { \ + std::cerr << std::boolalpha; \ + std::cerr << __FILE__ << '[' << __LINE__ << "]: ERROR: " \ + << (m) << std::endl; \ + std::cerr << "\ttest: " << #lhs << ' ' << #op << ' ' \ + << #rhs << std::endl; \ + std::cerr << "\tresult: " << (lhs) << ' ' << #op << ' ' \ + << (rhs) << std::endl; \ + return 1; \ + } \ + } while(0) #define ASSERT_EQ(lhs, rhs, m) ASSERT_OP(lhs, rhs, ==, m) #define ASSERT_NE(lhs, rhs, m) ASSERT_OP(lhs, rhs, !=, m) #define ASSERT_TRUE(p, m) ASSERT_OP(p, true, ==, m) #define ASSERT_FALSE(p, m) ASSERT_OP(p, true, !=, m) int main() { - json::Value e1(json::load_file("suites/api/test.json")); - json::Value e2(e1); - json::Value e3; - json::Value e4(json::load_string("{\"foo\": true, \"bar\": \"test\"}")); + json::Value e1(json::load_file("suites/api/test.json")); + json::Value e2(e1); + json::Value e3; + json::Value e4(json::load_string("{\"foo\": true, \"bar\": \"test\"}")); - ASSERT_TRUE(e1.is_object(), "e1 is not an object"); - ASSERT_TRUE(e2.is_object(), "e2 is not an object"); - ASSERT_TRUE(e3.is_undefined(), "e3 has a defined value"); - ASSERT_TRUE(e4.is_object(), "e4 is not an object"); + ASSERT_TRUE(e1.is_object(), "e1 is not an object"); + ASSERT_TRUE(e2.is_object(), "e2 is not an object"); + ASSERT_TRUE(e3.is_undefined(), "e3 has a defined value"); + ASSERT_TRUE(e4.is_object(), "e4 is not an object"); - ASSERT_EQ(e1.size(), 1, "e1 has too many properties"); - ASSERT_EQ(e2.size(), 1, "e2 has too many properties"); - ASSERT_EQ(e4.size(), 2, "e4 does not have 2 elements"); + ASSERT_EQ(e1.size(), 1, "e1 has too many properties"); + ASSERT_EQ(e2.size(), 1, "e2 has too many properties"); + ASSERT_EQ(e4.size(), 2, "e4 does not have 2 elements"); - ASSERT_TRUE(e1.get("web-app").is_object(), "e1[0].web-app is not an object"); - ASSERT_EQ(e1.get("web-app").get("servlet").at(0).get("servlet-class").as_string(), "org.cofax.cds.CDSServlet", "property has incorrect value"); - ASSERT_EQ(e1["web-app"]["servlet"][0]["servlet-class"].as_string(), "org.cofax.cds.CDSServlet", "property has incorrect value"); + ASSERT_TRUE(e1.get("web-app").is_object(), "e1[0].web-app is not an object"); + ASSERT_EQ(e1.get("web-app").get("servlet").at(0).get("servlet-class").as_string(), "org.cofax.cds.CDSServlet", "property has incorrect value"); + ASSERT_EQ(e1["web-app"]["servlet"][0]["servlet-class"].as_string(), "org.cofax.cds.CDSServlet", "property has incorrect value"); - ASSERT_EQ(e4["foo"].as_boolean(), true, "property has incorrect value"); + ASSERT_EQ(e4["foo"].as_boolean(), true, "property has incorrect value"); - json::Iterator i(e1.get("web-app")); - ASSERT_EQ(i.key(), "taglib", "first iterator result has incorrect key"); - i.next(); - ASSERT_EQ(i.key(), "servlet", "first iterator result has incorrect key"); - i.next(); - ASSERT_EQ(i.key(), "servlet-mapping", "first iterator result has incorrect key"); - i.next(); - ASSERT_FALSE(i.valid(), "iterator has more values than expected"); + json::Iterator i(e1.get("web-app")); + ASSERT_EQ(i.key(), "taglib", "first iterator result has incorrect key"); + i.next(); + ASSERT_EQ(i.key(), "servlet", "first iterator result has incorrect key"); + i.next(); + ASSERT_EQ(i.key(), "servlet-mapping", "first iterator result has incorrect key"); + i.next(); + ASSERT_FALSE(i.valid(), "iterator has more values than expected"); - json::Value e5(json::Value(12.34)); - ASSERT_TRUE(e5.is_number(), "e5 is not a number after assignment"); - ASSERT_EQ(e5.as_real(), 12.34, "e5 has incorrect value after assignment"); + json::Value e5(json::Value(12.34)); + ASSERT_TRUE(e5.is_number(), "e5 is not a number after assignment"); + ASSERT_EQ(e5.as_real(), 12.34, "e5 has incorrect value after assignment"); - json::Value e6(json::Value(true)); - ASSERT_TRUE(e6.is_boolean(), "e6 is not a boolean after assignment"); - ASSERT_EQ(e6.as_boolean(), true, "e6 has incorrect value after assignment"); + json::Value e6(json::Value(true)); + ASSERT_TRUE(e6.is_boolean(), "e6 is not a boolean after assignment"); + ASSERT_EQ(e6.as_boolean(), true, "e6 has incorrect value after assignment"); - json::Value e7(json::Value("foobar")); - ASSERT_TRUE(e7.is_string(), "e7 is not a string after assignment"); - ASSERT_EQ(e7.as_string(), "foobar", "e7 has incorrect value after assignment"); + json::Value e7(json::Value("foobar")); + ASSERT_TRUE(e7.is_string(), "e7 is not a string after assignment"); + ASSERT_EQ(e7.as_string(), "foobar", "e7 has incorrect value after assignment"); - json::Value e8(json::object()); - ASSERT_TRUE(e8.is_object(), "e8 is not an object after assignment"); + json::Value e8(json::object()); + ASSERT_TRUE(e8.is_object(), "e8 is not an object after assignment"); - json::Value e9(json::null()); - ASSERT_TRUE(e9.is_null(), "e9 is not null after assignment"); + json::Value e9(json::null()); + ASSERT_TRUE(e9.is_null(), "e9 is not null after assignment"); - json::Value e10(json::array()); - ASSERT_TRUE(e10.is_array(), "e10 is not an array after index assignment"); + json::Value e10(json::array()); + ASSERT_TRUE(e10.is_array(), "e10 is not an array after index assignment"); - e10.set_at(0, json::Value("foobar")); - ASSERT_EQ(e10.size(), 1, "e10 has incorrect number of elements after assignment"); - ASSERT_EQ(e10[0].as_string(), "foobar", "e10[0] has incorrect value after assignment"); + e10.set_at(0, json::Value("foobar")); + ASSERT_EQ(e10.size(), 1, "e10 has incorrect number of elements after assignment"); + ASSERT_EQ(e10[0].as_string(), "foobar", "e10[0] has incorrect value after assignment"); - e10.set_at(1, json::Value("foobar")); - ASSERT_TRUE(e10.is_array(), "e10 is not an array after index assignment"); - ASSERT_EQ(e10.size(), 2, "e10 has incorrect number of elements after assignment"); - ASSERT_EQ(e10[1].as_string(), "foobar", "e10[0] has incorrect value after assignment"); + e10.set_at(1, json::Value("foobar")); + ASSERT_TRUE(e10.is_array(), "e10 is not an array after index assignment"); + ASSERT_EQ(e10.size(), 2, "e10 has incorrect number of elements after assignment"); + ASSERT_EQ(e10[1].as_string(), "foobar", "e10[0] has incorrect value after assignment"); - e10.set_at(0, json::Value("barfoo")); - ASSERT_TRUE(e10.is_array(), "e10 is not an array after index assignment"); - ASSERT_EQ(e10.size(), 2, "e10 has incorrect number of elements after assignment"); - ASSERT_EQ(e10[0].as_string(), "barfoo", "e10[0] has incorrect value after assignment"); + e10.set_at(0, json::Value("barfoo")); + ASSERT_TRUE(e10.is_array(), "e10 is not an array after index assignment"); + ASSERT_EQ(e10.size(), 2, "e10 has incorrect number of elements after assignment"); + ASSERT_EQ(e10[0].as_string(), "barfoo", "e10[0] has incorrect value after assignment"); - e10.set_at(100, json::null()); - ASSERT_TRUE(e10.is_array(), "e10 is not an array after index assignment"); - ASSERT_EQ(e10.size(), 2, "e10 has incorrect number of elements after assignment"); + e10.set_at(100, json::null()); + ASSERT_TRUE(e10.is_array(), "e10 is not an array after index assignment"); + ASSERT_EQ(e10.size(), 2, "e10 has incorrect number of elements after assignment"); - e10.insert_at(1, json::Value("new")); - ASSERT_EQ(e10.size(), 3, "e10 has incorrect size after insert"); - ASSERT_EQ(e10[1].as_string(), "new", "e10[1] has incorrect value after insert"); - ASSERT_EQ(e10[2].as_string(), "foobar", "e10[2] has incorrect value after insert"); + e10.insert_at(1, json::Value("new")); + ASSERT_EQ(e10.size(), 3, "e10 has incorrect size after insert"); + ASSERT_EQ(e10[1].as_string(), "new", "e10[1] has incorrect value after insert"); + ASSERT_EQ(e10[2].as_string(), "foobar", "e10[2] has incorrect value after insert"); - e10.del_at(0); - ASSERT_EQ(e10.size(), 2, "e10 has incorrect size after delete"); - ASSERT_EQ(e10[1].as_string(), "foobar", "e10[1] has incorrect value after delete"); + e10.del_at(0); + ASSERT_EQ(e10.size(), 2, "e10 has incorrect size after delete"); + ASSERT_EQ(e10[1].as_string(), "foobar", "e10[1] has incorrect value after delete"); - e10.clear(); - ASSERT_EQ(e10.size(), 0, "e10 has incorrect number of elements after clear"); + e10.clear(); + ASSERT_EQ(e10.size(), 0, "e10 has incorrect number of elements after clear"); - json::Value e11(json::object()); - ASSERT_TRUE(e11.is_object(), "e11 is not an object after property assignment"); + json::Value e11(json::object()); + ASSERT_TRUE(e11.is_object(), "e11 is not an object after property assignment"); - e11.set_key("foo", json::Value("test")); - ASSERT_EQ(e11.size(), 1, "e11 has incorrect number of properties after assignment"); - ASSERT_EQ(e11["foo"].as_string(), "test", "e11.foo has incorrect value after assignment"); + e11.set_key("foo", json::Value("test")); + ASSERT_EQ(e11.size(), 1, "e11 has incorrect number of properties after assignment"); + ASSERT_EQ(e11["foo"].as_string(), "test", "e11.foo has incorrect value after assignment"); - e11.set_key("foo", json::Value("again")); - ASSERT_TRUE(e11.is_object(), "e11 is not an object after property assignment"); - ASSERT_EQ(e11.size(), 1, "e11 has incorrect number of properties after assignment"); - ASSERT_EQ(e11["foo"].as_string(), "again", "e11.foo has incorrect value after assignment"); + e11.set_key("foo", json::Value("again")); + ASSERT_TRUE(e11.is_object(), "e11 is not an object after property assignment"); + ASSERT_EQ(e11.size(), 1, "e11 has incorrect number of properties after assignment"); + ASSERT_EQ(e11["foo"].as_string(), "again", "e11.foo has incorrect value after assignment"); - e11.set_key("bar", json::Value("test")); - ASSERT_TRUE(e11.is_object(), "e11 is not an object after property assignment"); - ASSERT_EQ(e11.size(), 2, "e11 has incorrect number of properties after assignment"); - ASSERT_EQ(e11["bar"].as_string(), "test", "e11.foo has incorrect value after assignment"); + e11.set_key("bar", json::Value("test")); + ASSERT_TRUE(e11.is_object(), "e11 is not an object after property assignment"); + ASSERT_EQ(e11.size(), 2, "e11 has incorrect number of properties after assignment"); + ASSERT_EQ(e11["bar"].as_string(), "test", "e11.foo has incorrect value after assignment"); - e11.clear(); - ASSERT_EQ(e11.size(), 0, "e11 has incorrect number of properties after clear"); + e11.clear(); + ASSERT_EQ(e11.size(), 0, "e11 has incorrect number of properties after clear"); - json::Value e12(json::object()); - e12.set_key("foo", json::Value("test")); - e12.set_key("bar", json::Value(3)); - char* out_cstr = e12.save_string(0); - std::string out(out_cstr); - free(out_cstr); - ASSERT_EQ(out, "{\"bar\": 3, \"foo\": \"test\"}", "object did not serialize as expected"); + json::Value e12(json::object()); + e12.set_key("foo", json::Value("test")); + e12.set_key("bar", json::Value(3)); + char* out_cstr = e12.save_string(0); + std::string out(out_cstr); + free(out_cstr); + ASSERT_EQ(out, "{\"bar\": 3, \"foo\": \"test\"}", "object did not serialize as expected"); - std::istringstream instr(out); - instr >> e12; - ASSERT_TRUE(e12.is_object(), "e12 is not an object after stream read"); - ASSERT_EQ(e12.size(), 2, "e12 has wrong size after stream read"); - ASSERT_EQ(e12.get("bar").as_integer(), 3, "e12.bar has incorrect value after stream read"); - ASSERT_EQ(e12.get("foo").as_string(), "test", "ee12.test has incorrect value after stream read"); + std::istringstream instr(out); + instr >> e12; + ASSERT_TRUE(e12.is_object(), "e12 is not an object after stream read"); + ASSERT_EQ(e12.size(), 2, "e12 has wrong size after stream read"); + ASSERT_EQ(e12.get("bar").as_integer(), 3, "e12.bar has incorrect value after stream read"); + ASSERT_EQ(e12.get("foo").as_string(), "test", "ee12.test has incorrect value after stream read"); - std::ostringstream outstr; - outstr << e12; - ASSERT_EQ(instr.str(), "{\"bar\": 3, \"foo\": \"test\"}", "object did not serialize as expected"); + std::ostringstream outstr; + outstr << e12; + ASSERT_EQ(instr.str(), "{\"bar\": 3, \"foo\": \"test\"}", "object did not serialize as expected"); - const json::Value e13(e12); - ASSERT_EQ(e13["bar"].as_integer(), 3, "e13.bar has incorrect value after copy"); + const json::Value e13(e12); + ASSERT_EQ(e13["bar"].as_integer(), 3, "e13.bar has incorrect value after copy"); - json::Value e14(json::object()); - ASSERT_TRUE(e14.is_object(), "e14 is not an object after construction"); - e14.set_key("foo", json::object()); - ASSERT_TRUE(e14["foo"].is_object(), "e14.foo is not an object after assignment"); - e14["foo"]["bar"] = json::Value(42); - ASSERT_EQ(e14["foo"]["bar"].as_integer(), 42, "e14.foo.bar has incorrect value after assignment"); + json::Value e14(json::object()); + ASSERT_TRUE(e14.is_object(), "e14 is not an object after construction"); + e14.set_key("foo", json::object()); + ASSERT_TRUE(e14["foo"].is_object(), "e14.foo is not an object after assignment"); + e14["foo"]["bar"] = json::Value(42); + ASSERT_EQ(e14["foo"]["bar"].as_integer(), 42, "e14.foo.bar has incorrect value after assignment"); - json::Value e15(json::array()); - ASSERT_TRUE(e15.is_array(), "e15 is not an array after construction"); - e15.set_at(0, json::Value(42)); - ASSERT_EQ(e15[0].as_integer(), 42, "e15[0] has incorrect value after assignment"); - e15[0] = json::Value("foo"); - ASSERT_EQ(e15[0].as_string(), "foo", "e15[0] has incorrecy value after assignment"); - return 0; + json::Value e15(json::array()); + ASSERT_TRUE(e15.is_array(), "e15 is not an array after construction"); + e15.set_at(0, json::Value(42)); + ASSERT_EQ(e15[0].as_integer(), 42, "e15[0] has incorrect value after assignment"); + e15[0] = json::Value("foo"); + ASSERT_EQ(e15[0].as_string(), "foo", "e15[0] has incorrecy value after assignment"); + return 0; }