You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
264 lines
5.8 KiB
264 lines
5.8 KiB
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// 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 <iaswin32.h>
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CLASS
|
|
//
|
|
// ObjectPointer<T>
|
|
//
|
|
// 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 T>
|
|
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<T>
|
|
//
|
|
// DESCRIPTION
|
|
//
|
|
// Maintains an array of reference counted objects.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
template <class T>
|
|
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
|