aboutsummaryrefslogtreecommitdiffstats
path: root/var.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'var.cpp')
-rw-r--r--var.cpp715
1 files changed, 715 insertions, 0 deletions
diff --git a/var.cpp b/var.cpp
new file mode 100644
index 0000000..8aa85e6
--- /dev/null
+++ b/var.cpp
@@ -0,0 +1,715 @@
+// var.cpp
+// Revision 7-feb-2005
+
+//#define KEEP_IT_SIMPLE
+
+
+#include "var.h"
+#include "sysvar.h"
+#include "error.h"
+#include "util.h"
+
+#include <vector>
+#include <algorithm>
+#include <stdexcept>
+
+//#include <cctype>
+//using std::toupper;
+
+#include <iostream>
+using std::cerr;
+using std::endl;
+
+#ifdef __BORLANDC__
+#pragma warn -inl
+#if __BORLANDC__ >= 0x0560
+#pragma warn -8091
+#endif
+#endif
+
+#ifndef USE_HASH_MAP
+
+#include <map>
+#define MAP std::map
+
+#else
+
+#if __GNUC__ < 3
+#include <hash_map>
+#define N_MAP std
+#else
+#include <ext/hash_map>
+#define N_MAP __gnu_cxx
+#endif
+
+#define MAP N_MAP::hash_map
+
+namespace N_MAP {
+
+template <> struct hash <std::string>
+{
+ hash () : hashstr (hash <const char *> () ) { }
+ size_t operator () (const std::string & str) const
+ { return hashstr (str.c_str () ); }
+private:
+ hash <const char *> 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 <char c>
+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 <class C>
+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 C>
+class Table {
+ static const size_t chunk_size= 512;
+ std::vector <C *> vc;
+ size_t n;
+ static void clearchunk (C * pc);
+public:
+ Table ();
+ ~Table ();
+ void clear ();
+ C * newvar ();
+};
+
+template <class C>
+Table<C>::Table () :
+ n (0)
+{ }
+
+template <class C>
+Table<C>::~Table ()
+{
+ clear ();
+}
+
+template <class C>
+void Table<C>::clearchunk (C * pc)
+{
+ delete [] pc;
+}
+
+template <class C>
+void Table<C>::clear ()
+{
+ std::for_each (vc.begin (), vc.end (), clearchunk);
+ vc.clear ();
+ n= 0;
+}
+
+template <class C>
+C * Table<C>::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 <BlNumber> tablenumber;
+Table <BlInteger> tableinteger;
+Table <std::string> tablestring;
+
+template <class C>
+inline Table <C> & table ();
+
+template <>
+inline Table <BlNumber> & table <BlNumber> ()
+{ return tablenumber; }
+template <>
+inline Table <BlInteger> & table <BlInteger> ()
+{ return tableinteger; }
+template <>
+inline Table <std::string> & table <std::string> ()
+{ return tablestring; }
+
+MAP <std::string, BlNumber *> numvar;
+MAP <std::string, BlInteger *> integervar;
+MAP <std::string, std::string *> stringvar;
+
+template <class C>
+inline MAP <std::string, C *> & mapvar ();
+
+template <>
+inline MAP <std::string, BlNumber *> & mapvar <BlNumber> ()
+{ return numvar; }
+template <>
+inline MAP <std::string, BlInteger *> & mapvar <BlInteger> ()
+{ return integervar; }
+template <>
+inline MAP <std::string, std::string *> & mapvar <std::string> ()
+{ return stringvar; }
+
+template <class C>
+inline C * getaddr (const std::string name)
+{
+ C * addr= mapvar <C> () [name];
+ if (! addr)
+ {
+ addr= table <C> ().newvar ();
+ mapvar <C> () [name]= addr;
+ initnewvar (* addr);
+ }
+ return addr;
+}
+
+template <class C>
+inline void assignvar (const std::string & n, const C & value)
+{
+ C * pc= getaddr <C> (n);
+ * pc= value;
+}
+
+template <class C>
+inline C evaluatevar (const std::string & n)
+{
+ C * pc= getaddr <C> (n);
+ return * pc;
+}
+
+#else
+// Keep it Simple.
+
+MAP <std::string, BlNumber> varnumber;
+MAP <std::string, BlInteger> varinteger;
+MAP <std::string, std::string> 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 <BlNumber> (name);
+ // Ops, I forget to strip here.
+ return evaluatevar <BlNumber> (stripvarnumber (name) );
+ #else
+ return varnumber [stripvarnumber (name) ];
+ #endif
+}
+
+BlInteger evaluatevarinteger (const std::string & name)
+{
+ #ifndef KEEP_IT_SIMPLE
+ return evaluatevar <BlInteger> (stripvarinteger (name) );
+ #else
+ return varinteger [stripvarinteger (name) ];
+ #endif
+}
+
+std::string evaluatevarstring (const std::string & name)
+{
+ #ifndef KEEP_IT_SIMPLE
+ return evaluatevar <std::string> (stripvarstring (name) );
+ #else
+ return varstring [stripvarstring (name) ];
+ #endif
+}
+
+BlNumber * addrvarnumber (const std::string & name)
+{
+ #ifndef KEEP_IT_SIMPLE
+ //return getaddr <BlNumber> (name);
+ // Ops, I forget to strip here.
+ return getaddr <BlNumber> (stripvarnumber (name) );
+ #else
+ return & varnumber [stripvarnumber (name) ];
+ #endif
+}
+
+BlInteger * addrvarinteger (const std::string & name)
+{
+ #ifndef KEEP_IT_SIMPLE
+ return getaddr <BlInteger> (stripvarinteger (name) );
+ #else
+ return & varinteger [stripvarinteger (name) ];
+ #endif
+}
+
+std::string * addrvarstring (const std::string & name)
+{
+ #ifndef KEEP_IT_SIMPLE
+ return getaddr <std::string> (stripvarstring (name) );
+ #else
+ return & varstring [stripvarstring (name) ];
+ #endif
+}
+
+//*********************************************************
+// ARRAYS
+//*********************************************************
+
+namespace {
+
+template <class C>
+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 <class C>
+Array <C>::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 <C> );
+}
+
+template <class C>
+Array <C>::Array () : // Default constructor required for map []
+ pcount (new size_t),
+ value (new C [0] )
+{
+ * pcount= 1;
+}
+
+template <class C>
+Array <C>::Array (const Array & a) :
+ d (a.d),
+ pcount (a.pcount),
+ value (a.value)
+{
+ addref ();
+}
+
+template <class C>
+Array <C>::~Array ()
+{
+ delref ();
+}
+
+template <class C>
+void Array <C>::operator = (const Array & a)
+{
+ if (this != & a)
+ {
+ delref ();
+ d= a.d;
+ pcount= a.pcount;
+ value= a.value;
+ addref ();
+ }
+}
+
+template <class C>
+void Array <C>::addref ()
+{
+ ++ (* pcount);
+}
+
+template <class C>
+void Array <C>::delref ()
+{
+ if (-- (* pcount) == 0)
+ {
+ //cerr << "Array of dim " << d << " deleted" << endl;
+ delete [] value;
+ delete pcount;
+ }
+}
+
+#if 0
+template <class C>
+inline Array <C> makeArray (const Dimension & nd, C * nvalue)
+{
+ return Array <C> (nd, nvalue);
+}
+#endif
+
+template <class C>
+struct ArrayVar {
+ typedef MAP <std::string, Array <C> > map;
+ typedef typename map::iterator iterator;
+ typedef typename map::const_iterator const_iterator;
+ typedef typename map::value_type value_type;
+};
+
+MAP <std::string, Array <BlNumber> > arrayvarnumber;
+MAP <std::string, Array <BlInteger> > arrayvarinteger;
+MAP <std::string, Array <std::string> > arrayvarstring;
+
+template <class C>
+inline typename ArrayVar <C>::map & arrayvar ();
+// Se necesita como plantilla para usarlo en otras plantillas.
+// Lo definimos solamente para los tipos usados.
+
+template <>
+inline ArrayVar <BlNumber>::map &
+ arrayvar <BlNumber> ()
+{ return arrayvarnumber; }
+template <>
+inline ArrayVar <BlInteger>::map &
+ arrayvar <BlInteger> ()
+{ return arrayvarinteger; }
+template <>
+inline ArrayVar<std::string>::map &
+ arrayvar <std::string> ()
+{ return arrayvarstring; }
+
+template <class C>
+inline void dimvar (const std::string & name, const Dimension & d)
+{
+ typename ArrayVar <C>::iterator it= arrayvar <C> ().find (name),
+ end= arrayvar <C> ().end ();
+ //if (arrayvar <C> ().find (name) != arrayvar <C> ().end () )
+ // throw ErrAlreadyDim;
+ if (it != end && sysvar::get (sysvar::TypeOfDimCheck) == 0)
+ throw ErrAlreadyDim;
+ #if 0
+ size_t n= d.elements ();
+ util::auto_buffer <C> value (n);
+ arrayvar <C> () [name]= makeArray (d, value.data () );
+ #else
+ //Array <C> a (d);
+ //arrayvar <C> () [name]= a;
+ arrayvar <C> () [name]= Array <C> (d);
+ #endif
+ //std::for_each (value.begin (), value.end (), initnewvar <C> );
+ //value.release ();
+}
+
+template <class C>
+inline void erasevar (const std::string & name)
+{
+ typename ArrayVar <C>::const_iterator it=
+ arrayvar <C> ().find (name);
+ if (it == arrayvar <C> ().end () )
+ throw ErrFunctionCall;
+ arrayvar <C> ().erase (name);
+ //arrayvar <C> ().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 <class C>
+void createdefault (const std::string & name, const Dimension & d)
+{
+ Dimension n= defaultdimension (d);
+ dimvar<C> (name, n);
+}
+
+template <class C>
+inline C * addrdim (const std::string & name, const Dimension & d)
+{
+ typename ArrayVar <C>::iterator it=
+ arrayvar <C> ().find (name);
+ if (it == arrayvar <C> ().end () )
+ {
+ createdefault <C> (name, d);
+ it= arrayvar <C> ().find (name);
+ if (it == arrayvar <C> ().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 <class C>
+inline C valuedim (const std::string & name, const Dimension & d)
+{
+ return * addrdim <C> (name, d);
+}
+
+template <class C>
+inline void assigndim (const std::string & name,
+ const Dimension & d, const C & result)
+{
+ * addrdim <C> (name, d)= result;
+}
+
+} // namespace
+
+void dimvarnumber (const std::string & name, const Dimension & d)
+{
+ dimvar <BlNumber> (stripvarnumber (name), d);
+}
+
+void dimvarinteger (const std::string & name, const Dimension & d)
+{
+ dimvar <BlInteger> (stripvarinteger (name), d);
+}
+
+void dimvarstring (const std::string & name, const Dimension & d)
+{
+ dimvar <std::string> (stripvarstring (name), d);
+}
+
+void erasevarnumber (const std::string & name)
+{
+ erasevar <BlNumber> (stripvarnumber (name) );
+}
+
+void erasevarinteger (const std::string & name)
+{
+ erasevar <BlInteger> (stripvarinteger (name) );
+}
+
+void erasevarstring (const std::string & name)
+{
+ erasevar <std::string> (stripvarstring (name) );
+}
+
+BlNumber valuedimnumber (const std::string & name, const Dimension & d)
+{
+ return valuedim <BlNumber> (stripvarnumber (name), d);
+}
+
+BlInteger valuediminteger (const std::string & name, const Dimension & d)
+{
+ return valuedim <BlInteger> (stripvarinteger (name), d);
+}
+
+std::string valuedimstring (const std::string & name, const Dimension & d)
+{
+ return valuedim <std::string> (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 <BlNumber> (stripvarnumber (name), d);
+}
+
+BlInteger * addrdiminteger (const std::string & name, const Dimension & d)
+{
+ return addrdim <BlInteger> (stripvarinteger (name), d);
+}
+
+std::string * addrdimstring (const std::string & name, const Dimension & d)
+{
+ return addrdim <std::string> (stripvarstring (name), d);
+}
+
+//**********************************************************
+// Borrado de variables
+//**********************************************************
+
+namespace {
+
+#if 0
+template <class C>
+class FreeArray {
+public:
+ void operator ()
+ (const typename ArrayVar <C>::value_type & var)
+ {
+ delete [] var.second.value;
+ }
+};
+#endif
+
+template <class C>
+inline void cleararray ()
+{
+ //std::for_each (arrayvar <C> ().begin (), arrayvar <C> ().end (),
+ // FreeArray<C> () );
+ arrayvar <C> ().clear ();
+}
+
+#ifndef KEEP_IT_SIMPLE
+
+template <class C>
+void clear ()
+{
+ table <C> ().clear ();
+ mapvar <C> ().clear ();
+}
+
+#endif
+
+} // namespace
+
+void clearvars ()
+{
+ #ifndef KEEP_IT_SIMPLE
+ clear <BlNumber> ();
+ clear <BlInteger> ();
+ clear <std::string> ();
+ #else
+ varnumber.clear ();
+ varinteger.clear ();
+ varstring.clear ();
+ #endif
+
+ cleararray <BlNumber> ();
+ cleararray <BlInteger> ();
+ cleararray <std::string> ();
+}
+
+// Fin de var.cpp
Un proyecto texto-plano.xyz