天天看点

打造 C++ 最灵活动态数组结构 (二)

第二版代码如下:
           

1 MyData.h

/*--------------------------------*/

	C++ 散列化数组结构

	[email protected]

	cjxx 2008-06-27

/*--------------------------------*/

#ifndef __CJ_MY_DATA_H__

#define __CJ_MY_DATA_H__



#include <iostream>

#include <string>

#include <map>



using namespace std;



// 数字索引字符前缀

#define INT_INDEX_PRO_STR		"INT_INDEX_"



//	相关头信息

class MyData;

//	序列化时的风格类型

enum PRINT_R_STYLE {

	PHP,JS

};

//	序列化一个字串到MyData

MyData& Serialize(const char* serStr, MyData* dVal = NULL);



//	反序列化一个MyData到 字符串

bool UnSerialize(MyData* dVal, string& unserStr);



//	格式化输出一个MyData 结构 -- 调试用

void print_r(MyData& data);



//	构造MyData 格式化字串

string& print_s(MyData& data,  string& str, bool bFormat = false, enum PRINT_R_STYLE style = PHP, int level = 0) ;



//	递归遍历 MyData 并执行用户自定义函数

void ForEachData(MyData& data, void* pCallBackFunc);



class MyData {



public:

	enum ENUM_DATA_TYPE {

		DATA_TYPE_DEF = 0,  // 初始类型

		DATA_TYPE_DAT = 1,	// 数组类型

		DATA_TYPE_INT = 2,  // 整数类型

		DATA_TYPE_STR = 3,  // 字符类型

	};

	typedef map<string, MyData>  MAP_MY_DATA;

public:

	// 构造

	MyData() {

		this->Init();

	}

	// 序列化构造

	MyData(const char* dVal) {

		this->Init();

		Serialize(dVal, this);

	}

	// 析构

	~MyData() {

		this->Clear();

	}

	// 判断类型

	bool IsType(enum ENUM_DATA_TYPE eType) {

		return m_cType == eType;

	}

	// 获取类型

	enum ENUM_DATA_TYPE Type() {		

		return m_cType;

	}

	// 获取MAP

	MAP_MY_DATA& Map() {

		return m_mapMyData;

	}

	// 获取整形数据

	int i() {

		return (m_cType == DATA_TYPE_INT) ? m_intData : 0;

	}

	// 获取字符数据

	const char* c() {

		return (m_cType == DATA_TYPE_STR) ? m_strData.c_str() : "";

	}

	// 获取反序列化字串

	const char* u() {

		m_strUnSer = "";

		return UnSerialize(this, m_strUnSer) ? m_strUnSer.c_str() : "";

	}

	// 赋值为整数

	void operator=(int iVal) {

		this->Clear();

		m_intData = iVal;

		m_cType = DATA_TYPE_INT;

		this->SetFatherDat();

	}

	// 赋值为字符

	void operator=(const char* cVal) {

		this->Clear();

		m_strData = cVal;

		m_cType = DATA_TYPE_STR;

		this->SetFatherDat();

	}

	// 赋值为数据

	void operator=(const MyData& dVal) {

		this->Clear();

		m_strData	= dVal.m_strData;

		m_strUnSer	= dVal.m_strUnSer;

		m_intData	= dVal.m_intData;

		m_iNowIndex	= dVal.m_iNowIndex;

		m_mapMyData	= dVal.m_mapMyData;

		m_cType		= dVal.m_cType;

		this->SetFatherDat();

	}

	// 自动增加一个数字索引

	MyData& operator()() {

		m_iTmpIndex = m_iNowIndex;

		return this->Get(StrIndex(m_iNowIndex++));

	}

	// 整形索引

	MyData& operator[](int keyName) {

		m_iTmpIndex = keyName;

		return this->Get(StrIndex(keyName));

	}

	// 字符型索引

	MyData& operator[](const char* keyName) {

		m_iTmpIndex = 0;

		return this->Get(keyName);

	}

	// 自动转换成 int

	operator int() {

		return m_intData;

	}

	// 自动转换成 const char*

	operator const char*() {

		return m_strData.c_str();

	}

private:

	void Clear() {

		if (m_cType == DATA_TYPE_DAT) {

			m_mapMyData.clear();

		}

	}

	void Init() {

		m_iNowIndex = 0;

		m_iTmpIndex = 0;

		m_intData	= 0;

		m_pFather	= NULL;

		m_cType		= DATA_TYPE_DEF;

		m_mapMyData.clear();

	}

	const char* StrIndex(unsigned int index) {

		char buf[64] = {0};

		sprintf_s(buf, INT_INDEX_PRO_STR"%d", index);

		m_strUnSer = buf;

		return m_strUnSer.c_str();

	}

	MyData& Get(const char* keyName) {

		MAP_MY_DATA::iterator iter;

		if (NULL == keyName) {

			iter = m_mapMyData.find("");

		} else {

			iter = m_mapMyData.find(keyName);

		}

		if (iter != m_mapMyData.end()) {

			return (*iter).second;

		} else {

			pair<MAP_MY_DATA::iterator, bool> Insert_Pair;

			MyData data;

			if (NULL == keyName) {

				Insert_Pair = m_mapMyData.insert(MAP_MY_DATA::value_type("", data));

			} else {

				Insert_Pair = m_mapMyData.insert(MAP_MY_DATA::value_type(keyName, data));

			}

			(*Insert_Pair.first).second.SetFather(this);

			return (*Insert_Pair.first).second;

		}		

	}

	void SetFatherDat() {

		if (NULL != this->GetFather()) {

			if (! this->GetFather()->IsType(DATA_TYPE_DAT)) {

				this->GetFather()->m_cType = DATA_TYPE_DAT;

			}

			if (this->GetFather()->m_iNowIndex  < this->GetFather()->m_iTmpIndex) {

				this->GetFather()->m_iNowIndex = this->GetFather()->m_iTmpIndex + 1;

			}

			this->GetFather()->SetFatherDat();

		}

	}

	void SetFather(MyData* pData) {

		m_pFather = pData;

	}

	MyData* GetFather() {

		return m_pFather;

	}	

private:

	enum ENUM_DATA_TYPE		m_cType;

	string  				m_strData;

	string  				m_strUnSer;

	int 					m_intData;

	int						m_iNowIndex;

	int						m_iTmpIndex;

	MyData*					m_pFather;

	MAP_MY_DATA				m_mapMyData;

};

#endif //	end define __CJ_MY_DATA_H__
           
2 MyData.cpp
           
#include "MyData.h"





//	序列化成数据

MyData& Serialize(const char* serStr, MyData* dVal /*= NULL*/) {

	MyData* pDVal;

	if (dVal == NULL) {

		pDVal = new MyData;

	} else {

		pDVal = dVal;

	}

	// 序列化并添加数据



	return (*pDVal);

}

//	反序列化为字串

bool UnSerialize(MyData* dVal, string& unserStr) {

	if (NULL == dVal) {

		return false;

	}

	string str = "";

	if (dVal->IsType(MyData::DATA_TYPE_DAT)) {

		str += "{";

	}

	print_s(*dVal, str, false, JS, 0);

	if (dVal->IsType(MyData::DATA_TYPE_DAT)) {

		str += "}";

	}

	unserStr = str;

	return true;

}



string& print_s(MyData& data,  string& str, bool bFormat /*= false*/, enum PRINT_R_STYLE style /*= PHP*/, int level /*= 0*/) {

	char p_style[5][15] = {" =>array (", ")", "=>", "/"", ","};

	char j_style[5][15] = {": {"       , "}", ":" , "/"", ","};

	char (* u_style)[15] = style == PHP ? p_style : j_style;

	string space = "";

	if (bFormat) {

		for (int i = 0; i < level; i++) {

			space += " ";

		}

		++level;

	}

	if (data.IsType(MyData::DATA_TYPE_DAT)) {

		MyData::MAP_MY_DATA::iterator iter = data.Map().begin();

		for (;iter != data.Map().end();) {

			string keyString = "";

			if ((*iter).first.substr(0,strlen(INT_INDEX_PRO_STR)) == INT_INDEX_PRO_STR) {

				keyString = (*iter).first.substr(strlen(INT_INDEX_PRO_STR), (*iter).first.length());

			} else {

				keyString+= u_style[3];

				keyString+= (*iter).first.c_str();

				keyString+= u_style[3];

			}

			if ((*iter).second.IsType(MyData::DATA_TYPE_DAT)) {

				if (bFormat) {

					str += space;

				}

				str += keyString;

				str += u_style[0];

				if (bFormat) {

					str += "/n";

				}

				str  = print_s((*iter).second, str, bFormat, style, level);

				if (bFormat) {

					str += space;

				}

				str += u_style[1];

			} else if ((*iter).second.IsType(MyData::DATA_TYPE_INT)) {

				char buf[12] = {0};

				sprintf_s(buf, "%d", (*iter).second.i());

				if (bFormat) {

					str += space;

				}

				str += keyString;

				str += u_style[2];

				str += buf;

			} else if ((*iter).second.IsType(MyData::DATA_TYPE_STR)) {

				if (bFormat) {

					str += space;

				}

				str += keyString;

				str += u_style[2];

				str += (*iter).second.c();

			}

			if (++iter != data.Map().end()) {

				str += u_style[4];

			}

			if (bFormat) {

				str += "/n";

			}

		}

	} else if (data.IsType(MyData::DATA_TYPE_INT)) {

		char buf[12] = {0};

		sprintf_s(buf, "%d", data.i());

		if (bFormat) {

			str += space;

		}

		str += buf;

		if (bFormat) {

			str += "/n";

		}

	} else if (data.IsType(MyData::DATA_TYPE_STR)) {

		if (bFormat) {

			str += space;

		}

		str += data.c();

		if (bFormat) {

			str += "/n";

		}

	}

	return str;

}



void print_r(MyData& data) {

	string str = "/n{/n";

	print_s(data, str, true, JS, 1);

	str += "}";

	printf("%s", str.c_str());

}



void ForEachData(MyData& data, void* pCallBackFunc) {



}
           
3 testMain.cpp
           
#include "MyData.h"

int main(void)

{

	int i = 0;

	MyData testData;

	MyData testData2("[1:22, '2':0, 'dff': [1:3]]");

	testData[0]			= 100;

	testData[1]			= "abc";

	testData[3]			= 3;

	testData[1]			= 1;

	testData[6]			= 2;

	testData()[1]		= 41;

	testData[5]()[6]	= 506;

	testData[5]["a"][1]	= 501;

	testData[5][3][1]	= 511;

	testData[5]()[2]	= 541;

	testData["a"]()		= Serialize("[1:22, '2':0, 'dff': [1:3]]");

	testData["a"]		= "fuck";

	testData["a"][2]	= "a";

	testData["a"]()		= "b";

	testData["a"]()		= "c";

	testData2[1]		= "abc";

	testData2[2]		= 3;

	testData2[3]()		= 4;

	testData["c"]()		= 1;

	testData["c"]()		= testData2;

	testData[2][i][i]	= 2;



	int b = testData[0];

	const char* p = testData[1];

	printf("%d/n", b);

	printf("%s/n", p);



	print_r(testData);

	printf("%s", testData.u());



	getchar();

	return 1;

}
           
功能: 
1 增加了类型自动识别转换的操作,这个功能需要依赖C++的编译器而不是用户逻辑,使用时小心。
2 增加反序列化功能,此功能可以将自身导出成字串用来存储发送,目前两种可选方案 -- JSON -- PHP方式