620 lines
14 KiB
C++
620 lines
14 KiB
C++
//+------------------------------------------------------------------------
|
|
//
|
|
// File: netolary.cxx
|
|
//
|
|
// Contents: Generic dynamic array class
|
|
//
|
|
// Classes: CADsAry
|
|
//
|
|
// History:
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
|
|
#include "procs.hxx"
|
|
#pragma hdrstop
|
|
|
|
// CADsAry class
|
|
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Member: CADsAry::~CADsAry
|
|
//
|
|
// Synopsis: Resizeable array destructor. Frees storage allocated for the
|
|
// array.
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
CADsAry::~CADsAry( )
|
|
{
|
|
if (_pv)
|
|
LocalFree(_pv);
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Member: CADsAry::EnsureSize
|
|
//
|
|
// Synopsis: Ensures that the array is at least the given size. That is,
|
|
// if EnsureSize(c) succeeds, then (c-1) is a valid index. Note
|
|
// that the array maintains a separate count of the number of
|
|
// elements logically in the array, which is obtained with the
|
|
// Size/SetSize methods. The logical size of the array is never
|
|
// larger than the allocated size of the array.
|
|
//
|
|
// Arguments: [cb] Element size
|
|
// [c] New allocated size for the array.
|
|
//
|
|
// Returns: HRESULT
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
HRESULT
|
|
CADsAry::EnsureSize(size_t cb, int c)
|
|
{
|
|
void * pv;
|
|
|
|
if (c <= GetAlloced(cb))
|
|
return NOERROR;
|
|
|
|
// CONSIDER should we use a more sophisticated array-growing
|
|
// algorithm?
|
|
c = ((c - 1) & -8) + 8;
|
|
ADsAssert(c > 0);
|
|
if (!_pv)
|
|
{
|
|
pv = LocalAlloc(LMEM_FIXED, c * cb);
|
|
}
|
|
else
|
|
{
|
|
pv = LocalReAlloc(_pv, c * cb, LMEM_MOVEABLE);
|
|
}
|
|
|
|
if (!pv)
|
|
RRETURN(E_OUTOFMEMORY);
|
|
|
|
_pv = pv;
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Member: CADsAry::Append
|
|
//
|
|
// Synopsis: Appends the given pointer to the end of the array, incrementing
|
|
// the array's logical size, and growing its allocated size if
|
|
// necessary. This method should only be called for arrays of
|
|
// pointers; AppendIndirect should be used for arrays of
|
|
// non-pointers.
|
|
//
|
|
// Arguments: [pv] Pointer to append.
|
|
//
|
|
// Returns: HRESULT
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
HRESULT
|
|
CADsAry::Append(void * pv)
|
|
{
|
|
HRESULT hr;
|
|
|
|
ADsAssert(_cb == 4);
|
|
|
|
hr = EnsureSize(_c + 1);
|
|
if (hr)
|
|
RRETURN(hr);
|
|
|
|
* (void **) Deref(_c) = pv;
|
|
_c++;
|
|
|
|
return NOERROR;
|
|
}
|
|
#endif
|
|
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Member: CADsAry::AppendIndirect
|
|
//
|
|
// Synopsis: Appends the given element to the end of the array, incrementing
|
|
// the array's logical size, and growing the array's allocated
|
|
// size if necessary. Note that the element is passed with a
|
|
// pointer, rather than directly.
|
|
//
|
|
// Arguments: [cb] -- Element size
|
|
// [pv] -- Pointer to the element to be appended
|
|
//
|
|
// Returns: HRESULT
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
HRESULT
|
|
CADsAry::AppendIndirect(size_t cb, void * pv)
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = EnsureSize(cb, _c + 1);
|
|
if (hr)
|
|
RRETURN(hr);
|
|
|
|
memcpy(Deref(cb, _c), pv, cb);
|
|
_c++;
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Member: CADsAry::Delete
|
|
//
|
|
// Synopsis: Removes the i'th element of the array, shuffling all elements
|
|
// that follow one slot towards the beginning of the array.
|
|
//
|
|
// Arguments: [cb] Element size
|
|
// [i] Element to delete
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
void
|
|
CADsAry::Delete(size_t cb, int i)
|
|
{
|
|
ADsAssert(i >= 0);
|
|
ADsAssert(i < _c);
|
|
|
|
memmove(((BYTE *) _pv) + (i * cb),
|
|
((BYTE *) _pv) + ((i + 1) * cb),
|
|
(_c - i - 1) * cb);
|
|
|
|
_c--;
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Member: CADsAry::DeleteAll
|
|
//
|
|
// Synopsis: Efficient method for emptying array of any contents
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
void
|
|
CADsAry::DeleteAll(void)
|
|
{
|
|
if (_pv)
|
|
LocalFree(_pv);
|
|
|
|
_pv = NULL;
|
|
_c = 0;
|
|
}
|
|
|
|
|
|
#if 0
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Member: CADsAry::Insert
|
|
//
|
|
// Synopsis: Inserts a pointer pv at index i. The element previously at
|
|
// index i, and all elements that follow it, are shuffled one
|
|
// slot away towards the end of the array.
|
|
// This method should only be called for arrays of
|
|
// pointers; InsertIndirect should be used for arrays of
|
|
// non-pointers.
|
|
//
|
|
//
|
|
// Arguments: [i] Index to insert...
|
|
// [pv] ...this pointer at
|
|
//
|
|
// Returns: HRESULT
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
HRESULT
|
|
CADsAry::Insert(int i, void * pv)
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = EnsureSize(cb, _c + 1);
|
|
if (hr)
|
|
RRETURN(hr);
|
|
|
|
memmove(((BYTE *) _pv) + ((i + 1) * _cb),
|
|
((BYTE *) _pv) + (i * _cb),
|
|
(_c - i ) * _cb);
|
|
|
|
((void **) _pv)[i] = pv;
|
|
_c++;
|
|
return NOERROR;
|
|
}
|
|
#endif
|
|
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Member: CADsAry::InsertIndirect
|
|
//
|
|
// Synopsis: Inserts a pointer pv at index i. The element previously at
|
|
// index i, and all elements that follow it, are shuffled one
|
|
// slot away towards the end of the array.Note that the
|
|
// clement is passed with a pointer, rather than directly.
|
|
//
|
|
// Arguments: [cb] Element size
|
|
// [i] Index to insert...
|
|
// [pv] ...this pointer at
|
|
//
|
|
// Returns: HRESULT
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
HRESULT
|
|
CADsAry::InsertIndirect(size_t cb, int i, void *pv)
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = EnsureSize(cb, _c + 1);
|
|
if (hr)
|
|
RRETURN(hr);
|
|
|
|
memmove(((BYTE *) _pv) + ((i + 1) * cb),
|
|
((BYTE *) _pv) + (i * cb),
|
|
(_c - i ) * cb);
|
|
|
|
memcpy(Deref(cb, i), pv, cb);
|
|
_c++;
|
|
return NOERROR;
|
|
|
|
}
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Member: CADsAry::BringToFront
|
|
//
|
|
// Synopsis: Moves the i'th element to the front of the array, shuffling
|
|
// intervening elements to make room.
|
|
//
|
|
// Arguments: [i]
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
void
|
|
CADsAry::BringToFront(size_t cb, int i)
|
|
{
|
|
BYTE rgb[CADsAry_MAXELEMSIZE];
|
|
|
|
ADsAssert(cb <= CADsAry_MAXELEMSIZE);
|
|
|
|
memcpy(rgb, ((BYTE *) _pv) + (i * cb), cb);
|
|
memmove(((BYTE *) _pv) + cb, _pv, i * cb);
|
|
memcpy(_pv, rgb, cb);
|
|
}
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Member: CADsAry::SendToBack
|
|
//
|
|
// Synopsis: Moves the i'th element to the back of the array (that is,
|
|
// the largest index less than the logical size.) Any intervening
|
|
// elements are shuffled out of the way.
|
|
//
|
|
// Arguments: [i]
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
void
|
|
CADsAry::SendToBack(size_t cb, int i)
|
|
{
|
|
BYTE rgb[CADsAry_MAXELEMSIZE];
|
|
|
|
ADsAssert(cb <= CADsAry_MAXELEMSIZE);
|
|
|
|
memcpy(rgb, ((BYTE *) _pv) + (i * cb), cb);
|
|
memmove(((BYTE *) _pv) + (i * cb),
|
|
((BYTE *) _pv) + ((i + 1) * cb),
|
|
(_c - i - 1) * cb);
|
|
|
|
memcpy(((BYTE *) _pv) + ((_c - 1) * cb), rgb, cb);
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Member: CADsAry::Find
|
|
//
|
|
// Synopsis: Returns the index at which the given pointer is found, or -1
|
|
// if it is not found. The pointer values are compared directly;
|
|
// there is no compare function.
|
|
//
|
|
// Arguments: [pv] Pointer to find
|
|
//
|
|
// Returns: int; index of pointer, or -1 if not found
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
int
|
|
CADsAry::Find(void * pv)
|
|
{
|
|
int i;
|
|
void ** ppv;
|
|
|
|
Assert(_cb == 4);
|
|
|
|
for (i = 0, ppv = (void **) _pv; i < _c; i++, ppv++)
|
|
{
|
|
if (pv == *ppv)
|
|
return i;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
#endif
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CADsAry::Copy
|
|
//
|
|
// Synopsis: Creates a copy from another CADsAry object.
|
|
//
|
|
// Arguments: [ary] -- Object to copy.
|
|
// [fAddRef] -- Addref the elements on copy?
|
|
//
|
|
// Returns: HRESULT.
|
|
//
|
|
// Modifies: [this]
|
|
//
|
|
// History: 5-15-94 adams Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
CADsAry::Copy(size_t cb, const CADsAry& ary, BOOL fAddRef)
|
|
{
|
|
int cbArray; // size of array
|
|
IUnknown ** ppUnk; // elem to addref
|
|
int i; // counter
|
|
|
|
// avoid copy of self
|
|
if (this == &ary)
|
|
return S_OK;
|
|
|
|
DeleteAll();
|
|
if (ary._pv)
|
|
{
|
|
cbArray = ary._c * cb;
|
|
_pv = LocalAlloc(LMEM_FIXED, cbArray);
|
|
if (!_pv)
|
|
RRETURN(E_OUTOFMEMORY);
|
|
|
|
memcpy(_pv, ary._pv, cbArray);
|
|
}
|
|
|
|
_c = ary._c;
|
|
|
|
if (fAddRef)
|
|
{
|
|
for (i = 0, ppUnk = (IUnknown **) _pv; i < _c; i++, ppUnk++)
|
|
{
|
|
(*ppUnk)->AddRef();
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CADsAry::EnumElements
|
|
//
|
|
// Synopsis: Creates and returns an enumerator for the elements of the
|
|
// array.
|
|
//
|
|
// Arguments: [iid] -- Type of the enumerator.
|
|
// [ppv] -- Location to put enumerator.
|
|
// [fAddRef] -- AddRef enumerated elements?
|
|
// [fCopy] -- Create copy of this array for enumerator?
|
|
// [fDelete] -- Delete this after no longer being used by
|
|
// enumerators?
|
|
//
|
|
// Returns: HRESULT.
|
|
//
|
|
// History: 5-15-94 adams Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
CADsAry::EnumElements(
|
|
size_t cb,
|
|
REFIID iid,
|
|
void ** ppv,
|
|
BOOL fAddRef,
|
|
BOOL fCopy,
|
|
BOOL fDelete)
|
|
{
|
|
HRESULT hr;
|
|
|
|
ADsAssert(ppv);
|
|
hr = CEnumGeneric::Create(
|
|
cb,
|
|
this,
|
|
iid,
|
|
fAddRef,
|
|
fCopy,
|
|
fDelete,
|
|
(CEnumGeneric **)ppv);
|
|
RRETURN(hr);
|
|
}
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CADsAry::EnumElements
|
|
//
|
|
// Synopsis: Creates and returns an IEnumVARIANT enumerator for the elements
|
|
// of the array.
|
|
//
|
|
// Arguments: [vt] -- Type of elements enumerated.
|
|
// [ppv] -- Location to put enumerator.
|
|
// [fCopy] -- Create copy of this array for enumerator?
|
|
// [fDelete] -- Delete this after no longer being used by
|
|
// enumerators?
|
|
//
|
|
// Returns: HRESULT.
|
|
//
|
|
// History: 5-15-94 adams Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
CADsAry::EnumVARIANT(
|
|
size_t cb,
|
|
VARTYPE vt,
|
|
IEnumVARIANT ** ppenum,
|
|
BOOL fCopy,
|
|
BOOL fDelete)
|
|
{
|
|
HRESULT hr;
|
|
|
|
ADsAssert(ppenum);
|
|
hr = CEnumVARIANT::Create(cb, this, vt, fCopy, fDelete, ppenum);
|
|
RRETURN(hr);
|
|
}
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Member: CADsAry::Deref
|
|
//
|
|
// Synopsis: Returns a pointer to the i'th element of the array. This
|
|
// method is normally called by type-safe methods in derived
|
|
// classes.
|
|
//
|
|
// Arguments: [i]
|
|
//
|
|
// Returns: void *
|
|
//
|
|
// BUGBUG: This function should be inline; however, since nothing is
|
|
// inlined in debug builds, it requires an export, which
|
|
// then doesn't apply in retail builds and breaks the retail
|
|
// build. Near ship time, the def file will be fixed handle
|
|
// inlining.
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
|
|
void *
|
|
CADsAry::Deref(size_t cb, int i)
|
|
{
|
|
ADsAssert(i >= 0);
|
|
ADsAssert(i < GetAlloced(cb));
|
|
|
|
return ((BYTE *) _pv) + i * cb;
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT
|
|
CADsPtrAry::EnsureSize(int c)
|
|
{
|
|
return CADsAry::EnsureSize(sizeof(LPVOID), c);
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
CADsPtrAry::Append(void * pv)
|
|
{
|
|
return CADsAry::AppendIndirect(sizeof(void *), &pv);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CADsPtrAry::Insert(int i, void * pv)
|
|
{
|
|
return CADsAry::InsertIndirect(sizeof(void *), i, &pv);
|
|
}
|
|
|
|
|
|
int
|
|
CADsPtrAry::Find(void * pv)
|
|
{
|
|
int i;
|
|
void ** ppv;
|
|
|
|
for (i = 0, ppv = (void **) _pv; i < _c; i++, ppv++)
|
|
{
|
|
if (pv == *ppv)
|
|
return i;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
void
|
|
CADsPtrAry::Delete(int i)
|
|
{
|
|
CADsAry::Delete(sizeof(void *), i);
|
|
}
|
|
|
|
|
|
void
|
|
CADsPtrAry::BringToFront(int i)
|
|
{
|
|
CADsAry::BringToFront(sizeof(void *), i);
|
|
}
|
|
|
|
|
|
void
|
|
CADsPtrAry::SendToBack(int i)
|
|
{
|
|
CADsAry::SendToBack(sizeof(void *), i);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CADsPtrAry::Copy(const CADsAry& ary, BOOL fAddRef)
|
|
{
|
|
return CADsAry::Copy(sizeof(void *), ary, fAddRef);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CADsPtrAry::EnumElements(
|
|
REFIID iid,
|
|
void ** ppv,
|
|
BOOL fAddRef,
|
|
BOOL fCopy,
|
|
BOOL fDelete)
|
|
{
|
|
return CADsAry::EnumElements(
|
|
sizeof(void *),
|
|
iid,
|
|
ppv,
|
|
fAddRef,
|
|
fCopy,
|
|
fDelete);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CADsPtrAry::EnumVARIANT(
|
|
VARTYPE vt,
|
|
IEnumVARIANT ** ppenum,
|
|
BOOL fCopy,
|
|
BOOL fDelete)
|
|
{
|
|
return CADsAry::EnumVARIANT(
|
|
sizeof(void *),
|
|
vt,
|
|
ppenum,
|
|
fCopy,
|
|
fDelete);
|
|
}
|
|
|