#ifndef CPPTL_JSON_H_INCLUDED
# define CPPTL_JSON_H_INCLUDED
# include "json_forwards.h"
# include <string>
# include <map>
# include <vector>
# ifdef JSON_USE_CPPTL
# include <cpptl/forwards.h>
# endif
namespace Json {
class Value;
/** \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
};
# ifdef JSON_USE_CPPTL
typedef CppTL::AnyEnumerator<const char *> EnumMemberNames;
typedef CppTL::AnyEnumerator<const Value &> EnumValues;
# endif
/** \brief Represents a <a HREF="/?originalUrl=https%3A%2F%2Fsourceforge.net%2F%26quot%3Bhttp%3A%2F%2Fwww.json.org%26quot%3B%26gt%3BJSON%26lt%3B%2Fa%26gt%3B%2520value.%253C%2Fspan">
*
* 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 resize and initialized
* with #nullValue. resize() can be used to enlarge or truncate an #arrayValue.
*
* The get() methods can be used to obtanis default value in the case the required element
* does not exist.
*
* It is possible to iterate over the list of a #objectValue values using
* the getMemberNames() method.
*/
class JSON_API Value
{
public:
typedef std::vector<std::string> Members;
typedef int Int;
typedef unsigned int UInt;
static const Value null;
static const Int minInt;
static const Int maxInt;
static const UInt maxUInt;
Value( ValueType type = nullValue );
Value( Int value );
Value( UInt value );
Value( double value );
Value( const char *value );
Value( const std::string &value );
# ifdef JSON_USE_CPPTL
Value( const CppTL::ConstString &value );
# endif
Value( bool value );
Value( const Value &other );
~Value();
Value &operator=( const Value &other );
void swap( Value &other );
ValueType type() 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;
bool operator !=( const Value &other ) const;
int compare( const Value &other );
const char *asCString() const;
std::string asString() const;
# ifdef JSON_USE_CPPTL
CppTL::ConstString asConstString() const;
# endif
Int asInt() const;
UInt asUInt() const;
double asDouble() const;
bool asBool() const;
bool isBool() const;
bool isInt() const;
bool isUInt() 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
UInt size() const;
/// Removes all object members and array elements.
void clear();
/// Resize the array to size elements.
/// New elements are initialized to null.
/// May only be called on nullValue or arrayValue.
void resize( UInt size );
/// 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.
Value &operator[]( UInt index );
/// Access an array element (zero based index )
const Value &operator[]( UInt index ) const;
/// If the array contains at least index+1 elements, returns the element value,
/// otherwise returns defaultValue.
Value get( UInt index,
const Value &defaultValue ) const;
/// Returns true if index < size().
bool isValidIndex( UInt index ) const;
/// Append value to array at the end.
/// Equivalent to jsonvalue[jsonvalue.size()] = value;
Value &append( const Value &value );
// Access an object value by name, create a null member if it does not exist.
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.
Value &operator[]( const std::string &key );
// Access an object value by name, returns null if there is no member with that name.
const Value &operator[]( const std::string &key ) const;
# 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
/// Returns the member named key if it exist, defaultValue otherwise.
Value get( const char *key,
const Value &defaultValue ) const;
/// Returns the member named key if it exist, defaultValue otherwise.
Value get( const std::string &key,
const Value &defaultValue ) const;
# ifdef JSON_USE_CPPTL
/// Returns the member named key if it exist, defaultValue otherwise.
Value get( const CppTL::ConstString &key,
const Value &defaultValue ) const;
# endif
/// Returns true if the object has a member named key.
bool isMember( const char *key ) const;
/// Returns true if the object has a member named key.
bool isMember( const std::string &key ) const;
# ifdef JSON_USE_CPPTL
/// Returns true if the object has a member named key.
bool isMember( const CppTL::ConstString &key ) const;
# endif
// Returns a list of the member names.
Members getMemberNames() const;
# ifdef JSON_USE_CPPTL
EnumMemberNames enumMemberNames() const;
EnumValues enumValues() const;
# endif
void setComment( const char *comment,
CommentPlacement placement );
void setComment( const std::string &comment,
CommentPlacement placement );
bool hasComment( CommentPlacement placement ) const;
std::string getComment( CommentPlacement placement ) const;
std::string toStyledString() const;
private:
struct CommentInfo
{
CommentInfo();
~CommentInfo();
void setComment( const char *text );
char *comment_;
};
struct CZString
{
enum DuplicationPolicy
{
noDuplication = 0,
duplicate,
duplicateOnCopy
};
CZString( int index );
CZString( const char *cstr, DuplicationPolicy allocate );
CZString( const CZString &other );
~CZString();
CZString &operator =( const CZString &other );
bool operator<( const CZString &other ) const;
bool operator==( const CZString &other ) const;
int index() const;
const char *c_str() const;
private:
void swap( CZString &other );
const char *cstr_;
int index_;
};
typedef std::map<CZString, Value> ObjectValues;
struct MemberNamesTransform
{
typedef const char *result_type;
const char *operator()( const CZString &name ) const
{
return name.c_str();
}
};
union ValueHolder
{
Int int_;
UInt uint_;
double real_;
bool bool_;
char *string_;
ObjectValues *map_;
} value_;
ValueType type_;
CommentInfo *comments_;
};
/** \brief Experimental and untested: represents an element of the "path" to access a node.
*/
class PathArgument
{
public:
friend class Path;
PathArgument();
PathArgument( Value::UInt index );
PathArgument( const char *key );
PathArgument( const std::string &key );
private:
enum Kind
{
kindNone = 0,
kindIndex,
kindKey
};
std::string key_;
Value::UInt index_;
Kind kind_;
};
/** \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 provied as parameter
*/
class Path
{
public:
Path( const std::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<const PathArgument *> InArgs;
typedef std::vector<PathArgument> Args;
void makePath( const std::string &path,
const InArgs &in );
void addPathInArg( const std::string &path,
const InArgs &in,
InArgs::const_iterator &itInArg,
PathArgument::Kind kind );
void invalidPath( const std::string &path,
int location );
Args args_;
};
} // namespace Json
#endif // CPPTL_JSON_H_INCLUDED