2013年9月3日火曜日

C++でvar型変数を作ってみた。

C++言語にはJavaScriptやPythonのようなインタープリタ言語で使われているvariant型のvar変数がありません。
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 件のコメント:

コメントを投稿