00001
00002 #ifndef HASH_TYPES_H_INCLUDED
00003 #define HASH_TYPES_H_INCLUDED
00004
00005
00006
00007 class HASHobs;
00008 class hashdist;
00009 typedef ARRAYptrs<HASHobs *> HASHobs_list;
00010 class HASHobs {
00011 static HASHobs_list *_hash_obs_list;
00012 HASHobs_list *hash_list() { if (!_hash_obs_list)
00013 _hash_obs_list = new HASHobs_list;
00014 return _hash_obs_list; }
00015 public:
00016 virtual ~HASHobs() {}
00017 static void notify_hash_obs(CGELptr &o, hashdist *h)
00018 { if (!_hash_obs_list) return;
00019 for (int i=0;i<_hash_obs_list->num();i++)
00020 (*_hash_obs_list)[i]->notify_hash(o,h); }
00021 virtual void notify_hash(CGELptr &old, hashdist *h) = 0;
00022
00023 void hash_obs() { hash_list()->add_uniquely(this); }
00024 void unobs_hash() { hash_list()->rem (this); }
00025 };
00026
00027 class hashdist : public DATA_ITEM, public GELdistobs,
00028 public EXISTobs, public DUPobs {
00029 protected:
00030 str_ptr _str;
00031 const int _dist;
00032 HASH _dhash;
00033 const int _dup;
00034 TAGlist _tags;
00035 void *find(CGELptr &g) const { return _dhash.find((long) &*g);}
00036 void add (CGELptr &g, void *v) { _dhash.add((long) &*g, v); }
00037 virtual void del_item(void *) = 0;
00038 void del_hash_items() { ARRAY<long > keys;
00039 ARRAY<void *> items;
00040 _dhash.get_items(keys, items);
00041 for (int i=0; i<keys.num();i++){
00042 _dhash.del(keys[i]);
00043 del_item(items[i]);
00044 }
00045 }
00046 public:
00047 virtual ~hashdist() { }
00048 hashdist(Cstr_ptr &str, int dist, int dup=1):_str(str),
00049 _dist(dist), _dhash(16), _dup(dup) {
00050 if (_dist)
00051 distrib_obs();
00052 DATA_ITEM::add_decoder(_str, this);
00053 exist_obs();
00054 if (_dup)
00055 dup_obs();
00056 _tags += new TAG_meth<hashdist>("",
00057 &hashdist::put_dummy, &hashdist::get_var, 1);
00058 }
00059 void del(CGELptr &g) { void *ret = 0;
00060 if ((ret=find(g))) {
00061 _dhash.del((long) &*g);
00062 del_item(ret); }
00063 }
00064 int is_default(CGELptr &g)const { return find(g)==0; }
00065 CHASH &hash() const { return _dhash; }
00066 virtual CTAGlist &tags() const { return _tags; }
00067 virtual DATA_ITEM *dup() const { return 0; }
00068 virtual STAT_STR_RET class_name () const { return _str; }
00069 virtual void put_dummy(TAGformat &) const { }
00070 virtual void get_var (TAGformat &) = 0;
00071 virtual void notify_exist(CGELptr &g, int f) { if (!f) del(g); }
00072 virtual void notify_dup (CGELptr &old,CGELptr &newg) = 0;
00073 virtual void put_var(TAGformat &d, CGELptr &g) const=0;
00074 virtual void notify_distrib(STDdstream &ds,CGELptr&g) {
00075 TAGformat d(&ds,class_name(),1); put_var(d,g);}
00076 };
00077
00078 template <class T>
00079 class hashvar : public hashdist {
00080 T _val;
00081 virtual void del_item(void * item) { delete (TDI<T> *) item;}
00082 public :
00083 hashvar(Cstr_ptr &var, T val, int dist=0, int dup=1):
00084 hashdist(var,dist,dup), _val(val) {}
00085 virtual ~hashvar() { del_hash_items();}
00086
00087 T get(CGELptr &g) const { return find(g) ?
00088 ((TDI<T> *)find(g))->get() : _val; }
00089 void set(GELptr g, T v) { del(g);
00090 add(g, (void *)new TDI<T>(v));
00091 if (_dist)
00092 HASHobs::notify_hash_obs(g,this); }
00093 virtual void notify_dup(CGELptr &old, CGELptr &newg)
00094 { if (find(old)) set(newg, get(old));}
00095 virtual void put_var(TAGformat &d, CGELptr &g) const {
00096 if (_dist && find(g)) {
00097 d.id() << g->name() << get(g);
00098 d.end_id();} }
00099 virtual void get_var(TAGformat &d) { GELptr g;
00100 T inval;
00101 *d >> g >> inval;
00102 if (g) set(g, inval); }
00103 };
00104
00105
00106 #ifdef Free
00107 #undef Free
00108 #endif
00109 template <class T>
00110 class hashptr : public hashdist {
00111 T _val;
00112 virtual void del_item(void *item) { ((T) item)->Free(); }
00113 public :
00114 hashptr(Cstr_ptr &var, const T v, int dist=0,int dup=1):
00115 hashdist(var,dist,dup), _val(v) { if (v) v->Own(); }
00116 ~hashptr() { del_hash_items();}
00117 T get(CGELptr &g) { return find(g) ? (T)find(g) : _val;}
00118 void set(GELptr g, T v) { if (v) v->Own();
00119 del(g); add(g, (void *)v);
00120 if (_dist)
00121 HASHobs::notify_hash_obs(g,this); }
00122
00123
00124 virtual void put_var (TAGformat &, CGELptr&) const { }
00125 virtual void get_var (TAGformat &) { }
00126 virtual void notify_exist(CGELptr &g, int f) { if (!f&&g) del(g);}
00127 virtual void notify_dup (CGELptr &old, CGELptr &newg) { if (find(old))
00128 set(newg, get(old));}
00129 };
00130
00131 template <class T>
00132 class hashenum : public hashdist {
00133 T _val;
00134 virtual void del_item(void *item) { delete ((TDI<int> *) item); }
00135 public :
00136 hashenum(Cstr_ptr &var, T val, int dist=0, int dup=0):
00137 hashdist(var,dist,dup), _val(val) {}
00138 ~hashenum() { del_hash_items();}
00139 T get(CGELptr &g) const { return (T)(find(g) ?
00140 ((TDI<int> *)find(g))->get() : _val);}
00141 void set(GELptr g, T v) { del(g);
00142 add(g, (void *) new TDI<int>((int)v));
00143 if (_dist)
00144 HASHobs::notify_hash_obs(g,this); }
00145
00146
00147
00148
00149 virtual T str_to_enum(Cstr_ptr &s) const { return (T)atoi(**s); }
00150 virtual void put_var(TAGformat &d, CGELptr &gel) const {
00151 if (class_name() && find(gel)) {
00152 d.id() << gel->name() << " " << get(gel);
00153 d.end_id(); }
00154 }
00155 virtual void get_var(TAGformat &d) { GELptr g; str_ptr val;
00156 *d >> g >> val;
00157 if (g) set(g, str_to_enum(val)); }
00158
00159 virtual void notify_dup(CGELptr &old, CGELptr &newg)
00160 { if (find(old)) set(newg, get(old)); }
00161 };
00162
00163
00164 class GrabVar : public hashvar<int> {
00165 public :
00166 GrabVar() : hashvar<int>("GRABBED", 0, 0) { }
00167 void grab (CGELptr &g) { set(g, get(g)+1); GRABobs::notify_grab_obs(g,1); }
00168 void release (CGELptr &g) { set(g, get(g)-1); GRABobs::notify_grab_obs(g,0); }
00169 virtual void notify_dup(CGELptr &, CGELptr &) { }
00170 };
00171
00172
00173 #define MAKE_NET_HASHVAR(NAME, TYPE, VAL) hashvar<TYPE> NAME(#NAME, VAL, 1)
00174 #define MAKE_NET_HASHENUM(NAME,TYPE, VAL) hashenum<TYPE> NAME(#NAME, VAL, 1)
00175 #endif