00001 /* 00002 Copyright (c) 2012, The Cinder Project 00003 All rights reserved. 00004 00005 This code is designed for use with the Cinder C++ library, http://libcinder.org 00006 00007 Redistribution and use in source and binary forms, with or without modification, are permitted provided that 00008 the following conditions are met: 00009 00010 * Redistributions of source code must retain the above copyright notice, this list of conditions and 00011 the following disclaimer. 00012 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and 00013 the following disclaimer in the documentation and/or other materials provided with the distribution. 00014 00015 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED 00016 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 00017 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 00018 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 00019 TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00020 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00021 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00022 POSSIBILITY OF SUCH DAMAGE. 00023 */ 00024 00025 #pragma once 00026 00027 #include "cinder/DataSource.h" 00028 #include "cinder/DataTarget.h" 00029 #include "cinder/Exception.h" 00030 #include "cinder/Utilities.h" 00031 00032 #include <iterator> 00033 #include <string> 00034 #include <list> 00035 00036 namespace Json { 00037 class Value; 00038 } 00039 00040 namespace cinder { 00041 00042 class JsonTree { 00043 public: 00044 00046 typedef std::list<JsonTree>::const_iterator ConstIter; 00047 typedef std::list<JsonTree>::iterator Iter; 00049 00051 00052 private: 00053 00055 typedef enum 00056 { 00057 NODE_UNKNOWN, NODE_NULL, NODE_ARRAY, NODE_OBJECT, NODE_VALUE 00058 } NodeType; 00059 00060 typedef enum 00061 { 00062 VALUE_BOOL, VALUE_DOUBLE, VALUE_INT, VALUE_STRING, VALUE_UINT 00063 } ValueType; 00065 00067 00068 public: 00069 00071 class ParseOptions { 00072 public: 00074 ParseOptions(); 00076 ParseOptions& ignoreErrors( bool ignore = true ); 00078 bool getIgnoreErrors() const; 00079 00080 private: 00082 bool mIgnoreErrors; 00084 00085 }; 00086 00088 class WriteOptions { 00089 public: 00091 WriteOptions(); 00093 WriteOptions& createDocument( bool createDocument = true ); 00095 WriteOptions& indented( bool indent = true ); 00097 bool getCreateDocument() const; 00099 bool getIndented() const; 00100 00101 private: 00103 bool mCreateDocument; 00104 bool mIndented; 00106 00107 }; 00108 00110 00112 explicit JsonTree(); 00114 JsonTree( const JsonTree &jsonTree ); 00117 explicit JsonTree( DataSourceRef dataSource, ParseOptions parseOptions = ParseOptions() ); 00119 explicit JsonTree( const std::string &jsonString, ParseOptions parseOptions = ParseOptions() ); 00121 explicit JsonTree( const std::string &key, bool value ); 00123 explicit JsonTree( const std::string &key, double value ); 00125 explicit JsonTree( const std::string &key, float value ); 00127 explicit JsonTree( const std::string &key, int value ); 00129 explicit JsonTree( const std::string &key, const std::string &value ); 00131 explicit JsonTree( const std::string &key, const char *value ); 00133 explicit JsonTree( const std::string &key, uint32_t value ); 00135 explicit JsonTree( const std::string &key, int64_t value ); 00137 explicit JsonTree( const std::string &key, uint64_t value ); 00138 00140 static JsonTree makeArray( const std::string &key = "" ); 00142 static JsonTree makeObject( const std::string &key = "" ); 00143 00145 00147 std::string serialize() const; 00148 00150 Iter begin(); 00152 ConstIter begin() const; 00154 Iter end(); 00156 ConstIter end() const; 00157 00159 JsonTree& operator=( const JsonTree &jsonTree ); 00160 00163 JsonTree& operator[]( const std::string &relativePath ); 00166 const JsonTree& operator[]( const std::string &relativePath ) const; 00168 JsonTree& operator[]( size_t index ); 00170 const JsonTree& operator[]( size_t index ) const; 00172 friend std::ostream& operator<<( std::ostream &out, const JsonTree &json ); 00173 00176 JsonTree& getChild( const std::string &relativePath, bool caseSensitive = false, char separator = '.' ); 00179 const JsonTree& getChild( const std::string &relativePath, bool caseSensitive = false, char separator = '.' ) const; 00181 JsonTree& getChild( size_t index ); 00183 const JsonTree& getChild( size_t index ) const; 00185 const std::list<JsonTree>& getChildren() const; 00186 00189 bool hasChild( const std::string &relativePath, bool caseSensitive = false, char separator = '.' ) const; 00191 bool hasChildren() const; 00192 00194 JsonTree& getParent(); 00196 const JsonTree& getParent() const; 00198 bool hasParent() const; 00199 00201 void clear(); 00206 void pushBack( const JsonTree &newChild ); 00208 void removeChild( size_t index ); 00210 Iter removeChild( Iter pos ); 00212 void replaceChild( size_t index, const JsonTree &newChild ); 00214 void replaceChild( Iter pos, const JsonTree &newChild ); 00215 00219 void write( const fs::path &path, WriteOptions writeOptions = WriteOptions() ); 00223 void write( DataTargetRef target, WriteOptions writeOptions = WriteOptions() ); 00224 00226 const std::string& getKey() const; 00227 00229 std::string getPath( char separator = '.' ) const; 00230 00233 template <typename T> 00234 inline T getValue() const 00235 { 00236 try { 00237 return fromString<T>( mValue ); 00238 } catch ( boost::bad_lexical_cast &) { 00239 throw ExcNonConvertible( * this ); 00240 } 00241 return (T)0; // Unreachable. Prevents warning. 00242 } 00243 00245 const std::string& getValue() const { return mValue; } 00246 00247 private: 00248 00250 explicit JsonTree( const std::string &key, const Json::Value &value ); 00251 00252 Json::Value createNativeDoc( WriteOptions writeOptions = WriteOptions() ) const; 00253 static Json::Value deserializeNative( const std::string &jsonString, ParseOptions parseOptions ); 00254 static std::string serializeNative( const Json::Value &value ); 00255 00256 void init( const std::string &key, const Json::Value &value, bool setType = false, 00257 NodeType nodeType = NODE_VALUE, ValueType valueType = VALUE_STRING ); 00258 00259 JsonTree* getNodePtr( const std::string &relativePath, bool caseSensitive, char separator ) const; 00260 static bool isIndex( const std::string &key ); 00261 00262 std::list<JsonTree> mChildren; 00263 std::string mKey; 00264 JsonTree *mParent; 00265 NodeType mNodeType; 00266 std::string mValue; 00267 ValueType mValueType; 00269 00270 public: 00271 00273 00275 class Exception : public cinder::Exception 00276 { 00277 }; 00278 00280 class ExcChildNotFound : public JsonTree::Exception { 00281 public: 00282 ExcChildNotFound( const JsonTree &node, const std::string &key ) throw(); 00283 virtual const char* what() const throw() 00284 { 00285 return mMessage; 00286 } 00287 00288 private: 00289 char mMessage[ 2048 ]; 00290 }; 00291 00293 class ExcNonConvertible : public JsonTree::Exception { 00294 public: 00295 ExcNonConvertible( const JsonTree &node ) throw(); 00296 virtual const char* what() const throw() 00297 { 00298 return mMessage; 00299 } 00300 00301 private: 00302 char mMessage[ 2048 ]; 00303 }; 00304 00306 class ExcJsonParserError : public JsonTree::Exception { 00307 public: 00308 ExcJsonParserError( const std::string &errorMessage ) throw(); 00309 virtual const char* what() const throw() 00310 { 00311 return mMessage; 00312 } 00313 00314 private: 00315 char mMessage[ 2048 ]; 00316 }; 00317 00318 }; 00319 00320 std::ostream& operator<<( std::ostream &out, const JsonTree &json ); 00321 00322 }