661 lines
15 KiB
C++
661 lines
15 KiB
C++
//+----------------------------------------------------------------------------
|
|
//
|
|
// File: ary.cxx
|
|
//
|
|
// Module: CMDIAL32.DLL
|
|
//
|
|
// Synopsis: Generic dynamic array class -- CFormsAry
|
|
//
|
|
// Copyright (c) 1992-1998 Microsoft Corporation
|
|
//
|
|
// Author: quintinb Created Header 8/17/99
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
#include "cmmaster.h"
|
|
#include "cm_misc.h"
|
|
#include "ary.hxx"
|
|
|
|
#define CFORMSARY_MAXELEMSIZE 128
|
|
|
|
// CFormsAry class
|
|
//
|
|
//
|
|
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Member: CFormsAry::~CFormsAry
|
|
//
|
|
// Synopsis: Resizeable array destructor. Frees storage allocated for the
|
|
// array.
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
CFormsAry::~CFormsAry( )
|
|
{
|
|
MemFree(PData());
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Member: CFormsAry::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
|
|
CFormsAry::EnsureSize(size_t cb, int c)
|
|
{
|
|
HRESULT hr;
|
|
unsigned cbAlloc = ((c + 7) & ~7) * cb;
|
|
|
|
MYDBGASSERT(c >= 0);
|
|
|
|
if (c > ((_c + 7) & ~7) && cbAlloc > MemGetSize(PData()))
|
|
{
|
|
hr = MemRealloc((void **)&PData(), cbAlloc);
|
|
}
|
|
else
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Member: CFormsAry::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
|
|
CFormsAry::AppendIndirect(size_t cb, void * pv)
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = EnsureSize(cb, _c + 1);
|
|
if (hr)
|
|
return hr;
|
|
|
|
memcpy(Deref(cb, _c), pv, cb);
|
|
_c++;
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
#if 0
|
|
/*
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Member: CFormsAry::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
|
|
CFormsAry::Delete(size_t cb, int i)
|
|
{
|
|
MYDBGASSERT(i >= 0);
|
|
MYDBGASSERT(i < _c);
|
|
|
|
memmove(((BYTE *) PData()) + (i * cb),
|
|
((BYTE *) PData()) + ((i + 1) * cb),
|
|
(_c - i - 1) * cb);
|
|
|
|
_c--;
|
|
}
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Member: CFormsAry::DeleteByValueIndirect
|
|
//
|
|
// Synopsis: Removes the element matching the given value.
|
|
//
|
|
// Arguments: cb Element size
|
|
// pv Element to delete
|
|
//
|
|
// Returuns: True if found & deleted.
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
BOOL
|
|
CFormsAry::DeleteByValueIndirect(size_t cb, void *pv)
|
|
{
|
|
int i = FindIndirect(cb, pv);
|
|
if (i >= 0)
|
|
{
|
|
Delete(cb, i);
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Member: CFormsAry::DeleteMultiple
|
|
//
|
|
// Synopsis: Removes a range of elements of the array, shuffling all
|
|
// elements that follow the last element being deleted slot
|
|
// towards the beginning of the array.
|
|
//
|
|
// Arguments: cb Element size
|
|
// start First element to delete
|
|
// end Last element to delete
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
void
|
|
CFormsAry::DeleteMultiple(size_t cb, int start, int end)
|
|
{
|
|
MYDBGASSERT((start >= 0) && (end >= 0));
|
|
MYDBGASSERT((start < _c) && (end < _c));
|
|
MYDBGASSERT(end >= start);
|
|
|
|
if (end < (_c - 1))
|
|
{
|
|
memmove(((BYTE *) PData()) + (start * cb),
|
|
((BYTE *) PData()) + ((end + 1) * cb),
|
|
(_c - end - 1) * cb);
|
|
}
|
|
|
|
_c -= (end - start) + 1;
|
|
}
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Member: CFormsAry::DeleteAll
|
|
//
|
|
// Synopsis: Efficient method for emptying array of any contents
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
void
|
|
CFormsAry::DeleteAll(void)
|
|
{
|
|
MemFree(PData());
|
|
PData() = NULL;
|
|
_c = 0;
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Member: CFormsAry::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
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
HRESULT
|
|
CFormsAry::InsertIndirect(size_t cb, int i, void *pv)
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = EnsureSize(cb, _c + 1);
|
|
if (hr)
|
|
return hr;
|
|
|
|
memmove(((BYTE *) PData()) + ((i + 1) * cb),
|
|
((BYTE *) PData()) + (i * cb),
|
|
(_c - i ) * cb);
|
|
|
|
memcpy(Deref(cb, i), pv, cb);
|
|
_c++;
|
|
return NOERROR;
|
|
|
|
}
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Member: CFormsAry::BringToFront
|
|
//
|
|
// Synopsis: Moves the i'th element to the front of the array, shuffling
|
|
// intervening elements to make room.
|
|
//
|
|
// Arguments: i
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
void
|
|
CFormsAry::BringToFront(size_t cb, int i)
|
|
{
|
|
BYTE rgb[CFORMSARY_MAXELEMSIZE];
|
|
|
|
MYDBGASSERT(cb <= CFORMSARY_MAXELEMSIZE);
|
|
|
|
memcpy(rgb, ((BYTE *) PData()) + (i * cb), cb);
|
|
memmove(((BYTE *) PData()) + cb, PData(), i * cb);
|
|
memcpy(PData(), rgb, cb);
|
|
}
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Member: CFormsAry::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
|
|
CFormsAry::SendToBack(size_t cb, int i)
|
|
{
|
|
BYTE rgb[CFORMSARY_MAXELEMSIZE];
|
|
|
|
MYDBGASSERT(cb <= CFORMSARY_MAXELEMSIZE);
|
|
|
|
memcpy(rgb, ((BYTE *) PData()) + (i * cb), cb);
|
|
memmove(((BYTE *) PData()) + (i * cb),
|
|
((BYTE *) PData()) + ((i + 1) * cb),
|
|
(_c - i - 1) * cb);
|
|
|
|
memcpy(((BYTE *) PData()) + ((_c - 1) * cb), rgb, cb);
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CFormsAry::Swap
|
|
//
|
|
// Synopsis: swap two members of array with each other.
|
|
//
|
|
// Arguments: cb size of elements
|
|
// i1 1st element
|
|
// i2 2nd element
|
|
//----------------------------------------------------------------------------
|
|
void
|
|
CFormsAry::Swap(size_t cb, int i1, int i2)
|
|
{
|
|
BYTE rgb[CFORMSARY_MAXELEMSIZE];
|
|
|
|
MYDBGASSERT(cb <= CFORMSARY_MAXELEMSIZE);
|
|
|
|
if (i1 >= _c)
|
|
i1 = _c - 1;
|
|
if (i2 >= _c)
|
|
i2 = _c - 1;
|
|
|
|
if (i1 != i2)
|
|
{
|
|
memcpy(rgb, ((BYTE *) PData()) + (i1 * cb), cb);
|
|
memcpy(((BYTE *) PData()) + (i1 * cb), ((BYTE *) PData()) + (i2 * cb), cb);
|
|
memcpy(((BYTE *) PData()) + (i2 * cb), rgb, cb);
|
|
}
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CFormsAry::FindIndirect
|
|
//
|
|
// Synopsis: Finds an element of a non-pointer array.
|
|
//
|
|
// Arguments: cb The size of the element.
|
|
// pv Pointer to the element.
|
|
//
|
|
// Returns: The index of the element if found, otherwise -1.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
int
|
|
CFormsAry::FindIndirect(size_t cb, void * pv)
|
|
{
|
|
int i;
|
|
void * pvT;
|
|
|
|
pvT = PData();
|
|
for (i = _c; i > 0; i--)
|
|
{
|
|
if (!memcmp(pv, pvT, cb))
|
|
return _c - i;
|
|
|
|
pvT = (char *) pvT + cb;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CFormsAry::CopyAppend
|
|
//
|
|
// Synopsis: Copies the entire contents of another CFormsAry object and
|
|
// appends it to the end of the array.
|
|
//
|
|
// Arguments: ary Object to copy.
|
|
// fAddRef Addref the elements on copy?
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
CFormsAry::CopyAppend(size_t cb, const CFormsAry& ary, BOOL fAddRef)
|
|
{
|
|
return (CopyAppendIndirect(cb, ary._c, ((CFormsAry *)&ary)->PData(), fAddRef));
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFormsAry::CopyAppendIndirect(size_t cb, int c, void * pv, BOOL fAddRef)
|
|
{
|
|
IUnknown ** ppUnk; // elem to addref
|
|
|
|
if (EnsureSize(cb, _c + c))
|
|
return E_OUTOFMEMORY;
|
|
|
|
if (pv)
|
|
{
|
|
memcpy((BYTE*) PData() + (_c * cb), pv, c * cb);
|
|
}
|
|
|
|
_c += c;
|
|
|
|
if (fAddRef)
|
|
{
|
|
for (ppUnk = (IUnknown **) pv; c > 0; c--, ppUnk++)
|
|
{
|
|
(*ppUnk)->AddRef();
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CFormsAry::Copy
|
|
//
|
|
// Synopsis: Creates a copy from another CFormsAry object.
|
|
//
|
|
// Arguments: ary Object to copy.
|
|
// fAddRef Addref the elements on copy?
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
CFormsAry::Copy(size_t cb, const CFormsAry& ary, BOOL fAddRef)
|
|
{
|
|
return (CopyIndirect(cb, ary._c, ((CFormsAry *)&ary)->PData(), fAddRef));
|
|
}
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Member: CFormsAry::CopyIndirect
|
|
//
|
|
// Synopsis: Fills a forms array from a C-style array of raw data
|
|
//
|
|
// Arguments: [cb]
|
|
// [c]
|
|
// [pv]
|
|
// [fAddRef]
|
|
//
|
|
// Returns: HRESULT
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
CFormsAry::CopyIndirect(size_t cb, int c, void * pv, BOOL fAddRef)
|
|
{
|
|
size_t cbArray;
|
|
IUnknown ** ppUnk;
|
|
|
|
if (pv == PData())
|
|
return S_OK;
|
|
|
|
DeleteAll();
|
|
if (pv)
|
|
{
|
|
cbArray = c * cb;
|
|
PData() = MemAlloc(cbArray);
|
|
if (!PData())
|
|
return E_OUTOFMEMORY;
|
|
|
|
memcpy(PData(), pv, cbArray);
|
|
}
|
|
|
|
_c = c;
|
|
|
|
if (fAddRef)
|
|
{
|
|
for (ppUnk = (IUnknown **) PData(); c > 0; c--, ppUnk++)
|
|
{
|
|
(*ppUnk)->AddRef();
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT
|
|
CFormsPtrAry::ClearAndReset()
|
|
{
|
|
// why does this function reallocate memory, rather than
|
|
// just memset'ing to 0? (chrisz)
|
|
|
|
PData() = NULL;
|
|
HRESULT hr = EnsureSize(_c);
|
|
_c = 0;
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Member: CFormsPtrAry::*
|
|
//
|
|
// Synopsis: CFormsPtrAry elements are always of size four.
|
|
// The following functions encode this knowledge.
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
CFormsPtrAry::EnsureSize(int c)
|
|
{
|
|
return CFormsAry::EnsureSize(sizeof(void *), c);
|
|
}
|
|
|
|
HRESULT
|
|
CFormsPtrAry::Append(void * pv)
|
|
{
|
|
return CFormsAry::AppendIndirect(sizeof(void *), &pv);
|
|
}
|
|
|
|
HRESULT
|
|
CFormsPtrAry::Insert(int i, void * pv)
|
|
{
|
|
return CFormsAry::InsertIndirect(sizeof(void *), i, &pv);
|
|
}
|
|
|
|
int
|
|
CFormsPtrAry::Find(void * pv)
|
|
{
|
|
int i;
|
|
void ** ppv;
|
|
|
|
for (i = 0, ppv = (void **) PData(); i < _c; i++, ppv++)
|
|
{
|
|
if (pv == *ppv)
|
|
return i;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
void
|
|
CFormsPtrAry::Delete(int i)
|
|
{
|
|
CFormsAry::Delete(sizeof(void *), i);
|
|
}
|
|
|
|
BOOL
|
|
CFormsPtrAry::DeleteByValue(void *pv)
|
|
{
|
|
int i = Find(pv);
|
|
if (i >= 0)
|
|
{
|
|
CFormsAry::Delete(sizeof(void *), i);
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
void
|
|
CFormsPtrAry::DeleteMultiple(int start, int end)
|
|
{
|
|
CFormsAry::DeleteMultiple(sizeof(void*), start, end);
|
|
}
|
|
|
|
void
|
|
CFormsPtrAry::ReleaseAndDelete(int idx)
|
|
{
|
|
IUnknown * pUnk;
|
|
|
|
MYDBGASSERT(idx <= _c);
|
|
|
|
// grab element at idx
|
|
pUnk = ((IUnknown **) PData())[idx];
|
|
if (pUnk)
|
|
(pUnk)->Release();
|
|
|
|
Delete(idx);
|
|
}
|
|
|
|
|
|
void
|
|
CFormsPtrAry::ReleaseAll(void)
|
|
{
|
|
int i;
|
|
IUnknown ** ppUnk;
|
|
|
|
for (i = 0, ppUnk = (IUnknown **) PData(); i < _c; i++, ppUnk++)
|
|
{
|
|
if (*ppUnk)
|
|
(*ppUnk)->Release();
|
|
}
|
|
|
|
DeleteAll();
|
|
}
|
|
|
|
void
|
|
CFormsPtrAry::BringToFront(int i)
|
|
{
|
|
CFormsAry::BringToFront(sizeof(void *), i);
|
|
}
|
|
|
|
|
|
void
|
|
CFormsPtrAry::SendToBack(int i)
|
|
{
|
|
CFormsAry::SendToBack(sizeof(void *), i);
|
|
}
|
|
|
|
void
|
|
CFormsPtrAry::Swap(int i1, int i2)
|
|
{
|
|
CFormsAry::Swap(sizeof(void *), i1, i2);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CFormsPtrAry::CopyAppendIndirect(int c, void * pv, BOOL fAddRef)
|
|
{
|
|
return CFormsAry::CopyAppendIndirect(sizeof(void *), c, pv, fAddRef);
|
|
}
|
|
|
|
HRESULT
|
|
CFormsPtrAry::CopyAppend(const CFormsAry& ary, BOOL fAddRef)
|
|
{
|
|
return CFormsAry::CopyAppend(sizeof(void *), ary, fAddRef);
|
|
}
|
|
|
|
HRESULT
|
|
CFormsPtrAry::CopyIndirect(int c, void * pv, BOOL fAddRef)
|
|
{
|
|
return CFormsAry::CopyIndirect(sizeof(void *), c, pv, fAddRef);
|
|
}
|
|
|
|
HRESULT
|
|
CFormsPtrAry::Copy(const CFormsAry& ary, BOOL fAddRef)
|
|
{
|
|
return CFormsAry::Copy(sizeof(void *), ary, fAddRef);
|
|
}
|
|
|
|
HRESULT
|
|
CFormsPtrAry::EnumElements(
|
|
REFIID iid,
|
|
void ** ppv,
|
|
BOOL fAddRef,
|
|
BOOL fCopy,
|
|
BOOL fDelete)
|
|
{
|
|
return CFormsAry::EnumElements(
|
|
sizeof(void *),
|
|
iid,
|
|
ppv,
|
|
fAddRef,
|
|
fCopy,
|
|
fDelete);
|
|
}
|
|
|
|
HRESULT
|
|
CFormsPtrAry::EnumVARIANT(
|
|
VARTYPE vt,
|
|
IEnumVARIANT ** ppenum,
|
|
BOOL fCopy,
|
|
BOOL fDelete)
|
|
{
|
|
return CFormsAry::EnumVARIANT(
|
|
sizeof(void *),
|
|
vt,
|
|
ppenum,
|
|
fCopy,
|
|
fDelete);
|
|
}
|
|
*/
|
|
#endif
|