Skip to content

Commit

Permalink
Merge branch 'json'
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewfb committed Mar 26, 2012
2 parents de8e058 + b58a467 commit f64bbfc
Show file tree
Hide file tree
Showing 34 changed files with 9,964 additions and 1,213 deletions.
294 changes: 294 additions & 0 deletions include/cinder/Json.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,294 @@
/*
Copyright (c) 2012, The Cinder Project
All rights reserved.
This code is designed for use with the Cinder C++ library, http://libcinder.org
Redistribution and use in source and binary forms, with or without modification, are permitted provided that
the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and
the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/

#pragma once

#include "cinder/DataSource.h"
#include "cinder/DataTarget.h"
#include "cinder/Exception.h"
#include "cinder/Utilities.h"

#include <iterator>
#include <string>
#include <list>

namespace Json {
class Value;
}

namespace cinder {

class JsonTree {
public:

//! \cond
typedef std::list<JsonTree>::const_iterator ConstIter;
typedef std::list<JsonTree>::iterator Iter;
//! \endcond

/////////////////////////////////////////////////////////////////////////////////////////////////////////////

private:

//! \cond
typedef enum
{
NODE_UNKNOWN, NODE_NULL, NODE_ARRAY, NODE_OBJECT, NODE_VALUE
} NodeType;

typedef enum
{
VALUE_BOOL, VALUE_DOUBLE, VALUE_INT, VALUE_STRING, VALUE_UINT
} ValueType;
//! \endcond

/////////////////////////////////////////////////////////////////////////////////////////////////////////////

public:

//! Options for JSON parsing. Passed to the JsonTree constructor.
class ParseOptions {
public:
//! Default options. Enables parsing errors.
ParseOptions();
//! Sets if JSON parse errors are ignored. Default \c false.
ParseOptions& ignoreErrors( bool ignore = true );
//! Returns whether JSON parse errors are ignored.
bool getIgnoreErrors() const;

private:
//! \cond
bool mIgnoreErrors;
//! \endcond

};

/////////////////////////////////////////////////////////////////////////////////////////////////////////////

//! Creates a null JsonTree.
explicit JsonTree();
//! Parses the JSON contained in the string \a xmlString
JsonTree( const JsonTree &jsonTree );
/** \brief Parses JSON contained in \a dataSource. Commonly used with the results of loadUrl(), loadFile() or loadResource().
<br><tt>JsonTree myDoc( loadUrl( "http://search.twitter.com/search.json?q=libcinder&rpp=10&result_type=recent" ) );</tt> **/
explicit JsonTree( DataSourceRef dataSource, ParseOptions parseOptions = ParseOptions() );
//! Parses the JSON contained in the string \a jsonString .
explicit JsonTree( const std::string &jsonString, ParseOptions parseOptions = ParseOptions() );
//! Creates a JsonTree with key \a key and boolean \a value .
explicit JsonTree( const std::string &key, bool value );
//! Creates a JsonTree with key \a key and double \a value .
explicit JsonTree( const std::string &key, double value );
//! Creates a JsonTree with key \a key and double \a value cast from float.
explicit JsonTree( const std::string &key, float value );
//! Creates a JsonTree with key \a key and int \a value .
explicit JsonTree( const std::string &key, int value );
//! Creates a JsonTree with key \a key and string \a value .
explicit JsonTree( const std::string &key, const std::string &value );
//! Creates a JsonTree with key \a key and string \a value cast from const char*.
explicit JsonTree( const std::string &key, const char *value );
//! Creates a JsonTree with key \a key and uint32_t \a value .
explicit JsonTree( const std::string &key, uint32_t value );

/**! Creates a JsonTree with key \a key and an empty array. **/
static JsonTree makeArray( const std::string &key = "" );
/**! Creates a JsonTree with key \a key as an empty object. **/
static JsonTree makeObject( const std::string &key = "" );

/////////////////////////////////////////////////////////////////////////////////////////////////////////////

//! Returns the JsonTree as a string with standard formatting.
std::string serialize() const;

//! Returns an Iter to the first child of this node.
Iter begin();
//! Returns a ConstIter to the first child of this node.
ConstIter begin() const;
//! Returns an Iter which marks the end of the children of this node.
Iter end();
//! Returns a ConstIter which marks the end of the children of this node.
ConstIter end() const;

//! Assigns the JsonTree a new value, and creates it if it doesn't exist.
JsonTree& operator=( const JsonTree &jsonTree );

/**! Returns the child at \a relativePath. Throws ExcChildNotFound if none matches.
<br><tt>JsonTree node = myNode[ "path.to.child" ];</tt> **/
JsonTree& operator[]( const std::string &relativePath );
/**! Returns the child at \a relativePath. Throws ExcChildNotFound if none matches.
<br><tt>JsonTree node = myNode[ "path.to.child" ];</tt> **/
const JsonTree& operator[]( const std::string &relativePath ) const;
//! Returns the child at \a index. Throws ExcChildNotFound if none matches.
JsonTree& operator[]( size_t index );
//! Returns the child at \a index. Throws ExcChildNotFound if none matches.
const JsonTree& operator[]( size_t index ) const;
//! Streams the JsonTree \a json to std::ostream \a out with standard formatting.
friend std::ostream& operator<<( std::ostream &out, const JsonTree &json );

/**! Returns the child at \a relativePath. Throws ExcChildNotFound if none matches.
<br><tt>JsonTree node = myNode.getChild( "path.to.child" );</tt> **/
JsonTree& getChild( const std::string &relativePath, bool caseSensitive = false, char separator = '.' );
/**! Returns the child at \a relativePath. Throws ExcChildNotFound if none matches.
<br><tt>JsonTree node = myNode.getChild( "path.to.child" );</tt> **/
const JsonTree& getChild( const std::string &relativePath, bool caseSensitive = false, char separator = '.' ) const;
//! Returns the child at \a index. Throws ExcChildNotFound if none matches.
JsonTree& getChild( size_t index );
//! Returns the child at \a index. Throws ExcChildNotFound if none matches.
const JsonTree& getChild( size_t index ) const;
//! Returns a reference to the node's list of children nodes.
const std::list<JsonTree>& getChildren() const;

/**! Returns whether the child at \a relativePath exists.
<br><tt>bool nodeExists = myNode.hasChild( "path.to.child" );</tt> **/
bool hasChild( const std::string &relativePath, bool caseSensitive = false, char separator = '.' ) const;
//! Returns whether this node has a parent node.
bool hasChildren() const;

//! Returns a reference to the node which is the parent of this node.
JsonTree& getParent();
//! Returns a reference to the node which is the parent of this node.
const JsonTree& getParent() const;
//! Returns whether this node has a parent node.
bool hasParent() const;

//! Removes all child nodes
void clear();
/**! Appends a copy of the node \a newChild to the children of this node.
If \a this is a value node, it will change to an object or an array.
If \a newChild has a key, \a this becomes an object node.
If not, \a this becomes an array node. **/
void pushBack( const JsonTree &newChild );
//! Removes the child at \a index. Throws ExcChildNotFound if none matches.
void removeChild( size_t index );
//! Removes the child at \a pos. Throws ExcChildNotFound if none matches.
Iter removeChild( Iter pos );
//! Repalces the child at \a index with JsonTree \a newChild. Throws ExcChildNotFound if none matches.
void replaceChild( size_t index, const JsonTree &newChild );
//! Repalces the child at \a pos with JsonTree \a newChild. Throws ExcChildNotFound if none matches.
void replaceChild( Iter pos, const JsonTree &newChild );

/**! Writes this JsonTree to \a path with standard formatting.
If \a createDocument is true then an implicit parent object node is created when necessary and \a this is treated as the root element. **/
void write( const fs::path &path, bool createDocument = true );
/**! Writes this JsonTree to \a target with standard formatting.
If \a createDocument is true then an implicit parent object node is created when necessary and \a this is treated as the root element. **/
void write( DataTargetRef target, bool createDocument = true );

//! Returns the node's key as a string. Returns index if node does not have a key.
const std::string& getKey() const;

/**! Returns a path to this node, separated by the character \a separator. **/
std::string getPath( char separator = '.' ) const;

/**! \brief Returns the value of the node cast to T using ci::fromString().
<br><tt>float value = myNode.getValue<float>( "key" );</tt> **/
template <typename T>
inline T getValue() const
{
try {
return fromString<T>( mValue );
} catch ( boost::bad_lexical_cast &) {
throw ExcNonConvertible( * this );
}
return (T)0; // Unreachable. Prevents warning.
}

//! Returns the value of the node.
const std::string& getValue() const { return mValue; }

private:

//! \cond
explicit JsonTree( const std::string &key, const Json::Value &value );

Json::Value createNativeDoc( bool createDocument = false ) const;
static Json::Value deserializeNative( const std::string &jsonString, ParseOptions parseOptions );
static std::string serializeNative( const Json::Value &value );

void init( const std::string &key, const Json::Value &value, bool setType = false,
NodeType nodeType = NODE_VALUE, ValueType valueType = VALUE_STRING );

JsonTree* getNodePtr( const std::string &relativePath, bool caseSensitive, char separator ) const;
static bool isIndex( const std::string &key );

std::list<JsonTree> mChildren;
std::string mKey;
JsonTree *mParent;
NodeType mNodeType;
std::string mValue;
ValueType mValueType;
//! \cond

public:

/////////////////////////////////////////////////////////////////////////////////////////////////////////////

//! Base class for JsonTree exceptions.
class Exception : public cinder::Exception
{
};

//! Exception expressing the absence of an expected child node.
class ExcChildNotFound : public JsonTree::Exception {
public:
ExcChildNotFound( const JsonTree &node, const std::string &key ) throw();
virtual const char* what() const throw()
{
return mMessage;
}

private:
char mMessage[ 2048 ];
};

//! Exception expressing the inability to convert a node's value to a requested type.
class ExcNonConvertible : public JsonTree::Exception {
public:
ExcNonConvertible( const JsonTree &node ) throw();
virtual const char* what() const throw()
{
return mMessage;
}

private:
char mMessage[ 2048 ];
};

//! Exception expressing the existence of errors when serializing or deserializing JSON.
class ExcJsonParserError : public JsonTree::Exception {
public:
ExcJsonParserError( const std::string &errorMessage ) throw();
virtual const char* what() const throw()
{
return mMessage;
}

private:
char mMessage[ 2048 ];
};

};

std::ostream& operator<<( std::ostream &out, const JsonTree &json );

}
24 changes: 24 additions & 0 deletions include/json/autolink.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright 2007-2010 Baptiste Lepilleur
// 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 JSON_AUTOLINK_H_INCLUDED
# define JSON_AUTOLINK_H_INCLUDED

# include "config.h"

# ifdef JSON_IN_CPPTL
# include <cpptl/cpptl_autolink.h>
# endif

# if !defined(JSON_NO_AUTOLINK) && !defined(JSON_DLL_BUILD) && !defined(JSON_IN_CPPTL)
# define CPPTL_AUTOLINK_NAME "json"
# undef CPPTL_AUTOLINK_DLL
# ifdef JSON_DLL
# define CPPTL_AUTOLINK_DLL
# endif
# include "autolink.h"
# endif

#endif // JSON_AUTOLINK_H_INCLUDED
Loading

0 comments on commit f64bbfc

Please sign in to comment.