[cocos2d-x]将ccb场景的plist文件转换为lua的table格式。

[cocos2d-x]将ccb场景的plist文件转换为lua的table格式。

//仅仅是一个练手,无实质性作用

#include "stdafx.h"

enum ValueType
{
    VT_NONE,
    VT_VALUE,     /*  real integer true false   */
    VT_STRING, 
    VT_DICT,
    VT_ARRAY,
};

class CBaseValue
{
public:
    CBaseValue(ValueType vt)
        : m_eType(vt)
    {

    }

     virtual std:: string toString() = 0;

     virtual ~CBaseValue()
    {
    }

protected:
    ValueType m_eType;
};

class CValue :  public CBaseValue
{
public:
    CValue( const std:: string& value)
        : CBaseValue(VT_VALUE)
        , m_sValue(value)
    {
    }

    std:: string toString()
    {
         return m_sValue;
    }

protected:
    std:: string m_sValue;
};

class CString :  public CBaseValue
{
public:
    CString( const std:: string& value)
        : CBaseValue(VT_STRING)
        , m_sValue("\"" + value + "\"")
    {
    }

    std:: string toString()
    {
         return m_sValue;
    }

protected:
    std:: string m_sValue;
};

class CArray :  public CBaseValue
{
public:
    CArray( int depth = 0)
        : CBaseValue(VT_ARRAY)
        , m_nDepth(depth)
    {
    }

    ~CArray()
    {
        std::for_each(m_aValues.begin(), m_aValues.end(), [](CBaseValue* value)
        {
            delete value;
        });
    }

     void add(CBaseValue* value)
    {
        m_aValues.push_back(value);
    }

    std:: string toString()
    {
        std:: string prefix(m_nDepth, '\t');
        std:: string text = "{\n";
        prefix.push_back('\t');
        std::for_each(m_aValues.begin(), m_aValues.end(), [&](CBaseValue* value)
        {
            text += prefix + value->toString() + ",\n";
        });
        prefix.pop_back();
        text += prefix + "}";

         return text;
    }

protected:
     int m_nDepth;
    std::vector<CBaseValue*>  m_aValues;
};

class CDict :  public CBaseValue
{
public:
    CDict( int depth = 0)
        : CBaseValue(VT_DICT)
        , m_nDepth(depth)
    {
    }

    ~CDict()
    {
        std::for_each(m_mapValues.begin(), m_mapValues.end(), [](std::pair<std:: string, CBaseValue*> keyValue)
        {
            delete keyValue.second;
        });
    }

     void add( const std:: string& key, CBaseValue* value)
    {
        m_mapValues.insert(std::make_pair(key, value));
    }

    std:: string toString()
    {
        std:: string prefix(m_nDepth, '\t');
        std:: string text = "{\n";
        prefix.push_back('\t');
        std::for_each(m_mapValues.begin(), m_mapValues.end(), [&]( const std::pair<std:: string, CBaseValue*> keyValue)
        {
            text += prefix + keyValue.first + " = ";
            text += keyValue.second->toString() + ",\n";
        });
        prefix.pop_back();
        text += prefix + "}";

         return text;
    }

protected:
     int m_nDepth;
    std::map<std:: string, CBaseValue*>  m_mapValues;
};

CArray* parseArray(pugi::xml_node& node,  int depth = 0);
CDict* parseDict(pugi::xml_node& node,  int depth = 0);

CBaseValue* parseValue(pugi::xml_node& node,  int depth = 0)
{
    std:: string name = node.name();

     if (name == "real" || name == "integer")
    {
         return  new CValue(node.text(). get());
    }
     else  if (name == "true")
    {
         return  new CValue("true");
    }
     else  if (name == "false")
    {
         return  new CValue("false");
    }
     else  if (name == "string")
    {
         return  new CString(node.text(). get());
    }
     else  if (name == "array")
    {
         return parseArray(node, depth + 1);
    }
     else  if (name == "dict")
    {
         return parseDict(node, depth + 1);
    }
     else
    {
        assert( false && "error type");
    }
     return NULL;
}

CArray* parseArray(pugi::xml_node& node,  int depth)
{
    CArray* array =  new CArray(depth);

     for (auto i = node.begin(); i != node.end(); )
    {
         /*  value  */
        assert(i != node.end());
        CBaseValue* value = parseValue(*i, depth);

        ++i;

        array->add(value);
    }

     return array;
}

CDict* parseDict(pugi::xml_node& node,  int depth)
{
    CDict* dict =  new CDict(depth);

     for (auto i = node.begin(); i != node.end(); )
    {
         /*  key  */
        assert(i->name() == std:: string("key"));
        std:: string key = std:: string("[\"") + i->text().get() + "\"]";

        ++i;

         /*  value  */
        assert(i != node.end());
        CBaseValue* value = parseValue(*i, depth);

        ++i;

        dict->add(key, value);
    }

     return dict;
}

CDict* parseCCB( const std:: string& filename)
{
    pugi::xml_document doc;

     if (doc.load_file(filename.c_str()))
    {
        auto plist = doc.child("plist");
        
         /*  <plist> == <dict>  */
         if (plist)
        {
             return parseDict(plist.child("dict"));
        }
    }

     return NULL;
}

bool ccbToLua( const std:: string& filename, std::ostream& os = std::cout)
{
    CDict* dict = parseCCB(filename);
     if (dict)
    {
        os << "return" << std::endl;
        os << dict->toString() << std::endl;
        delete dict;
    }

     return  false;
}

int _tmain( int argc, _TCHAR* argv[])
{
    std::ofstream os("test.out.lua");
    ccbToLua("test.ccb", os);
    os.close();
     return 0;
}

你可能感兴趣的:([cocos2d-x]将ccb场景的plist文件转换为lua的table格式。)