本文来自http://blog.csdn.net/runaying ,引用必须注明出处!
cocos2d-X 节点(CCDictionary)API
///\cocos2d-x-3.0alpha0\cocos2dx\cocoa
#ifndef __CCDICTIONARY_H__
#define __CCDICTIONARY_H__
#include "support/data_support/uthash.h"
#include "CCObject.h"
#include "CCArray.h"
#include "CCString.h"
NS_CC_BEGIN
class Dictionary;
/**
* @addtogroup data_structures
* @{
*/
/**
* DictElement 元素用于遍历字典。
*
* 一个 DictElement 是一个 Dictionary 元素, 它包含两个属性关键字和对象
* 他的关键字(DictElement 存储的对象将根据他索引)有两个类型 (整数或字符串).
*
* @note 在字典中的所有元素具有相同的密钥类型(整数或字符串)。
* @code
* DictElement* pElement;
* CCDICT_FOREACH(dict, pElement)
* {
* const char*key = pElement->getStrKey();
* // 你知道类型的值是什么,我们假设他是一个 Sprite.
* Sprite* pSprite = static_cast<Sprite*>(pElement->getObject());
* // ......
* }
* @endcode
*
*/
class CC_DLL DictElement
{
private:
/**
* DictElement 的构造函数.他只在这个类的内部使用.字典对其它的 class 都很友好,可以存储他们.
*
* @param pszKey 这个元素的关键字
* @param pObject 这个元素的对象.
*/
DictElement(const char* pszKey, Object* pObject);
/**
* DictElement 的构造函数.他只在这个类的内部使用.字典对其它的 class 都很友好,可以存储他们.
*
* @param iKey 这个元素的关键字
* @param pObject 这个元素的对象.
*/
DictElement(intptr_t iKey, Object* pObject);
public:
/**
* DictElement的析构函数.
* @js NA
* @lua NA
*/
~DictElement();
// Inline functions need to be implemented in header file on Android.
/**
* Get 获取这个元素的 String 类型的关键字
* @note 这个方法假设你知道关键字的类型
* 如果这个元素的关键字是一个 integer 类型,使用此方法将抛出一个异常
*
* @return 这个元素的关键字(String).
*/
inline const char* getStrKey() const
{
CCASSERT(_strKey[0] != '\0', "Should not call this function for integer dictionary");
return _strKey;
}
/**
* Get 获取这个元素的 integer 类型的关键字
* @note 这个方法假设你知道关键字的类型
* 如果这个元素的关键字是一个 integer 类型,使用此方法将抛出一个异常
*
* @return 这个元素的关键字(Integer).
*/
inline intptr_t getIntKey() const
{
CCASSERT(_strKey[0] == '\0', "Should not call this function for string dictionary");
return _intKey;
}
/**
* Get 这个元素所存储的对象
*
* @return 这个元素所存储的对象
*/
inline Object* getObject() const { return _object; }
private:
// 关键字的最大长度(String )
#define MAX_KEY_LEN 256
// 在 UT_HASH 的 HASH_ADD_STR 数组(String类型的关键字初始化需要一个数组长度)
//这是非常糟糕的,因为所有的元素数组都要分配 256 bytes ,
char _strKey[MAX_KEY_LEN]; //字符串类型的哈希键(String)
intptr_t _intKey; // 整数类型的哈希键(integer )
Object* _object; // 哈希值
public:
UT_hash_handle hh; // 制作这个类的 hashable
friend class Dictionary; // 声明一个字典类
};
/** 遍历字典的宏
*
* @note 使用它获取所有关键字对应的对象,比使用 objectForKey 更快.
* 他还可以在查找元素的时候安全删除元素.
*/
#define CCDICT_FOREACH(__dict__, __el__) \
DictElement* pTmp##__dict__##__el__ = nullptr; \
if (__dict__) \
HASH_ITER(hh, (__dict__)->_elements, __el__, pTmp##__dict__##__el__)
/**
* Dictionary 就像 Obj-C 里面的 NSDictionary 对象.
*
* @note 只有 对象或其子类 可以插入到 Dictionary.
* @code
* // 创建一个 dictionary 对象, return a一个自动释放的对象.
* Dictionary* pDict = Dictionary::create();
*
* // 插入一个 dictionary 对象
* String* pValue1 = String::create("100");
* String* pValue2 = String::create("120");
* Integer* pValue3 = Integer::create(200);
* pDict->setObject(pValue1, "key1");
* pDict->setObject(pValue2, "key2");
* pDict->setObject(pValue3, "key3");
*
* // Get 关键字所对应的对象
* String* pStr1 = (String*)pDict->objectForKey("key1");
* log("{ key1: %s }", pStr1->getCString());
* Integer* pInteger = (Integer*)pDict->objectForKey("key3");
* log("{ key3: %d }", pInteger->getValue());
* @endcode
*
*/
class CC_DLL Dictionary : public Object, public Clonable
{
public:
/**
* Dictionary 的构造函数.
* @js NA
* @lua NA
*/
Dictionary();
/**
* Dictionary 的析构函数
* @js NA
* @lua NA
*/
~Dictionary();
/** 初始化一个字典. returns true 如果初始化成功.
* @js NA
* @lua NA
*/
bool init();
/**
* Get Dictionary 元素的总数.
*
* @return The count of elements.
* @js NA
*/
unsigned int count();
/**
* Return 所有元素的关键字.
*
* @return 该数组包含所有元素所对应的关键字。这是一个自动释放对象。
* @js NA
*/
Array* allKeys();
/**
* Get 所有指定的对象所对应的关键字.
* @warning 我们使用 '=='比较两个对象
* @return 该数组包含所有元素所包含的对象。这是一个自动释放对象。
* @js NA
*/
Array* allKeysForObject(Object* object);
/**
* Get 指定关键字所对应的对象.
*
* @note 这个 dictionary 需要使用 string 作为关键字,如果使用 integer 作为关键字会抛出异常.
* @param key 搜索的关键字.
* @return 关键字所对应的 object. 你需要把它强制类型准换成它原有的数据类型
* @code
* // 假设元素是 String* 类型的指针。使用下面的代码准换.
* String* pStr = (String*)pDict->objectForKey("key1");
* //对 pStr 做一些处理.
* // 如果你不知道 object 的类型, 你就需要使用 dynamic_cast<SomeType*>来检查她了.
* String* pStr2 = dynamic_cast<String*>(pDict->objectForKey("key1"));
* if (pStr2 != NULL) {
* // 再对 pStr2 做一些处理
* }
* @endcode
* @see objectForKey(intptr_t)
* @js NA
*/
Object* objectForKey(const std::string& key);
/**
* Get 指定关键字所对应的对象.
*
* @note e 这个 dictionary 需要使用 integer 作为关键字,如果使用 String 作为关键字会抛出异常.
* @param key 搜索的关键字.
* @return 和关键字匹配的对象.
* @see objectForKey(const std::string&)
* @js NA
*/
Object* objectForKey(intptr_t key);
/** Get指定关键字所对应的对象(string).
*
* @note 使用这个功能时要小心,因为它假设在 dictonary 里面的对象是 string* 指针.
* @param key 搜索的关键字.
* @return 一个实例(string).
* 如果对象不是一个String 指针或者通过关键字没有找到,他会返回一个空string .
* @see valueForKey(intptr_t)
* @js NA
*/
const String* valueForKey(const std::string& key);
/** Get 指定关键字所对应的对象(integer).
*
* @note 使用这个功能时要小心,因为它假设在 dictonary 里面的对象是 string* 指针.
* @param key 搜索的关键字.
* @return 一个实例(string).
* 如果对象不是一个String 指针或者通过关键字没有找到,他会返回一个空string .
* @see valueForKey(intptr_t)
* @js NA
*/
const String* valueForKey(intptr_t key);
/** 匹配关键字并在 dictionary 的相应位置插入一个对象.
*
* @note 第一次调用这个方法时关键字类型会被设置成 string 类型.
* 当然你不可以使用 integer 类型的数据来作为 setObject 的关键字.
* 如果 dictionary 包含了你使用的关键字,那么和关键字匹配的对象会从 dictionary 里面移除,并释放.
* 然后一个新的对象会插入到关键字所在的位置。
*
* @param pObject 要插入的对象.
* @param key 搜索的关键字.
* @see setObject(Object*, intptr_t)
* @js NA
*/
void setObject(Object* pObject, const std::string& key);
/** 匹配关键字并在 dictionary 的相应位置插入一个对象.
*
* @note 第一次调用这个方法时关键字类型会被设置成 integer 类型.
* 当然你不可以使用 integer 类型的数据来作为 string 的关键字.
* 如果 dictionary 包含了你使用的关键字,那么和关键字匹配的对象会从 dictionary 里面移除,并释放.
* 然后一个新的对象会插入到关键字所在的位置。
* @param pObject 要插入的对象.
* @param key 搜索的关键字.
* @see setObject(Object*, const std::string&)
* @js NA
*/
void setObject(Object* pObject, intptr_t key);
/**
* Remove 移除关键字(string)所对应的对象.
*
* @param key 搜索的关键字(string).
* @see removeObjectForKey(intptr_t), removeObjectsForKeys(Array*),
* removeObjectForElememt(DictElement*), removeAllObjects().
* @js NA
*/
void removeObjectForKey(const std::string& key);
/**
* Remove 移除关键字(integer)所对应的对象.
*
* @param key 搜索的关键字(integer).
* @see removeObjectForKey(const std::string&), removeObjectsForKeys(Array*),
* removeObjectForElememt(DictElement*), removeAllObjects().
* @js NA
*/
void removeObjectForKey(intptr_t key);
/**
* Remove 一组 keys(关键字)所对应的对象.
*
* @param pKeyArray 这一组 keys(关键字)所对应的对象会被移除.
* @see removeObjectForKey(const std::string&), removeObjectForKey(intptr_t),
* removeObjectForElememt(DictElement*), removeAllObjects().
* @js NA
*/
void removeObjectsForKeys(Array* pKeyArray);
/**
* Remove 元素多对应的对象.
*
* @param pElement 需要移除的元素.
* @see removeObjectForKey(const std::string&), removeObjectForKey(intptr_t),
* removeObjectsForKeys(Array*), removeAllObjects().
* @js NA
* @lua NA
*/
void removeObjectForElememt(DictElement* pElement);
/**
* Remove dictionary 里面的所有对象.
*
* @see removeObjectForKey(const std::string&), removeObjectForKey(intptr_t),
* removeObjectsForKeys(Array*), removeObjectForElememt(DictElement*).
* @js NA
*/
void removeAllObjects();
/**
* Return 一个随机的 dictionary 对象.
*
* @return 随机的 dictionary 对象.
* @see objectForKey(intptr_t), objectForKey(const std::string&)
* @js NA
* @lua NA
*/
Object* randomObject();
/**
* Create 一个 dictionary.
* @return A dictionary which is an autorelease object.
* @see createWithDictionary(Dictionary*), createWithContentsOfFile(const char*), createWithContentsOfFileThreadSafe(const char*).
* @js NA
*/
static Dictionary* create();
/**
* 使用现有的 dictionary 对象创建一个 dictionary.
*
* @param srcDict 现有的 dictionary.
* @return 一个自动释放的 dictionary 对象.
* @see create(), createWithContentsOfFile(const char*), createWithContentsOfFileThreadSafe(const char*).
* @js NA
*/
static Dictionary* createWithDictionary(Dictionary* srcDict);
/**
* 从 plist file'(一种 ios 支持的配置文件)创建一个 dictionary
* @param pFileName plist file (一种 ios 支持的配置文件)的名字.
* @return 一个自动释放的 dictionary 对象.
* @see create(), createWithDictionary(Dictionary*), createWithContentsOfFileThreadSafe(const char*).
* @js NA
*/
static Dictionary* createWithContentsOfFile(const char *pFileName);
/**
* 把 dictionary字典对象写入到一个 plist file (一种 ios 支持的配置文件).
* @param fullPath 完整的 plist file(一种 ios 支持的配置文件)路径. 你可以使用 getWritablePath() 得到一个可写的路径。
* @return true if successed, false if failed
* @js NA
* @lua NA
*/
bool writeToFile(const char *fullPath);
/**
* 使用 plist file'(一种 ios 支持的配置文件)创建一个 dictionary
*
* @note返回的对象不是一个自动释放的对象.
* 这可以确保在一个新的线程里不使用自动释放池.
* 因此你需要管理返回对象的生命周期.
* 这意味着你不需要他是你需要调用 CC_SAFE_RELEASE .
*
* @param pFileName plist file (一种 ios 支持的配置文件)的名字.
* @return 一个不是自动释放的 dictionary 的对象.
* @js NA
* @lua NA
*/
static Dictionary* createWithContentsOfFileThreadSafe(const char *pFileName);
/* override functions
* @js NA
* @lua NA
*/
virtual void acceptVisitor(DataVisitor &visitor);
/**
* @js NA
* @lua NA
*/
virtual Dictionary* clone() const;
private:
/**
* 内部使用, 在 setObject 里面调用.
*/
void setObjectUnSafe(Object* pObject, const std::string& key);
void setObjectUnSafe(Object* pObject, const intptr_t key);
public:
/**
* dictionary 里面的所有元素.
*
* @note 内部使用, 我们需要把这个成员变量声明为 public 因为他在 UT_HASH 里面使用.
*/
DictElement* _elements;
private:
/** dictionary 支持的类型, 确认他们是在 setObject 里面被调用. */
enum DictType
{
kDictUnknown = 0,
kDictStr,
kDictInt
};
/**
* 字典类型, 默认情况下栽 kDictUnknown 里面分配
*/
DictType _dictType;
};
// end of data_structure group
/// @}
NS_CC_END
#endif /* __CCDICTIONARY_H__ */