//
// Copyright (C) 1999-2004 Toshikaz Hirabayashi
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// TOSHIKAZ HIRABAYASHI BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
// OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// Except as contained in this notice, the name of Toshikaz Hirabayashi shall
// not be used in advertising or otherwise to promote the sale, use or other
// dealings in this Software without prior written authorization from
// Toshikaz Hirabayashi.

#include <WScom.h>
#include <WSCvariant.h>
#include <WSCstring.h>
#include <WSCbase.h>


WSCvariant::~WSCvariant(){
  clear();
}
WSCvariant::WSCvariant(){
  _type = WSTlong;
  _data = (void*)0;
  _data2 = NULL;
  _type_name = NULL;
}
WSCvariant::WSCvariant(char data){
  long data1 = (long)data;
  _type = WSTchar;
  _data = (void*)data1;
  _data2 = NULL;
  _type_name = NULL;
}
WSCvariant::WSCvariant(WSCuchar data){
  long data1 = (long)data;
  _type = WSTuchar;
  _data = (void*)data1;
  _data2 = NULL;
  _type_name = NULL;
}
WSCvariant::WSCvariant(short data){
  long data1 = (long)data;
  _type = WSTshort;
  _data = (void*)data1;
  _data2 = NULL;
  _type_name = NULL;
}
WSCvariant::WSCvariant(WSCushort data){
  long data1 = (long)data;
  _type = WSTushort;
  _data = (void*)data1;
  _data2 = NULL;
  _type_name = NULL;
}

WSCvariant::WSCvariant(long data){
  _type = WSTlong;
  _data = (void*)data;
  _data2 = NULL;
  _type_name = NULL;
}
WSCvariant::WSCvariant(WSCulong data){
  _type = WSTulong;
  _data = (void*)data;
  _data2 = NULL;
  _type_name = NULL;
}
WSCvariant::WSCvariant(int data){
  _type = WSTint;
  _data = (void*)data;
  _data2 = NULL;
  _type_name = NULL;
}
WSCvariant::WSCvariant(WSCuint data){
  _type = WSTuint;
  _data = (void*)data;
  _data2 = NULL;
  _type_name = NULL;
}


WSCvariant::WSCvariant(float data){
  _type = WSTfloat;
  memcpy(&_data,&data,sizeof(void*));
  _data2 = NULL;
  _type_name = NULL;
}
WSCvariant::WSCvariant(double data){
  _type = WSTdouble;
  _data = (void*)(new double);
  memcpy(_data,&data,sizeof(double));
  _data2 = NULL;
  _type_name = NULL;
}
WSCvariant::WSCvariant(void* data,char* tname){
  _type = WSTvoidptr;
  _data = (void*)data;
  _data2 = NULL;
  if (tname != NULL){
    _type_name = WSGFstrdup(tname);
  }else{
    _type_name = NULL;
  }
}
WSCvariant::WSCvariant(WSCbase* data){
  _type = WSTvoidptr;
  _data = (void*)data;
  _data2 = NULL;
  _type_name = WSGFstrdup("WSCbase*");
}

WSCvariant::WSCvariant(char* data){
  _type = WSTcharptr;
  WSCstring* str = new WSCstring;
  str->setString(data);
  _data = (void*)str;
  _data2 = NULL;
  _type_name = NULL;
}
#if 0
WSCvariant::WSCvariant(WSCstring data){
  _type = WSTcharptr;
  WSCstring* str = new WSCstring;
  str->setString(data.getString());
  _data = (void*)str;
  _data2 = NULL;
  _type_name = NULL;
}
#endif
WSCvariant::WSCvariant(const WSCvariant& src){
  _type = src._type;
  _type_name = NULL;
  if (src._type_name != NULL){
    _type_name = WSGFstrdup(src._type_name);
  }
  if (_type == WSTcharptr){
    WSCstring* str = new WSCstring;
    WSCstring* sstr = (WSCstring*)src._data;
    str->setString(sstr->getString());
    _data = (void*)str;
    _data2 = NULL;
  }else if (_type == WSTdouble){
    _data = (void*)new double;
    memcpy(_data,src._data,sizeof(double));
    _data2 = NULL;
  }else{
    _data = src._data;
    _data2 = NULL;
  }
}
void WSCvariant::clear(){
  if (_data2 != NULL){
    delete _data2;
    _data2 = NULL;
  }
  if (_type == WSTdouble){
    delete (double*)_data;
    _data = NULL;
  }else
  if (_type == WSTcharptr){
    WSCstring* ptr = (WSCstring*)_data;
    if (ptr != NULL){
      delete ptr;
    }
    _data = NULL;
  }
  if (_type_name != NULL){
    delete _type_name;
    _type_name = NULL;
  }
  _type = WSTlong;
  if (_data2 != NULL){
    delete _data2;
    _data2 = NULL;
  }
}
char WSCvariant::getChar(){
  if (_type == WSTchar || _type == WSTuchar ||
      _type == WSTshort || _type == WSTushort ||
      _type == WSTint || _type == WSTuint ||
      _type == WSTlong || _type == WSTulong ||
      _type == WSTvoidptr ){
    long val = (long)_data;
    return (char)val;
  }
  if (_type == WSTfloat){
    float val;
    memcpy(&val,&_data,sizeof(void*));
    return (char)val;
  }
  if (_type == WSTdouble){
    double val = *(double*)_data;
    return (char)val;
  }
  if (_type == WSTcharptr){
    WSCstring* str = (WSCstring*)_data;
    return (char)atoi(str->getString());
  }
  return 0;
}

WSCuchar WSCvariant::getUnsignedChar(){
  if (_type == WSTchar || _type == WSTuchar ||
      _type == WSTshort || _type == WSTushort ||
      _type == WSTint || _type == WSTuint ||
      _type == WSTlong || _type == WSTulong ||
      _type == WSTvoidptr ){
    long val = (long)_data;
    return (WSCuchar)val;
  }
  if (_type == WSTfloat){
    float val;
    memcpy(&val,&_data,sizeof(void*));
    return (WSCuchar)val;
  }
  if (_type == WSTdouble){
    double val = *(double*)_data;
    return (WSCuchar)val;
  }
  if (_type == WSTcharptr){
    WSCstring* str = (WSCstring*)_data;
    return (WSCuchar)atoi(str->getString());
  }
  return 0;
}

short WSCvariant::getShort(){
  if (_type == WSTchar || _type == WSTuchar ||
      _type == WSTshort || _type == WSTushort ||
      _type == WSTint || _type == WSTuint ||
      _type == WSTlong || _type == WSTulong ||
      _type == WSTvoidptr ){
    long val = (long)_data;
    return (short)val;
  }
  if (_type == WSTfloat){
    float val;
    memcpy(&val,&_data,sizeof(void*));
    return (short)val;
  }
  if (_type == WSTdouble){
    double val = *(double*)_data;
    return (short)val;
  }
  if (_type == WSTcharptr){
    WSCstring* str = (WSCstring*)_data;
    return (short)atoi(str->getString());
  }
  return 0;
}
WSCushort WSCvariant::getUnsignedShort(){
  if (_type == WSTchar || _type == WSTuchar ||
      _type == WSTshort || _type == WSTushort ||
      _type == WSTint || _type == WSTuint ||
      _type == WSTlong || _type == WSTulong ||
      _type == WSTvoidptr ){
    long val = (long)_data;
    return (WSCushort)val;
  }
  if (_type == WSTfloat){
    float val;
    memcpy(&val,&_data,sizeof(void*));
    return (WSCushort)val;
  }
  if (_type == WSTdouble){
    double val = *(double*)_data;
    return (WSCushort)val;
  }
  if (_type == WSTcharptr){
    WSCstring* str = (WSCstring*)_data;
    return (WSCushort)atoi(str->getString());
  }
  return 0;
}
long WSCvariant::getLong(){
  if (_type == WSTchar || _type == WSTuchar ||
      _type == WSTshort || _type == WSTushort ||
      _type == WSTint || _type == WSTuint ||
      _type == WSTlong || _type == WSTulong ||
      _type == WSTvoidptr ){
    long val = (long)_data;
    return (long)val;
  }
  if (_type == WSTfloat){
    float val;
    memcpy(&val,&_data,sizeof(void*));
    return (long)val;
  }
  if (_type == WSTdouble){
    double val = *(double*)_data;
    return (long)val;
  }
  if (_type == WSTvoidptr){
    return (long)_data;
  }
  if (_type == WSTcharptr){
    WSCstring* str = (WSCstring*)_data;
    return (long)atoi(str->getString());
  }
  return 0;
}
WSCulong WSCvariant::getUnsignedLong(){
  if (_type == WSTchar || _type == WSTuchar ||
      _type == WSTshort || _type == WSTushort ||
      _type == WSTint || _type == WSTuint ||
      _type == WSTlong || _type == WSTulong ||
      _type == WSTvoidptr ){
    long val = (long)_data;
    return (WSCulong)val;
  }
  if (_type == WSTfloat){
    float val;
    memcpy(&val,&_data,sizeof(void*));
    return (WSCulong)val;
  }
  if (_type == WSTdouble){
    double val = *(double*)_data;
    return (WSCulong)val;
  }
  if (_type == WSTcharptr){
    WSCstring* str = (WSCstring*)_data;
    return (WSCulong)atoi(str->getString());
  }
  return 0;
}
int WSCvariant::getInt(){
  if (_type == WSTchar || _type == WSTuchar ||
      _type == WSTshort || _type == WSTushort ||
      _type == WSTint || _type == WSTuint ||
      _type == WSTlong || _type == WSTulong ||
      _type == WSTvoidptr ){
    long val = (long)_data;
    return (int)val;
  }
  if (_type == WSTfloat){
    float val;
    memcpy(&val,&_data,sizeof(void*));
    return (int)val;
  }
  if (_type == WSTdouble){
    double val = *(double*)_data;
    return (int)val;
  }
  if (_type == WSTcharptr){
    WSCstring* str = (WSCstring*)_data;
    return (int)atoi(str->getString());
  }
  return 0;
}
WSCuint WSCvariant::getUnsignedInt(){
  if (_type == WSTchar || _type == WSTuchar ||
      _type == WSTshort || _type == WSTushort ||
      _type == WSTint || _type == WSTuint ||
      _type == WSTlong || _type == WSTulong ||
      _type == WSTvoidptr ){
    long val = (long)_data;
    return (WSCuint)val;
  }
  if (_type == WSTfloat){
    float val;
    memcpy(&val,&_data,sizeof(void*));
    return (WSCuint)val;
  }
  if (_type == WSTdouble){
    double val = *(double*)_data;
    return (WSCuint)val;
  }
  if (_type == WSTcharptr){
    WSCstring* str = (WSCstring*)_data;
    return (WSCuint)atoi(str->getString());
  }
  return 0;
}

float WSCvariant::getFloat(){
  if (_type == WSTchar || _type == WSTuchar ||
      _type == WSTshort || _type == WSTushort ||
      _type == WSTint || _type == WSTuint ||
      _type == WSTlong || _type == WSTulong ||
      _type == WSTvoidptr){
    long val = (long)_data;
    return (float)val;
  }
  if (_type == WSTfloat){
    float val;
    memcpy(&val,&_data,sizeof(void*));
    return val;
  }
  if (_type == WSTdouble){
    double val = *(double*)_data;
    return (float)val;
  }
  if (_type == WSTcharptr){
    WSCstring* str = (WSCstring*)_data;
    return (float)atof(str->getString());
  }
  return 0;
}
double WSCvariant::getDouble(){
  if (_type == WSTchar || _type == WSTuchar ||
      _type == WSTshort || _type == WSTushort ||
      _type == WSTint || _type == WSTuint ||
      _type == WSTlong || _type == WSTulong ||
      _type == WSTvoidptr ){
    long val = (long)_data;
    return (double)val;
  }
  if (_type == WSTfloat){
    float val;
    memcpy(&val,&_data,sizeof(void*));
    return (double)val;
  }
  if (_type == WSTdouble){
    double val = *(double*)_data;
    return (double)val;
  }
  if (_type == WSTcharptr){
    WSCstring* str = (WSCstring*)_data;
    return atof(str->getString());
  }
  return (double)0;
}

WSCbase* WSCvariant::getInstancePtr(){
  if (_type == WSTvoidptr ){
    if (!strcmp(_type_name,"WSCbase*")){
      return (WSCbase*)_data;
    }
  }
  return NULL;
}

void* WSCvariant::getVoidPtr(){
  if (_type == WSTchar || _type == WSTuchar ||
      _type == WSTshort || _type == WSTushort ||
      _type == WSTint || _type == WSTuint ||
      _type == WSTlong || _type == WSTulong ||
      _type == WSTvoidptr ){
    return _data;
  }
  if (_type == WSTfloat){
    float val;
    memcpy(&val,&_data,sizeof(void*));
    long val2 = (long)val;
    return (void*)val2;
  }
  if (_type == WSTdouble){
    double val = *(double*)_data;
    long val2 = (long)val;
    return (void*)val2;
  }
  if (_type == WSTcharptr){
    WSCstring* str = (WSCstring*)_data;
    return (void*)atoi(str->getString());
  }
  return (void*)0;
}

char* WSCvariant::getCharPtr(){
  if (_type == WSTchar || _type == WSTuchar ||
      _type == WSTshort || _type == WSTushort ||
      _type == WSTint || _type == WSTuint ||
      _type == WSTlong || _type == WSTulong ||
      _type == WSTvoidptr ){
    if (_data2 != NULL){
      return _data2;
    }
    char buffer[64];
    sprintf(buffer,"%d",(long)_data);
    _data2 = WSGFstrdup(buffer);    
    return _data2;
//    return WSGFltoa((long)_data);
  }
  if (_type == WSTfloat){
    if (_data2 != NULL){
      return _data2;
    }
    float val;
    memcpy(&val,&_data,sizeof(void*));
    char buffer[128];
    sprintf(buffer,"%10.10lf",val);
    _data2 = WSGFstrdup(buffer);    
    return _data2;
  }
  if (_type == WSTdouble){
    if (_data2 != NULL){
      return _data2;
    }
    double val = *(double*)_data;
    char buffer[128];
    sprintf(buffer,"%10.10lf",val);
    _data2 = WSGFstrdup(buffer);    
    return _data2;
  }
  if (_type == WSTcharptr){
    WSCstring* str = (WSCstring*)_data;
    return str->getString();
  }
  return "";
}

long WSCvariant::getType(){
  return _type;
}
char* WSCvariant::getTypeName(){
  if (_type_name != NULL){
    return _type_name;
  }
static char* buf[16];
static char fl = False;
  if (fl == False){
    fl = True;
    buf[WSTchar] = "char";
    buf[WSTuchar] = "unsigned uchar";
    buf[WSTshort] = "short";
    buf[WSTushort] = "unsigned short";
    buf[WSTlong] = "long";
    buf[WSTulong] = "unsigned long";
    buf[WSTbool] = "WSCbool";
    buf[WSTcharptr] = "char*";
    buf[WSTfloat] = "float";
    buf[WSTdouble] = "double";
    buf[WSTvoidptr] = "void*";
    buf[WSTint] = "int";
    buf[WSTuint] = "unsigned int";
  }
  if (-1 < _type && _type < WSTuint +1){
    return buf[_type];
  }
  return "long";
}

void WSCvariant::setValue(char val){
  clear();
  long val2 = (long)val;
  _data = (void*)val2;
  _type = WSTchar;
}
void WSCvariant::setValue(WSCuchar val){
  clear();
  long val2 = (long)val;
  _data = (void*)val2;
  _type = WSTuchar;
}
void WSCvariant::setValue(short val){
  clear();
  long val2 = (long)val;
  _data = (void*)val2;
  _type = WSTshort;
}
void WSCvariant::setValue(WSCushort val){
  clear();
  long val2 = (long)val;
  _data = (void*)val2;
  _type = WSTushort;
}
void WSCvariant::setValue(long val){
  clear();
  _data = (void*)val;
  _type = WSTlong;
}
void WSCvariant::setValue(WSCulong val){
  clear();
  _data = (void*)val;
  _type = WSTulong;
}
void WSCvariant::setValue(int val){
  clear();
  long val2 = (long)val;
  _data = (void*)val2;
  _type = WSTint;
}
void WSCvariant::setValue(WSCuint val){
  clear();
  long val2 = (long)val;
  _data = (void*)val2;
  _type = WSTuint;
}
void WSCvariant::setValue(char* val){
  clear();
  _type = WSTcharptr;
  WSCstring* str = new WSCstring;
  str->setString(val);
  _data = (void*)str;
  _type_name = NULL;
}
void WSCvariant::setValue(void* val,char* cname){
  clear();
  _data = val;
  _type = WSTvoidptr;
  if (cname != NULL){
    _type_name = WSGFstrdup(cname);
  }
}
void WSCvariant::setValue(WSCbase* val){
  clear();
  _data = (void*)val;
  _type = WSTvoidptr;
  if (_type_name != NULL){
    delete _type_name;
    _type_name = NULL;
  }
  _type_name = WSGFstrdup("WSCbase*");
}
void WSCvariant::setValue(float val){
  clear();
  memcpy(&_data,&val,sizeof(void*));
  _type = WSTfloat;
}
void WSCvariant::setValue(double val){
  clear();
  _data =(void*) new double;
  memcpy(_data,&val,sizeof(double));
  _type = WSTdouble;
}
WSCvariant& WSCvariant::operator =(const WSCvariant& src){
  if (&src != this){
    clear();
    _type = src._type;
    _type_name = NULL;
    if (src._type_name != NULL){
      _type_name = WSGFstrdup(src._type_name);
    }
    if (_type == WSTcharptr){
      WSCstring* str = new WSCstring;
      WSCstring* sstr = (WSCstring*)src._data;
      str->setString(sstr->getString());
      _data = (void*)str;
    }else if (_type == WSTdouble){
      _data = (void*)new double;
      memcpy(_data,src._data,sizeof(double));
    }else{
      _data = src._data;
    }
  }
  return *this;
}
WSCvariant& WSCvariant::operator =(char val){
  setValue(val);
  return *this;
}
WSCvariant& WSCvariant::operator =(WSCuchar val){
  setValue(val);
  return *this;
}
WSCvariant& WSCvariant::operator =(short val){
  setValue(val);
  return *this;
}
WSCvariant& WSCvariant::operator =(WSCushort val){
  setValue(val);
  return *this;
}
WSCvariant& WSCvariant::operator =(long val){
  setValue(val);
  return *this;
}
WSCvariant& WSCvariant::operator =(WSCulong val){
  setValue(val);
  return *this;
}
WSCvariant& WSCvariant::operator =(int val){
  setValue(val);
  return *this;
}
WSCvariant& WSCvariant::operator =(WSCuint val){
  setValue(val);
  return *this;
}
WSCvariant& WSCvariant::operator =(float val){
  setValue(val);
  return *this;
}
WSCvariant& WSCvariant::operator =(double val){
  setValue(val);
  return *this;
}
WSCvariant& WSCvariant::operator =(char* val){
  setValue(val);
  return *this;
}
WSCvariant& WSCvariant::operator =(WSCbase* val){
  setValue(val);
  return *this;
}
#if 0
WSCvariant& WSCvariant::operator =(WSCstring val){
  setValue(val.getString());
  return *this;
}
#endif
WSCvariant& WSCvariant::operator =(void* val){
  setValue(val,NULL);
  return *this;
}
WSCvariant::operator char (){
  return getChar();
}
WSCvariant::operator WSCuchar (){
  return getUnsignedChar();
}
WSCvariant::operator short (){
  return getShort();
}
WSCvariant::operator WSCushort (){
  return getUnsignedShort();
}
WSCvariant::operator long (){
  return getLong();
}
WSCvariant::operator WSCulong (){
  return getUnsignedLong();
}
WSCvariant::operator int (){
  return getInt();
}
WSCvariant::operator WSCuint (){
  return getUnsignedInt();
}
WSCvariant::operator float (){
  return getFloat();
}
WSCvariant::operator double (){
  return getDouble();
}
WSCvariant::operator char* (){
  return getCharPtr();
}
WSCvariant::operator WSCbase* (){
  return getInstancePtr();
}
#if 0
WSCvariant::operator WSCstring(){
  WSCstring str;
  str.setString(getCharPtr());
  return str;
}
#endif
WSCvariant::operator void* (){
  return getVoidPtr();
}

