Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

660 lines
15 KiB

//+----------------------------------------------------------------------------
//
// 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