diff options
Diffstat (limited to 'lib/omega/include/basic/Map.h')
-rw-r--r-- | lib/omega/include/basic/Map.h | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/lib/omega/include/basic/Map.h b/lib/omega/include/basic/Map.h new file mode 100644 index 0000000..25a116d --- /dev/null +++ b/lib/omega/include/basic/Map.h @@ -0,0 +1,127 @@ +#if ! defined _Map_h +#define _Map_h 1 + +#include <basic/Link.h> +#include <stdio.h> // for NULL + +namespace omega { + +#define foreach_map(k,K,v,V,M,A) {for (omega::MapElementIterator<K,V> __M_##k = (M).iterator();__M_##k;__M_##k++) {K & k = *__M_##k; V & v = __M_##k.value(); A;}} + +template <class K, class V> class MapElement { +public: + K k; + V v; + MapElement<K,V> *tail; + MapElement(const MapElement<K,V>&); + MapElement() {} + MapElement & operator=(const MapElement<K,V>&); + ~MapElement() { delete tail; } +}; + +template<class K, class V> class MapElementIterator { +public: + MapElementIterator(MapElement<K,V>* j) { i = j;} + virtual const K & operator*() const { return i->k; } + virtual K & operator*() { return i->k;} + virtual const V & value() const { return i->v; } + virtual V & value() { return i->v; } + virtual void operator++(int) { i = i->tail; } + virtual void operator++() { i = i->tail; } + virtual bool live() const { return i != NULL; } + operator bool() const { return live(); } +protected: +MapElement<K,V> *i; +}; + +template <class K, class V> class Map { +public: +#if ! defined linux + Map(const V &default_value); +#else + // work around for '386 g++ on Linux + Map(V default_value); +#endif + ~Map(); + MapElementIterator<K,V> iterator() + {return MapElementIterator<K,V>(contents);} + int empty() const {return contents == NULL;} + V operator()(K) const; + V& operator[](K); +private: + MapElement<K,V> * contents; + V _default_value; +}; + +} // namespace + +#define instantiate_Map(T1,T2) template class Map<T1,T2>; \ + template class MapElement<T1,T2>; \ + template class MapElementIterator<T1,T2>; +#define instantiate_MapElement(T1,T2) instantiate_Map(T1,T2) +#define instantiate_MapElementIterator(T1,T2) instantiate_Map(T1,T2) + +namespace omega { + +template<class K, class V> MapElement<K,V>:: MapElement(const MapElement<K,V>& M) { + if (M.tail) tail = new MapElement<K,V>(*M.tail); + else tail = 0; + k = M.k; + v = M.v; + } + +template<class K, class V> MapElement<K,V> & + MapElement<K,V>:: operator=(const MapElement<K,V>& M) { + if (this != &M) { + if (tail) delete tail; + if (M.tail) tail = new MapElement<K,V>(*M.tail); + else tail = 0; + k = M.k; + v = M.v; + } + return *this; + } + + + + +#if ! defined linux +template <class K, class V> Map <K,V>::Map(const V &default_value) +#else +template <class K, class V> Map <K,V>::Map(V default_value) +#endif + : _default_value(default_value) + { + contents = 0; + } + +template <class K, class V> Map <K,V>::~Map() + { + delete contents; + } + +template <class K, class V> V Map<K,V>::operator()(K k) const { + MapElement <K,V> * P = contents; + while (P) { + if (P->k == k) return P->v; + P = P->tail; + }; + return _default_value; + } + +template <class K, class V> V & Map<K,V>::operator[](K k) { + MapElement <K,V> * P = contents; + while (P) { + if (P->k == k) return P->v; + P = P->tail; + }; + P = new MapElement <K,V>; + P->k = k; + P->v = _default_value; + P->tail = contents; + contents = P; + return P->v; + } + +} // namespace +#endif |