boost::variantというライブラリがありますが、他の言語と比べるとあまり似ていません。
なので頭の体操を兼ねて、C++のvar型を作ってみました。
var型の「+」と「+=」がまだありませんが、必要になったらそのうち作ります。
------------------------------
variant.cpp
------------------------------
#include <stdio.h>
#include "variant.h"
#if defined(_WIN32) && !defined(__GNUC__)
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#endif
static var var_null;
var::var()
{
type=0;
m_val=0;
}
var::var(int v)
{
type=VAR_TYPE_INT;
m_val=v;
}
var::var(const char*str)
{
var((std::string)str);
}
var::var(std::string str)
{
type=VAR_TYPE_STRING;
m_str=str;
}
var::var(var& val)
{
(*this)=val;
}
var::~var()
{
var* ret;
std::map<std::string,var*>::iterator ite;
ite=m_map.begin();
while( ite != m_map.end() )
{
ret=(*ite).second;
delete ret;
ite++;
}
}
var& var::operator[](const char* str)
{
if(str==NULL){
return var_null;
}
return operator[]((std::string)str);
}
var& var::operator[](std::string str)
{
var* ret=&var_null;
if(type!=0 && type!=VAR_TYPE_MAP){
return *ret;
}
switch(type){
case 0:
type=VAR_TYPE_MAP;
case VAR_TYPE_MAP:
ret=m_map[str];
if(ret==NULL){
ret=new var();
m_map[str]=ret;
}
break;
}
return *ret;
}
var& var::operator[](int v)
{
var* ret=&var_null;
char tmp[64];
tmp[0]=0;
sprintf(tmp,"%d",v);
std::string str=tmp;
if(type!=0 && type!=VAR_TYPE_MAP){
return *ret;
}
switch(type){
case 0:
type=VAR_TYPE_MAP;
case VAR_TYPE_MAP:
ret=m_map[str];
if(ret==NULL){
ret=new var();
m_map[str]=ret;
}
break;
}
return *ret;
}
var& var::operator =(std::string str)
{
if(type!=0 && type!=VAR_TYPE_STRING){
return var_null;
}
type=VAR_TYPE_STRING;
m_str=str;
return *this;
}
var& var::operator =(int val)
{
if(type!=0 && type!=VAR_TYPE_INT){
return var_null;
}
type=VAR_TYPE_INT;
m_val=val;
return *this;
}
var& var::operator =(var& val)
{
var* ret;
std::map<std::string,var*>::iterator ite;
//clear all
ite=m_map.begin();
while( ite != m_map.end() )
{
ret=(*ite).second;
delete ret;
ite++;
}
m_map.clear();
type=0;
switch(val.type){
case VAR_TYPE_INT:
type=VAR_TYPE_INT;
m_val=val.m_val;
break;
case VAR_TYPE_STRING:
type=VAR_TYPE_STRING;
m_str=val.m_str;
break;
case VAR_TYPE_MAP:
std::map<std::string,var*>::iterator ite;
type=VAR_TYPE_MAP;
ite=val.m_map.begin();
while( ite != val.m_map.end() ) // 先頭まで
{
m_map[(*ite).first]=new var();
*(m_map[(*ite).first])=*(*ite).second;
ite++;
}
break;
}
return *this;
}
var::operator std::string()
{
if(type==0){
return "null";
}
if(type==VAR_TYPE_STRING){
return m_str;
}
if(type==VAR_TYPE_INT){
return toString();
}
if(type==VAR_TYPE_MAP){
return "objrct";
}
return "broken";
}
var::operator int()
{
if(type==VAR_TYPE_INT){
return m_val;
}
if(type==VAR_TYPE_STRING){
return toInt();
}
return -1;
}
const char* var::pchar()
{
if(type==0){
return "null";
}
if(type==VAR_TYPE_STRING){
return m_str.c_str();
}
if(type==VAR_TYPE_INT){
return toString().c_str();
}
if(type==VAR_TYPE_MAP){
return "objrct";
}
return "broken";
}
int var::toInt()
{
int ret=0;
if(type==VAR_TYPE_STRING){
sscanf(m_str.c_str(),"%d",&ret);
}
return ret;
}
std::string var::toString()
{
std::string ret;
if(type==VAR_TYPE_INT){
char tmp[64];
tmp[0]=0;
sprintf(tmp,"%d",m_val);
ret=tmp;
}
return ret;
}
bool var::operator ==(int v)
{
if(v==0 && type==0)return true;
return false;
}
bool var::operator !=(int v)
{
if(v==0 && type==0)return false;
return true;
}
bool var::operator ==(var& val)
{
switch(type){
case 0:
if(val.type==0)return true;
return false;
case VAR_TYPE_INT:
if(val.type==VAR_TYPE_INT && m_val==val.m_val)return true;
return false;
case VAR_TYPE_STRING:
if(val.type==VAR_TYPE_STRING && m_str==val.m_str)return true;
return false;
case VAR_TYPE_MAP:
//no implement
return false;
}
return false;
}
bool var::operator !=(var& val)
{
switch(type){
case 0:
if(val.type==0)return false;
return true;
case VAR_TYPE_INT:
if(val.type==VAR_TYPE_INT && m_val==val.m_val)return false;
return true;
case VAR_TYPE_STRING:
if(val.type==VAR_TYPE_STRING && m_str==val.m_str)return false;
return true;
case VAR_TYPE_MAP:
//no implement
return true;
}
return true;
}
#if 1
int main(int argc,char* argv[])
{
#if defined(_WIN32) && !defined(__GNUC__)
// _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_WNDW);
// _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_WNDW);
// _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_WNDW);
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF);
#endif
var a,b,c,d,e,f;
var g=5;
var h="hoge";
var j=(std::string)"hoge";
var k=j;
std::string str;
int i=-1;
if(a==NULL)printf("a is null\n");
else printf("a is NOT null\n");
if(a!=NULL)printf("a is NOT null\n");
else printf("a is null\n");
a["key"]="value";
a[5]=10;
if(a==NULL)printf("a is null\n");
else printf("a is NOT null\n");
if(a!=NULL)printf("a is NOT null\n");
else printf("a is null\n");
i=a[5];
b["hoge"]=a;
c=b;
d=c["hoge"];
if(a["key"]==e)printf("a[key]is e\n");
else printf("a[key]is NOT e\n");
if(a["key"]!=e)printf("a[key]is NOT e\n");
else printf("a[key]is e\n");
if(a[5]==f)printf("a[key]is f\n");
else printf("a[key]is NOT f\n");
if(a[5]!=f)printf("a[key]is NOT f\n");
else printf("a[key]is f\n");
e="value";
f=10;
printf("str=>>%s<<\n",((std::string)e).c_str());
printf("str=>>%s<<\n",e.pchar());
if(a["key"]==e)printf("a[key]is e\n");
else printf("a[key]is NOT e\n");
if(a[5]==f)printf("a[key]is f\n");
else printf("a[key]is NOT f\n");
str=a["key"];
a["key"]="hoge!!!!";
printf("i=%d\n",i);
printf("str=>>%s<<\n",str.c_str());
str=d["key"];
printf("str=>>%s<<\n",str.c_str());
str=a["key"];
printf("str=>>%s<<\n",str.c_str());
str=a[5];
printf("str=>>%s<<\n",str.c_str());
a["key"]="123";
i=a["key"];
printf("i=%d\n",i);
return 0;
}
#endif
variant.h
------------------------------
#include <string>
#include <map>
#define VAR_TYPE_NULL 0
#define VAR_TYPE_INT 1
#define VAR_TYPE_STRING 2
#define VAR_TYPE_MAP 3
#define VAR_TYPE_LIST 4
class var{
public:
var();
var(int v);
var(const char* str);
var(std::string str);
var(var& val);
virtual ~var();
var& operator[](std::string str);
var& operator[](const char* str);
var& operator[](int);
var& operator =(std::string str);
var& operator =(int val);
var& operator =(var& val);
bool operator ==(int);
bool operator !=(int);
bool operator ==(var& val);
bool operator !=(var& val);
// you should implement
//var& operator +=(std::string str);
//var& operator +=(const char* str);
//var& operator +=(int val);
//var& operator +=(var& val);
// you should implement
//var operator +(std::string str);
//var operator +(const char* str);
//var operator +(int val);
//var operator +(var& val);
operator std::string();
operator int();
int toInt();
std::string toString();
// you should implement
//std::string typeOf();
//int length();
const char* pchar();
private:
int type;
std::map<std::string,var*> m_map;
std::string m_str;
int m_val;
};
0 件のコメント:
コメントを投稿