Skip to content

Commit

Permalink
Merge pull request cocos2d#2361 from tiantian20007/dictStuff
Browse files Browse the repository at this point in the history
Implement CCDictionary::writeToFile();
  • Loading branch information
minggo committed May 7, 2013
2 parents ff610ee + 2ba5035 commit ea5d7bc
Show file tree
Hide file tree
Showing 10 changed files with 393 additions and 2 deletions.
6 changes: 6 additions & 0 deletions cocos2dx/cocoa/CCDictionary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -415,4 +415,10 @@ CCDictionary* CCDictionary::createWithContentsOfFile(const char *pFileName)
return pRet;
}

bool CCDictionary::writeToFile(const char *fullPath)
{
return CCFileUtils::sharedFileUtils()->writeToFile(this, fullPath);
}


NS_CC_END
9 changes: 8 additions & 1 deletion cocos2dx/cocoa/CCDictionary.h
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,14 @@ class CC_DLL CCDictionary : public CCObject
* @see create(), createWithDictionary(CCDictionary*), createWithContentsOfFileThreadSafe(const char*).
*/
static CCDictionary* createWithContentsOfFile(const char *pFileName);


/**
* Write a dictionary to a plist file.
* @param fullPath The full path of the plist file. You can get writeable path by getWritablePath()
* @return true if successed, false if failed
*/
bool writeToFile(const char *fullPath);

/**
* Create a dictionary with a plist file.
*
Expand Down
119 changes: 119 additions & 0 deletions cocos2dx/platform/CCFileUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ THE SOFTWARE.
#include "cocoa/CCDictionary.h"
#include "cocoa/CCString.h"
#include "CCSAXParser.h"
#include "support/tinyxml2/tinyxml2.h"
#include "support/zip_support/unzip.h"
#include <stack>

Expand Down Expand Up @@ -326,11 +327,129 @@ CCArray* CCFileUtils::createCCArrayWithContentsOfFile(const std::string& filenam
return tMaker.arrayWithContentsOfFile(fullPath.c_str());
}

/*
* forward statement
*/
static tinyxml2::XMLElement* generateElementForArray(cocos2d::CCArray *array, tinyxml2::XMLDocument *pDoc);
static tinyxml2::XMLElement* generateElementForDict(cocos2d::CCDictionary *dict, tinyxml2::XMLDocument *pDoc);

/*
* Use tinyxml2 to write plist files
*/
bool CCFileUtils::writeToFile(cocos2d::CCDictionary *dict, const std::string &fullPath)
{
//CCLOG("tinyxml2 CCDictionary %d writeToFile %s", dict->m_uID, fullPath.c_str());
tinyxml2::XMLDocument *pDoc = new tinyxml2::XMLDocument();
if (NULL == pDoc)
return false;

tinyxml2::XMLDeclaration *pDeclaration = pDoc->NewDeclaration("xml version=\"1.0\" encoding=\"UTF-8\"");
if (NULL == pDeclaration)
{
delete pDoc;
return false;
}

pDoc->LinkEndChild(pDeclaration);
tinyxml2::XMLElement *docType = pDoc->NewElement("!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\"");
pDoc->LinkEndChild(docType);

tinyxml2::XMLElement *pRootEle = pDoc->NewElement("plist");
pRootEle->SetAttribute("version", "1.0");
if (NULL == pRootEle)
{
delete pDoc;
return false;
}
pDoc->LinkEndChild(pRootEle);

tinyxml2::XMLElement *innerDict = generateElementForDict(dict, pDoc);
if (NULL == innerDict )
{
delete pDoc;
return false;
}
pRootEle->LinkEndChild(innerDict);

bool bRet = tinyxml2::XML_SUCCESS == pDoc->SaveFile(fullPath.c_str());

delete pDoc;
return bRet;
}

/*
* Generate tinyxml2::XMLElement for CCObject through a tinyxml2::XMLDocument
*/
static tinyxml2::XMLElement* generateElementForObject(cocos2d::CCObject *object, tinyxml2::XMLDocument *pDoc)
{
// object is CCString
if (CCString *str = dynamic_cast<CCString *>(object))
{
tinyxml2::XMLElement* node = pDoc->NewElement("string");
tinyxml2::XMLText* content = pDoc->NewText(str->getCString());
node->LinkEndChild(content);
return node;
}

// object is CCArray
if (CCArray *array = dynamic_cast<CCArray *>(object))
return generateElementForArray(array, pDoc);

// object is CCDictionary
if (CCDictionary *innerDict = dynamic_cast<CCDictionary *>(object))
return generateElementForDict(innerDict, pDoc);

CCLOG("This type cannot appear in property list");
return NULL;
}

/*
* Generate tinyxml2::XMLElement for CCDictionary through a tinyxml2::XMLDocument
*/
static tinyxml2::XMLElement* generateElementForDict(cocos2d::CCDictionary *dict, tinyxml2::XMLDocument *pDoc)
{
tinyxml2::XMLElement* rootNode = pDoc->NewElement("dict");

CCDictElement *dictElement = NULL;
CCDICT_FOREACH(dict, dictElement)
{
tinyxml2::XMLElement* tmpNode = pDoc->NewElement("key");
rootNode->LinkEndChild(tmpNode);
tinyxml2::XMLText* content = pDoc->NewText(dictElement->getStrKey());
tmpNode->LinkEndChild(content);

CCObject *object = dictElement->getObject();
tinyxml2::XMLElement *element = generateElementForObject(object, pDoc);
if (element)
rootNode->LinkEndChild(element);
}
return rootNode;
}

/*
* Generate tinyxml2::XMLElement for CCArray through a tinyxml2::XMLDocument
*/
static tinyxml2::XMLElement* generateElementForArray(cocos2d::CCArray *array, tinyxml2::XMLDocument *pDoc)
{
tinyxml2::XMLElement* rootNode = pDoc->NewElement("array");

CCObject *object = NULL;
CCARRAY_FOREACH(array, object)
{
tinyxml2::XMLElement *element = generateElementForObject(object, pDoc);
if (element)
rootNode->LinkEndChild(element);
}
return rootNode;
}


#else
NS_CC_BEGIN

/* The subclass CCFileUtilsIOS and CCFileUtilsMac should override these two method. */
CCDictionary* CCFileUtils::createCCDictionaryWithContentsOfFile(const std::string& filename) {return NULL;}
bool CCFileUtils::writeToFile(cocos2d::CCDictionary *dict, const std::string &fullPath) {return NULL;}
CCArray* CCFileUtils::createCCArrayWithContentsOfFile(const std::string& filename) {return NULL;}

#endif /* (CC_TARGET_PLATFORM != CC_PLATFORM_IOS) && (CC_TARGET_PLATFORM != CC_PLATFORM_MAC) */
Expand Down
6 changes: 6 additions & 0 deletions cocos2dx/platform/CCFileUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,12 @@ class CC_DLL CCFileUtils : public TypeInfo
*/
virtual CCDictionary* createCCDictionaryWithContentsOfFile(const std::string& filename);

/**
* Write a dictionary to a plist file.
* @note This method is used internally.
*/
virtual bool writeToFile(CCDictionary *dict, const std::string& fullPath);

/**
* Creates an array by the contents of a file.
* @note This method is used internally.
Expand Down
2 changes: 2 additions & 0 deletions cocos2dx/platform/ios/CCFileUtilsIOS.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ class CC_DLL CCFileUtilsIOS : public CCFileUtils
virtual std::string getFullPathForDirectoryAndFilename(const std::string& strDirectory, const std::string& strFilename);

virtual CCDictionary* createCCDictionaryWithContentsOfFile(const std::string& filename);
virtual bool writeToFile(CCDictionary *dict, const std::string& fullPath);

virtual CCArray* createCCArrayWithContentsOfFile(const std::string& filename);
};

Expand Down
90 changes: 90 additions & 0 deletions cocos2dx/platform/ios/CCFileUtilsIOS.mm
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ of this software and associated documentation files (the "Software"), to deal
NS_CC_BEGIN

static void addValueToCCDict(id key, id value, CCDictionary* pDict);
static void addCCObjectToNSDict(const char*key, CCObject* object, NSMutableDictionary *dict);

static void addItemToCCArray(id item, CCArray *pArray)
{
Expand Down Expand Up @@ -86,6 +87,40 @@ static void addItemToCCArray(id item, CCArray *pArray)
}
}

static void addCCObjectToNSArray(CCObject *object, NSMutableArray *array)
{
// add string into array
if (CCString *ccString = dynamic_cast<CCString *>(object)) {
NSString *strElement = [NSString stringWithCString:ccString->getCString() encoding:NSUTF8StringEncoding];
[array addObject:strElement];
return;
}

// add array into array
if (CCArray *ccArray = dynamic_cast<CCArray *>(object)) {
NSMutableArray *arrElement = [NSMutableArray array];
CCObject *element = NULL;
CCARRAY_FOREACH(ccArray, element)
{
addCCObjectToNSArray(element, arrElement);
}
[array addObject:arrElement];
return;
}

// add dictionary value into array
if (CCDictionary *ccDict = dynamic_cast<CCDictionary *>(object)) {
NSMutableDictionary *dictElement = [NSMutableDictionary dictionary];
CCDictElement *element = NULL;
CCDICT_FOREACH(ccDict, element)
{
addCCObjectToNSDict(element->getStrKey(), element->getObject(), dictElement);
}
[array addObject:dictElement];
}

}

static void addValueToCCDict(id key, id value, CCDictionary* pDict)
{
// the key must be a string
Expand Down Expand Up @@ -136,6 +171,43 @@ static void addValueToCCDict(id key, id value, CCDictionary* pDict)
}
}

static void addCCObjectToNSDict(const char * key, CCObject* object, NSMutableDictionary *dict)
{
NSString *NSkey = [NSString stringWithCString:key encoding:NSUTF8StringEncoding];

// the object is a CCDictionary
if (CCDictionary *ccDict = dynamic_cast<CCDictionary *>(object)) {
NSMutableDictionary *dictElement = [NSMutableDictionary dictionary];
CCDictElement *element = NULL;
CCDICT_FOREACH(ccDict, element)
{
addCCObjectToNSDict(element->getStrKey(), element->getObject(), dictElement);
}

[dict setObject:dictElement forKey:NSkey];
return;
}

// the object is a CCString
if (CCString *element = dynamic_cast<CCString *>(object)) {
NSString *strElement = [NSString stringWithCString:element->getCString() encoding:NSUTF8StringEncoding];
[dict setObject:strElement forKey:NSkey];
return;
}

// the object is a CCArray
if (CCArray *ccArray = dynamic_cast<CCArray *>(object)) {
NSMutableArray *arrElement = [NSMutableArray array];
CCObject *element = NULL;
CCARRAY_FOREACH(ccArray, element)
{
addCCObjectToNSArray(element, arrElement);
}
[dict setObject:arrElement forKey:NSkey];
return;
}
}

CCFileUtils* CCFileUtils::sharedFileUtils()
{
if (s_sharedFileUtils == NULL)
Expand Down Expand Up @@ -244,6 +316,24 @@ static void addValueToCCDict(id key, id value, CCDictionary* pDict)
return pRet;
}

bool CCFileUtilsIOS::writeToFile(CCDictionary *dict, const std::string &fullPath)
{
//CCLOG("iOS||Mac CCDictionary %d write to file %s", dict->m_uID, fullPath.c_str());
NSMutableDictionary *nsDict = [NSMutableDictionary dictionary];

CCDictElement *element = NULL;
CCDICT_FOREACH(dict, element)
{
addCCObjectToNSDict(element->getStrKey(), element->getObject(), nsDict);
}

NSString *file = [NSString stringWithUTF8String:fullPath.c_str()];
// do it atomically
[nsDict writeToFile:file atomically:YES];

return true;
}

CCArray* CCFileUtilsIOS::createCCArrayWithContentsOfFile(const std::string& filename)
{
// NSString* pPath = [NSString stringWithUTF8String:pFileName];
Expand Down
2 changes: 2 additions & 0 deletions cocos2dx/platform/mac/CCFileUtilsMac.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ class CC_DLL CCFileUtilsMac : public CCFileUtils
virtual std::string getFullPathForDirectoryAndFilename(const std::string& strDirectory, const std::string& strFilename);

virtual CCDictionary* createCCDictionaryWithContentsOfFile(const std::string& filename);
virtual bool writeToFile(CCDictionary *dict, const std::string& fullPath);

virtual CCArray* createCCArrayWithContentsOfFile(const std::string& filename);

};
Expand Down
Loading

0 comments on commit ea5d7bc

Please sign in to comment.