Windows2003-3790/multimedia/directx/dinput/dx8/dll/dilist.c
2020-09-30 16:53:55 +02:00

301 lines
6.8 KiB
C

/*****************************************************************************
*
* DIList.c
*
* Copyright (c) 1997 Microsoft Corporation. All Rights Reserved.
*
* Abstract:
*
* List management. Really, array management, since our lists
* never get very big.
*
* We call them "GPA"s, which stands for "Growable Pointer Array".
*
* There is a more general GXA gizmo in Dr Watson, but we don't
* need it yet. So far, all we need to track is unsorted
* lists of pointers.
*
* Yes, there exists a matching concept in COMCTL32, but we can't
* use it because
*
* (1) it's not documented,
* (2) COMCTL32 puts them into shared memory, which is just
* begging for a memory leak.
*
* Contents:
*
* GPA_Init
* GPA_Term
*
*****************************************************************************/
#include "dinputpr.h"
/*****************************************************************************
*
* The sqiffle for this file.
*
*****************************************************************************/
#define sqfl sqflGpa
/*****************************************************************************
*
* @doc INTERNAL
*
* @func HRESULT | GPA_Print |
*
* Print state of the growing pointer array.
*
* @parm HGPA | hgpa |
*
* @returns void
*
*****************************************************************************/
void INTERNAL
GPA_Print(HGPA hgpa)
{
int ipv;
for (ipv = 0; ipv < hgpa->cpv; ipv++)
{
// 7/18/2000(a-JiTay): IA64: Use %p format specifier for 32/64-bit pointers.
SquirtSqflPtszV( sqflError,
TEXT("ipv=%d,hgpa->rgpv[ipv]=%p"),
ipv, hgpa->rgpv[ipv]);
}
}
/*****************************************************************************
*
* @doc INTERNAL
*
* @func HRESULT | GPA_Append |
*
* Add a new item to the growing pointer array.
*
* Note that we add 8 after doubling, so that we don't get
* stuck if cxAlloc is zero.
*
* @parm HGPA | hgpa |
*
* Handle to pointer array.
*
* @parm PV | pv |
*
* Pointer to add.
*
* @returns
*
* Returns a COM error code.
*
*****************************************************************************/
STDMETHODIMP
GPA_Append(HGPA hgpa, PV pv)
{
HRESULT hres;
if (hgpa->cpv >= hgpa->cpvAlloc) {
hres = ReallocCbPpv(cbX(PV) * (hgpa->cpvAlloc * 2 + 8),
&hgpa->rgpv);
// Prefix: Whistler 45077.
if (FAILED(hres) || ( hgpa->rgpv == NULL) ) {
goto done;
}
hgpa->cpvAlloc = hgpa->cpvAlloc * 2 + 8;
}
//hgpa->rgpv[hgpa->cpv++] = pv;
hgpa->rgpv[hgpa->cpv] = pv;
InterlockedIncrement(&hgpa->cpv);
hres = S_OK;
done:;
//GPA_Print(hgpa);
return hres;
}
/*****************************************************************************
*
* @doc INTERNAL
*
* @func BOOL | GPA_FindPtr |
*
* Determine whether a pointer is in the GPA.
*
* @parm HGPA | hgpa |
*
* Handle to pointer array.
*
* @parm PV | pv |
*
* Pointer to locate.
*
* @returns
*
* Returns a COM error code on failure.
*
* On success, returns the number of items left in the GPA.
*
*****************************************************************************/
BOOL EXTERNAL
GPA_FindPtr(HGPA hgpa, PV pv)
{
BOOL fRc;
int ipv;
for (ipv = 0; ipv < hgpa->cpv; ipv++) {
if (hgpa->rgpv[ipv] == pv) {
fRc = TRUE;
goto done;
}
}
fRc = FALSE;
done:;
return fRc;
}
/*****************************************************************************
*
* @doc INTERNAL
*
* @func HRESULT | GPA_DeletePtr |
*
* Remove the indicated pointer from the GPA. The order of
* the remaining items is unspecified.
*
* Note that CEm_LL_ThreadProc assumes that no items before
* the deleted item are affected by the deletion.
*
* @parm HGPA | hgpa |
*
* Handle to pointer array.
*
* @parm PV | pv |
*
* Pointer to delete.
*
* @returns
*
* Returns a COM error code on failure.
*
* On success, returns the number of items left in the GPA.
*
*****************************************************************************/
STDMETHODIMP
GPA_DeletePtr(HGPA hgpa, PV pv)
{
HRESULT hres;
int ipv;
for (ipv = 0; ipv < hgpa->cpv; ipv++) {
if (hgpa->rgpv[ipv] == pv) {
//hgpa->rgpv[ipv] = hgpa->rgpv[--hgpa->cpv];
InterlockedDecrement(&hgpa->cpv);
hgpa->rgpv[ipv] = hgpa->rgpv[hgpa->cpv];
hres = hgpa->cpv;
goto done;
}
}
hres = E_FAIL;
done:;
//GPA_Print(hgpa);
return hres;
}
/*****************************************************************************
*
* @doc INTERNAL
*
* @func HRESULT | GPA_Clone |
*
* Copy the contents of one GPA to another.
*
* @parm HGPA | hgpaDst |
*
* Handle to destination pointer array.
*
* @parm HGPA | hgpaSrc |
*
* Handle to source pointer array.
*
*****************************************************************************/
STDMETHODIMP
GPA_Clone(HGPA hgpaDst, HGPA hgpaSrc)
{
HRESULT hres;
hres = AllocCbPpv(cbCxX(hgpaSrc->cpv, PV), &hgpaDst->rgpv);
if (SUCCEEDED(hres)) {
CopyMemory(hgpaDst->rgpv, hgpaSrc->rgpv, cbCxX(hgpaSrc->cpv, PV));
hgpaDst->cpv = hgpaSrc->cpv;
hgpaDst->cpvAlloc = hgpaSrc->cpvAlloc;
}
return hres;
}
/*****************************************************************************
*
* @doc INTERNAL
*
* @func void | GPA_Init |
*
* Initialize a GPA structure with no elements.
*
* @parm HGPA | hgpa |
*
* Handle to pointer array.
*
*****************************************************************************/
void EXTERNAL
GPA_Init(HGPA hgpa)
{
hgpa->rgpv = 0;
hgpa->cpv = 0;
hgpa->cpvAlloc = 0;
}
/*****************************************************************************
*
* @doc INTERNAL
*
* @func void | GPA_Term |
*
* Clean up an existing GPA.
*
* @parm HGPA | hgpa |
*
* Handle to pointer array.
*
*****************************************************************************/
void EXTERNAL
GPA_Term(HGPA hgpa)
{
FreePpv(&hgpa->rgpv);
GPA_Init(hgpa);
}