//+----------------------------------------------------------------------------+ //| Description: Magic Set Editor - Program to make Magic (tm) cards | //| Copyright: (C) 2001 - 2009 Twan van Laarhoven and Sean Hunt | //| License: GNU General Public License 2 or later (see file COPYING) | //+----------------------------------------------------------------------------+ #ifndef HEADER_UTIL_ORDER_CACHE #define HEADER_UTIL_ORDER_CACHE // ----------------------------------------------------------------------------- : Includes #include // ----------------------------------------------------------------------------- : OrderCache /// Object that cashes an ordered version of a list of items, for finding the position of objects /** Can be used as a map "void* -> int" for finding the position of an object */ template class OrderCache : public IntrusivePtrBase > { public: /// Initialize the order cache, ordering the keys by their string values from the other vector /** Optionally filter the list using a vector of booleans of items to keep (note: vector is evil) * @pre keys.size() == values.size() */ OrderCache(const vector& keys, const vector& values, vector* keep = nullptr); /// Find the position of the given key in the cache, returns -1 if not found int find(const T& key) const; private: struct CompareKeys; struct CompareValues; typedef pair KV; vector positions; }; // ----------------------------------------------------------------------------- : Implementation template struct OrderCache::CompareKeys { inline bool operator () (const KV& a, void* b) { return a.first < b; } inline bool operator () (const KV& a, const KV& b) { return a.first < b.first; } inline bool operator () (void* a, const KV& b) { return a < b.first; } }; template struct OrderCache::CompareValues { const vector& values; CompareValues(const vector& values) : values(values) {} inline bool operator () (const KV& a, const KV& b) { return smart_less(values[a.second], values[b.second]); } }; template OrderCache::OrderCache(const vector& keys, const vector& values, vector* keep) { assert(keys.size() == values.size()); assert(!keep || keep->size() == keys.size()); // initialize positions, use pos to point back to the values vector positions.reserve(keys.size()); int i = 0; for (typename vector::const_iterator it = keys.begin() ; it != keys.end() ; ++it, ++i) { if (!keep || (*keep)[i]) { positions.push_back(KV(&**it, i)); } } // sort the KVs by the values sort(positions.begin(), positions.end(), CompareValues(values)); // update positions, to point to sorted list i = 0; for (typename vector::iterator it = positions.begin() ; it != positions.end() ; ++it, ++i) { it->second = i; } // sort the KVs by the keys sort(positions.begin(), positions.end(), CompareKeys()); } template int OrderCache::find(const T& key) const { vector::const_iterator it = lower_bound(positions.begin(), positions.end(), &*key, CompareKeys()); if (it == positions.end() || it->first != &*key) return -1; return it->second; } // ----------------------------------------------------------------------------- : EOF #endif