Variant-自己写任意类型存储[流输入输出有待改进]

1 篇文章 0 订阅

Variant.h

/********************************************************************
	created:	26:5:2015   18:32
	filename: 	c:\Users\Think pad\Documents\Visual Studio 2013\Projects\boost\boost_6_8 any\Variant.h
	file path:	c:\Users\Think pad\Documents\Visual Studio 2013\Projects\boost\boost_6_8 any
	file base:	Variant
	file ext:	h
	author:		zxj
	
	purpose:	任意类型变量,且支持流输入输出,该类并非模板类
*********************************************************************/
#ifndef VARIANT_H
#define VARIANT_H

#include <boost\any.hpp>
#include <boost\shared_ptr.hpp>
#include <boost\make_shared.hpp>
#include <boost\function.hpp>
#include <boost\bind.hpp>
#include <boost\tuple\tuple.hpp>
#include <list>
#include <map>
#include <boost\assert.hpp>
#include <boost/swap.hpp>

#pragma region 声明所有支持的变量
class Variant;

typedef bool Var_Bool;
typedef int Var_Int;
typedef unsigned int Var_Uint;
typedef short Var_Short;
typedef unsigned short Var_UShort;
typedef long Var_Long;
typedef unsigned long Var_Ulong;
typedef float Var_Float;
typedef double Var_Double;
typedef char Var_Char;
typedef std::map<std::string,Variant> Var_Map;
typedef std::list<Variant> Var_List;
typedef std::string Var_String;
#pragma endregion

class VariantRegister
{
	friend class Variant;

public:
	typedef boost::function<void(std::ostream&, void*)> SaveCallback;//流输出函数
	typedef boost::function<void(std::istream&, void*)> LoadCallback;//流输入函数
	typedef boost::tuple<std::string, int, SaveCallback, LoadCallback> RegisterInfo;//自定义类型需要注册信息

	VariantRegister(){}

	VariantRegister(RegisterInfo& info)
	{
		int index = info.get<1>();
		std::map<int, RegisterInfo>::iterator it = userTypeMap().find(index);

		BOOST_ASSERT(index >= 127 && it == userTypeMap().end(), "Please make sure your type number >= UserType and unique.");
		
		userTypeMap().insert(std::map<int, RegisterInfo>::value_type(index, info));
	}

	static std::map<int, RegisterInfo>& userTypeMap()
	{
		static std::map<int, RegisterInfo> _user_type_map;
		return _user_type_map;
	}

	RegisterInfo getUserTypeInfo(int type)
	{
		std::map<int, RegisterInfo>::iterator it = userTypeMap().find(type);
		if (it != userTypeMap().end())
		{
			return it->second;
		}
		else
		{
			return RegisterInfo("Unknow", 0);
		}
	}

	RegisterInfo getUserTypeInfo(std::string name)
	{
		std::map<int, RegisterInfo>::iterator it = userTypeMap().begin();
		for (; it != userTypeMap().end(); ++it)
		{
			if (it->second.get<0>() == name)
			{
				return it->second;
			}
		}

		return RegisterInfo("Unknow", 0);
	}

private:
	
};

class Variant
{
	friend class VariantRegister;
public:

#pragma region 定义支持类型的枚举型
	enum VariantType
	{
		Invalid = 0,
		Bool = 1,
		Int = 2,
		UInt = 3,
		Short = 4,
		UShort = 5,
		Long = 6,
		ULong = 7,
		Float = 8,
		Double = 9,
		Char = 10,
		Map = 11,
		List = 12,
		String = 13,

		UserType = 127,

		//LastType = 0xfffffff;
	};
#pragma endregion

#pragma region 实现所有类型的构造函数重载
	Variant()
		:_data(boost::make_shared<boost::any>()),
		_type(Invalid)
	{

	}
	
	Variant(Var_Bool value) 
		:_data(boost::make_shared<boost::any>(value)) ,
		 _type(Bool)
	{
	
	}

	Variant(Var_Int value)
		:_data(boost::make_shared<boost::any>(value)),
		_type(Int)
	{
		
	}

	Variant(Var_Uint value)
		:_data(boost::make_shared<boost::any>(value)),
		_type(UInt)
	{

	}

	Variant(Var_Short value)
		:_data(boost::make_shared<boost::any>(value)),
		_type(Short)
	{

	}

	Variant(Var_UShort value)
		:_data(boost::make_shared<boost::any>(value)),
		_type(UShort)
	{

	}

	Variant(Var_Long value)
		:_data(boost::make_shared<boost::any>(value)),
		_type(Long)
	{

	}

	Variant(Var_Float value)
		:_data(boost::make_shared<boost::any>(value)),
		_type(Float)
	{

	}

	Variant(Var_Double value)
		:_data(boost::make_shared<boost::any>(value)),
		_type(Double)
	{

	}

	Variant(Var_Char value)
		:_data(boost::make_shared<boost::any>(value)),
		_type(Char)
	{

	}

	Variant(Var_String value)
		:_data(boost::make_shared<boost::any>(value)),
		_type(String)
	{

	}

	Variant(Var_Map value)
		:_data(boost::make_shared<boost::any>(value)),
		_type(Map)
	{

	}

	Variant(Var_List value)
		:_data(boost::make_shared<boost::any>(value)),
		_type(List)
	{

	}

	Variant(const Variant& value)
	{
		_type = value._type;
		_data = value._data;
		_user_data_ptr = value._user_data_ptr;
	}

	template<typename T>
	Variant(const T& value)
		:_data(boost::make_shared<boost::any>())
	{
		int type = nameToType(typeid(T).name());
		BOOST_ASSERT(type != Invalid);

		_type = type;
		if (_type < UserType)
		{
			*_data = value;
		}
		else
		{
			*_data = value;
			_user_data_ptr = &_getValueRef<T>();
		}
	}

	template<typename T>
	Variant(const std::list<T>& value)
		:_data(boost::make_shared<boost::any>())
	{
		int type = nameToType(typeid(T).name());
		BOOST_ASSERT(type != Invalid);

		Var_List ret;
		typename std::list<T>::const_iterator it;
		it = value.begin();
		for (; it != value.end(); ++it)
		{
			Variant var = *it;
			ret.push_back(var);
		}
		_type = List;
		*_data = ret;
		return *this;
	}

	template<typename T>
	Variant(const std::map<std::string, T>& value)
		:_data(boost::make_shared<boost::any>())
	{
		int type = nameToType(typeid(T).name());
		BOOST_ASSERT(type != Invalid);

		Var_Map ret;
		typename std::map<T>::const_iterator it;
		it = value.begin();
		for (; it != value.end(); ++it)
		{
			Variant var = *it;
			ret.insert(Var_Map::value_type(it->first, it->second));
		}
		_type = List;
		*_data = ret;
		return *this;
	}

#pragma endregion

	~Variant(){}

	//交换
	void swap(Variant& other)
	{ 
		boost::swap(other._type, _type); 
		boost::swap(other._data, _data);
	} 

	//操作存储值的类型
	inline int type() const{ return _type; }

	const char* type_name() const { return _data->type().name(); }
	//const char* typeName() const(){ return "null"; }

	//是否可转型
	inline bool canConvert(VariantType t) const{ return _type == t; }

	template<typename T>
	bool canConvert() const
	{
		return _data->type() == typeid(T);
	}

	//是否有效值
	inline bool isValid() const{ return !_data->empty(); }

	//清除存放的值
	void clear(){ _type = Invalid; _data->clear(); }

#pragma region toXXX函数声明
	Var_Bool toBool()
	{
		BOOST_ASSERT(_type == Bool);
		return boost::any_cast<Var_Bool>(*_data);
	}

	Var_Int toInt()
	{
		BOOST_ASSERT(_type == Int);
		return boost::any_cast<Var_Int>(*_data);
	}

	Var_Uint toUInt()
	{
		BOOST_ASSERT(_type == UInt);
		return boost::any_cast<Var_Uint>(*_data);
	}

	Var_Short toShort()
	{
		BOOST_ASSERT(_type == Short);
		return boost::any_cast<Var_Short>(*_data);
	}

	Var_UShort toUShort()
	{
		BOOST_ASSERT(_type == UShort);
		return boost::any_cast<Var_UShort>(*_data);
	}

	Var_Long toLong()
	{
		BOOST_ASSERT(_type == Long);
		return boost::any_cast<Var_Long>(*_data);
	}

	Var_Ulong toULong()
	{
		BOOST_ASSERT(_type == ULong);
		return boost::any_cast<Var_Ulong>(*_data);
	}

	Var_Float toFloat()
	{
		BOOST_ASSERT(_type == Float);
		return boost::any_cast<Var_Float>(*_data);
	}

	Var_Double toDouble()
	{
		BOOST_ASSERT(_type == Float);
		return boost::any_cast<Var_Double>(*_data);
	}

	Var_Char toChar()
	{
		BOOST_ASSERT(_type == Char);
		return boost::any_cast<Var_Char>(*_data);
	}

	Var_String toString()
	{
		BOOST_ASSERT(_type == String);
		return boost::any_cast<Var_String>(*_data);
	}

	Var_Map toMap()
	{
		BOOST_ASSERT(_type == Map);
		return boost::any_cast<Var_Map>(*_data);
	}

	Var_List toList()
	{
		BOOST_ASSERT(_type == List);
		return boost::any_cast<Var_List>(*_data);
	}

	template<typename T>
	T toUserData()
	{
		BOOST_ASSERT(canConvert<T>());
		return boost::any_cast<T>(*_data);
	}
#pragma endregion

	//输入与输出
	void load(std::istream& in)
	{
		in >> _type;
		if (_type == Invalid)
		{
			Var_String s;
			in >> s;
		}
		else if (_type == Bool)
		{
			Var_Bool tmp;
			in >> tmp;
			*_data = tmp;
		}
		else if (_type == Int)
		{
			Var_Int tmp;
			in >> tmp;
			*_data = tmp;
		}
		else if (_type >= UserType)
		{
			VariantRegister tmp;
			VariantRegister::LoadCallback _loadf;

			boost::tie(boost::tuples::ignore, boost::tuples::ignore, boost::tuples::ignore, _loadf) = tmp.getUserTypeInfo(_type);
			_loadf(in, _user_data_ptr);
		}
	}

	void save(std::ostream& out) const
	{
		out << _type;
		if (_type == Invalid)
		{
			out << Var_String();
		}
		else if (_type == Bool)
		{
			out << boost::any_cast<Var_Bool>(*_data);
		}
		else if (_type == Int)
		{
			out << boost::any_cast<Var_Int>(*_data);
		}
		else if (_type == UInt)
		{
			out << boost::any_cast<Var_Uint>(*_data);
		}
		else if (_type == Short)
		{
			out << boost::any_cast<Var_Float>(*_data);
		}
		else if (_type == UShort)
		{
			out << boost::any_cast<Var_UShort>(*_data);
		}
		else if (_type == Long)
		{
			out << boost::any_cast<Var_Long>(*_data);
		}
		else if (_type == ULong)
		{
			out << boost::any_cast<Var_Ulong>(*_data);
		}
		else if (_type == Float)
		{
			out << boost::any_cast<Var_Float>(*_data);
		}
		else if (_type == Double)
		{
			out << boost::any_cast<Var_Double>(*_data);
		}
		else if (_type == Char)
		{
			out << boost::any_cast<Var_Char>(*_data);
		}
		else if (_type == String)
		{
			out << boost::any_cast<Var_String>(*_data);
		}
		else if (_type == List)
		{
			Var_List tmp = boost::any_cast<Var_List>(*_data);
			for (Var_List::iterator it = tmp.begin(); it != tmp.end();++it)
			{
				it->save(out);
			}
		}
		else if (_type == Map)
		{
			Var_Map tmp = boost::any_cast<Var_Map>(*_data);
			for (Var_Map::iterator it = tmp.begin(); it != tmp.end(); ++it)
			{
				out << it->first;
				it->second.save(out);
			}
		}
		else if (_type >= UserType)
		{
			VariantRegister tmp;
			VariantRegister::SaveCallback _savef;

			boost::tie(boost::tuples::ignore, boost::tuples::ignore, _savef, boost::tuples::ignore) = tmp.getUserTypeInfo(_type);
			_savef(out, _user_data_ptr);
		}
	}

	static std::string typeToName(VariantType type)
	{
		if (type >= UserType)
		{
			std::string name;
			VariantRegister tmp;
			boost::tie(name, boost::tuples::ignore, boost::tuples::ignore, boost::tuples::ignore)
				= tmp.getUserTypeInfo(type);
			return name;
		}

		switch (type)
		{
		case Invalid:
			return "Invalid";
		case Bool:
			return typeid(Var_Bool).name();
		case Int:
			return typeid(Var_Int).name();
		case UInt:
			return typeid(Var_Uint).name();
		case Short:
			return typeid(Var_Short).name();
		case UShort:
			return typeid(Var_UShort).name();
		case Long:
			return typeid(Var_Long).name();
		case ULong:
			return typeid(Var_Ulong).name();
		case Float:
			return typeid(Var_Float).name();
		case Double:
			return typeid(Var_Double).name();
		case Char:
			return typeid(Var_Char).name();
		case Map:
			return typeid(Var_Map).name();
		case List:
			return typeid(Var_List).name();
		case String:
			return typeid(Var_String).name();
		default:
			return "Unkonw";
		}
	}

	static int nameToType(const char* name)
	{
		if (strcmp(name, "Invalid") == 0)
		{
			return Invalid;
		}
		else if (strcmp(name, typeid(Var_Bool).name()) == 0)
		{
			return Bool;
		}
		else if (strcmp(name, typeid(Var_Int).name()) == 0)
		{
			return Bool;
		}
		else if (strcmp(name, typeid(Var_Uint).name()) == 0)
		{
			return Bool;
		}
		else if (strcmp(name, typeid(Var_Short).name()) == 0)
		{
			return Bool;
		}
		else if (strcmp(name, typeid(Var_UShort).name()) == 0)
		{
			return Bool;
		}
		else if (strcmp(name, typeid(Var_Long).name()) == 0)
		{
			return Bool;
		}
		else if (strcmp(name, typeid(Var_Ulong).name()) == 0)
		{
			return Bool;
		}
		else if (strcmp(name, typeid(Var_Float).name()) == 0)
		{
			return Bool;
		}
		else if (strcmp(name, typeid(Var_Double).name()) == 0)
		{
			return Bool;
		}
		else if (strcmp(name, typeid(Var_Char).name()) == 0)
		{
			return Bool;
		}
		else if (strcmp(name, typeid(Var_Map).name()) == 0)
		{
			return Bool;
		}
		else if (strcmp(name, typeid(Var_List).name()) == 0)
		{
			return Bool;
		}
		else if (strcmp(name, typeid(Var_String).name()) == 0)
		{
			return Bool;
		}
		else
		{
			int type = Invalid;
			VariantRegister tmp;
			boost::tie(boost::tuples::ignore, type, boost::tuples::ignore, boost::tuples::ignore)
				= tmp.getUserTypeInfo(name);
			return type;
		}

		return Invalid;
	}

	Variant& operator=(Var_Bool value)
	{
		_type = Bool;
		*_data = value;
		return *this;
	}

	Variant& operator=(Var_Int value)
	{
		_type = Int;
		*_data = value;
		return *this;
	}

	Variant& operator=(Var_Uint value)
	{
		_type = UInt;
		*_data = value;
		return *this;
	}

	Variant& operator=(Var_Short value)
	{
		_type = Short;
		*_data = value;
		return *this;
	}

	Variant& operator=(Var_UShort value)
	{
		_type = UShort;
		*_data = value;
		return *this;
	}

	Variant& operator=(Var_Long value)
	{
		_type = Long;
		*_data = value;
		return *this;
	}

	Variant& operator=(Var_Ulong value)
	{
		_type = ULong;
		*_data = value;
		return *this;
	}

	Variant& operator=(Var_Float value)
	{
		_type = Float;
		*_data = value;
		return *this;
	}

	Variant& operator=(Var_Double value)
	{
		_type = Double;
		*_data = value;
		return *this;
	}

	Variant& operator=(Var_Char value)
	{
		_type = Char;
		*_data = value;
		return *this;
	}

	Variant& operator=(Var_String value)
	{
		_type = String;
		*_data = value;
		return *this;
	}

	Variant& operator=(Var_Map value)
	{
		_type = Map;
		*_data = value;
		return *this;
	}

	Variant& operator=(Var_List value)
	{
		_type = List;
		*_data = value;
		return *this;
	}

	Variant& operator=(const Variant& value)
	{
		_type = value._type;
		_data = value._data;
		_user_data_ptr = value._user_data_ptr;
		return *this;
	}

	template<typename T>
	Variant& operator=(const T& value)
	{
		int type = nameToType(typeid(T).name());
		BOOST_ASSERT(type != Invalid);

		_type = type;
		if (_type < UserType)
		{
			*_data = value;
		}
		else
		{
			*_data = value;
			_user_data_ptr = &_getValueRef<T>();
		}

		return *this;
	}

	template<typename T>
	Variant& operator=(const std::list<T>& value)
	{
		int type = nameToType(typeid(T).name());
		BOOST_ASSERT(type != Invalid);

		Var_List ret;
		typename std::list<T>::const_iterator it;
		it = value.begin();
		for (; it != value.end(); ++it)
		{
			Variant var = *it;
			ret.push_back(var);
		}
		_type = List;
		*_data = ret;
		return *this;
	}

	template<typename T>
	Variant& operator=(const std::map<std::string,T>& value)
	{
		int type = nameToType(typeid(T).name());
		BOOST_ASSERT(type != Invalid);

		Var_Map ret;
		typename std::map<T>::const_iterator it;
		it = value.begin();
		for (; it != value.end(); ++it)
		{
			Variant var = *it;
			ret.insert(Var_Map::value_type(it->first,it->second));
		}
		_type = List;
		*_data = ret;
		return *this;
	}

#pragma region 操作符重载
	//bool operator==(const Variant& v) const;
	//bool operator!=(const Variant& v) const;

	friend std::istream& operator>>(std::istream&,Variant&);
	friend std::ostream& operator<<(std::ostream&, const Variant&);
#pragma endregion

protected:
	template<typename T>
	inline T _getValue()
	{
		return any_cast<T>(*_data);
	}

	template<typename T>
	inline T& _getValueRef()
	{
		return any_cast<T&>(*_data);
	}

private:
	typedef boost::shared_ptr<boost::any> ValueType;
	ValueType _data; //使用any存放任意类型数据,使用shared_ptr使类可以深度拷贝构造
	int _type;//类型
	void* _user_data_ptr;
};

#define VARIANT_REGISTER(classname,num) \
	BOOST_STATIC_ASSERT(num>= Variant::UserType); \
	void* create_variant_##classname() {return new classname();} \
	void var_save_##classname(std::ostream& out,void* data){ \
		classname* p = static_cast<classname*>(data); \
		if(p) out<<*p; \
	} \
	void var_load_##classname(std::istream& in,void* data){ \
		classname* p = static_cast<classname*>(data); \
		if(p) in>>*p; \
	} \
	VariantRegister variantregister_##classname( \
		VariantRegister::RegisterInfo(typeid(classname).name() , num, boost::bind(var_save_##classname, _1, _2), boost::bind(var_load_##classname, _1, _2))); \


#endif //VARIANT_H

Variant.cpp

#include "Variant.h"

std::istream& operator>>(std::istream& in, Variant& var)
{
	var.load(in);
	return in;
}

std::ostream& operator<<(std::ostream& out, const Variant& var)
{
	var.save(out);
	return out;
}


使用说明:如果希望Variant支持自定义类型数据,要在类实现文件全局作用域内声明宏,宏需要两个参数,第一个是类型名,第二个是与类型对应的id号,id号必须全局唯一,否则程序在启动阶段会异常终止,id必须大于等于UserType,否则编译阶段会报错,例如VARIANT_REGISTER(TEST,Variant::UserType+1) 
以上只是基本功能,还不支持一些有用的特性,比如相识数字类型的转换,Variant的比较操作,流输入输出等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值