| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*  dictionary.cpp                                                       */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*                       This file is part of:                           */ | 
					
						
							|  |  |  | /*                           GODOT ENGINE                                */ | 
					
						
							|  |  |  | /*                    http://www.godotengine.org                         */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur.                 */ | 
					
						
							|  |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* Permission is hereby granted, free of charge, to any person obtaining */ | 
					
						
							|  |  |  | /* a copy of this software and associated documentation files (the       */ | 
					
						
							|  |  |  | /* "Software"), to deal in the Software without restriction, including   */ | 
					
						
							|  |  |  | /* without limitation the rights to use, copy, modify, merge, publish,   */ | 
					
						
							|  |  |  | /* distribute, sublicense, and/or sell copies of the Software, and to    */ | 
					
						
							|  |  |  | /* permit persons to whom the Software is furnished to do so, subject to */ | 
					
						
							|  |  |  | /* the following conditions:                                             */ | 
					
						
							|  |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* The above copyright notice and this permission notice shall be        */ | 
					
						
							|  |  |  | /* included in all copies or substantial portions of the Software.       */ | 
					
						
							|  |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */ | 
					
						
							|  |  |  | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */ | 
					
						
							|  |  |  | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ | 
					
						
							|  |  |  | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */ | 
					
						
							|  |  |  | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */ | 
					
						
							|  |  |  | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */ | 
					
						
							|  |  |  | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | #include "dictionary.h"
 | 
					
						
							|  |  |  | #include "safe_refcount.h"
 | 
					
						
							|  |  |  | #include "variant.h"
 | 
					
						
							|  |  |  | #include "io/json.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct _DictionaryVariantHash { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	static _FORCE_INLINE_ uint32_t hash(const Variant &p_variant)  { return p_variant.hash(); } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct DictionaryPrivate { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	SafeRefCount refcount; | 
					
						
							|  |  |  | 	HashMap<Variant,Variant,_DictionaryVariantHash> variant_map; | 
					
						
							|  |  |  | 	bool shared; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Dictionary::get_key_list( List<Variant> *p_keys) const { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	_p->variant_map.get_key_list(p_keys); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Dictionary::_copy_on_write() const { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	//make a copy of what we have
 | 
					
						
							|  |  |  | 	if (_p->shared) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	DictionaryPrivate *p = memnew(DictionaryPrivate); | 
					
						
							|  |  |  | 	p->shared=_p->shared; | 
					
						
							|  |  |  | 	p->variant_map=_p->variant_map; | 
					
						
							|  |  |  | 	p->refcount.init(); | 
					
						
							|  |  |  | 	_unref(); | 
					
						
							|  |  |  | 	_p=p; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Variant& Dictionary::operator[](const Variant& p_key) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	_copy_on_write(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return _p->variant_map[p_key]; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const Variant& Dictionary::operator[](const Variant& p_key) const { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return _p->variant_map[p_key]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | const Variant* Dictionary::getptr(const Variant& p_key) const { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return _p->variant_map.getptr(p_key); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | Variant* Dictionary::getptr(const Variant& p_key) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	_copy_on_write(); | 
					
						
							|  |  |  | 	return _p->variant_map.getptr(p_key); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Variant Dictionary::get_valid(const Variant& p_key) const { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	const Variant *v = getptr(p_key); | 
					
						
							|  |  |  | 	if (!v) | 
					
						
							|  |  |  | 		return Variant(); | 
					
						
							|  |  |  | 	return *v; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int Dictionary::size() const { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return _p->variant_map.size(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | bool Dictionary::empty() const { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return !_p->variant_map.size(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool Dictionary::has(const Variant& p_key) const { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return _p->variant_map.has(p_key); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | void Dictionary::erase(const Variant& p_key) { | 
					
						
							|  |  |  | 	_copy_on_write(); | 
					
						
							|  |  |  | 	_p->variant_map.erase(p_key); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool Dictionary::operator==(const Dictionary& p_dictionary) const { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return _p==p_dictionary._p; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Dictionary::_ref(const Dictionary& p_from) const { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	//make a copy first (thread safe)
 | 
					
						
							|  |  |  | 	if (!p_from._p->refcount.ref()) | 
					
						
							|  |  |  | 		return; // couldn't copy
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	//if this is the same, unreference the other one
 | 
					
						
							|  |  |  | 	if (p_from._p==_p) { | 
					
						
							|  |  |  | 		_p->refcount.unref(); | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (_p) | 
					
						
							|  |  |  | 		_unref(); | 
					
						
							|  |  |  | 	_p=p_from._p; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Dictionary::clear() { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	_copy_on_write(); | 
					
						
							|  |  |  | 	_p->variant_map.clear(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool Dictionary::is_shared() const { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return _p->shared; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Dictionary::_unref() const { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ERR_FAIL_COND(!_p); | 
					
						
							|  |  |  | 	if (_p->refcount.unref()) { | 
					
						
							|  |  |  | 		memdelete(_p); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	_p=NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | uint32_t Dictionary::hash() const { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return hash_djb2_one_64(make_uint64_t(_p)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Array Dictionary::keys() const { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Array karr; | 
					
						
							|  |  |  | 	karr.resize(size()); | 
					
						
							|  |  |  | 	const Variant *K=NULL; | 
					
						
							|  |  |  | 	int idx=0; | 
					
						
							|  |  |  | 	while((K=next(K))) { | 
					
						
							|  |  |  | 		karr[idx++]=(*K); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return karr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const Variant* Dictionary::next(const Variant* p_key) const { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return _p->variant_map.next(p_key); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Error Dictionary::parse_json(const String& p_json) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	String errstr; | 
					
						
							|  |  |  | 	int errline=0; | 
					
						
							| 
									
										
										
										
											2015-01-02 13:31:25 +02:00
										 |  |  | 	if (p_json != ""){ | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	Error err = JSON::parse(p_json,*this,errstr,errline); | 
					
						
							|  |  |  | 	if (err!=OK) { | 
					
						
							|  |  |  | 		ERR_EXPLAIN("Error parsing JSON: "+errstr+" at line: "+itos(errline)); | 
					
						
							|  |  |  | 		ERR_FAIL_COND_V(err!=OK,err); | 
					
						
							| 
									
										
										
										
											2015-01-02 13:31:25 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return OK; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | String Dictionary::to_json() const { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return JSON::print(*this); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Dictionary::operator=(const Dictionary& p_dictionary) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	_ref(p_dictionary); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Dictionary::Dictionary(const Dictionary& p_from) { | 
					
						
							|  |  |  | 	_p=NULL; | 
					
						
							|  |  |  | 	_ref(p_from); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Dictionary::Dictionary(bool p_shared) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	_p=memnew( DictionaryPrivate ); | 
					
						
							|  |  |  | 	_p->refcount.init(); | 
					
						
							|  |  |  | 	_p->shared=p_shared; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | Dictionary::~Dictionary() { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	_unref(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 |