/////////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2000, Microsoft Corp. All rights reserved. // // FILE // // iasobj.h // // SYNOPSIS // // Declares the classes ObjectPointer and ObjectVector for manipulating // reference counted objects. // // MODIFICATION HISTORY // // 02/08/2000 Original version. // /////////////////////////////////////////////////////////////////////////////// #ifndef IASOBJ_H #define IASOBJ_H #if _MSC_VER >= 1000 #pragma once #endif #include /////////////////////////////////////////////////////////////////////////////// // // CLASS // // ObjectPointer // // DESCRIPTION // // Smart pointer to a reference counted object. This is useful because it // doesn't require the object to derive from IUnknown like the ATL or VC // smart pointers. // /////////////////////////////////////////////////////////////////////////////// template class ObjectPointer { public: ObjectPointer() throw () : p(NULL) { } ObjectPointer(T* lp, bool addRef = true) throw () : p(lp) { if (addRef) _addref(); } ObjectPointer(const ObjectPointer& lp) throw () : p(lp.p) { _addref(); } T* operator=(T* lp) throw () { attach(lp); return p; } ObjectPointer& operator=(const ObjectPointer& lp) throw () { if (this != &lp) attach(lp.p); return *this; } ~ObjectPointer() throw () { _release(); } operator T*() const throw () { return p; } T* operator->() const throw () { return p; } T& operator*() const throw () { return *p; } bool operator!() const throw () { return p == NULL; } void attach(T* lp) throw () { _release(); p = lp; _addref(); } void release() throw () { _release(); p = NULL; } private: // Safe versions of AddRef and Release. void _addref() throw () { if (p) { p->AddRef(); } } void _release() throw () { if (p) { p->Release(); } } T* p; }; /////////////////////////////////////////////////////////////////////////////// // // CLASS // // ObjectVector // // DESCRIPTION // // Maintains an array of reference counted objects. // /////////////////////////////////////////////////////////////////////////////// template class ObjectVector { public: typedef T* const* iterator; typedef int (__cdecl *SortFn)( const T* const* t1, const T* const* t2 ) throw (); typedef int (__cdecl *SearchFn)( const void* key, const T* const* t ) throw (); ObjectVector() throw () : first(NULL), last(NULL), cap(NULL) { } ObjectVector(const ObjectVector& v) : first(NULL), last(NULL), cap(NULL) { assign(v.begin(), v.end()); } ObjectVector(iterator first, iterator last) : first(NULL), last(NULL), cap(NULL) { assign(first, last); } ObjectVector(size_t nelem) : first(NULL), last(NULL), cap(NULL) { reserve(nelem); } ObjectVector& operator=(const ObjectVector& v) { if (this != &v) { assign(v.begin(), v.end()); } return *this; } ~ObjectVector() throw () { clear(); delete[] first; } void assign(iterator i1, iterator i2) { reserve(i2 - i1); clear(); for (iterator i = i1; i != i2; ++i) { (*last++ = *i)->AddRef(); } } // Returns the capacity of the array. size_t capacity() const throw () { return cap - first; } void clear() throw () { while (last > first) (*--last)->Release(); } bool contains(T* elem) throw () { return find(elem) != last; } bool empty() const throw () { return last == first; } iterator erase(iterator i) throw () { memmove((void*)i, (void*)(i + 1), (--last - i) * sizeof(T*)); return i; } iterator find(T* elem) throw () { for (iterator i = first; i != last && *i != elem; ++i) { } return i; } void push_back(T* elem) throw () { if (last == cap) { reserve(empty() ? 1 : capacity() * 2); } (*last++ = elem)->AddRef(); } bool remove(T* elem) throw () { iterator i = find(elem); if (i == last) { return false; } (*i)->Release(); return true; } void reserve(size_t nelem) { if (nelem > capacity()) { T** t = new T*[nelem]; memcpy(t, first, size() * sizeof(T*)); last = t + size(); cap = t + nelem; delete[] first; first = t; } } T* search(const void* key, SearchFn pfn) const throw () { T** t = (T**)bsearch(key, begin(), size(), sizeof(T*), (CompFn)pfn); return t ? *t : NULL; } size_t size() const throw () { return last - first; } void sort(SortFn pfn) throw () { qsort((void*)begin(), size(), sizeof(T*), (CompFn)pfn); } void swap(ObjectVector& v) throw () { T** firstTmp = first; T** lastTmp = last; T** capTmp = cap; first = v.first; last = v.last; cap = v.cap; v.first = firstTmp; v.last = lastTmp; v.cap = capTmp; } // Methods to iterate the array elements. iterator begin() const throw () { return first; } iterator end() const throw () { return last; } T* operator[](size_t index) const throw () { return first[index]; } private: typedef int (__cdecl *CompFn)(const void*, const void*); T** first; T** last; T** cap; }; #endif // IASOBJ_H