| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328 |
- /*
- * Copyright (c) 2014, Oculus VR, Inc.
- * All rights reserved.
- *
- * This source code is licensed under the BSD-style license found in the
- * LICENSE file in the root directory of this source tree. An additional grant
- * of patent rights can be found in the PATENTS file in the same directory.
- *
- */
- /// \file DS_Map.h
- /// \internal
- /// \brief Map
- ///
- #ifndef __RAKNET_MAP_H
- #define __RAKNET_MAP_H
- #include "DS_OrderedList.h"
- #include "Export.h"
- #include "RakMemoryOverride.h"
- #include "RakAssert.h"
- // If I want to change this to a red-black tree, this is a good site: http://www.cs.auckland.ac.nz/software/AlgAnim/red_black.html
- // This makes insertions and deletions faster. But then traversals are slow, while they are currently fast.
- /// The namespace DataStructures was only added to avoid compiler errors for commonly named data structures
- /// As these data structures are stand-alone, you can use them outside of RakNet for your own projects if you wish.
- namespace DataStructures
- {
- /// The default comparison has to be first so it can be called as a default parameter.
- /// It then is followed by MapNode, followed by NodeComparisonFunc
- template <class key_type>
- int defaultMapKeyComparison(const key_type &a, const key_type &b)
- {
- if (a<b) return -1; if (a==b) return 0; return 1;
- }
- /// \note IMPORTANT! If you use defaultMapKeyComparison then call IMPLEMENT_DEFAULT_COMPARISON or you will get an unresolved external linker error.
- template <class key_type, class data_type, int (*key_comparison_func)(const key_type&, const key_type&)=defaultMapKeyComparison<key_type> >
- class RAK_DLL_EXPORT Map
- {
- public:
- static void IMPLEMENT_DEFAULT_COMPARISON(void) {DataStructures::defaultMapKeyComparison<key_type>(key_type(),key_type());}
- struct MapNode
- {
- MapNode() {}
- MapNode(key_type _key, data_type _data) : mapNodeKey(_key), mapNodeData(_data) {}
- MapNode& operator = ( const MapNode& input ) {mapNodeKey=input.mapNodeKey; mapNodeData=input.mapNodeData; return *this;}
- MapNode( const MapNode & input) {mapNodeKey=input.mapNodeKey; mapNodeData=input.mapNodeData;}
- key_type mapNodeKey;
- data_type mapNodeData;
- };
- // Has to be a static because the comparison callback for DataStructures::OrderedList is a C function
- static int NodeComparisonFunc(const key_type &a, const MapNode &b)
- {
- #ifdef _MSC_VER
- #pragma warning( disable : 4127 ) // warning C4127: conditional expression is constant
- #endif
- return key_comparison_func(a, b.mapNodeKey);
- }
- Map();
- ~Map();
- Map( const Map& original_copy );
- Map& operator= ( const Map& original_copy );
- data_type& Get(const key_type &key) const;
- data_type Pop(const key_type &key);
- // Add if needed
- void Set(const key_type &key, const data_type &data);
- // Must already exist
- void SetExisting(const key_type &key, const data_type &data);
- // Must add
- void SetNew(const key_type &key, const data_type &data);
- bool Has(const key_type &key) const;
- bool Delete(const key_type &key);
- data_type& operator[] ( const unsigned int position ) const;
- key_type GetKeyAtIndex( const unsigned int position ) const;
- unsigned GetIndexAtKey( const key_type &key );
- void RemoveAtIndex(const unsigned index);
- void Clear(void);
- unsigned Size(void) const;
- protected:
- DataStructures::OrderedList< key_type,MapNode,&Map::NodeComparisonFunc > mapNodeList;
- void SaveLastSearch(const key_type &key, unsigned index) const;
- bool HasSavedSearchResult(const key_type &key) const;
- unsigned lastSearchIndex;
- key_type lastSearchKey;
- bool lastSearchIndexValid;
- };
- template <class key_type, class data_type, int (*key_comparison_func)(const key_type&,const key_type&)>
- Map<key_type, data_type, key_comparison_func>::Map()
- {
- lastSearchIndexValid=false;
- }
- template <class key_type, class data_type, int (*key_comparison_func)(const key_type&,const key_type&)>
- Map<key_type, data_type, key_comparison_func>::~Map()
- {
- Clear();
- }
- template <class key_type, class data_type, int (*key_comparison_func)(const key_type&,const key_type&)>
- Map<key_type, data_type, key_comparison_func>::Map( const Map& original_copy )
- {
- mapNodeList=original_copy.mapNodeList;
- lastSearchIndex=original_copy.lastSearchIndex;
- lastSearchKey=original_copy.lastSearchKey;
- lastSearchIndexValid=original_copy.lastSearchIndexValid;
- }
- template <class key_type, class data_type, int (*key_comparison_func)(const key_type&,const key_type&)>
- Map<key_type, data_type, key_comparison_func>& Map<key_type, data_type, key_comparison_func>::operator= ( const Map& original_copy )
- {
- mapNodeList=original_copy.mapNodeList;
- lastSearchIndex=original_copy.lastSearchIndex;
- lastSearchKey=original_copy.lastSearchKey;
- lastSearchIndexValid=original_copy.lastSearchIndexValid;
- return *this;
- }
- template <class key_type, class data_type, int (*key_comparison_func)(const key_type&,const key_type&)>
- data_type& Map<key_type, data_type, key_comparison_func>::Get(const key_type &key) const
- {
- if (HasSavedSearchResult(key))
- return mapNodeList[lastSearchIndex].mapNodeData;
- bool objectExists;
- unsigned index;
- index=mapNodeList.GetIndexFromKey(key, &objectExists);
- RakAssert(objectExists);
- SaveLastSearch(key,index);
- return mapNodeList[index].mapNodeData;
- }
- template <class key_type, class data_type, int (*key_comparison_func)(const key_type&,const key_type&)>
- unsigned Map<key_type, data_type, key_comparison_func>::GetIndexAtKey( const key_type &key )
- {
- if (HasSavedSearchResult(key))
- return lastSearchIndex;
- bool objectExists;
- unsigned index;
- index=mapNodeList.GetIndexFromKey(key, &objectExists);
- if (objectExists==false)
- {
- RakAssert(objectExists);
- }
- SaveLastSearch(key,index);
- return index;
- }
- template <class key_type, class data_type, int (*key_comparison_func)(const key_type&,const key_type&)>
- void Map<key_type, data_type, key_comparison_func>::RemoveAtIndex(const unsigned index)
- {
- mapNodeList.RemoveAtIndex(index);
- lastSearchIndexValid=false;
- }
- template <class key_type, class data_type, int (*key_comparison_func)(const key_type&,const key_type&)>
- data_type Map<key_type, data_type, key_comparison_func>::Pop(const key_type &key)
- {
- bool objectExists;
- unsigned index;
- if (HasSavedSearchResult(key))
- index=lastSearchIndex;
- else
- {
- index=mapNodeList.GetIndexFromKey(key, &objectExists);
- RakAssert(objectExists);
- }
- data_type tmp = mapNodeList[index].mapNodeData;
- mapNodeList.RemoveAtIndex(index);
- lastSearchIndexValid=false;
- return tmp;
- }
- template <class key_type, class data_type, int (*key_comparison_func)(const key_type&,const key_type&)>
- void Map<key_type, data_type, key_comparison_func>::Set(const key_type &key, const data_type &data)
- {
- bool objectExists;
- unsigned index;
- if (HasSavedSearchResult(key))
- {
- mapNodeList[lastSearchIndex].mapNodeData=data;
- return;
- }
-
- index=mapNodeList.GetIndexFromKey(key, &objectExists);
- if (objectExists)
- {
- SaveLastSearch(key,index);
- mapNodeList[index].mapNodeData=data;
- }
- else
- {
- SaveLastSearch(key,mapNodeList.Insert(key,MapNode(key,data), true, _FILE_AND_LINE_));
- }
- }
- template <class key_type, class data_type, int (*key_comparison_func)(const key_type&,const key_type&)>
- void Map<key_type, data_type, key_comparison_func>::SetExisting(const key_type &key, const data_type &data)
- {
- bool objectExists;
- unsigned index;
- if (HasSavedSearchResult(key))
- {
- index=lastSearchIndex;
- }
- else
- {
- index=mapNodeList.GetIndexFromKey(key, &objectExists);
- RakAssert(objectExists);
- SaveLastSearch(key,index);
- }
- mapNodeList[index].mapNodeData=data;
- }
- template <class key_type, class data_type, int (*key_comparison_func)(const key_type&,const key_type&)>
- void Map<key_type, data_type, key_comparison_func>::SetNew(const key_type &key, const data_type &data)
- {
- #ifdef _DEBUG
- bool objectExists;
- mapNodeList.GetIndexFromKey(key, &objectExists);
- RakAssert(objectExists==false);
- #endif
- SaveLastSearch(key,mapNodeList.Insert(key,MapNode(key,data), true, _FILE_AND_LINE_));
- }
- template <class key_type, class data_type, int (*key_comparison_func)(const key_type&,const key_type&)>
- bool Map<key_type, data_type, key_comparison_func>::Has(const key_type &key) const
- {
- if (HasSavedSearchResult(key))
- return true;
- bool objectExists;
- unsigned index;
- index=mapNodeList.GetIndexFromKey(key, &objectExists);
- if (objectExists)
- SaveLastSearch(key,index);
- return objectExists;
- }
- template <class key_type, class data_type, int (*key_comparison_func)(const key_type&,const key_type&)>
- bool Map<key_type, data_type, key_comparison_func>::Delete(const key_type &key)
- {
- if (HasSavedSearchResult(key))
- {
- lastSearchIndexValid=false;
- mapNodeList.RemoveAtIndex(lastSearchIndex);
- return true;
- }
- bool objectExists;
- unsigned index;
- index=mapNodeList.GetIndexFromKey(key, &objectExists);
- if (objectExists)
- {
- lastSearchIndexValid=false;
- mapNodeList.RemoveAtIndex(index);
- return true;
- }
- else
- return false;
- }
- template <class key_type, class data_type, int (*key_comparison_func)(const key_type&,const key_type&)>
- void Map<key_type, data_type, key_comparison_func>::Clear(void)
- {
- lastSearchIndexValid=false;
- mapNodeList.Clear(false, _FILE_AND_LINE_);
- }
- template <class key_type, class data_type, int (*key_comparison_func)(const key_type&,const key_type&)>
- data_type& Map<key_type, data_type, key_comparison_func>::operator[]( const unsigned int position ) const
- {
- return mapNodeList[position].mapNodeData;
- }
- template <class key_type, class data_type, int (*key_comparison_func)(const key_type&,const key_type&)>
- key_type Map<key_type, data_type, key_comparison_func>::GetKeyAtIndex( const unsigned int position ) const
- {
- return mapNodeList[position].mapNodeKey;
- }
- template <class key_type, class data_type, int (*key_comparison_func)(const key_type&,const key_type&)>
- unsigned Map<key_type, data_type, key_comparison_func>::Size(void) const
- {
- return mapNodeList.Size();
- }
- template <class key_type, class data_type, int (*key_comparison_func)(const key_type&,const key_type&)>
- void Map<key_type, data_type, key_comparison_func>::SaveLastSearch(const key_type &key, const unsigned index) const
- {
- (void) key;
- (void) index;
- /*
- lastSearchIndex=index;
- lastSearchKey=key;
- lastSearchIndexValid=true;
- */
- }
- template <class key_type, class data_type, int (*key_comparison_func)(const key_type&,const key_type&)>
- bool Map<key_type, data_type, key_comparison_func>::HasSavedSearchResult(const key_type &key) const
- {
- (void) key;
- // Not threadsafe!
- return false;
- // return lastSearchIndexValid && key_comparison_func(key,lastSearchKey)==0;
- }
- }
- #endif
|