// TYPES.CPP provides the code to create and destroy typed-value
// objects and to convert the internal value of an object into
// an ordinary program variable of any of the supported types.

 #include <string.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <values.h>
 #include <types.h>


 ///////Code for the value classes
 //The code for each function is kept in parallel so we can
 //take advantage of the symmetry across the types


 //constructors
 char* invalid="invalid";//Address indicates error

 value::value(){namptr=NULL;};
 value::value(char* namestr){
      namptr=namestr? strdup(namestr):NULL;
      if(!namptr) namptr=invalid;}
 ival::ival(char* namestr, int val):value(namestr){
      data=val;}
 lval::lval(char* namestr, long val):value(namestr){
      data=val;}
 sval::sval(char* namestr, char* val):value(namestr){
      data=val? strdup(val):NULL;
      if(!data) namptr=invalid;}


 //destructors
 value::~value(){if(namptr!=invalid) delete namptr;}
 sval::~sval(){delete data;};


 //characteristics
 value::valid(){return namptr!=invalid;}//address, NOT string


 datatype value::type(){return EMPTY;};
 datatype ival::type(){return INT;};
 datatype lval::type(){return LONG;};
 datatype sval::type(){return STRING;};


 char* value::typename(){return "EMPTY";}
 char* ival::typename(){return "INT";}
 char* lval::typename(){return "LONG";}
 char* sval::typename(){return "STRING";}

 //function required for tests below
 long absval(long N){return N>0? N:-N;}


 //return value as specified variable type
 //signed integer - returns zero if conversion not possible
 int value::asint(){return 0;}
 int ival::asint(){return data;}
 int lval::asint(){return (absval(data)<=MAXINT)? data:0;}
 int sval::asint(){return atoi(data);}


 //signed long - returns zero if conversion not possible
 long value::aslong(){return 0;};
 long ival::aslong(){return data;}
 long lval::aslong(){return data;}
 long sval::aslong(){return atol(data);}


 //string - re-uses same buffer at each call
 static char valbuf[40];
 const char* value::asstring(){return typename();}
 const char* ival::asstring(){return itoa(data,valbuf,10);}
 const char* lval::asstring(){return ltoa(data,valbuf,10);}
 const char* sval::asstring(){return data;}

