c++以太坊访问:封装编码数据类型(二)

需要对solidity的应用二进制接口进行编码,因此简单的模仿json库的类型格式进行封装。

头文件如下:

#pragma once
#include "define.h"
enum ValueType {
	nullValue = 0, ///< 'null' value
	intValue,      ///< signed integer value
	uintValue,     ///< unsigned integer value
	longlongValue,
	realValue,     ///< double value
	stringValue,   ///< UTF-8 string value
	booleanValue,  ///< bool value
	ListStringValue,    ///< array value (ordered list)
	ListDoubleValue,
	ListIntValue,
	AddressValue,
	ListAddressValue,
	ByteValue    ///< object value (collection of name/value pairs).
};

const int INTMAX = 2147483647;
const int INTMIN = -2147483647;
const unsigned int TOTALMIN = 4294967295;
typedef list<string> listStr;
typedef list<int> listInt;
typedef list<double> listDouble;
typedef list<Address*> listAddress;

class EthType
{
public:
	EthType(ValueType type = nullValue);
	EthType(int value);
	EthType(unsigned int value);
	EthType(int64_t value);
	EthType(uint64_t value);
	EthType(Address *value);
	EthType(float value);
	EthType(double value);
	EthType(const string& value);
	EthType(const char *value);
	EthType(bool value);
	EthType(const EthType& other);
	EthType(listStr *value);
	EthType(listAddress *value);
	EthType(list<double> *value);
	EthType(list<int> *value);
	EthType(byte *value);
	~EthType();

	int asInt()const;
	unsigned int asUint()const;
	int64_t asInt64()const;
	uint64_t asUint64()const;
	float asFloat()const;
	double asDouble()const;
	bool asBool()const;
	string asString()const;
	listStr asListString();
	list<double> asListDouble();
	list<int> asListint();
	byte* asBytes();
	Address* asAddress()const;
	listAddress asListAddress()const;
	bool isNull() const;
	bool isBool() const;
	bool isInt() const;
	bool isInt64() const;
	bool isUInt() const;
	bool isUInt64() const;
	bool isDouble() const;
	bool isString() const;
	bool isBytes() const;
	bool isListString()const;
	bool isListDouble()const;
	bool isListint()const;
	bool isAddress()const;
	bool isListAddress()const;
	bool empty() const;

	void setType(ValueType type_);
	ValueType getType()const;

	void setStringValue(const string& value);
	void setAddressValue(Address* value);
	void setIntValue(int value);
	void setUIntValue(unsigned int value);
	void setInt64Value(int64_t value);
	void setUInt64Value(uint64_t value);
	void setFloatValue(float value);
	void setDoubleValue(double value);
	void setCharsValue(const char *value);
	void setBoolValue(bool value);
	void setListStringValue(listStr *value);
	void setListDoubleValue(list<double> *value);
	void setListIntValue(list<int> *value);
	void setBytesValue(byte *value);
	void setListAddressValue(listAddress *value);

private:
	union ValueHolder {
		long long int_;
		unsigned long long uint_;
		double real_;
		bool bool_;
		char* string_; // if allocated_, ptr to { unsigned, char[] }.
		listStr *l_str;
		listInt *l_int;
		listDouble *l_double;
		byte *bytes;
		Address* addr;
		listAddress*l_addr;
	} value_;
    //此处使用联合体来进行存储数据(占用同一空间)


	bool isAllocated = false;
	ValueType type;
};


cpp文件:

#include "TypeValue.h"

static inline char* duplicateAndPrefixStringValue(const char* value,
	unsigned int length) {	
	if (value == nullptr) return nullptr;
	auto newString = (char *)malloc(length + 1);
	memcpy(newString, value, length + 1);

	return newString;
}
EthType::EthType(ValueType type)
{
	this->type = type;
}

EthType::EthType(int value)
{
	setIntValue(value);
}
void EthType::setIntValue(int value)
{
	type = intValue;
	value_.int_ = value;
}
EthType::EthType(unsigned int value)
{
	setUIntValue(value);
}
void EthType::setUIntValue(unsigned int value)
{
	type = uintValue;
	value_.uint_ = value;
}
EthType::EthType(int64_t value)
{
	setInt64Value(value);
}
void EthType::setInt64Value(int64_t value)
{
	type = longlongValue;
	value_.int_ = value;
}
void EthType::setUInt64Value(uint64_t value)
{
	type = uintValue;
	value_.uint_ = value;
}

EthType::EthType(uint64_t value)
{
	setUInt64Value(value);
}
EthType::EthType(float value)
{
	setFloatValue(value);
}
EthType::EthType(double value)
{
	setDoubleValue(value);
}
void EthType::setFloatValue(float value)
{
	type = realValue;
	value_.real_ = value;
}
void EthType::setDoubleValue(double value)
{
	type = realValue;
	value_.real_ = value;
}
EthType::EthType(const string& value)
{
	setStringValue(value);
}
void EthType::setStringValue(const string &value)
{
	type = stringValue;
	if (value_.string_ != nullptr && isAllocated)
	{
		free(value_.string_);
		value_.string_ = nullptr;
	}

	value_.string_ = duplicateAndPrefixStringValue(value.data(), static_cast<unsigned>(value.length()));
	isAllocated = true;
}

EthType::EthType(const char *value)
{
	setCharsValue(value);
}
void EthType::setCharsValue(const char *value)
{
	type = stringValue;
	if (value_.string_ != nullptr&& isAllocated)
	{
		free(value_.string_);
		value_.string_ = nullptr;
	}

	value_.string_ = duplicateAndPrefixStringValue(value, static_cast<unsigned>(strlen(value)));
	isAllocated = true;
}
void EthType::setBoolValue(bool value)
{
	type = booleanValue;
	value_.bool_ = value;
}
EthType::EthType(bool value)
{
	setBoolValue(value);
}
EthType::EthType(const EthType& other)
{
	this->type = other.type;
	if (type == stringValue)
	{
		string cc = other.asString();
		if (value_.string_ != nullptr&& isAllocated)
		{
			free(value_.string_);
			value_.string_ = nullptr;
		}
			
		value_.string_ = duplicateAndPrefixStringValue(cc.data(), static_cast<unsigned>(cc.length()));
		isAllocated = true;
	}
}
void EthType::setType(ValueType type_)
{
	type = type_;
}
ValueType EthType::getType()const
{
	return type;
}
EthType::~EthType()
{
	if (value_.string_ != nullptr && type == stringValue)
		free(value_.string_);
//	value_.uint_ = 0;
}

int EthType::asInt()const
{
	switch (type)
	{
	case intValue:
		return value_.int_;
	case uintValue:
		return (unsigned int)value_.int_;
	case realValue:
		return (int)value_.real_;
	case booleanValue:
		return value_.bool_ ? 1 : 0;
	default:
		break;
	}
	return false;
}
unsigned int EthType::asUint()const
{
	switch (type)
	{
	case intValue:
		return (unsigned int)value_.int_;
	case uintValue:
		return value_.int_;
	case realValue:
		return (unsigned int)value_.real_;
	case booleanValue:
		return value_.bool_ ? 1 : 0;
	default:
		break;
	}
	return false;
}
int64_t EthType::asInt64()const
{
	switch (type)
	{
	case intValue:
		return value_.int_;
	case uintValue:
		return value_.int_;
	case realValue:
		return (int64_t)value_.real_;
	case longlongValue:
		return (int64_t)value_.int_;
	case booleanValue:
		return value_.bool_ ? 1 : 0;
	default:
		break;
	}
	return false;
}
uint64_t EthType::asUint64()const
{
	switch (type)
	{
	case intValue:
		return value_.int_;
	case uintValue:
		return value_.int_;
	case realValue:
		return (uint64_t)value_.real_;
	case longlongValue:
		return (uint64_t)value_.int_;
	case booleanValue:
		return value_.bool_ ? 1 : 0;
	default:
		break;
	}
	return false;
}
float EthType::asFloat()const
{
	switch (type)
	{
	case intValue:
		return (float)value_.int_;
	case uintValue:
		return (float)value_.uint_;
	case longlongValue:
		return (float)value_.int_;
	case realValue:
		return value_.real_;
	default:
		break;
	}
	return false;
}
double EthType::asDouble()const
{
	switch (type)
	{
	case intValue:
		return (double)value_.int_;
	case uintValue:
		return (double)value_.uint_;
	case longlongValue:
		return (double)value_.int_;
	case realValue:
		return value_.real_;
	default:
		break;
	}
	return false;
}
bool EthType::asBool()const
{
	switch (type)
	{
	case intValue:
		return value_.int_;
	case uintValue:
		return value_.uint_;
	case longlongValue:
		return value_.int_;
	case realValue:
		return value_.real_;
	case stringValue:
		return value_.string_;
	case booleanValue:
		return value_.bool_;
	default:
		break;
	}
	return false;
}
string EthType::asString()const
{
	switch (type) {
	case nullValue:
		return "";
	case stringValue:
	{
		if (value_.string_ == nullptr)
			return "";	
		return string(value_.string_);
	}
	case booleanValue:
		return value_.bool_ ? "true" : "false";
	case intValue:
		return to_string(value_.int_);
	case uintValue:
		return to_string(value_.uint_);
	case realValue:
		return to_string(value_.real_);
	default:
		cout << "type is not convertible to string";
	}
	return "";
}


bool EthType::isNull() const
{
	return type == nullValue;
}
bool EthType::isBool() const
{
	return type == booleanValue;
}
bool EthType::isInt() const
{
	switch (type)
	{
	case nullValue:
		break;
	case intValue:
		return value_.int_ > INTMIN && value_.int_ <= INTMAX;
	case uintValue:
		return value_.int_ >= 0 && value_.int_ <= INTMAX;
	case longlongValue:
		return  value_.int_ < INTMAX;
	case realValue:	
		break;
	default:
		break;
	}
	return false;
}
bool EthType::isInt64() const
{
	return type == intValue;
}
bool EthType::isUInt() const
{
	return type == uintValue;
}
bool EthType::isUInt64() const
{
	return type == uintValue; 
}
bool EthType::isDouble() const
{
	return type == intValue || type == uintValue || type == realValue;
}
bool EthType::isString() const
{
	return type == stringValue;
}

bool EthType::empty() const
{
	return type == nullValue;
}
listStr EthType::asListString()
{
	if (type == ListStringValue)
	{
		return *value_.l_str;
	}
	else
		return listStr();
}
EthType::EthType(listStr *value)
{
	setListStringValue(value);
}

EthType::EthType(list<double> *value)
{
	setListDoubleValue(value);
}
EthType::EthType(list<int> *value)
{
	setListIntValue(value);
}
list<double> EthType::asListDouble()
{
	if (type == ListDoubleValue)
	{
		return *value_.l_double;
	}
	else
		return list<double>();
}
list<int> EthType::asListint()
{
	if (type == ListIntValue)
	{
		return *value_.l_int;
	}
	else
		return list<int>();

}
void EthType::setListStringValue(listStr *value)
{
	type = ListStringValue;

	value_.l_str = value;
}
void EthType::setListDoubleValue(list<double> *value)
{
	type = ListDoubleValue;

	value_.l_double = value;
}
void EthType::setListIntValue(list<int> *value)
{
	type = ListIntValue;

	value_.l_int = value;
}
void EthType::setBytesValue(byte *value)
{
	type = ByteValue;
	if (value_.bytes != nullptr && isAllocated)
	{
		free(value_.bytes);
		value_.bytes = nullptr;
	}
	value_.bytes = value;
	isAllocated = true;
}
EthType::EthType(byte *value)
{
	setBytesValue(value);
}
byte* EthType::asBytes()
{
	return value_.bytes;
}
bool EthType::isBytes() const
{
	return type == ByteValue;
}
bool EthType::isListString()const
{
	return type == ListStringValue;
}
bool EthType::isListDouble()const
{
	return type == ListDoubleValue;
}
bool EthType::isListint()const
{
	return type == ListIntValue;
}
EthType::EthType(Address *value)
{
	setAddressValue(value);
}
void EthType::setAddressValue(Address* value)
{
	type = AddressValue;
	if (value != nullptr)
	{
		value_.addr = value;
	}
}
bool EthType::isAddress()const
{
	return type == AddressValue;
}
Address* EthType::asAddress()const
{
	if (type == AddressValue)
	{
		return value_.addr;
	}
	else
		return nullptr;
}
EthType::EthType(listAddress *value)
{
	setListAddressValue(value);
}

listAddress EthType::asListAddress()const
{
	if (type == ListAddressValue)
		return *value_.l_addr;
	return listAddress();
}
bool EthType::isListAddress()const
{
	return type == ListAddressValue;
}
void EthType::setListAddressValue(listAddress * value)
{
	type = ListAddressValue;
	value_.l_addr = value;
}

为什么要进行类型的封装呢?主要是方便于后期对应用二进制接口编码时好进行相关的操作。(代码比较粗糙,没有进行优化)

对于address类型的封装,我用得比较笨的方式去实现(类里面存储一个string变量),为什么不直接存储string的原因是,address 和 string应用二进制接口编码不一样,所以才进行这样的封装。

class Address
{
public:
	Address(std::string hexVal);
	std::string getValue();
	std::string getType();
	
	
private:
	std::string value;

};

Address::Address(std::string hexVal)
{
	value = hexVal;
}

std::string Address::getValue()
{
	return value;
}

std::string Address::getType() {
	return "Address";
}

在这里只是为了实现功能,达到相关的目的,没有对其进行重构优化等。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值