// var.cpp // Revision 7-feb-2005 //#define KEEP_IT_SIMPLE #include "var.h" #include "sysvar.h" #include "error.h" #include "util.h" #include #include #include //#include //using std::toupper; #include using std::cerr; using std::endl; #ifdef __BORLANDC__ #pragma warn -inl #if __BORLANDC__ >= 0x0560 #pragma warn -8091 #endif #endif #ifndef USE_HASH_MAP #include #define MAP std::map #else #if __GNUC__ < 3 #include #define N_MAP std #else #include #define N_MAP __gnu_cxx #endif #define MAP N_MAP::hash_map namespace N_MAP { template <> struct hash { hash () : hashstr (hash () ) { } size_t operator () (const std::string & str) const { return hashstr (str.c_str () ); } private: hash hashstr; }; } // namespace N_MAP #endif namespace sysvar= blassic::sysvar; namespace { VarType tabletype [27]; bool inittabletype () { std::fill_n (tabletype, util::dim_array (tabletype), VarNumber); return true; } bool table_inited= inittabletype (); } VarType typeofvar (const std::string & name) { switch (name [name.size () - 1] ) { case '#': // There is no single or double distiction. return VarNumber; case '!': return VarNumber; case '%': return VarInteger; case '$': return VarString; default: //return tabletype [toupper (name [0]) - 'A']; return tabletype [name [0] - 'A']; } } void definevar (VarType type, char c) { //tabletype [toupper (c) - 'A']= type; tabletype [c - 'A']= type; } void definevar (VarType type, char cfrom, char cto) { //size_t from= toupper (cfrom) - 'A'; //size_t to= toupper (cto) - 'A'; size_t from= cfrom - 'A'; size_t to= cto - 'A'; std::fill (tabletype + from, tabletype + to + 1, type); } namespace { template inline std::string stripvar (const std::string n) { const std::string::size_type l= n.size () - 1; if (n [l] == c) return n.substr (0, l); return n; } inline std::string stripvarnumber (const std::string & n) { //return stripvar <'!'> (n); const std::string::size_type l= n.size () - 1; if (n [l] == '!' || n [l] == '#') return n.substr (0, l); return n; } inline std::string stripvarinteger (const std::string & n) { return stripvar <'%'> (n); } inline std::string stripvarstring (const std::string & n) { return stripvar <'$'> (n); } template inline void initnewvar (C &) { } template <> inline void initnewvar (BlNumber & n) { n= BlNumber (); } template <> inline void initnewvar (BlInteger & n) { n= BlInteger (); } #ifndef KEEP_IT_SIMPLE template class Table { static const size_t chunk_size= 512; std::vector vc; size_t n; static void clearchunk (C * pc); public: Table (); ~Table (); void clear (); C * newvar (); }; template Table::Table () : n (0) { } template Table::~Table () { clear (); } template void Table::clearchunk (C * pc) { delete [] pc; } template void Table::clear () { std::for_each (vc.begin (), vc.end (), clearchunk); vc.clear (); n= 0; } template C * Table::newvar () { size_t nelem= n % chunk_size; if (nelem == 0) { C * pnc= new C [chunk_size]; vc.push_back (pnc); } size_t nchunk= n / chunk_size; ++n; return & vc [nchunk] [nelem]; } Table tablenumber; Table tableinteger; Table tablestring; template inline Table & table (); template <> inline Table & table () { return tablenumber; } template <> inline Table & table () { return tableinteger; } template <> inline Table & table () { return tablestring; } MAP numvar; MAP integervar; MAP stringvar; template inline MAP & mapvar (); template <> inline MAP & mapvar () { return numvar; } template <> inline MAP & mapvar () { return integervar; } template <> inline MAP & mapvar () { return stringvar; } template inline C * getaddr (const std::string name) { C * addr= mapvar () [name]; if (! addr) { addr= table ().newvar (); mapvar () [name]= addr; initnewvar (* addr); } return addr; } template inline void assignvar (const std::string & n, const C & value) { C * pc= getaddr (n); * pc= value; } template inline C evaluatevar (const std::string & n) { C * pc= getaddr (n); return * pc; } #else // Keep it Simple. MAP varnumber; MAP varinteger; MAP varstring; #endif } // namespace void assignvarnumber (const std::string & name, BlNumber value) { #ifndef KEEP_IT_SIMPLE //assignvar (name, value); // Ops, I forget to strip here. assignvar (stripvarnumber (name), value); #else varnumber [stripvarnumber (name) ]= value; #endif } void assignvarinteger (const std::string & name, BlInteger value) { #ifndef KEEP_IT_SIMPLE assignvar (stripvarinteger (name), value); #else varinteger [stripvarinteger (name) ]= value; #endif } void assignvarstring (const std::string & name, const std::string & value) { #ifndef KEEP_IT_SIMPLE assignvar (stripvarstring (name), value); #else varstring [stripvarstring (name) ]= value; #endif } BlNumber evaluatevarnumber (const std::string & name) { #ifndef KEEP_IT_SIMPLE //return evaluatevar (name); // Ops, I forget to strip here. return evaluatevar (stripvarnumber (name) ); #else return varnumber [stripvarnumber (name) ]; #endif } BlInteger evaluatevarinteger (const std::string & name) { #ifndef KEEP_IT_SIMPLE return evaluatevar (stripvarinteger (name) ); #else return varinteger [stripvarinteger (name) ]; #endif } std::string evaluatevarstring (const std::string & name) { #ifndef KEEP_IT_SIMPLE return evaluatevar (stripvarstring (name) ); #else return varstring [stripvarstring (name) ]; #endif } BlNumber * addrvarnumber (const std::string & name) { #ifndef KEEP_IT_SIMPLE //return getaddr (name); // Ops, I forget to strip here. return getaddr (stripvarnumber (name) ); #else return & varnumber [stripvarnumber (name) ]; #endif } BlInteger * addrvarinteger (const std::string & name) { #ifndef KEEP_IT_SIMPLE return getaddr (stripvarinteger (name) ); #else return & varinteger [stripvarinteger (name) ]; #endif } std::string * addrvarstring (const std::string & name) { #ifndef KEEP_IT_SIMPLE return getaddr (stripvarstring (name) ); #else return & varstring [stripvarstring (name) ]; #endif } //********************************************************* // ARRAYS //********************************************************* namespace { template class Array { public: Array (const Dimension & nd); Array (); // Default constructor required for map [] Array (const Array & a); ~Array (); void operator = (const Array & a); const Dimension & dim () const { return d; } C * getvalue (size_t n) { return value + n; } private: Dimension d; size_t * pcount; C * value; void addref (); void delref (); }; template Array ::Array (const Dimension & nd) : d (nd), pcount (new size_t), value (new C [nd.elements () ] ) { if (value == NULL) throw ErrOutMemory; * pcount= 1; std::for_each (value, value + nd.elements (), initnewvar ); } template Array ::Array () : // Default constructor required for map [] pcount (new size_t), value (new C [0] ) { * pcount= 1; } template Array ::Array (const Array & a) : d (a.d), pcount (a.pcount), value (a.value) { addref (); } template Array ::~Array () { delref (); } template void Array ::operator = (const Array & a) { if (this != & a) { delref (); d= a.d; pcount= a.pcount; value= a.value; addref (); } } template void Array ::addref () { ++ (* pcount); } template void Array ::delref () { if (-- (* pcount) == 0) { //cerr << "Array of dim " << d << " deleted" << endl; delete [] value; delete pcount; } } #if 0 template inline Array makeArray (const Dimension & nd, C * nvalue) { return Array (nd, nvalue); } #endif template struct ArrayVar { typedef MAP > map; typedef typename map::iterator iterator; typedef typename map::const_iterator const_iterator; typedef typename map::value_type value_type; }; MAP > arrayvarnumber; MAP > arrayvarinteger; MAP > arrayvarstring; template inline typename ArrayVar ::map & arrayvar (); // Se necesita como plantilla para usarlo en otras plantillas. // Lo definimos solamente para los tipos usados. template <> inline ArrayVar ::map & arrayvar () { return arrayvarnumber; } template <> inline ArrayVar ::map & arrayvar () { return arrayvarinteger; } template <> inline ArrayVar::map & arrayvar () { return arrayvarstring; } template inline void dimvar (const std::string & name, const Dimension & d) { typename ArrayVar ::iterator it= arrayvar ().find (name), end= arrayvar ().end (); //if (arrayvar ().find (name) != arrayvar ().end () ) // throw ErrAlreadyDim; if (it != end && sysvar::get (sysvar::TypeOfDimCheck) == 0) throw ErrAlreadyDim; #if 0 size_t n= d.elements (); util::auto_buffer value (n); arrayvar () [name]= makeArray (d, value.data () ); #else //Array a (d); //arrayvar () [name]= a; arrayvar () [name]= Array (d); #endif //std::for_each (value.begin (), value.end (), initnewvar ); //value.release (); } template inline void erasevar (const std::string & name) { typename ArrayVar ::const_iterator it= arrayvar ().find (name); if (it == arrayvar ().end () ) throw ErrFunctionCall; arrayvar ().erase (name); //arrayvar ().erase (* it); } Dimension defaultdimension (const Dimension & d) { Dimension n; for (size_t i= 0, l= d.size (); i < l; ++i) n.add (10); return n; } template void createdefault (const std::string & name, const Dimension & d) { Dimension n= defaultdimension (d); dimvar (name, n); } template inline C * addrdim (const std::string & name, const Dimension & d) { typename ArrayVar ::iterator it= arrayvar ().find (name); if (it == arrayvar ().end () ) { createdefault (name, d); it= arrayvar ().find (name); if (it == arrayvar ().end () ) { if (showdebuginfo () ) cerr << "Default creation of array failed" << endl; throw ErrBlassicInternal; } } size_t n= it->second.dim ().evalpos (d); //return it->second.value + n; return it->second.getvalue (n); } template inline C valuedim (const std::string & name, const Dimension & d) { return * addrdim (name, d); } template inline void assigndim (const std::string & name, const Dimension & d, const C & result) { * addrdim (name, d)= result; } } // namespace void dimvarnumber (const std::string & name, const Dimension & d) { dimvar (stripvarnumber (name), d); } void dimvarinteger (const std::string & name, const Dimension & d) { dimvar (stripvarinteger (name), d); } void dimvarstring (const std::string & name, const Dimension & d) { dimvar (stripvarstring (name), d); } void erasevarnumber (const std::string & name) { erasevar (stripvarnumber (name) ); } void erasevarinteger (const std::string & name) { erasevar (stripvarinteger (name) ); } void erasevarstring (const std::string & name) { erasevar (stripvarstring (name) ); } BlNumber valuedimnumber (const std::string & name, const Dimension & d) { return valuedim (stripvarnumber (name), d); } BlInteger valuediminteger (const std::string & name, const Dimension & d) { return valuedim (stripvarinteger (name), d); } std::string valuedimstring (const std::string & name, const Dimension & d) { return valuedim (stripvarstring (name), d); } void assigndimnumber (const std::string & name, const Dimension & d, BlNumber result) { assigndim (stripvarnumber (name), d, result); } void assigndiminteger (const std::string & name, const Dimension & d, BlInteger result) { assigndim (stripvarinteger (name), d, result); } void assigndimstring (const std::string & name, const Dimension & d, const std::string & result) { assigndim (stripvarstring (name), d, result); } BlNumber * addrdimnumber (const std::string & name, const Dimension & d) { return addrdim (stripvarnumber (name), d); } BlInteger * addrdiminteger (const std::string & name, const Dimension & d) { return addrdim (stripvarinteger (name), d); } std::string * addrdimstring (const std::string & name, const Dimension & d) { return addrdim (stripvarstring (name), d); } //********************************************************** // Borrado de variables //********************************************************** namespace { #if 0 template class FreeArray { public: void operator () (const typename ArrayVar ::value_type & var) { delete [] var.second.value; } }; #endif template inline void cleararray () { //std::for_each (arrayvar ().begin (), arrayvar ().end (), // FreeArray () ); arrayvar ().clear (); } #ifndef KEEP_IT_SIMPLE template void clear () { table ().clear (); mapvar ().clear (); } #endif } // namespace void clearvars () { #ifndef KEEP_IT_SIMPLE clear (); clear (); clear (); #else varnumber.clear (); varinteger.clear (); varstring.clear (); #endif cleararray (); cleararray (); cleararray (); } // Fin de var.cpp