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