#ifndef MAP_H #define MAP_H #include #include #include #include // Ian Gipson's Map. // Similar to STL map but with the addition of a reserve function that works much // like the original stl::vector::reserve. // I've made 2 minor changes. One is prefixing the Map namespace to the iterators // that prevent the PS2 version from compiling because of typedef confusion // with STL's vectors and I've moved the STL onto Darwin's // persistent_allocator for memory tracking //============================================================================= // ForwardReference //============================================================================= template < class KeyClass, class T > class Map; //============================================================================= // MapElement //============================================================================= template < class KeyClass, class T > class MapElement { public: KeyClass first; T second; bool operator<( const MapElement& right ) const{ return first < right.first;} bool operator==( const MapElement& right ) const{ return first == right.first;} protected: }; //============================================================================= // Map //============================================================================= template < class KeyClass, class T > class Map { public: //========================================================================= // iterator //========================================================================= typedef MapElement< KeyClass, T > MapElementType; typedef std::vector< MapElementType, s2alloc< MapElementType > > MapElementVector; typedef typename MapElementVector::iterator iterator; typedef typename MapElementVector::const_iterator const_iterator; //========================================================================= Map(); typename Map::const_iterator begin() const; typename Map::iterator begin(); size_t capacity() const; void clear(); typename Map::const_iterator end() const; typename Map::iterator end(); typename Map::iterator erase( typename Map::iterator it ); size_t erase( const KeyClass& key ); typename Map::const_iterator find( const KeyClass& key ) const; typename Map::iterator find( const KeyClass& key ); T& get( const KeyClass& key ); void insert( const KeyClass& key, const T& element ); const T& operator[]( const KeyClass& key ) const; void reserve( const size_t size ); size_t size() const; protected: void RefreshIfDirty() const; mutable MapElementVector m_Elements; //oh how i lie about constness... mutable bool m_Dirty; }; //============================================================================= // Constructor //============================================================================= template < class KeyClass, class T > Map< KeyClass, T >::Map( ): m_Dirty( false ) { // // nothing // } //============================================================================= // begin //============================================================================= template < class KeyClass, class T > typename Map< KeyClass, T >::const_iterator Map< KeyClass, T >::begin() const { return m_Elements.begin(); } //============================================================================= // begin //============================================================================= template < class KeyClass, class T > typename Map< KeyClass, T >::iterator Map< KeyClass, T >::begin() { return m_Elements.begin(); } //============================================================================= // capacity //============================================================================= template < class KeyClass, class T > size_t Map< KeyClass, T >::capacity() const { return m_Elements.capacity(); } //============================================================================= // clear //============================================================================= template < class KeyClass, class T > void Map< KeyClass, T >::clear() { m_Elements.erase( m_Elements.begin(), m_Elements.end() ); } //============================================================================= // end //============================================================================= template < class KeyClass, class T > typename Map< KeyClass, T >::const_iterator Map< KeyClass, T >::end() const { return m_Elements.end(); } //============================================================================= // end //============================================================================= template < class KeyClass, class T > typename Map< KeyClass, T >::iterator Map< KeyClass, T >::end() { return m_Elements.end(); } //============================================================================= // erase //============================================================================= template < class KeyClass, class T > typename Map< KeyClass, T >::iterator Map< KeyClass, T >::erase( typename Map< KeyClass, T >::iterator it ) { return m_Elements.erase( it ); } //============================================================================= // erase //============================================================================= template < class KeyClass, class T > size_t Map< KeyClass, T >::erase( const KeyClass& key ) { MapElementVector::iterator it; for( it = m_Elements.begin(); it != m_Elements.end(); ++it ) { if( (*it).first == key ) { it = m_Elements.erase( it ); return 1; } } return 0; } //======`======================================================================= // find //============================================================================= template < class KeyClass, class T > typename Map< KeyClass, T >::const_iterator Map< KeyClass, T >::find( const KeyClass& key ) const { RefreshIfDirty(); MapElement< KeyClass, T > findme; findme.first = key; const Map::iterator it = std::lower_bound( m_Elements.begin(), m_Elements.end(), findme ); return it; } //============================================================================= // find //============================================================================= template < class KeyClass, class T > typename Map< KeyClass, T >::iterator Map< KeyClass, T >::find( const KeyClass& key ) { RefreshIfDirty(); MapElement< KeyClass, T > findme; findme.first = key; Map::iterator it = std::lower_bound( m_Elements.begin(), m_Elements.end(), findme ); if( it != m_Elements.end() ) { if( ( *it).first == key ) { return it; } } return m_Elements.end(); } //============================================================================= // insert //============================================================================= template < class KeyClass, class T > void Map< KeyClass, T >::insert( const KeyClass& key, const T& element ) { //if the key is already in the map, then just replace it Map::iterator found = find( key ); if( found != end() ) { ( *found ).second = element; } else { // this function could be faster, not requiring a sort every time // something gets inserted. if maps turn out to be slow, make this // adjustment MapElement< KeyClass, T > me; me.first = key; me.second = element; #ifdef RAD_DEBUG size_t capacityBefore = m_Elements.capacity(); #endif m_Elements.push_back( me ); #ifdef RAD_DEBUG size_t capacityAfter = m_Elements.capacity(); if( capacityBefore != capacityAfter ) { //rDebugPrintf( "This map should have been RESERVED larger before use\n" ); } #endif m_Dirty = true; } } //============================================================================= // operator[] //============================================================================= template < class KeyClass, class T > const T& Map< KeyClass, T >::operator[]( const KeyClass& key ) const { Map::const_iterator it = find( key ); rAssert( it != end() ); return (*it).second; } //============================================================================= // get //============================================================================= template < class KeyClass, class T > T& Map< KeyClass, T >::get( const KeyClass& key ) { Map::iterator it = find( key ); rAssert( it != end() ); return (*it).second; } //============================================================================= // Refresh the sorting of the map if it is currently dirty //============================================================================= template < class KeyClass, class T > void Map< KeyClass, T >::RefreshIfDirty() const { //THIS FUNCTION DOES NOTHING if( m_Dirty ) { std::sort( m_Elements.begin(), m_Elements.end() ); m_Dirty = false; } } //============================================================================= // Reserves space in the map, so that it won't have to autoresize //============================================================================= template < class KeyClass, class T > void Map< KeyClass, T >::reserve( const size_t size ) { m_Elements.reserve( size ); } //============================================================================= // returns the number of elements in the map //============================================================================= template < class KeyClass, class T > size_t Map< KeyClass, T >::size() const { return m_Elements.size(); } #endif