windows-nt/Source/XPSP1/NT/ds/adsi/utils/netolary.cxx
2020-09-26 16:20:57 +08:00

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);
}