/* Open Tracker License Terms and Conditions Copyright (c) 1991-2000, Be Incorporated. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice applies to all licensees and shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of Be Incorporated shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Be Incorporated. Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks of Be Incorporated in the United States and other countries. Other brand product names are registered trademarks or trademarks of their respective holders. All rights reserved. */ #ifndef _OBJECT_LIST_H #define _OBJECT_LIST_H #include #include #include // // ObjectList is a wrapper around BList that adds type safety, // optional object ownership, search, insert operations, etc. // template class BObjectList; template struct UnaryPredicate { virtual int operator()(const T *) const // virtual could be avoided here if FindBinaryInsertionIndex, // etc. were member template functions { return 0; } private: static int _unary_predicate_glue(const void *item, void *context); friend class BObjectList; }; template int UnaryPredicate::_unary_predicate_glue(const void *item, void *context) { return ((UnaryPredicate *)context)->operator()((const T *)item); } class _PointerList_ : public BList { public: _PointerList_(const _PointerList_ &list); _PointerList_(int32 itemsPerBlock = 20, bool owning = false); ~_PointerList_(); typedef void *(* GenericEachFunction)(void *, void *); typedef int (* GenericCompareFunction)(const void *, const void *); typedef int (* GenericCompareFunctionWithState)(const void *, const void *, void *); typedef int (* UnaryPredicateGlue)(const void *, void *); void *EachElement(GenericEachFunction, void *); void SortItems(GenericCompareFunction); void SortItems(GenericCompareFunctionWithState, void *state); void HSortItems(GenericCompareFunction); void HSortItems(GenericCompareFunctionWithState, void *state); void *BinarySearch(const void *, GenericCompareFunction) const; void *BinarySearch(const void *, GenericCompareFunctionWithState, void *state) const; int32 BinarySearchIndex(const void *, GenericCompareFunction) const; int32 BinarySearchIndex(const void *, GenericCompareFunctionWithState, void *state) const; int32 BinarySearchIndexByPredicate(const void *, UnaryPredicateGlue) const; bool Owning() const; bool ReplaceItem(int32, void *); protected: bool owning; }; template class BObjectList : private _PointerList_ { public: // iteration and sorting typedef T* (*EachFunction)(T*, void*); typedef const T* (*ConstEachFunction)(const T*, void*); typedef int (*CompareFunction)(const T*, const T*); typedef int (*CompareFunctionWithState)(const T*, const T*, void* state); BObjectList(int32 itemsPerBlock = 20, bool owning = false); BObjectList(const BObjectList& list); // clones list; if list is owning, makes // copies of all the items virtual ~BObjectList(); BObjectList& operator=(const BObjectList& list); // clones list; if list is owning, makes // copies of all the items // adding and removing bool AddItem(T*); bool AddItem(T*, int32); bool AddList(BObjectList*); bool AddList(BObjectList*, int32); bool RemoveItem(T*, bool deleteIfOwning = true); // if owning, deletes the removed item T* RemoveItemAt(int32); // returns the removed item void MakeEmpty(bool deleteIfOwning = true); // item access T* ItemAt(int32) const; bool ReplaceItem(int32 index, T*); // if list is owning, deletes the item // at first T* SwapWithItem(int32 index, T* newItem); // same as ReplaceItem, except does not // delete old item at , returns it // instead T* FirstItem() const; T* LastItem() const; // misc. getters int32 IndexOf(const T*) const; bool HasItem(const T*) const; bool IsEmpty() const; int32 CountItems() const; T* EachElement(EachFunction, void*); const T* EachElement(ConstEachFunction, void*) const; void SortItems(CompareFunction); void SortItems(CompareFunctionWithState, void* state); void HSortItems(CompareFunction); void HSortItems(CompareFunctionWithState, void* state); // linear search, returns first item that // matches predicate const T* FindIf(const UnaryPredicate&) const; T* FindIf(const UnaryPredicate&); // list must be sorted with CompareFunction for // these to work T* BinarySearch(const T&, CompareFunction) const; T* BinarySearch(const T&, CompareFunctionWithState, void* state) const; template T* BinarySearchByKey(const Key& key, int (*compare)(const Key*, const T*)) const; template T* BinarySearchByKey(const Key& key, int (*compare)(const Key*, const T*, void*), void* state) const; int32 BinarySearchIndex(const T&item, CompareFunction compare) const; int32 BinarySearchIndex(const T&item, CompareFunctionWithState compare, void* state) const; template int32 BinarySearchIndexByKey(const Key& key, int (*compare)(const Key*, const T*)) const; // Binary insertion - list must be sorted with // CompareFunction for these to work // simple insert bool BinaryInsert(T*, CompareFunction); bool BinaryInsert(T*, CompareFunctionWithState, void* state); bool BinaryInsert(T*, const UnaryPredicate&); // unique insert, returns false if item already // in list bool BinaryInsertUnique(T*, CompareFunction); bool BinaryInsertUnique(T*, CompareFunctionWithState, void* state); bool BinaryInsertUnique(T*, const UnaryPredicate&); // insert a copy of the item, returns new // inserted item T* BinaryInsertCopy(const T& copyThis, CompareFunction); T* BinaryInsertCopy(const T& copyThis, CompareFunctionWithState, void* state); // insert a copy of the item if not in list // already returns new inserted item or existing // item in case of a conflict T* BinaryInsertCopyUnique(const T& copyThis, CompareFunction); T* BinaryInsertCopyUnique(const T& copyThis, CompareFunctionWithState, void* state); int32 FindBinaryInsertionIndex( const UnaryPredicate&, bool* alreadyInList = 0) const; // returns either the index into which a new // item should be inserted or index of an // existing item that matches the predicate class Private; private: friend class Private; void _SetItem(int32, T*); }; template Result WhileEachListItem(BObjectList* list, Result (Item::*func)(Param1), Param1 p1) { Result result = 0; int32 count = list->CountItems(); for (int32 index = 0; index < count; index++) { if ((result = (list->ItemAt(index)->*func)(p1)) != 0) break; } return result; } template Result WhileEachListItem(BObjectList* list, Result (*func)(Item*, Param1), Param1 p1) { Result result = 0; int32 count = list->CountItems(); for (int32 index = 0; index < count; index++) { if ((result = (*func)(list->ItemAt(index), p1)) != 0) break; } return result; } template Result WhileEachListItem(BObjectList* list, Result (Item::*func)(Param1, Param2), Param1 p1, Param2 p2) { Result result = 0; int32 count = list->CountItems(); for (int32 index = 0; index < count; index++) { if ((result = (list->ItemAt(index)->*func)(p1, p2)) != 0) break; } return result; } template Result WhileEachListItem(BObjectList* list, Result (*func)(Item*, Param1, Param2), Param1 p1, Param2 p2) { Result result = 0; int32 count = list->CountItems(); for (int32 index = 0; index < count; index++) { if ((result = (*func)(list->ItemAt(index), p1, p2)) != 0) break; } return result; } template Result WhileEachListItem(BObjectList* list, Result (*func)(Item*, Param1, Param2, Param3, Param4), Param1 p1, Param2 p2, Param3 p3, Param4 p4) { Result result = 0; int32 count = list->CountItems(); for (int32 index = 0; index < count; index++) { if ((result = (*func)(list->ItemAt(index), p1, p2, p3, p4)) != 0) break; } return result; } template void EachListItemIgnoreResult(BObjectList* list, Result (Item::*func)()) { int32 count = list->CountItems(); for (int32 index = 0; index < count; index++) (list->ItemAt(index)->*func)(); } template void EachListItem(BObjectList* list, void (*func)(Item*, Param1), Param1 p1) { int32 count = list->CountItems(); for (int32 index = 0; index < count; index++) (func)(list->ItemAt(index), p1); } template void EachListItem(BObjectList* list, void (Item::*func)(Param1, Param2), Param1 p1, Param2 p2) { int32 count = list->CountItems(); for (int32 index = 0; index < count; index++) (list->ItemAt(index)->*func)(p1, p2); } template void EachListItem(BObjectList* list, void (*func)(Item*,Param1, Param2), Param1 p1, Param2 p2) { int32 count = list->CountItems(); for (int32 index = 0; index < count; index++) (func)(list->ItemAt(index), p1, p2); } template void EachListItem(BObjectList* list, void (*func)(Item*,Param1, Param2, Param3), Param1 p1, Param2 p2, Param3 p3) { int32 count = list->CountItems(); for (int32 index = 0; index < count; index++) (func)(list->ItemAt(index), p1, p2, p3); } template void EachListItem(BObjectList* list, void (*func)(Item*,Param1, Param2, Param3, Param4), Param1 p1, Param2 p2, Param3 p3, Param4 p4) { int32 count = list->CountItems(); for (int32 index = 0; index < count; index++) (func)(list->ItemAt(index), p1, p2, p3, p4); } // inline code inline bool _PointerList_::Owning() const { return owning; } template BObjectList::BObjectList(int32 itemsPerBlock, bool owning) : _PointerList_(itemsPerBlock, owning) { } template BObjectList::BObjectList(const BObjectList &list) : _PointerList_(list) { owning = list.owning; if (owning) { // make our own copies in an owning list int32 count = list.CountItems(); for (int32 index = 0; index < count; index++) { T* item = list.ItemAt(index); if (item) item = new (std::nothrow) T(*item); _SetItem(index, item); } } } template BObjectList::~BObjectList() { if (Owning()) { // have to nuke elements first MakeEmpty(); } } template BObjectList& BObjectList::operator=(const BObjectList& list) { owning = list.owning; BObjectList &result = (BObjectList&)_PointerList_::operator=(list); if (owning) { // make our own copies in an owning list int32 count = list.CountItems(); for (int32 index = 0; index < count; index++) { T* item = list.ItemAt(index); if (item) item = new (std::nothrow) T(*item); _SetItem(index, item); } } return result; } template bool BObjectList::AddItem(T* item) { // need to cast to void* to make T work for const pointers return _PointerList_::AddItem((void*)item); } template bool BObjectList::AddItem(T* item, int32 atIndex) { return _PointerList_::AddItem((void*)item, atIndex); } template bool BObjectList::AddList(BObjectList* newItems) { return _PointerList_::AddList(newItems); } template bool BObjectList::AddList(BObjectList* newItems, int32 atIndex) { return _PointerList_::AddList(newItems, atIndex); } template bool BObjectList::RemoveItem(T* item, bool deleteIfOwning) { bool result = _PointerList_::RemoveItem((void*)item); if (result && Owning() && deleteIfOwning) delete item; return result; } template T* BObjectList::RemoveItemAt(int32 index) { return (T*)_PointerList_::RemoveItem(index); } template inline T* BObjectList::ItemAt(int32 index) const { return (T*)_PointerList_::ItemAt(index); } template bool BObjectList::ReplaceItem(int32 index, T* item) { if (owning) delete ItemAt(index); return _PointerList_::ReplaceItem(index, (void*)item); } template T* BObjectList::SwapWithItem(int32 index, T* newItem) { T* result = ItemAt(index); _PointerList_::ReplaceItem(index, (void*)newItem); return result; } template void BObjectList::_SetItem(int32 index, T* newItem) { _PointerList_::ReplaceItem(index, (void*)newItem); } template int32 BObjectList::IndexOf(const T* item) const { return _PointerList_::IndexOf((void*)item); } template T* BObjectList::FirstItem() const { return (T*)_PointerList_::FirstItem(); } template T* BObjectList::LastItem() const { return (T*)_PointerList_::LastItem(); } template bool BObjectList::HasItem(const T* item) const { return _PointerList_::HasItem((void*)item); } template bool BObjectList::IsEmpty() const { return _PointerList_::IsEmpty(); } template int32 BObjectList::CountItems() const { return _PointerList_::CountItems(); } template void BObjectList::MakeEmpty(bool deleteIfOwning) { if (owning && deleteIfOwning) { int32 count = CountItems(); for (int32 index = 0; index < count; index++) delete ItemAt(index); } _PointerList_::MakeEmpty(); } template T* BObjectList::EachElement(EachFunction func, void* params) { return (T*)_PointerList_::EachElement((GenericEachFunction)func, params); } template const T* BObjectList::EachElement(ConstEachFunction func, void* params) const { return (const T*) const_cast*>(this)->_PointerList_::EachElement( (GenericEachFunction)func, params); } template const T* BObjectList::FindIf(const UnaryPredicate& predicate) const { int32 count = CountItems(); for (int32 index = 0; index < count; index++) { if (predicate.operator()(ItemAt(index)) == 0) return ItemAt(index); } return 0; } template T* BObjectList::FindIf(const UnaryPredicate& predicate) { int32 count = CountItems(); for (int32 index = 0; index < count; index++) { if (predicate.operator()(ItemAt(index)) == 0) return ItemAt(index); } return 0; } template void BObjectList::SortItems(CompareFunction function) { _PointerList_::SortItems((GenericCompareFunction)function); } template void BObjectList::SortItems(CompareFunctionWithState function, void* state) { _PointerList_::SortItems((GenericCompareFunctionWithState)function, state); } template void BObjectList::HSortItems(CompareFunction function) { _PointerList_::HSortItems((GenericCompareFunction)function); } template void BObjectList::HSortItems(CompareFunctionWithState function, void* state) { _PointerList_::HSortItems((GenericCompareFunctionWithState)function, state); } template T* BObjectList::BinarySearch(const T& key, CompareFunction func) const { return (T*)_PointerList_::BinarySearch(&key, (GenericCompareFunction)func); } template T* BObjectList::BinarySearch(const T& key, CompareFunctionWithState func, void* state) const { return (T*)_PointerList_::BinarySearch(&key, (GenericCompareFunctionWithState)func, state); } template template T* BObjectList::BinarySearchByKey(const Key& key, int (*compare)(const Key*, const T*)) const { return (T*)_PointerList_::BinarySearch(&key, (GenericCompareFunction)compare); } template template T* BObjectList::BinarySearchByKey(const Key &key, int (*compare)(const Key*, const T*, void*), void* state) const { return (T*)_PointerList_::BinarySearch(&key, (GenericCompareFunctionWithState)compare, state); } template int32 BObjectList::BinarySearchIndex(const T& item, CompareFunction compare) const { return _PointerList_::BinarySearchIndex(&item, (GenericCompareFunction)compare); } template int32 BObjectList::BinarySearchIndex(const T& item, CompareFunctionWithState compare, void* state) const { return _PointerList_::BinarySearchIndex(&item, (GenericCompareFunctionWithState)compare, state); } template template int32 BObjectList::BinarySearchIndexByKey(const Key& key, int (*compare)(const Key*, const T*)) const { return _PointerList_::BinarySearchIndex(&key, (GenericCompareFunction)compare); } template bool BObjectList::BinaryInsert(T* item, CompareFunction func) { int32 index = _PointerList_::BinarySearchIndex(item, (GenericCompareFunction)func); if (index >= 0) { // already in list, add after existing return AddItem(item, index + 1); } return AddItem(item, -index - 1); } template bool BObjectList::BinaryInsert(T* item, CompareFunctionWithState func, void* state) { int32 index = _PointerList_::BinarySearchIndex(item, (GenericCompareFunctionWithState)func, state); if (index >= 0) { // already in list, add after existing return AddItem(item, index + 1); } return AddItem(item, -index - 1); } template bool BObjectList::BinaryInsertUnique(T* item, CompareFunction func) { int32 index = _PointerList_::BinarySearchIndex(item, (GenericCompareFunction)func); if (index >= 0) return false; return AddItem(item, -index - 1); } template bool BObjectList::BinaryInsertUnique(T* item, CompareFunctionWithState func, void* state) { int32 index = _PointerList_::BinarySearchIndex(item, (GenericCompareFunctionWithState)func, state); if (index >= 0) return false; return AddItem(item, -index - 1); } template T* BObjectList::BinaryInsertCopy(const T& copyThis, CompareFunction func) { int32 index = _PointerList_::BinarySearchIndex(©This, (GenericCompareFunction)func); if (index >= 0) index++; else index = -index - 1; T* newItem = new (std::nothrow) T(copyThis); AddItem(newItem, index); return newItem; } template T* BObjectList::BinaryInsertCopy(const T& copyThis, CompareFunctionWithState func, void* state) { int32 index = _PointerList_::BinarySearchIndex(©This, (GenericCompareFunctionWithState)func, state); if (index >= 0) index++; else index = -index - 1; T* newItem = new (std::nothrow) T(copyThis); AddItem(newItem, index); return newItem; } template T* BObjectList::BinaryInsertCopyUnique(const T& copyThis, CompareFunction func) { int32 index = _PointerList_::BinarySearchIndex(©This, (GenericCompareFunction)func); if (index >= 0) return ItemAt(index); index = -index - 1; T* newItem = new (std::nothrow) T(copyThis); AddItem(newItem, index); return newItem; } template T* BObjectList::BinaryInsertCopyUnique(const T& copyThis, CompareFunctionWithState func, void* state) { int32 index = _PointerList_::BinarySearchIndex(©This, (GenericCompareFunctionWithState)func, state); if (index >= 0) return ItemAt(index); index = -index - 1; T* newItem = new (std::nothrow) T(copyThis); AddItem(newItem, index); return newItem; } template int32 BObjectList::FindBinaryInsertionIndex(const UnaryPredicate& pred, bool* alreadyInList) const { int32 index = _PointerList_::BinarySearchIndexByPredicate(&pred, (UnaryPredicateGlue)&UnaryPredicate::_unary_predicate_glue); if (alreadyInList) *alreadyInList = index >= 0; if (index < 0) index = -index - 1; return index; } template bool BObjectList::BinaryInsert(T* item, const UnaryPredicate& pred) { return AddItem(item, FindBinaryInsertionIndex(pred)); } template bool BObjectList::BinaryInsertUnique(T* item, const UnaryPredicate& pred) { bool alreadyInList; int32 index = FindBinaryInsertionIndex(pred, &alreadyInList); if (alreadyInList) return false; AddItem(item, index); return true; } #endif /* _OBJECT_LIST_H */