#ifndef __casac_variant_h__ #define __casac_variant_h__ #include <string> #include <vector> #include <complex> namespace casac { class record; class variant { public: enum TYPE { RECORD, BOOL, INT, UINT, LONG, DOUBLE, COMPLEX, STRING, BOOLVEC, INTVEC, UINTVEC, LONGVEC, DOUBLEVEC, COMPLEXVEC, STRINGVEC }; static TYPE compatible_type( TYPE one, TYPE two ); class error { public: error( std::string msg ) : message_(msg) { } const std::string &message( ) const { return message_; } private: std::string message_; }; class overflow : public error { public: overflow( std::string lbl ) : error(lbl + ": overflow error") { } }; variant *clone() const { return new variant(*this); } int compare(const variant*) const; variant( ); variant(const variant &); variant(bool arg) : typev(BOOL), shape_(1,1) { val.b = arg; } variant(int arg) : typev(INT), shape_(1,1) { val.i = arg; } variant(unsigned int arg) : typev(UINT), shape_(1,1) { val.ui = arg; } variant(long long arg) : typev(LONG), shape_(1,1) { val.l = arg; } variant(double arg) : typev(DOUBLE), shape_(1,1) { val.d = arg; } variant(std::complex<double> arg) : typev(COMPLEX) { val.c = new std::complex<double>(arg); } variant(const char *arg) : typev(STRING), shape_(1,1) { val.s = new std::string(arg); } variant(const std::string &arg) : typev(STRING), shape_(1,1) { val.s = new std::string(arg); } // variant(const std::vector<bool> &arg) : typev(BOOLVEC), shape_(1,arg.size()) { val.bv = new std::vector<bool>(arg); } variant(const std::vector<bool> &arg, const std::vector<int> &theshape) : typev(BOOLVEC), shape_(theshape) { val.bv = new std::vector<bool>(arg); } variant(std::vector<bool> *arg) : typev(BOOLVEC), shape_(1,arg->size()) { val.bv = arg; } variant(std::vector<bool> *arg, std::vector<int> &theshape) : typev(BOOLVEC), shape_(theshape) { val.bv = arg; } // variant(const std::vector<int> &arg) : typev(INTVEC), shape_(1,arg.size()) { val.iv = new std::vector<int>(arg); } variant(const std::vector<int> &arg, const std::vector<int> &theshape) : typev(INTVEC), shape_(theshape) { val.iv = new std::vector<int>(arg); } variant(std::vector<int> *arg) : typev(INTVEC), shape_(1, arg->size()) { val.iv = arg; } variant(std::vector<int> *arg, std::vector<int> &theshape) : typev(INTVEC), shape_(theshape) { val.iv = arg; } variant(const std::vector<unsigned int> &arg) : typev(UINTVEC), shape_(1,arg.size()) { val.uiv = new std::vector<unsigned int>(arg); } variant(const std::vector<unsigned int> &arg, const std::vector<int> &theshape) : typev(UINTVEC), shape_(theshape) { val.uiv = new std::vector<unsigned int>(arg); } variant(std::vector<unsigned int> *arg) : typev(UINTVEC), shape_(1, arg->size()) { val.uiv = arg; } variant(std::vector<unsigned int> *arg, std::vector<int> &theshape) : typev(UINTVEC), shape_(theshape) { val.uiv = arg; } // variant(const std::vector<long long> &arg) : typev(LONGVEC), shape_(1,arg.size()) { val.lv = new std::vector<long long>(arg); } variant(const std::vector<long long> &arg, const std::vector<int> &theshape) : typev(LONGVEC), shape_(theshape) { val.lv = new std::vector<long long>(arg); } variant(std::vector<long long> *arg) : typev(LONGVEC), shape_(1, arg->size()) { val.lv = arg; } variant(std::vector<long long> *arg, std::vector<int> &theshape) : typev(LONGVEC), shape_(theshape) { val.lv = arg; } // variant(const std::vector<double> &arg) : typev(DOUBLEVEC), shape_(1,arg.size()) { val.dv = new std::vector<double>(arg); } variant(const std::vector<double> &arg, const std::vector<int> &theshape) : typev(DOUBLEVEC), shape_(theshape) { val.dv = new std::vector<double>(arg); } variant(std::vector<double> *arg) : typev(DOUBLEVEC), shape_(1,arg->size()) { val.dv = arg; } variant(std::vector<double> *arg, std::vector<int> &theshape) : typev(DOUBLEVEC), shape_(theshape) { val.dv = arg; } variant(const std::vector<std::complex<double> > &arg) : typev(COMPLEXVEC), shape_(1, arg.size()) { val.cv = new std::vector<std::complex<double> >(arg); } variant(const std::vector<std::complex<double> > &arg, const std::vector<int> &theshape) : typev(COMPLEXVEC), shape_(theshape) { val.cv = new std::vector<std::complex<double> >(arg); } variant(std::vector<std::complex<double> > *arg) : typev(COMPLEXVEC), shape_(1,arg->size()) { val.cv = arg; } variant(std::vector<std::complex<double> > *arg, std::vector<int> &theshape) : typev(COMPLEXVEC), shape_(theshape) { val.cv = arg; } // variant(const std::vector<std::string> &arg, const std::vector<int> &theshape) : typev(STRINGVEC), shape_(theshape) { val.sv = new std::vector<std::string>(arg); } variant(const std::vector<std::string> &arg) : typev(STRINGVEC), shape_(1,arg.size()) { val.sv = new std::vector<std::string>(arg); } variant(std::vector<std::string> *arg) : typev(STRINGVEC), shape_(1, arg->size()) { val.sv = arg; } variant(std::vector<std::string> *arg, std::vector<int> &theshape) : typev(STRINGVEC), shape_(theshape) { val.sv = arg; } // variant(const record &arg); variant(record *arg); ~variant( ); variant & operator= (const variant &other); bool toBool( ) const; int toInt( ) const; unsigned int touInt( ) const; long long toLong( ) const; double toDouble( ) const; std::complex<double> toComplex( ) const; std::string toString( bool no_brackets=false ) const; std::vector<bool> toBoolVec( ) const; std::vector<int> toIntVec( ) const; std::vector<unsigned int> touIntVec( ) const; std::vector<long long> toLongVec( ) const; std::vector<double> toDoubleVec( ) const; std::vector<std::complex<double> > toComplexVec( ) const; std::vector<std::string> toStringVec( ) const; // Yet to be implemented // Modify // --------------------------------------------------- bool &asBool( ); int &asInt( ); unsigned int &asuInt( ); long long &asLong( ); double &asDouble( ); std::complex<double> &asComplex( ); std::string &asString( ); std::vector<int> &asIntVec( int size=-1 ); std::vector<unsigned int> &asuIntVec( int size=-1 ); std::vector<long long> &asLongVec( int size=-1 ); std::vector<bool> &asBoolVec( int size=-1 ); std::vector<double> &asDoubleVec( int size=-1 ); std::vector<std::complex<double> > &asComplexVec( int size=-1 ); std::vector<std::string> &asStringVec( int size=-1 ); casac::record &asRecord( ); void as( TYPE t, int size=-1 ); // Const // --------------------------------------------------- bool getBool( ) const throw(error); int getInt( ) const throw(error); unsigned int getuInt( ) const throw(error); long long getLong( ) const throw(error); double getDouble( ) const throw(error); const std::complex<double> &getComplex( ) const throw(error); const std::string &getString( ) const throw(error); const std::vector<int> &getIntVec( ) const throw(error); const std::vector<unsigned int> &getuIntVec( ) const throw(error); const std::vector<long long> &getLongVec( ) const throw(error); const std::vector<bool> &getBoolVec( ) const throw(error); const std::vector<double> &getDoubleVec( ) const throw(error); const std::vector<std::complex<double> > &getComplexVec( ) const throw(error); const std::vector<std::string> &getStringVec( ) const throw(error); const record &getRecord( ) const throw(error); const std::vector<int> &shape() const; const std::vector<int> &arrayshape() const {return shape();} // Modify // --------------------------------------------------- bool &getBoolMod( ) throw(error); int &getIntMod( ) throw(error); unsigned int &getuIntMod( ) throw(error); double &getDoubleMod( ) throw(error); std::complex<double> &getComplexMod( ) throw(error); std::string &getStringMod( ) throw(error); std::vector<int> &getIntVecMod( ) throw(error); std::vector<unsigned int> &getuIntVecMod( ) throw(error); std::vector<bool> &getBoolVecMod( ) throw(error); std::vector<double> &getDoubleVecMod( ) throw(error); std::vector<std::complex<double> > &getComplexVecMod( ) throw(error); std::vector<std::string> &getStringVecMod( ) throw(error); record &getRecordMod( ) throw(error); std::vector<int> &shape(); std::vector<int> &arrayshape() {return shape();} const std::string &typeString( ) const; TYPE type( ) const { return typev; } void push(bool, bool conform = true); void push(int, bool conform = true); void push(unsigned int, bool conform = true); void push(long long, bool conform = true); void push(double, bool conform = true); void push(std::vector<long long>, bool conform = true); void push(std::complex<double>, bool conform = true); void push(const std::string&, bool conform = true); void place(bool, unsigned int index, bool conform = true); void place(int, unsigned int index, bool conform = true); void place(unsigned int, unsigned int index, bool conform = true); void place(long long, unsigned int index, bool conform = true); void place(double, unsigned int index, bool conform = true); void place(std::vector<long long>, unsigned int index, bool conform = true); void place(std::complex<double>, unsigned int index, bool conform = true); void place(const std::string&, unsigned int index, bool conform = true); int size( ) const { return typev >= BOOLVEC ? vec_size() : 1; } void resize( int size ); void dump() const; // return true if empty string, empty record, or size 0 vector. // always returns false if object is a non-array bool or numerical type bool empty() const; private: void freeStorage (); // what size does the shape imply int shape_size( ) const; // 4294967295 static unsigned int record_id_count; int vec_size( ) const; TYPE typev; union { bool b; std::vector<bool> *bv; int i; unsigned int ui; long long l; std::vector<int> *iv; std::vector<unsigned int> *uiv; std::vector<long long> *lv; double d; std::vector<double> *dv; std::complex<double> *c; std::vector<std::complex<double> > *cv; std::string *s; std::vector<std::string> *sv; record *recordv; } val; std::vector<int> shape_; std::string create_message( const std::string s ) const; }; variant initialize_variant( const std::string & ); } // casac namespace #endif