//仅仅是一个练手,无实质性作用
#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;
}