summaryrefslogtreecommitdiff
path: root/cpp/include/Freeze/Map.h
diff options
context:
space:
mode:
Diffstat (limited to 'cpp/include/Freeze/Map.h')
-rw-r--r--cpp/include/Freeze/Map.h1610
1 files changed, 805 insertions, 805 deletions
diff --git a/cpp/include/Freeze/Map.h b/cpp/include/Freeze/Map.h
index 47f28f2c320..d02d5c4ca6b 100644
--- a/cpp/include/Freeze/Map.h
+++ b/cpp/include/Freeze/Map.h
@@ -1,805 +1,805 @@
-// **********************************************************************
-//
-// Copyright (c) 2001
-// MutableRealms, Inc.
-// Huntsville, AL, USA
-//
-// All Rights Reserved
-//
-// **********************************************************************
-
-#ifndef FREEZE_MAP_H
-#define FREEZE_MAP_H
-
-#include <Ice/Ice.h>
-#include <Freeze/DB.h>
-
-#include <iterator>
-
-namespace Freeze
-{
-
-//
-// Forward declaration
-//
-template <typename key_type, typename mapped_type, typename KeyCodec, typename ValueCodec>
-class DBMap;
-template <typename key_type, typename mapped_type, typename KeyCodec, typename ValueCodec>
-class ConstDBIterator;
-
-//
-// This is necessary for MSVC support.
-//
-struct DBIteratorBase
-{
- typedef std::forward_iterator_tag iterator_category;
-};
-
-//
-// Database iterator. This implements a forward iterator with the
-// restriction that it's only possible to explicitely write back into
-// the database.
-//
-// Equality and inequality are based on whether the iterator is
-// "valid". An valid iterator contains a valid database and cursor
-// pointer, otherwise the iterator is invalid.
-//
-// TODO: It's possible to implement bidirectional iterators, if
-// necessary.
-//
-template <typename key_type, typename mapped_type, typename KeyCodec, typename ValueCodec>
-class DBIterator : public DBIteratorBase
-{
-public:
-
- typedef ptrdiff_t difference_type;
-
- typedef std::pair<const key_type, const mapped_type> value_type;
-
- typedef value_type* pointer;
-
- typedef value_type& reference;
-
- DBIterator(const DBPtr& db, const DBCursorPtr& cursor)
- : _db(db), _cursor(cursor)
- {
- }
-
- DBIterator()
- {
- }
-
- DBIterator(const DBIterator& rhs)
- {
- if(rhs._cursor)
- {
- _cursor = rhs._cursor->clone();
- }
-
- _db = rhs._db;
- }
-
- DBIterator& operator=(const DBIterator& rhs)
- {
- if(_cursor)
- {
- _cursor->close();
- }
-
- if(rhs._cursor)
- {
- _cursor = rhs._cursor->clone();
- }
-
- _db = rhs._db;
-
- return *this;
- }
-
- ~DBIterator()
- {
- if(_cursor)
- {
- _cursor->close();
- }
- }
-
- bool operator==(const DBIterator& rhs) const
- {
- if(!_db && !rhs._db)
- {
- return true;
- }
- return false;
- }
-
- bool operator!=(const DBIterator& rhs) const
- {
- return !(*this == rhs);
- }
-
- DBIterator& operator++()
- {
- incr();
- return *this;
- }
-
- DBIterator operator++(int)
- {
- DBIterator tmp = *this;
- tmp.incr();
- return tmp;
- }
-
- //
- // Note that this doesn't follow the regular iterator mapping:
- //
- // value_type& operator*(), value_type operator*() const
- //
- value_type& operator*() const
- {
- key_type key;
- mapped_type value;
-
- getCurrentValue(key, value);
-
- //
- // !IMPORTANT!
- //
- // This method has to cache the returned value to implement
- // operator->().
- //
- const_cast<key_type&>(_ref.first) = key;
- const_cast<mapped_type&>(_ref.second) = value;
- return _ref;
- }
-
- value_type* operator->() { return &(operator*()); }
-
- //
- // This special method allows writing back into the database.
- //
- void set(const mapped_type& value)
- {
- Freeze::Value v;
- ValueCodec::write(value, v, _db->getCommunicator());
- _cursor->set(v);
- }
-
-private:
-
- void incr()
- {
- assert(_cursor && _db);
- if(!_cursor->next())
- {
- //
- // The iterator has been moved past the end, and is now
- // invalid.
- //
- _cursor->close();
- _cursor = 0;
- _db = 0;
- }
- }
-
- void getCurrentValue(key_type& key, mapped_type& value) const
- {
- Freeze::Key k;
- Freeze::Value v;
-
- _cursor->curr(k, v);
-
- ::Ice::CommunicatorPtr communicator = _db->getCommunicator();
- KeyCodec::read(key, k, communicator);
- ValueCodec::read(value, v, communicator);
- }
-
- friend class ConstDBIterator<key_type, mapped_type, KeyCodec, ValueCodec>;
- friend class DBMap<key_type, mapped_type, KeyCodec, ValueCodec>;
-
- DBPtr _db;
- DBCursorPtr _cursor;
-
- //
- // Cached last return value. This is so that operator->() can
- // actually return a pointer.
- //
- mutable value_type _ref;
-};
-
-//
-// See DBIterator comments for design notes
-//
-template <typename key_type, typename mapped_type, typename KeyCodec, typename ValueCodec>
-class ConstDBIterator : public DBIteratorBase
-{
-public:
-
- typedef ptrdiff_t difference_type;
-
- typedef std::pair<const key_type, const mapped_type> value_type;
-
- typedef value_type* pointer;
-
- typedef value_type& reference;
-
- ConstDBIterator(const DBPtr& db, const DBCursorPtr& cursor)
- : _db(db), _cursor(cursor)
- {
- }
- ConstDBIterator() { }
-
- ConstDBIterator(const ConstDBIterator& rhs)
- {
- if(rhs._cursor)
- {
- _cursor = rhs._cursor->clone();
- }
-
- _db = rhs._db;
- }
-
- //
- // A DBIterator can be converted to a ConstDBIterator (but not
- // vice versa) - same for operator=.
- //
- ConstDBIterator(const DBIterator<key_type, mapped_type, KeyCodec, ValueCodec>& rhs)
- {
- if(rhs._cursor)
- {
- _cursor = rhs._cursor->clone();
- }
-
- _db = rhs._db;
- }
-
- ConstDBIterator& operator=(const ConstDBIterator& rhs)
- {
- if(_cursor)
- {
- _cursor->close();
- }
-
- if(rhs._cursor)
- {
- _cursor = rhs._cursor->clone();
- }
-
- _db = rhs._db;
-
- return *this;
- }
-
- //
- // Create const_iterator from iterator.
- //
- ConstDBIterator& operator=(const DBIterator<key_type, mapped_type, KeyCodec, ValueCodec>& rhs)
- {
- if(_cursor)
- {
- _cursor->close();
- }
-
- if(rhs._cursor)
- {
- _cursor = rhs._cursor->clone();
- }
-
- _db = rhs._db;
-
- return *this;
- }
-
- ~ConstDBIterator()
- {
- if(_cursor)
- {
- _cursor->close();
- }
- }
-
- bool operator==(const ConstDBIterator& rhs)
- {
- if(!_db && !rhs._db)
- {
- return true;
- }
- return false;
- }
-
- bool operator!=(const ConstDBIterator& rhs)
- {
- return !(*this == rhs);
- }
-
- ConstDBIterator& operator++()
- {
- incr();
- return *this;
- }
-
- ConstDBIterator operator++(int)
- {
- ConstDBIterator tmp = *this;
- tmp.incr();
- return tmp;
- }
-
- //
- // Note that this doesn't follow the regular iterator mapping:
- //
- // value_type operator*() const
- //
- value_type& operator*() const
- {
- key_type key;
- mapped_type value;
-
- getCurrentValue(key, value);
-
- //
- // !IMPORTANT!
- //
- // This method has to cache the returned value to implement
- // operator->().
- //
- const_cast<key_type&>(_ref.first) = key;
- const_cast<mapped_type&>(_ref.second) = value;
- return _ref;
- }
-
- pointer operator->() const { return &(operator*()); }
-
-private:
-
- void incr()
- {
- assert(_cursor);
- if(!_cursor->next())
- {
- //
- // The iterator has been moved past the end, and is now
- // invalid.
- //
- _cursor->close();
- _cursor = 0;
- _db = 0;
- }
- }
-
- void getCurrentValue(key_type& key, mapped_type& value) const
- {
- Freeze::Key k;
- Freeze::Value v;
-
- _cursor->curr(k, v);
-
- ::Ice::CommunicatorPtr communicator = _db->getCommunicator();
- KeyCodec::read(key, k, communicator);
- ValueCodec::read(value, v, communicator);
- }
-
- friend class DBMap<key_type, mapped_type, KeyCodec, ValueCodec>;
-
- DBPtr _db;
- DBCursorPtr _cursor;
-
- //
- // Cached last return value. This is so that operator->() can
- // actually return a pointer.
- //
- mutable value_type _ref;
-};
-
-//
-// This is an STL container that matches the requirements of a
-// Associated Container - with the restriction that operator[] isn't
-// implemented. It also supports the same interface as a Hashed
-// Associative Container (with the above restrictions), except the
-// hasher & key_equal methods.
-//
-// TODO: If necessary it would be possible to implement reverse and
-// bidirectional iterators.
-//
-template <typename key_type, typename mapped_type, typename KeyCodec, typename ValueCodec>
-class DBMap
-{
-public:
-
- typedef std::pair<const key_type, const mapped_type> value_type;
-
- //
- // These are not supported:
- //
- // hasher, key_equal, key_compare, value_compare
- //
-
- typedef DBIterator<key_type, mapped_type, KeyCodec, ValueCodec > iterator;
- typedef ConstDBIterator<key_type, mapped_type, KeyCodec, ValueCodec > const_iterator;
-
- //
- // No definition for reference, const_reference, pointer or
- // const_pointer.
- //
-
- typedef size_t size_type;
- typedef ptrdiff_t difference_type;
-
- //
- // Allocators are not supported.
- //
- // allocator_type
- //
-
- //
- // Constructors
- //
- DBMap(const DBPtr& db) :
- _db(db)
- {
- }
-
-#ifdef __STL_MEMBER_TEMPLATES
- template <class _InputIterator>
- DBMap(const DBPtr& db, _InputIterator first, _InputIterator last) :
- _db(db)
- {
- while(first != last)
- {
- insert(*first);
- ++first;
- }
- }
-#else
- DBMap(const DBPtr& db, const value_type* first, const value_type* last) :
- _db(db)
- {
- while(first != last)
- {
- insert(*first);
- ++first;
- }
- }
- DBMap(const DBPtr& db, const_iterator first, const_iterator last) :
- _db(db)
- {
- while(first != last)
- {
- insert(*first);
- ++first;
- }
- }
-#endif /*__STL_MEMBER_TEMPLATES */
-
- ~DBMap()
- {
- }
-
- //
- // Neither of these operations are supported.
- //
- // key_compare key_comp() const, value_compare value_comp() const,
- // hasher hash_funct() const, key_equal key_eq() const
- //
-
- bool operator==(const DBMap& rhs) const
- {
- //
- // This does a memberwise equality for the entire contents of
- // the database. While slow this is always correct. Database
- // equality is not necessarily correct in the context of a
- // transaction.
- //
- if(count() != rhs.count())
- return false;
-
- for(const_iterator p = rhs.begin() ; p != rhs.end() ; ++p)
- {
- const_iterator q = rhs.find(p->first);
- if(q == rhs.end())
- {
- return false;
- }
- if(p->second != q->second)
- {
- return false;
- }
- }
- return true;
- }
-
- bool operator!=(const DBMap& rhs) const
- {
- return !(*this == rhs);
- }
-
- void swap(DBMap& rhs)
- {
- DBPtr tmp = _db;
- _db = rhs._db;
- rhs._db = tmp;
- }
-
- iterator begin()
- {
- try
- {
- return iterator(_db, _db->getCursor());
- }
- catch(const DBNotFoundException&)
- {
- return iterator();
- }
- }
- const_iterator begin() const
- {
- try
- {
- return const_iterator(_db, _db->getCursor());
- }
- catch(const DBNotFoundException&)
- {
- return const_iterator();
- }
- }
-
- iterator end()
- {
- return iterator();
- }
-
- const_iterator end() const
- {
- return const_iterator();
- }
-
- bool empty() const
- {
- return size() == 0;
- }
-
- size_type size() const
- {
- return (size_type)_db->getNumberOfRecords();
- }
-
- size_type max_size() const
- {
- return 0xffffffff; // TODO: is this the max?
- }
-
- //
- // This method isn't implemented.
- //
- // mapped_type& operator[](const key_type& key)
- //
-
- //
- // This method isn't in the STLport library - but it's referenced
- // in "STL Tutorial and Refrence Guide, Second Edition". It's not
- // currently implemented.
- //
- // const mapped_type& operator[](const key_type& key) const;
- //
-
- //
- // No allocators.
- //
- //allocator_type get_allocator() const;
- //
-
- iterator insert(iterator /*position*/, const value_type& key)
- {
- //
- // position is ignored.
- //
- ::Ice::CommunicatorPtr communicator = _db->getCommunicator();
-
- Freeze::Key k;
- Freeze::Value v;
- KeyCodec::write(key.first, k, communicator);
- ValueCodec::write(key.second, v, communicator);
-
- _db->put(k, v);
- DBCursorPtr cursor = _db->getCursorAtKey(k);
-
- return iterator(_db, cursor);
- }
-
- std::pair<iterator, bool> insert(const value_type& key)
- {
- ::Ice::CommunicatorPtr communicator = _db->getCommunicator();
-
- Freeze::Key k;
- Freeze::Value v;
- KeyCodec::write(key.first, k, communicator);
- ValueCodec::write(key.second, v, communicator);
-
- DBCursorPtr cursor;
- bool inserted;
-
- try
- {
- //
- // Does the value exist already?
- //
- cursor = _db->getCursorAtKey(k);
- inserted = false;
- }
- catch(const DBNotFoundException&)
- {
- inserted = true;
- }
-
- _db->put(k, v);
- if(inserted)
- {
- cursor = _db->getCursorAtKey(k);
- }
- return std::pair<iterator, bool>(iterator(_db, cursor), inserted);
- }
-
-#ifdef __STL_MEMBER_TEMPLATES
- template <typename InputIterator>
- void insert(InputIterator first, InputIterator last)
- {
- while(first != last)
- {
- insert(*first);
- ++first;
- }
- }
-#else
- void insert(const value_type* first, const value_type* last)
- {
- while(first != last)
- {
- insert(*first);
- ++first;
- }
- }
- void insert(const_iterator first, const_iterator last)
- {
- while(first != last)
- {
- insert(*first);
- ++first;
- }
- }
-#endif
-
- void erase(iterator position)
- {
- position._cursor->del();
- }
-
- size_type erase(const key_type& key)
- {
- Freeze::Key k;
- KeyCodec::write(key, k, _db->getCommunicator());
-
- try
- {
- _db->del(k);
- }
- catch(const DBNotFoundException&)
- {
- return 0;
- }
-
- return 1;
- }
-
- void erase(iterator first, iterator last)
- {
- while(first != last)
- {
- first._cursor->del();
- ++first;
- }
- }
-
- void clear()
- {
- _db->clear();
- }
-
- iterator find(const key_type& key)
- {
- Freeze::Key k;
- KeyCodec::write(key, k, _db->getCommunicator());
-
- try
- {
- DBCursorPtr cursor = _db->getCursorAtKey(k);
- return iterator(_db, cursor);
- }
- catch(const DBNotFoundException&)
- {
- //
- // The record doesn't exist, return the end() iterator.
- //
- }
- return end();
- }
-
- const_iterator find(const key_type& key) const
- {
- Freeze::Key k;
- KeyCodec::write(key, k, _db->getCommunicator());
-
- try
- {
- DBCursorPtr cursor = _db->getCursorAtKey(k);
- return const_iterator(_db, cursor);
- }
- catch(const DBNotFoundException&)
- {
- //
- // The record doesn't exist, return the end() iterator.
- //
- }
- return end();
- }
-
- size_type count(const key_type& key) const
- {
- if(find(key) != end())
- return 1;
- return 0;
- }
-
- std::pair<iterator, iterator> equal_range(const key_type& key)
- {
- iterator p = find(key);
- return std::pair<iterator,iterator>(p,p);
- }
-
- std::pair<const_iterator, const_iterator> equal_range(const key_type& key) const
- {
- const_iterator p = find(key);
- return std::pair<const_iterator,const_iterator>(p,p);
- }
-
-private:
-
- DBPtr _db;
-};
-
-} // End namespace Freeze
-
-//
-// This is for MSVC.
-//
-# ifdef _STLP_USE_OLD_HP_ITERATOR_QUERIES
-namespace std
-{
-
-//XXX update
-template <class key_type, class mapped_type, class KeyCodec, class ValueCodec>
-inline pair<const key_type, const mapped_type>*
-value_type(const Freeze::DBIterator<key_type, mapped_type, KeyCodec, ValueCodec>&)
-{
- return (pair<const key_type, const mapped_type>*)0;
-}
-
-template <class key_type, class mapped_type, class KeyCodec, class ValueCodec>
-inline pair<const key_type, const mapped_type>*
-value_type(const Freeze::ConstDBIterator<key_type, mapped_type, KeyCodec, ValueCodec>&)
-{
- return (pair<const key_type, const mapped_type>*)0;
-}
-
-inline forward_iterator_tag iterator_category(const Freeze::DBIteratorBase&)
-{
- return forward_iterator_tag();
-}
-
-inline ptrdiff_t* distance_type(const Freeze::DBIteratorBase&) { return (ptrdiff_t*) 0; }
-
-} // End namespace std
-
-#endif /* _STLP_CLASS_PARTIAL_SPECIALIZATION */
-
-#endif
+// **********************************************************************
+//
+// Copyright (c) 2001
+// MutableRealms, Inc.
+// Huntsville, AL, USA
+//
+// All Rights Reserved
+//
+// **********************************************************************
+
+#ifndef FREEZE_MAP_H
+#define FREEZE_MAP_H
+
+#include <Ice/Ice.h>
+#include <Freeze/DB.h>
+
+#include <iterator>
+
+namespace Freeze
+{
+
+//
+// Forward declaration
+//
+template <typename key_type, typename mapped_type, typename KeyCodec, typename ValueCodec>
+class DBMap;
+template <typename key_type, typename mapped_type, typename KeyCodec, typename ValueCodec>
+class ConstDBIterator;
+
+//
+// This is necessary for MSVC support.
+//
+struct DBIteratorBase
+{
+ typedef std::forward_iterator_tag iterator_category;
+};
+
+//
+// Database iterator. This implements a forward iterator with the
+// restriction that it's only possible to explicitely write back into
+// the database.
+//
+// Equality and inequality are based on whether the iterator is
+// "valid". An valid iterator contains a valid database and cursor
+// pointer, otherwise the iterator is invalid.
+//
+// TODO: It's possible to implement bidirectional iterators, if
+// necessary.
+//
+template <typename key_type, typename mapped_type, typename KeyCodec, typename ValueCodec>
+class DBIterator : public DBIteratorBase
+{
+public:
+
+ typedef ptrdiff_t difference_type;
+
+ typedef std::pair<const key_type, const mapped_type> value_type;
+
+ typedef value_type* pointer;
+
+ typedef value_type& reference;
+
+ DBIterator(const DBPtr& db, const DBCursorPtr& cursor)
+ : _db(db), _cursor(cursor)
+ {
+ }
+
+ DBIterator()
+ {
+ }
+
+ DBIterator(const DBIterator& rhs)
+ {
+ if(rhs._cursor)
+ {
+ _cursor = rhs._cursor->clone();
+ }
+
+ _db = rhs._db;
+ }
+
+ DBIterator& operator=(const DBIterator& rhs)
+ {
+ if(_cursor)
+ {
+ _cursor->close();
+ }
+
+ if(rhs._cursor)
+ {
+ _cursor = rhs._cursor->clone();
+ }
+
+ _db = rhs._db;
+
+ return *this;
+ }
+
+ ~DBIterator()
+ {
+ if(_cursor)
+ {
+ _cursor->close();
+ }
+ }
+
+ bool operator==(const DBIterator& rhs) const
+ {
+ if(!_db && !rhs._db)
+ {
+ return true;
+ }
+ return false;
+ }
+
+ bool operator!=(const DBIterator& rhs) const
+ {
+ return !(*this == rhs);
+ }
+
+ DBIterator& operator++()
+ {
+ incr();
+ return *this;
+ }
+
+ DBIterator operator++(int)
+ {
+ DBIterator tmp = *this;
+ tmp.incr();
+ return tmp;
+ }
+
+ //
+ // Note that this doesn't follow the regular iterator mapping:
+ //
+ // value_type& operator*(), value_type operator*() const
+ //
+ value_type& operator*() const
+ {
+ key_type key;
+ mapped_type value;
+
+ getCurrentValue(key, value);
+
+ //
+ // !IMPORTANT!
+ //
+ // This method has to cache the returned value to implement
+ // operator->().
+ //
+ const_cast<key_type&>(_ref.first) = key;
+ const_cast<mapped_type&>(_ref.second) = value;
+ return _ref;
+ }
+
+ value_type* operator->() { return &(operator*()); }
+
+ //
+ // This special method allows writing back into the database.
+ //
+ void set(const mapped_type& value)
+ {
+ Freeze::Value v;
+ ValueCodec::write(value, v, _db->getCommunicator());
+ _cursor->set(v);
+ }
+
+private:
+
+ void incr()
+ {
+ assert(_cursor && _db);
+ if(!_cursor->next())
+ {
+ //
+ // The iterator has been moved past the end, and is now
+ // invalid.
+ //
+ _cursor->close();
+ _cursor = 0;
+ _db = 0;
+ }
+ }
+
+ void getCurrentValue(key_type& key, mapped_type& value) const
+ {
+ Freeze::Key k;
+ Freeze::Value v;
+
+ _cursor->curr(k, v);
+
+ ::Ice::CommunicatorPtr communicator = _db->getCommunicator();
+ KeyCodec::read(key, k, communicator);
+ ValueCodec::read(value, v, communicator);
+ }
+
+ friend class ConstDBIterator<key_type, mapped_type, KeyCodec, ValueCodec>;
+ friend class DBMap<key_type, mapped_type, KeyCodec, ValueCodec>;
+
+ DBPtr _db;
+ DBCursorPtr _cursor;
+
+ //
+ // Cached last return value. This is so that operator->() can
+ // actually return a pointer.
+ //
+ mutable value_type _ref;
+};
+
+//
+// See DBIterator comments for design notes
+//
+template <typename key_type, typename mapped_type, typename KeyCodec, typename ValueCodec>
+class ConstDBIterator : public DBIteratorBase
+{
+public:
+
+ typedef ptrdiff_t difference_type;
+
+ typedef std::pair<const key_type, const mapped_type> value_type;
+
+ typedef value_type* pointer;
+
+ typedef value_type& reference;
+
+ ConstDBIterator(const DBPtr& db, const DBCursorPtr& cursor)
+ : _db(db), _cursor(cursor)
+ {
+ }
+ ConstDBIterator() { }
+
+ ConstDBIterator(const ConstDBIterator& rhs)
+ {
+ if(rhs._cursor)
+ {
+ _cursor = rhs._cursor->clone();
+ }
+
+ _db = rhs._db;
+ }
+
+ //
+ // A DBIterator can be converted to a ConstDBIterator (but not
+ // vice versa) - same for operator=.
+ //
+ ConstDBIterator(const DBIterator<key_type, mapped_type, KeyCodec, ValueCodec>& rhs)
+ {
+ if(rhs._cursor)
+ {
+ _cursor = rhs._cursor->clone();
+ }
+
+ _db = rhs._db;
+ }
+
+ ConstDBIterator& operator=(const ConstDBIterator& rhs)
+ {
+ if(_cursor)
+ {
+ _cursor->close();
+ }
+
+ if(rhs._cursor)
+ {
+ _cursor = rhs._cursor->clone();
+ }
+
+ _db = rhs._db;
+
+ return *this;
+ }
+
+ //
+ // Create const_iterator from iterator.
+ //
+ ConstDBIterator& operator=(const DBIterator<key_type, mapped_type, KeyCodec, ValueCodec>& rhs)
+ {
+ if(_cursor)
+ {
+ _cursor->close();
+ }
+
+ if(rhs._cursor)
+ {
+ _cursor = rhs._cursor->clone();
+ }
+
+ _db = rhs._db;
+
+ return *this;
+ }
+
+ ~ConstDBIterator()
+ {
+ if(_cursor)
+ {
+ _cursor->close();
+ }
+ }
+
+ bool operator==(const ConstDBIterator& rhs)
+ {
+ if(!_db && !rhs._db)
+ {
+ return true;
+ }
+ return false;
+ }
+
+ bool operator!=(const ConstDBIterator& rhs)
+ {
+ return !(*this == rhs);
+ }
+
+ ConstDBIterator& operator++()
+ {
+ incr();
+ return *this;
+ }
+
+ ConstDBIterator operator++(int)
+ {
+ ConstDBIterator tmp = *this;
+ tmp.incr();
+ return tmp;
+ }
+
+ //
+ // Note that this doesn't follow the regular iterator mapping:
+ //
+ // value_type operator*() const
+ //
+ value_type& operator*() const
+ {
+ key_type key;
+ mapped_type value;
+
+ getCurrentValue(key, value);
+
+ //
+ // !IMPORTANT!
+ //
+ // This method has to cache the returned value to implement
+ // operator->().
+ //
+ const_cast<key_type&>(_ref.first) = key;
+ const_cast<mapped_type&>(_ref.second) = value;
+ return _ref;
+ }
+
+ pointer operator->() const { return &(operator*()); }
+
+private:
+
+ void incr()
+ {
+ assert(_cursor);
+ if(!_cursor->next())
+ {
+ //
+ // The iterator has been moved past the end, and is now
+ // invalid.
+ //
+ _cursor->close();
+ _cursor = 0;
+ _db = 0;
+ }
+ }
+
+ void getCurrentValue(key_type& key, mapped_type& value) const
+ {
+ Freeze::Key k;
+ Freeze::Value v;
+
+ _cursor->curr(k, v);
+
+ ::Ice::CommunicatorPtr communicator = _db->getCommunicator();
+ KeyCodec::read(key, k, communicator);
+ ValueCodec::read(value, v, communicator);
+ }
+
+ friend class DBMap<key_type, mapped_type, KeyCodec, ValueCodec>;
+
+ DBPtr _db;
+ DBCursorPtr _cursor;
+
+ //
+ // Cached last return value. This is so that operator->() can
+ // actually return a pointer.
+ //
+ mutable value_type _ref;
+};
+
+//
+// This is an STL container that matches the requirements of a
+// Associated Container - with the restriction that operator[] isn't
+// implemented. It also supports the same interface as a Hashed
+// Associative Container (with the above restrictions), except the
+// hasher & key_equal methods.
+//
+// TODO: If necessary it would be possible to implement reverse and
+// bidirectional iterators.
+//
+template <typename key_type, typename mapped_type, typename KeyCodec, typename ValueCodec>
+class DBMap
+{
+public:
+
+ typedef std::pair<const key_type, const mapped_type> value_type;
+
+ //
+ // These are not supported:
+ //
+ // hasher, key_equal, key_compare, value_compare
+ //
+
+ typedef DBIterator<key_type, mapped_type, KeyCodec, ValueCodec > iterator;
+ typedef ConstDBIterator<key_type, mapped_type, KeyCodec, ValueCodec > const_iterator;
+
+ //
+ // No definition for reference, const_reference, pointer or
+ // const_pointer.
+ //
+
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+
+ //
+ // Allocators are not supported.
+ //
+ // allocator_type
+ //
+
+ //
+ // Constructors
+ //
+ DBMap(const DBPtr& db) :
+ _db(db)
+ {
+ }
+
+#ifdef __STL_MEMBER_TEMPLATES
+ template <class _InputIterator>
+ DBMap(const DBPtr& db, _InputIterator first, _InputIterator last) :
+ _db(db)
+ {
+ while(first != last)
+ {
+ insert(*first);
+ ++first;
+ }
+ }
+#else
+ DBMap(const DBPtr& db, const value_type* first, const value_type* last) :
+ _db(db)
+ {
+ while(first != last)
+ {
+ insert(*first);
+ ++first;
+ }
+ }
+ DBMap(const DBPtr& db, const_iterator first, const_iterator last) :
+ _db(db)
+ {
+ while(first != last)
+ {
+ insert(*first);
+ ++first;
+ }
+ }
+#endif /*__STL_MEMBER_TEMPLATES */
+
+ ~DBMap()
+ {
+ }
+
+ //
+ // Neither of these operations are supported.
+ //
+ // key_compare key_comp() const, value_compare value_comp() const,
+ // hasher hash_funct() const, key_equal key_eq() const
+ //
+
+ bool operator==(const DBMap& rhs) const
+ {
+ //
+ // This does a memberwise equality for the entire contents of
+ // the database. While slow this is always correct. Database
+ // equality is not necessarily correct in the context of a
+ // transaction.
+ //
+ if(count() != rhs.count())
+ return false;
+
+ for(const_iterator p = rhs.begin() ; p != rhs.end() ; ++p)
+ {
+ const_iterator q = rhs.find(p->first);
+ if(q == rhs.end())
+ {
+ return false;
+ }
+ if(p->second != q->second)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ bool operator!=(const DBMap& rhs) const
+ {
+ return !(*this == rhs);
+ }
+
+ void swap(DBMap& rhs)
+ {
+ DBPtr tmp = _db;
+ _db = rhs._db;
+ rhs._db = tmp;
+ }
+
+ iterator begin()
+ {
+ try
+ {
+ return iterator(_db, _db->getCursor());
+ }
+ catch(const DBNotFoundException&)
+ {
+ return iterator();
+ }
+ }
+ const_iterator begin() const
+ {
+ try
+ {
+ return const_iterator(_db, _db->getCursor());
+ }
+ catch(const DBNotFoundException&)
+ {
+ return const_iterator();
+ }
+ }
+
+ iterator end()
+ {
+ return iterator();
+ }
+
+ const_iterator end() const
+ {
+ return const_iterator();
+ }
+
+ bool empty() const
+ {
+ return size() == 0;
+ }
+
+ size_type size() const
+ {
+ return (size_type)_db->getNumberOfRecords();
+ }
+
+ size_type max_size() const
+ {
+ return 0xffffffff; // TODO: is this the max?
+ }
+
+ //
+ // This method isn't implemented.
+ //
+ // mapped_type& operator[](const key_type& key)
+ //
+
+ //
+ // This method isn't in the STLport library - but it's referenced
+ // in "STL Tutorial and Refrence Guide, Second Edition". It's not
+ // currently implemented.
+ //
+ // const mapped_type& operator[](const key_type& key) const;
+ //
+
+ //
+ // No allocators.
+ //
+ //allocator_type get_allocator() const;
+ //
+
+ iterator insert(iterator /*position*/, const value_type& key)
+ {
+ //
+ // position is ignored.
+ //
+ ::Ice::CommunicatorPtr communicator = _db->getCommunicator();
+
+ Freeze::Key k;
+ Freeze::Value v;
+ KeyCodec::write(key.first, k, communicator);
+ ValueCodec::write(key.second, v, communicator);
+
+ _db->put(k, v);
+ DBCursorPtr cursor = _db->getCursorAtKey(k);
+
+ return iterator(_db, cursor);
+ }
+
+ std::pair<iterator, bool> insert(const value_type& key)
+ {
+ ::Ice::CommunicatorPtr communicator = _db->getCommunicator();
+
+ Freeze::Key k;
+ Freeze::Value v;
+ KeyCodec::write(key.first, k, communicator);
+ ValueCodec::write(key.second, v, communicator);
+
+ DBCursorPtr cursor;
+ bool inserted;
+
+ try
+ {
+ //
+ // Does the value exist already?
+ //
+ cursor = _db->getCursorAtKey(k);
+ inserted = false;
+ }
+ catch(const DBNotFoundException&)
+ {
+ inserted = true;
+ }
+
+ _db->put(k, v);
+ if(inserted)
+ {
+ cursor = _db->getCursorAtKey(k);
+ }
+ return std::pair<iterator, bool>(iterator(_db, cursor), inserted);
+ }
+
+#ifdef __STL_MEMBER_TEMPLATES
+ template <typename InputIterator>
+ void insert(InputIterator first, InputIterator last)
+ {
+ while(first != last)
+ {
+ insert(*first);
+ ++first;
+ }
+ }
+#else
+ void insert(const value_type* first, const value_type* last)
+ {
+ while(first != last)
+ {
+ insert(*first);
+ ++first;
+ }
+ }
+ void insert(const_iterator first, const_iterator last)
+ {
+ while(first != last)
+ {
+ insert(*first);
+ ++first;
+ }
+ }
+#endif
+
+ void erase(iterator position)
+ {
+ position._cursor->del();
+ }
+
+ size_type erase(const key_type& key)
+ {
+ Freeze::Key k;
+ KeyCodec::write(key, k, _db->getCommunicator());
+
+ try
+ {
+ _db->del(k);
+ }
+ catch(const DBNotFoundException&)
+ {
+ return 0;
+ }
+
+ return 1;
+ }
+
+ void erase(iterator first, iterator last)
+ {
+ while(first != last)
+ {
+ first._cursor->del();
+ ++first;
+ }
+ }
+
+ void clear()
+ {
+ _db->clear();
+ }
+
+ iterator find(const key_type& key)
+ {
+ Freeze::Key k;
+ KeyCodec::write(key, k, _db->getCommunicator());
+
+ try
+ {
+ DBCursorPtr cursor = _db->getCursorAtKey(k);
+ return iterator(_db, cursor);
+ }
+ catch(const DBNotFoundException&)
+ {
+ //
+ // The record doesn't exist, return the end() iterator.
+ //
+ }
+ return end();
+ }
+
+ const_iterator find(const key_type& key) const
+ {
+ Freeze::Key k;
+ KeyCodec::write(key, k, _db->getCommunicator());
+
+ try
+ {
+ DBCursorPtr cursor = _db->getCursorAtKey(k);
+ return const_iterator(_db, cursor);
+ }
+ catch(const DBNotFoundException&)
+ {
+ //
+ // The record doesn't exist, return the end() iterator.
+ //
+ }
+ return end();
+ }
+
+ size_type count(const key_type& key) const
+ {
+ if(find(key) != end())
+ return 1;
+ return 0;
+ }
+
+ std::pair<iterator, iterator> equal_range(const key_type& key)
+ {
+ iterator p = find(key);
+ return std::pair<iterator,iterator>(p,p);
+ }
+
+ std::pair<const_iterator, const_iterator> equal_range(const key_type& key) const
+ {
+ const_iterator p = find(key);
+ return std::pair<const_iterator,const_iterator>(p,p);
+ }
+
+private:
+
+ DBPtr _db;
+};
+
+} // End namespace Freeze
+
+//
+// This is for MSVC.
+//
+# ifdef _STLP_USE_OLD_HP_ITERATOR_QUERIES
+namespace std
+{
+
+//XXX update
+template <class key_type, class mapped_type, class KeyCodec, class ValueCodec>
+inline pair<const key_type, const mapped_type>*
+value_type(const Freeze::DBIterator<key_type, mapped_type, KeyCodec, ValueCodec>&)
+{
+ return (pair<const key_type, const mapped_type>*)0;
+}
+
+template <class key_type, class mapped_type, class KeyCodec, class ValueCodec>
+inline pair<const key_type, const mapped_type>*
+value_type(const Freeze::ConstDBIterator<key_type, mapped_type, KeyCodec, ValueCodec>&)
+{
+ return (pair<const key_type, const mapped_type>*)0;
+}
+
+inline forward_iterator_tag iterator_category(const Freeze::DBIteratorBase&)
+{
+ return forward_iterator_tag();
+}
+
+inline ptrdiff_t* distance_type(const Freeze::DBIteratorBase&) { return (ptrdiff_t*) 0; }
+
+} // End namespace std
+
+#endif /* _STLP_CLASS_PARTIAL_SPECIALIZATION */
+
+#endif