// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors // Distributed under MIT license, or public domain if desired and // recognized in your jurisdiction. // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE #ifndef CPPTL_JSON_H_INCLUDED #define CPPTL_JSON_H_INCLUDED #if !defined(JSON_IS_AMALGAMATION) #include "forwards.h" #endif // if !defined(JSON_IS_AMALGAMATION) #include #include #include #include #include #ifndef JSON_USE_CPPTL_SMALLMAP #include #else #include #endif #ifdef JSON_USE_CPPTL #include #endif // Disable warning C4251: : needs to have dll-interface to // be used by... #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) #pragma warning(push) #pragma warning(disable : 4251) #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) #pragma pack(push, 8) /** \brief JSON (JavaScript Object Notation). */ namespace Json { #if JSON_USE_EXCEPTION /** Base class for all exceptions we throw. * * We use nothing but these internally. Of course, STL can throw others. */ class JSON_API Exception : public std::exception { public: Exception(String msg); ~Exception() JSONCPP_NOEXCEPT override; char const* what() const JSONCPP_NOEXCEPT override; protected: String msg_; }; /** Exceptions which the user cannot easily avoid. * * E.g. out-of-memory (when we use malloc), stack-overflow, malicious input * * \remark derived from Json::Exception */ class JSON_API RuntimeError : public Exception { public: RuntimeError(String const& msg); }; /** Exceptions thrown by JSON_ASSERT/JSON_FAIL macros. * * These are precondition-violations (user bugs) and internal errors (our bugs). * * \remark derived from Json::Exception */ class JSON_API LogicError : public Exception { public: LogicError(String const& msg); }; #endif /// used internally [[noreturn]] void throwRuntimeError(String const& msg); /// used internally [[noreturn]] void throwLogicError(String const& msg); /** \brief Type of the value held by a Value object. */ enum ValueType { nullValue = 0, ///< 'null' value intValue, ///< signed integer value uintValue, ///< unsigned integer value realValue, ///< double value stringValue, ///< UTF-8 string value booleanValue, ///< bool value arrayValue, ///< array value (ordered list) objectValue ///< object value (collection of name/value pairs). }; enum CommentPlacement { commentBefore = 0, ///< a comment placed on the line before a value commentAfterOnSameLine, ///< a comment just after a value on the same line commentAfter, ///< a comment on the line after a value (only make sense for /// root value) numberOfCommentPlacement }; /** \brief Type of precision for formatting of real values. */ enum PrecisionType { significantDigits = 0, ///< we set max number of significant digits in string decimalPlaces ///< we set max number of digits after "." in string }; //# ifdef JSON_USE_CPPTL // typedef CppTL::AnyEnumerator EnumMemberNames; // typedef CppTL::AnyEnumerator EnumValues; //# endif /** \brief Lightweight wrapper to tag static string. * * Value constructor and objectValue member assignment takes advantage of the * StaticString and avoid the cost of string duplication when storing the * string or the member name. * * Example of usage: * \code * Json::Value aValue( StaticString("some text") ); * Json::Value object; * static const StaticString code("code"); * object[code] = 1234; * \endcode */ class JSON_API StaticString { public: explicit StaticString(const char* czstring) : c_str_(czstring) {} operator const char*() const { return c_str_; } const char* c_str() const { return c_str_; } private: const char* c_str_; }; /** \brief Represents a JSON value. * * This class is a discriminated union wrapper that can represents a: * - signed integer [range: Value::minInt - Value::maxInt] * - unsigned integer (range: 0 - Value::maxUInt) * - double * - UTF-8 string * - boolean * - 'null' * - an ordered list of Value * - collection of name/value pairs (javascript object) * * The type of the held value is represented by a #ValueType and * can be obtained using type(). * * Values of an #objectValue or #arrayValue can be accessed using operator[]() * methods. * Non-const methods will automatically create the a #nullValue element * if it does not exist. * The sequence of an #arrayValue will be automatically resized and initialized * with #nullValue. resize() can be used to enlarge or truncate an #arrayValue. * * The get() methods can be used to obtain default value in the case the * required element does not exist. * * It is possible to iterate over the list of member keys of an object using * the getMemberNames() method. * * \note #Value string-length fit in size_t, but keys must be < 2^30. * (The reason is an implementation detail.) A #CharReader will raise an * exception if a bound is exceeded to avoid security holes in your app, * but the Value API does *not* check bounds. That is the responsibility * of the caller. */ class JSON_API Value { friend class ValueIteratorBase; public: typedef std::vector Members; typedef ValueIterator iterator; typedef ValueConstIterator const_iterator; typedef Json::UInt UInt; typedef Json::Int Int; #if defined(JSON_HAS_INT64) typedef Json::UInt64 UInt64; typedef Json::Int64 Int64; #endif // defined(JSON_HAS_INT64) typedef Json::LargestInt LargestInt; typedef Json::LargestUInt LargestUInt; typedef Json::ArrayIndex ArrayIndex; // Required for boost integration, e. g. BOOST_TEST typedef std::string value_type; #if JSON_USE_NULLREF // Binary compatibility kludges, do not use. static const Value& null; static const Value& nullRef; #endif // null and nullRef are deprecated, use this instead. static Value const& nullSingleton(); /// Minimum signed integer value that can be stored in a Json::Value. static constexpr LargestInt minLargestInt = LargestInt(~(LargestUInt(-1) / 2)); /// Maximum signed integer value that can be stored in a Json::Value. static constexpr LargestInt maxLargestInt = LargestInt(LargestUInt(-1) / 2); /// Maximum unsigned integer value that can be stored in a Json::Value. static constexpr LargestUInt maxLargestUInt = LargestUInt(-1); /// Minimum signed int value that can be stored in a Json::Value. static constexpr Int minInt = Int(~(UInt(-1) / 2)); /// Maximum signed int value that can be stored in a Json::Value. static constexpr Int maxInt = Int(UInt(-1) / 2); /// Maximum unsigned int value that can be stored in a Json::Value. static constexpr UInt maxUInt = UInt(-1); #if defined(JSON_HAS_INT64) /// Minimum signed 64 bits int value that can be stored in a Json::Value. static constexpr Int64 minInt64 = Int64(~(UInt64(-1) / 2)); /// Maximum signed 64 bits int value that can be stored in a Json::Value. static constexpr Int64 maxInt64 = Int64(UInt64(-1) / 2); /// Maximum unsigned 64 bits int value that can be stored in a Json::Value. static constexpr UInt64 maxUInt64 = UInt64(-1); #endif // defined(JSON_HAS_INT64) /// Default precision for real value for string representation. static constexpr UInt defaultRealPrecision = 17; // The constant is hard-coded because some compiler have trouble // converting Value::maxUInt64 to a double correctly (AIX/xlC). // Assumes that UInt64 is a 64 bits integer. static constexpr double maxUInt64AsDouble = 18446744073709551615.0; // Workaround for bug in the NVIDIAs CUDA 9.1 nvcc compiler // when using gcc and clang backend compilers. CZString // cannot be defined as private. See issue #486 #ifdef __NVCC__ public: #else private: #endif #ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION class CZString { public: enum DuplicationPolicy { noDuplication = 0, duplicate, duplicateOnCopy }; CZString(ArrayIndex index); CZString(char const* str, unsigned length, DuplicationPolicy allocate); CZString(CZString const& other); CZString(CZString&& other); ~CZString(); CZString& operator=(const CZString& other); CZString& operator=(CZString&& other); bool operator<(CZString const& other) const; bool operator==(CZString const& other) const; ArrayIndex index() const; // const char* c_str() const; ///< \deprecated char const* data() const; unsigned length() const; bool isStaticString() const; private: void swap(CZString& other); struct StringStorage { unsigned policy_ : 2; unsigned length_ : 30; // 1GB max }; char const* cstr_; // actually, a prefixed string, unless policy is noDup union { ArrayIndex index_; StringStorage storage_; }; }; public: #ifndef JSON_USE_CPPTL_SMALLMAP typedef std::map ObjectValues; #else typedef CppTL::SmallMap ObjectValues; #endif // ifndef JSON_USE_CPPTL_SMALLMAP #endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION public: /** * \brief Create a default Value of the given type. * * This is a very useful constructor. * To create an empty array, pass arrayValue. * To create an empty object, pass objectValue. * Another Value can then be set to this one by assignment. * This is useful since clear() and resize() will not alter types. * * Examples: * \code * Json::Value null_value; // null * Json::Value arr_value(Json::arrayValue); // [] * Json::Value obj_value(Json::objectValue); // {} * \endcode */ Value(ValueType type = nullValue); Value(Int value); Value(UInt value); #if defined(JSON_HAS_INT64) Value(Int64 value); Value(UInt64 value); #endif // if defined(JSON_HAS_INT64) Value(double value); Value(const char* value); ///< Copy til first 0. (NULL causes to seg-fault.) Value(const char* begin, const char* end); ///< Copy all, incl zeroes. /** * \brief Constructs a value from a static string. * * Like other value string constructor but do not duplicate the string for * internal storage. The given string must remain alive after the call to * this constructor. * * \note This works only for null-terminated strings. (We cannot change the * size of this class, so we have nowhere to store the length, which might be * computed later for various operations.) * * Example of usage: * \code * static StaticString foo("some text"); * Json::Value aValue(foo); * \endcode */ Value(const StaticString& value); Value(const String& value); #ifdef JSON_USE_CPPTL Value(const CppTL::ConstString& value); #endif Value(bool value); Value(const Value& other); Value(Value&& other); ~Value(); /// \note Overwrite existing comments. To preserve comments, use /// #swapPayload(). Value& operator=(const Value& other); Value& operator=(Value&& other); /// Swap everything. void swap(Value& other); /// Swap values but leave comments and source offsets in place. void swapPayload(Value& other); /// copy everything. void copy(const Value& other); /// copy values but leave comments and source offsets in place. void copyPayload(const Value& other); ValueType type() const; /// Compare payload only, not comments etc. bool operator<(const Value& other) const; bool operator<=(const Value& other) const; bool operator>=(const Value& other) const; bool operator>(const Value& other) const; bool operator==(const Value& other) const; bool operator!=(const Value& other) const; int compare(const Value& other) const; const char* asCString() const; ///< Embedded zeroes could cause you trouble! #if JSONCPP_USING_SECURE_MEMORY unsigned getCStringLength() const; // Allows you to understand the length of // the CString #endif String asString() const; ///< Embedded zeroes are possible. /** Get raw char* of string-value. * \return false if !string. (Seg-fault if str or end are NULL.) */ bool getString(char const** begin, char const** end) const; #ifdef JSON_USE_CPPTL CppTL::ConstString asConstString() const; #endif Int asInt() const; UInt asUInt() const; #if defined(JSON_HAS_INT64) Int64 asInt64() const; UInt64 asUInt64() const; #endif // if defined(JSON_HAS_INT64) LargestInt asLargestInt() const; LargestUInt asLargestUInt() const; float asFloat() const; double asDouble() const; bool asBool() const; bool isNull() const; bool isBool() const; bool isInt() const; bool isInt64() const; bool isUInt() const; bool isUInt64() const; bool isIntegral() const; bool isDouble() const; bool isNumeric() const; bool isString() const; bool isArray() const; bool isObject() const; bool isConvertibleTo(ValueType other) const; /// Number of values in array or object ArrayIndex size() const; /// \brief Return true if empty array, empty object, or null; /// otherwise, false. bool empty() const; /// Return !isNull() JSONCPP_OP_EXPLICIT operator bool() const; /// Remove all object members and array elements. /// \pre type() is arrayValue, objectValue, or nullValue /// \post type() is unchanged void clear(); /// Resize the array to newSize elements. /// New elements are initialized to null. /// May only be called on nullValue or arrayValue. /// \pre type() is arrayValue or nullValue /// \post type() is arrayValue void resize(ArrayIndex newSize); //@{ /// Access an array element (zero based index). If the array contains less /// than index element, then null value are inserted in the array so that /// its size is index+1. /// (You may need to say 'value[0u]' to get your compiler to distinguish /// this from the operator[] which takes a string.) Value& operator[](ArrayIndex index); Value& operator[](int index); //@} //@{ /// Access an array element (zero based index). /// (You may need to say 'value[0u]' to get your compiler to distinguish /// this from the operator[] which takes a string.) const Value& operator[](ArrayIndex index) const; const Value& operator[](int index) const; //@} /// If the array contains at least index+1 elements, returns the element /// value, otherwise returns defaultValue. Value get(ArrayIndex index, const Value& defaultValue) const; /// Return true if index < size(). bool isValidIndex(ArrayIndex index) const; /// \brief Append value to array at the end. /// /// Equivalent to jsonvalue[jsonvalue.size()] = value; Value& append(const Value& value); Value& append(Value&& value); /// Access an object value by name, create a null member if it does not exist. /// \note Because of our implementation, keys are limited to 2^30 -1 chars. /// Exceeding that will cause an exception. Value& operator[](const char* key); /// Access an object value by name, returns null if there is no member with /// that name. const Value& operator[](const char* key) const; /// Access an object value by name, create a null member if it does not exist. /// \param key may contain embedded nulls. Value& operator[](const String& key); /// Access an object value by name, returns null if there is no member with /// that name. /// \param key may contain embedded nulls. const Value& operator[](const String& key) const; /** \brief Access an object value by name, create a null member if it does not * exist. * * If the object has no entry for that name, then the member name used to * store the new entry is not duplicated. * Example of use: * \code * Json::Value object; * static const StaticString code("code"); * object[code] = 1234; * \endcode */ Value& operator[](const StaticString& key); #ifdef JSON_USE_CPPTL /// Access an object value by name, create a null member if it does not exist. Value& operator[](const CppTL::ConstString& key); /// Access an object value by name, returns null if there is no member with /// that name. const Value& operator[](const CppTL::ConstString& key) const; #endif /// Return the member named key if it exist, defaultValue otherwise. /// \note deep copy Value get(const char* key, const Value& defaultValue) const; /// Return the member named key if it exist, defaultValue otherwise. /// \note deep copy /// \note key may contain embedded nulls. Value get(const char* begin, const char* end, const Value& defaultValue) const; /// Return the member named key if it exist, defaultValue otherwise. /// \note deep copy /// \param key may contain embedded nulls. Value get(const String& key, const Value& defaultValue) const; #ifdef JSON_USE_CPPTL /// Return the member named key if it exist, defaultValue otherwise. /// \note deep copy Value get(const CppTL::ConstString& key, const Value& defaultValue) const; #endif /// Most general and efficient version of isMember()const, get()const, /// and operator[]const /// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30 Value const* find(char const* begin, char const* end) const; /// Most general and efficient version of object-mutators. /// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30 /// \return non-zero, but JSON_ASSERT if this is neither object nor nullValue. Value* demand(char const* begin, char const* end); /// \brief Remove and return the named member. /// /// Do nothing if it did not exist. /// \pre type() is objectValue or nullValue /// \post type() is unchanged void removeMember(const char* key); /// Same as removeMember(const char*) /// \param key may contain embedded nulls. void removeMember(const String& key); /// Same as removeMember(const char* begin, const char* end, Value* removed), /// but 'key' is null-terminated. bool removeMember(const char* key, Value* removed); /** \brief Remove the named map member. * * Update 'removed' iff removed. * \param key may contain embedded nulls. * \return true iff removed (no exceptions) */ bool removeMember(String const& key, Value* removed); /// Same as removeMember(String const& key, Value* removed) bool removeMember(const char* begin, const char* end, Value* removed); /** \brief Remove the indexed array element. * * O(n) expensive operations. * Update 'removed' iff removed. * \return true if removed (no exceptions) */ bool removeIndex(ArrayIndex index, Value* removed); /// Return true if the object has a member named key. /// \note 'key' must be null-terminated. bool isMember(const char* key) const; /// Return true if the object has a member named key. /// \param key may contain embedded nulls. bool isMember(const String& key) const; /// Same as isMember(String const& key)const bool isMember(const char* begin, const char* end) const; #ifdef JSON_USE_CPPTL /// Return true if the object has a member named key. bool isMember(const CppTL::ConstString& key) const; #endif /// \brief Return a list of the member names. /// /// If null, return an empty list. /// \pre type() is objectValue or nullValue /// \post if type() was nullValue, it remains nullValue Members getMemberNames() const; //# ifdef JSON_USE_CPPTL // EnumMemberNames enumMemberNames() const; // EnumValues enumValues() const; //# endif /// \deprecated Always pass len. [[deprecated("Use setComment(String const&) instead.")]] void setComment(const char* comment, CommentPlacement placement) { setComment(String(comment, strlen(comment)), placement); } /// Comments must be //... or /* ... */ void setComment(const char* comment, size_t len, CommentPlacement placement) { setComment(String(comment, len), placement); } /// Comments must be //... or /* ... */ void setComment(String comment, CommentPlacement placement); bool hasComment(CommentPlacement placement) const; /// Include delimiters and embedded newlines. String getComment(CommentPlacement placement) const; String toStyledString() const; const_iterator begin() const; const_iterator end() const; iterator begin(); iterator end(); // Accessors for the [start, limit) range of bytes within the JSON text from // which this value was parsed, if any. void setOffsetStart(ptrdiff_t start); void setOffsetLimit(ptrdiff_t limit); ptrdiff_t getOffsetStart() const; ptrdiff_t getOffsetLimit() const; private: void setType(ValueType v) { bits_.value_type_ = static_cast(v); } bool isAllocated() const { return bits_.allocated_; } void setIsAllocated(bool v) { bits_.allocated_ = v; } void initBasic(ValueType type, bool allocated = false); void dupPayload(const Value& other); void releasePayload(); void dupMeta(const Value& other); Value& resolveReference(const char* key); Value& resolveReference(const char* key, const char* end); // struct MemberNamesTransform //{ // typedef const char *result_type; // const char *operator()( const CZString &name ) const // { // return name.c_str(); // } //}; union ValueHolder { LargestInt int_; LargestUInt uint_; double real_; bool bool_; char* string_; // if allocated_, ptr to { unsigned, char[] }. ObjectValues* map_; } value_; struct { // Really a ValueType, but types should agree for bitfield packing. unsigned int value_type_ : 8; // Unless allocated_, string_ must be null-terminated. unsigned int allocated_ : 1; } bits_; class Comments { public: Comments() = default; Comments(const Comments& that); Comments(Comments&& that); Comments& operator=(const Comments& that); Comments& operator=(Comments&& that); bool has(CommentPlacement slot) const; String get(CommentPlacement slot) const; void set(CommentPlacement slot, String s); private: using Array = std::array; std::unique_ptr ptr_; }; Comments comments_; // [start, limit) byte offsets in the source JSON text from which this Value // was extracted. ptrdiff_t start_; ptrdiff_t limit_; }; /** \brief Experimental and untested: represents an element of the "path" to * access a node. */ class JSON_API PathArgument { public: friend class Path; PathArgument(); PathArgument(ArrayIndex index); PathArgument(const char* key); PathArgument(const String& key); private: enum Kind { kindNone = 0, kindIndex, kindKey }; String key_; ArrayIndex index_{}; Kind kind_{kindNone}; }; /** \brief Experimental and untested: represents a "path" to access a node. * * Syntax: * - "." => root node * - ".[n]" => elements at index 'n' of root node (an array value) * - ".name" => member named 'name' of root node (an object value) * - ".name1.name2.name3" * - ".[0][1][2].name1[3]" * - ".%" => member name is provided as parameter * - ".[%]" => index is provided as parameter */ class JSON_API Path { public: Path(const String& path, const PathArgument& a1 = PathArgument(), const PathArgument& a2 = PathArgument(), const PathArgument& a3 = PathArgument(), const PathArgument& a4 = PathArgument(), const PathArgument& a5 = PathArgument()); const Value& resolve(const Value& root) const; Value resolve(const Value& root, const Value& defaultValue) const; /// Creates the "path" to access the specified node and returns a reference on /// the node. Value& make(Value& root) const; private: typedef std::vector InArgs; typedef std::vector Args; void makePath(const String& path, const InArgs& in); void addPathInArg(const String& path, const InArgs& in, InArgs::const_iterator& itInArg, PathArgument::Kind kind); static void invalidPath(const String& path, int location); Args args_; }; /** \brief base class for Value iterators. * */ class JSON_API ValueIteratorBase { public: typedef std::bidirectional_iterator_tag iterator_category; typedef unsigned int size_t; typedef int difference_type; typedef ValueIteratorBase SelfType; bool operator==(const SelfType& other) const { return isEqual(other); } bool operator!=(const SelfType& other) const { return !isEqual(other); } difference_type operator-(const SelfType& other) const { return other.computeDistance(*this); } /// Return either the index or the member name of the referenced value as a /// Value. Value key() const; /// Return the index of the referenced Value, or -1 if it is not an /// arrayValue. UInt index() const; /// Return the member name of the referenced Value, or "" if it is not an /// objectValue. /// \note Avoid `c_str()` on result, as embedded zeroes are possible. String name() const; /// Return the member name of the referenced Value. "" if it is not an /// objectValue. /// \deprecated This cannot be used for UTF-8 strings, since there can be /// embedded nulls. [[deprecated("Use `key = name();` instead.")]] char const* memberName() const; /// Return the member name of the referenced Value, or NULL if it is not an /// objectValue. /// \note Better version than memberName(). Allows embedded nulls. char const* memberName(char const** end) const; protected: Value& deref() const; void increment(); void decrement(); difference_type computeDistance(const SelfType& other) const; bool isEqual(const SelfType& other) const; void copy(const SelfType& other); private: Value::ObjectValues::iterator current_; // Indicates that iterator is for a null value. bool isNull_{true}; public: // For some reason, BORLAND needs these at the end, rather // than earlier. No idea why. ValueIteratorBase(); explicit ValueIteratorBase(const Value::ObjectValues::iterator& current); }; /** \brief const iterator for object and array value. * */ class JSON_API ValueConstIterator : public ValueIteratorBase { friend class Value; public: typedef const Value value_type; // typedef unsigned int size_t; // typedef int difference_type; typedef const Value& reference; typedef const Value* pointer; typedef ValueConstIterator SelfType; ValueConstIterator(); ValueConstIterator(ValueIterator const& other); private: /*! \internal Use by Value to create an iterator. */ explicit ValueConstIterator(const Value::ObjectValues::iterator& current); public: SelfType& operator=(const ValueIteratorBase& other); SelfType operator++(int) { SelfType temp(*this); ++*this; return temp; } SelfType operator--(int) { SelfType temp(*this); --*this; return temp; } SelfType& operator--() { decrement(); return *this; } SelfType& operator++() { increment(); return *this; } reference operator*() const { return deref(); } pointer operator->() const { return &deref(); } }; /** \brief Iterator for object and array value. */ class JSON_API ValueIterator : public ValueIteratorBase { friend class Value; public: typedef Value value_type; typedef unsigned int size_t; typedef int difference_type; typedef Value& reference; typedef Value* pointer; typedef ValueIterator SelfType; ValueIterator(); explicit ValueIterator(const ValueConstIterator& other); ValueIterator(const ValueIterator& other); private: /*! \internal Use by Value to create an iterator. */ explicit ValueIterator(const Value::ObjectValues::iterator& current); public: SelfType& operator=(const SelfType& other); SelfType operator++(int) { SelfType temp(*this); ++*this; return temp; } SelfType operator--(int) { SelfType temp(*this); --*this; return temp; } SelfType& operator--() { decrement(); return *this; } SelfType& operator++() { increment(); return *this; } reference operator*() const { return deref(); } pointer operator->() const { return &deref(); } }; inline void swap(Value& a, Value& b) { a.swap(b); } } // namespace Json #pragma pack(pop) #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) #pragma warning(pop) #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) #endif // CPPTL_JSON_H_INCLUDED