fixed #2142: Adding CCDataVisitor and Implementing CCPrettyPrinter, iOS port is ok.

This commit is contained in:
James Chen 2013-05-10 15:07:05 +08:00
parent c25c89e5a8
commit cbafaf67a6
21 changed files with 509 additions and 4 deletions

View File

@ -391,4 +391,9 @@ CCObject* CCArray::copyWithZone(CCZone* pZone)
return pArray;
}
void CCArray::acceptVisitor(CCDataVisitor &visitor)
{
visitor.visit(this);
}
NS_CC_END

View File

@ -210,6 +210,9 @@ public:
/* override functions */
virtual CCObject* copyWithZone(CCZone* pZone);
/* override functions */
virtual void acceptVisitor(CCDataVisitor &visitor);
public:
ccArray* data;
CCArray();

View File

@ -50,6 +50,10 @@ public:
}
return pRet;
}
/* override functions */
virtual void acceptVisitor(CCDataVisitor &visitor) { visitor.visit(this); }
private:
bool m_bValue;
};

View File

@ -0,0 +1,227 @@
/****************************************************************************
Copyright (c) 2013 cocos2d-x.org
http://www.cocos2d-x.org
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 "CCObject.h"
#include "CCBool.h"
#include "CCInteger.h"
#include "CCFloat.h"
#include "CCDouble.h"
#include "CCString.h"
#include "CCArray.h"
#include "CCDictionary.h"
#include "CCSet.h"
NS_CC_BEGIN
void CCDataVisitor::visit(const CCBool *value)
{
visitObject(value);
}
void CCDataVisitor::visit(const CCInteger *value)
{
visitObject(value);
}
void CCDataVisitor::visit(const CCFloat *value)
{
visitObject(value);
}
void CCDataVisitor::visit(const CCDouble *value)
{
visitObject(value);
}
void CCDataVisitor::visit(const CCString *value)
{
visitObject(value);
}
void CCDataVisitor::visit(const CCArray *value)
{
visitObject(value);
}
void CCDataVisitor::visit(const CCDictionary *value)
{
visitObject(value);
}
void CCDataVisitor::visit(const CCSet *value)
{
visitObject(value);
}
// CCPrettyPrinter
CCPrettyPrinter::CCPrettyPrinter(int indentLevel/* = 0 */)
{
setIndentLevel(indentLevel);
}
void CCPrettyPrinter::clear()
{
_result.clear();
}
std::string CCPrettyPrinter::getResult()
{
return _result;
}
void CCPrettyPrinter::visitObject(const CCObject *p)
{
char buf[50] = {0};
sprintf(buf, "%p", p);
_result += buf;
}
void CCPrettyPrinter::visit(const CCBool * p)
{
char buf[50] = {0};
sprintf(buf, "%s", p->getValue() ? "true" : "false");
}
void CCPrettyPrinter::visit(const CCInteger *p)
{
char buf[50] = {0};
sprintf(buf, "%d", p->getValue());
_result += buf;
}
void CCPrettyPrinter::visit(const CCFloat *p)
{
char buf[50] = {0};
sprintf(buf, "%f", p->getValue());
_result += buf;
}
void CCPrettyPrinter::visit(const CCDouble *p)
{
char buf[50] = {0};
sprintf(buf, "%lf", p->getValue());
_result += buf;
}
void CCPrettyPrinter::visit(const CCString *p)
{
_result += p->getCString();
}
void CCPrettyPrinter::visit(const CCArray *p)
{
_result += "\n";
_result += _indentStr;
_result += "<array>\n";
setIndentLevel(_indentLevel+1);
CCObject* obj;
int i = 0;
char buf[50] = {0};
CCARRAY_FOREACH(p, obj)
{
if (i > 0) {
_result += "\n";
}
sprintf(buf, "%s%02d: ", _indentStr.c_str(), i);
_result += buf;
CCPrettyPrinter v(_indentLevel);
obj->acceptVisitor(v);
_result += v.getResult();
i++;
}
setIndentLevel(_indentLevel-1);
_result += "\n";
_result += _indentStr;
_result += "</array>";
}
void CCPrettyPrinter::visit(const CCDictionary *p)
{
_result += "\n";
_result += _indentStr;
_result += "<dict>\n";
setIndentLevel(_indentLevel+1);
CCDictElement* element;
bool bFirstElement = true;
char buf[1000] = {0};
CCDICT_FOREACH(p, element)
{
if (!bFirstElement) {
_result += "\n";
}
sprintf(buf, "%s%s: ", _indentStr.c_str(),element->getStrKey());
_result += buf;
CCPrettyPrinter v(_indentLevel);
element->getObject()->acceptVisitor(v);
_result += v.getResult();
bFirstElement = false;
}
setIndentLevel(_indentLevel-1);
_result += "\n";
_result += _indentStr;
_result += "</dict>";
}
void CCPrettyPrinter::visit(const CCSet *p)
{
_result += "\n";
_result += _indentStr;
_result += "<set>\n";
setIndentLevel(_indentLevel+1);
int i = 0;
CCSet* tmp = const_cast<CCSet*>(p);
CCSetIterator it = tmp->begin();
for (; it != tmp->end(); ++it, ++i) {
if (i > 0) {
_result += "\n";
}
_result += _indentStr.c_str();
CCPrettyPrinter v(_indentLevel);
(*it)->acceptVisitor(v);
_result += v.getResult();
}
setIndentLevel(_indentLevel-1);
_result += "\n";
_result += _indentStr;
_result += "</set>\n";
}
void CCPrettyPrinter::setIndentLevel(int indentLevel)
{
_indentLevel = indentLevel;
_indentStr.clear();
for (int i = 0; i < _indentLevel; ++i) {
_indentStr += "\t";
}
}
NS_CC_END

View File

@ -0,0 +1,110 @@
/****************************************************************************
Copyright (c) 2013 cocos2d-x.org
http://www.cocos2d-x.org
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.
****************************************************************************/
#ifndef __CCDATAVISITOR_H__
#define __CCDATAVISITOR_H__
#include "platform/CCPlatformMacros.h"
#include <string>
NS_CC_BEGIN
class CCObject;
class CCBool;
class CCInteger;
class CCFloat;
class CCDouble;
class CCString;
class CCArray;
class CCDictionary;
class CCSet;
/**
* @addtogroup data_structures
* @{
*/
/**
* Visitor that helps to perform action that depends on polymorphic object type
*
* Use cases:
* - data serialization,
* - pretty printing of \a CCObject *
* - safe value reading from \a CCArray, \a CCDictionary, \a CCSet
*
* Usage:
* 1. subclass CCDataVisitor
* 2. overload visit() methods for object that you need to handle
* 3. handle other objects in \a visitObject()
* 4. pass your visitor to \a CCObject::acceptVisitor()
*/
class CC_DLL CCDataVisitor
{
public:
virtual ~CCDataVisitor() {}
/** default method, called from non-overloaded methods and for unrecognized objects */
virtual void visitObject(const CCObject *p) = 0;
virtual void visit(const CCBool *p);
virtual void visit(const CCInteger *p);
virtual void visit(const CCFloat *p);
virtual void visit(const CCDouble *p);
virtual void visit(const CCString *p);
virtual void visit(const CCArray *p);
virtual void visit(const CCDictionary *p);
virtual void visit(const CCSet *p);
};
class CC_DLL CCPrettyPrinter : public CCDataVisitor
{
public:
CCPrettyPrinter(int indentLevel = 0);
virtual void clear();
virtual std::string getResult();
virtual void visitObject(const CCObject *p);
virtual void visit(const CCBool * p);
virtual void visit(const CCInteger *p);
virtual void visit(const CCFloat *p);
virtual void visit(const CCDouble *p);
virtual void visit(const CCString *p);
virtual void visit(const CCArray *p);
virtual void visit(const CCDictionary *p);
virtual void visit(const CCSet *p);
private:
void setIndentLevel(int indentLevel);
int _indentLevel;
std::string _indentStr;
std::string _result;
};
// end of data_structure group
/// @}
NS_CC_END
#endif // __CCDATAVISITOR_H__

View File

@ -408,6 +408,11 @@ CCDictionary* CCDictionary::createWithContentsOfFileThreadSafe(const char *pFile
return CCFileUtils::sharedFileUtils()->createCCDictionaryWithContentsOfFile(pFileName);
}
void CCDictionary::acceptVisitor(CCDataVisitor &visitor)
{
return visitor.visit(this);
}
CCDictionary* CCDictionary::createWithContentsOfFile(const char *pFileName)
{
CCDictionary* pRet = createWithContentsOfFileThreadSafe(pFileName);

View File

@ -382,6 +382,9 @@ public:
*/
static CCDictionary* createWithContentsOfFileThreadSafe(const char *pFileName);
/* override functions */
virtual void acceptVisitor(CCDataVisitor &visitor);
private:
/**
* For internal usage, invoked by setObject.

View File

@ -50,6 +50,10 @@ public:
}
return pRet;
}
/* override functions */
virtual void acceptVisitor(CCDataVisitor &visitor) { visitor.visit(this); }
private:
double m_dValue;
};

View File

@ -50,6 +50,10 @@ public:
}
return pRet;
}
/* override functions */
virtual void acceptVisitor(CCDataVisitor &visitor) { visitor.visit(this); }
private:
float m_fValue;
};

View File

@ -115,4 +115,9 @@ bool CCObject::isEqual(const CCObject *pObject)
return this == pObject;
}
void CCObject::acceptVisitor(CCDataVisitor &visitor)
{
visitor.visitObject(this);
}
NS_CC_END

View File

@ -25,7 +25,7 @@ THE SOFTWARE.
#ifndef __CCOBJECT_H__
#define __CCOBJECT_H__
#include "platform/CCPlatformMacros.h"
#include "CCDataVisitor.h"
#ifdef EMSCRIPTEN
#include <GLES2/gl2.h>
@ -73,6 +73,8 @@ public:
unsigned int retainCount(void) const;
virtual bool isEqual(const CCObject* pObject);
virtual void acceptVisitor(CCDataVisitor &visitor);
virtual void update(float dt) {CC_UNUSED_PARAM(dt);};
friend class CCAutoreleasePool;

View File

@ -56,6 +56,11 @@ CCSet::~CCSet(void)
CC_SAFE_DELETE(m_pSet);
}
void CCSet::acceptVisitor(CCDataVisitor &visitor)
{
visitor.visit(this);
}
CCSet * CCSet::create()
{
CCSet * pRet = new CCSet();

View File

@ -90,6 +90,8 @@ public:
*/
CCObject* anyObject();
virtual void acceptVisitor(CCDataVisitor &visitor);
private:
std::set<CCObject *> *m_pSet;
};

View File

@ -200,4 +200,9 @@ CCString* CCString::createWithContentsOfFile(const char* pszFileName)
return pRet;
}
void CCString::acceptVisitor(CCDataVisitor &visitor)
{
visitor.visit(this);
}
NS_CC_END

View File

@ -109,6 +109,8 @@ public:
*/
static CCString* createWithContentsOfFile(const char* pszFileName);
virtual void acceptVisitor(CCDataVisitor &visitor);
private:
/** only for internal use */

View File

@ -1 +1 @@
ab1a108831dfdc88ca340350536987da48bccfdc
89741f647de6b40616d5c45625fcd3c2d8e9d20a

View File

@ -0,0 +1,86 @@
#include "DataVisitorTest.h"
#include "../testResource.h"
std::string PrettyPrinterDemo::title()
{
return "PrettyPrinter Test";
}
std::string PrettyPrinterDemo::subtitle()
{
return "Please see log!";
}
void PrettyPrinterDemo::addSprite()
{
// create sprites
CCSprite *s1 = CCSprite::create("Images/grossini.png");
CCSprite *s2 = CCSprite::create("Images/grossini_dance_01.png");
CCSprite *s3 = CCSprite::create("Images/grossini_dance_02.png");
CCSprite *s4 = CCSprite::create("Images/grossini_dance_03.png");
CCSprite *s5 = CCSprite::create("Images/grossini_dance_04.png");
s1->setPosition(ccp(50, 50));
s2->setPosition(ccp(60, 50));
s3->setPosition(ccp(70, 50));
s4->setPosition(ccp(80, 50));
s5->setPosition(ccp(90, 50));
this->addChild(s1);
this->addChild(s2);
this->addChild(s3);
this->addChild(s4);
this->addChild(s5);
}
void PrettyPrinterDemo::onEnter()
{
CCLayer::onEnter();
CCSize s = CCDirector::sharedDirector()->getWinSize();
CCLabelTTF* label = CCLabelTTF::create(title().c_str(), "Arial", 28);
label->setPosition( ccp(s.width/2, s.height * 4/5) );
this->addChild(label, 1);
std::string strSubtitle = subtitle();
if(strSubtitle.empty() == false)
{
CCLabelTTF* subLabel = CCLabelTTF::create(strSubtitle.c_str(), "Thonburi", 16);
subLabel->setPosition( ccp(s.width/2, s.height * 3/5) );
this->addChild(subLabel, 1);
}
// Test code
CCPrettyPrinter vistor;
// print dictionary
CCDictionary* pDict = CCDictionary::createWithContentsOfFile("animations/animations.plist");
pDict->acceptVisitor(vistor);
CCLog("%s", vistor.getResult().c_str());
CCLog("-------------------------------");
CCSet myset;
for (int i = 0; i < 30; ++i) {
myset.addObject(CCString::createWithFormat("str: %d", i));
}
vistor.clear();
myset.acceptVisitor(vistor);
CCLog("%s", vistor.getResult().c_str());
CCLog("-------------------------------");
vistor.clear();
addSprite();
pDict = CCTextureCache::sharedTextureCache()->snapshotTextures();
pDict->acceptVisitor(vistor);
CCLog("%s", vistor.getResult().c_str());
}
void DataVisitorTestScene::runThisTest()
{
CCLayer *layer = new PrettyPrinterDemo();
layer->autorelease();
addChild(layer);
CCDirector::sharedDirector()->replaceScene(this);
}

View File

@ -0,0 +1,27 @@
#ifndef __DATAVISITOR_TEST_H__
#define __DATAVISITOR_TEST_H__
#include "../testBasic.h"
#include <string>
class PrettyPrinterDemo : public CCLayer
{
public:
virtual std::string title();
virtual std::string subtitle();
virtual void onEnter();
void addSprite();
protected:
std::string m_strTitle;
};
class DataVisitorTestScene : public TestScene
{
public:
virtual void runThisTest();
CREATE_FUNC(DataVisitorTestScene);
};
#endif // __DATAVISITOR_TEST_H__

View File

@ -125,6 +125,9 @@ static TestScene* CreateTestScene(int nIdx)
case TEST_TEXTUREPACKER_ENCRYPTION:
pScene = new TextureAtlasEncryptionTestScene();
break;
case TEST_DATAVISTOR:
pScene = new DataVisitorTestScene();
break;
default:
break;
}

View File

@ -57,6 +57,7 @@
#include "FileUtilsTest/FileUtilsTest.h"
#include "SpineTest/SpineTest.h"
#include "TexturePackerEncryptionTest/TextureAtlasEncryptionTest.h"
#include "DataVisitorTest/DataVisitorTest.h"
enum
{
@ -115,6 +116,7 @@ enum
TEST_FILEUTILS,
TEST_SPINE,
TEST_TEXTUREPACKER_ENCRYPTION,
TEST_DATAVISTOR,
TESTS_COUNT,
};
@ -175,7 +177,8 @@ const std::string g_aTestNames[TESTS_COUNT] = {
#endif
"FileUtilsTest",
"SpineTest",
"TexturePackerEncryption"
"TexturePackerEncryption",
"DataVistorTest"
};
#endif

View File

@ -1 +1 @@
3477f91e036be581ecbe80f832acb2bf956f543c
6b5e473d37f1653e3e4098f7a69cd6be2b4bc4b4