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.
 
 
 
 
 
 

646 lines
17 KiB

//***************************************************************************
//
// (c) 1996-2001 by Microsoft Corp.
//
// FLEXARRY.CPP
//
// CFlexArray implementation (non-arena).
//
// 15-Jul-97 raymcc Created.
//
//***************************************************************************
#include "precomp.h"
#include <stdio.h>
#include <flexarry.h>
//***************************************************************************
//
// CFlexArray::CFlexArray
//
// Constructs the array.
//
// Parameters:
// <nSize> The starting preallocated size of the array.
// <nGrowBy> The amount to grow by when the array fills up.
//
// Size() returns the number of elements in use, not the 'true' size.
//
//***************************************************************************
// ok
CFlexArray::CFlexArray(
int nSize,
int nGrowBy
)
{
m_nExtent = nSize;
m_nSize = 0;
m_nGrowBy = nGrowBy;
m_pArray = (void **) LocalAlloc(LMEM_ZEROINIT, sizeof(void *) * nSize);
}
//***************************************************************************
//
// CFlexArray::~CFlexArray
//
//***************************************************************************
// ok
CFlexArray::~CFlexArray()
{
LocalFree(m_pArray);
}
//***************************************************************************
//
// Copy constructor.
//
// Copies the pointers, not their contents.
//
//***************************************************************************
// ok
CFlexArray::CFlexArray(CFlexArray &Src)
{
m_pArray = 0;
m_nSize = 0;
m_nExtent = 0;
m_nGrowBy = 0;
*this = Src;
}
//***************************************************************************
//
// operator =
//
// Assignment operator.
//
// Arenas are not copied. This allows transfer of arrays between arenas.
// Arrays are copied by pointer only.
//
//***************************************************************************
// ok
CFlexArray& CFlexArray::operator=(CFlexArray &Src)
{
m_nSize = Src.m_nSize;
m_nExtent = Src.m_nExtent;
m_nGrowBy = Src.m_nGrowBy;
LocalFree(m_pArray);
m_pArray = (void **) LocalAlloc(LMEM_ZEROINIT, sizeof(void *) * m_nExtent);
memcpy(m_pArray, Src.m_pArray, sizeof(void *) * m_nExtent);
return *this;
}
//***************************************************************************
//
// CFlexArray::RemoveAt
//
// Removes the element at the specified location. Does not
// actually delete the pointer. Shrinks the array over the top of
// the 'doomed' element.
//
// Parameters:
// <nIndex> The location of the element.
//
// Return value:
// range_error The index is not legal.
// no_error Success.
//
//***************************************************************************
// ok
int CFlexArray::RemoveAt(int nIndex)
{
if (nIndex >= m_nSize)
return range_error;
for (int i = nIndex; i < m_nSize - 1; i++)
m_pArray[i] = m_pArray[i + 1];
m_nSize--;
m_pArray[m_nSize] = 0;
return no_error;
}
//***************************************************************************
//
// CFlexArray::InsertAt
//
// Inserts a new element at the specified location. The pointer is copied.
//
// Parameters:
// <nIndex> The 0-origin location at which to insert the new element.
// <pSrc> The pointer to copy. (contents are not copied).
//
// Return value:
// array_full
// out_of_memory
// no_error
//
//***************************************************************************
// ok
int CFlexArray::InsertAt(int nIndex, void *pSrc)
{
// If the array is full, we need to expand it.
// ===========================================
if (m_nSize == m_nExtent)
{
if (m_nGrowBy == 0)
return array_full;
m_nExtent += m_nGrowBy;
void **pTmp = (void **) LocalAlloc(LMEM_ZEROINIT, sizeof(void *) * m_nExtent);
if (!pTmp)
return out_of_memory;
for (int i = 0; i < m_nSize; i++)
pTmp[i] = m_pArray[i];
LocalFree(m_pArray);
m_pArray = pTmp;
}
// Special case of appending. This is so frequent
// compared to true insertion that we want to optimize.
// ====================================================
if (nIndex == m_nSize)
{
m_pArray[m_nSize++] = pSrc;
return no_error;
}
// If here, we are inserting at some random location.
// We start at the end of the array and copy all the elements
// one position farther to the end to make a 'hole' for
// the new element.
// ==========================================================
for (int i = m_nSize; i > nIndex; i--)
m_pArray[i] = m_pArray[i - 1];
m_pArray[nIndex] = pSrc;
m_nSize++;
return no_error;
}
//***************************************************************************
//
// CFlexArray::DebugDump
//
//***************************************************************************
void CFlexArray::DebugDump()
{
printf("----CFlexArray Debug Dump----\n");
printf("m_pArray = 0x%X\n", m_pArray);
printf("m_nSize = %d\n", m_nSize);
printf("m_nExtent = %d\n", m_nExtent);
printf("m_nGrowBy = %d\n", m_nGrowBy);
for (int i = 0; i < m_nExtent; i++)
{
if (i < m_nSize)
printf("![%d] = %X\n", i, m_pArray[i]);
else
printf("?[%d] = %X\n", i, m_pArray[i]);
}
}
//***************************************************************************
//
// CFlexArray::Compress
//
// Removes NULL elements by moving all non-NULL pointers to the beginning
// of the array. The array "Size" changes, but the extent is untouched.
//
//***************************************************************************
// ok
void CFlexArray::Compress()
{
int nLeftCursor = 0, nRightCursor = 0;
while (nLeftCursor < m_nSize - 1) {
if (m_pArray[nLeftCursor]) {
nLeftCursor++;
continue;
}
else {
nRightCursor = nLeftCursor + 1;
while (m_pArray[nRightCursor] == 0 && nRightCursor < m_nSize)
nRightCursor++;
if (nRightCursor == m_nSize)
break; // Short circuit, no more nonzero elements.
m_pArray[nLeftCursor] = m_pArray[nRightCursor];
m_pArray[nRightCursor] = 0;
}
}
while (m_pArray[m_nSize - 1] == 0 && m_nSize > 0) m_nSize--;
}
//***************************************************************************
//
// CFlexArray::Empty
//
// Clears the array of all pointers (does not deallocate them) and sets
// its apparent size to zero.
//
//***************************************************************************
// ok
void CFlexArray::Empty()
{
LocalFree(m_pArray);
m_pArray = (void **) LocalAlloc(LMEM_ZEROINIT, sizeof(void *) * m_nGrowBy);
m_nSize = 0;
m_nExtent = m_nGrowBy;
}
//***************************************************************************
//
// CFlexArray::UnbindPtr
//
// Empties the array and returns the pointer to the data it contained
//
//***************************************************************************
void** CFlexArray::UnbindPtr()
{
void** pp = m_pArray;
Empty();
return pp;
}
//***************************************************************************
//
// CWStringArray::CWStringArray
//
// Constructs a wide-string array.
//
// Parameters:
// <nSize> The starting preallocated size of the array.
// <nGrowBy> The amount to grow by when the array fills up.
//
// Size() returns the number of elements in use, not the 'true' size.
//
//***************************************************************************
CWStringArray::CWStringArray(
int nSize,
int nGrowBy
)
:
m_Array(nSize, nGrowBy)
{
}
//***************************************************************************
//
// Copy constructor.
//
//***************************************************************************
CWStringArray::CWStringArray(CWStringArray &Src)
{
*this = Src;
}
//***************************************************************************
//
// Destructor. Cleans up all the strings.
//
//***************************************************************************
CWStringArray::~CWStringArray()
{
Empty();
}
//***************************************************************************
//
// CWStringArray::DeleteStr
//
// Frees the string at the specified index and sets the element to NULL.
// Does not compress array.
//
// Does not currently do a range check.
//
// Parameters:
// <nIndex> The 0-origin index of the string to remove.
//
// Return values:
// no_error
//
//***************************************************************************
int CWStringArray::DeleteStr(int nIndex)
{
LocalFree(m_Array[nIndex]);
m_Array[nIndex] = 0;
return no_error;
}
//***************************************************************************
//
// CWStringArray::FindStr
//
// Finds the specified string and returns its location.
//
// Parameters:
// <pTarget> The string to find.
// <nFlags> <no_case> or <with_case>
//
// Return value:
// The 0-origin location of the string, or -1 if not found.
//
//***************************************************************************
int CWStringArray::FindStr(wchar_t *pTarget, int nFlags)
{
if (nFlags == no_case)
{
for (int i = 0; i < m_Array.Size(); i++)
if (_wcsicmp((wchar_t *) m_Array[i], pTarget) == 0)
return i;
}
else
{
for (int i = 0; i < m_Array.Size(); i++)
if (wcscmp((wchar_t *) m_Array[i], pTarget) == 0)
return i;
}
return not_found;
}
//***************************************************************************
//
// operator =
//
//***************************************************************************
// Heap handle & allocation functions are not copied. This allows
// transfer of arrays between heaps.
CWStringArray& CWStringArray::operator =(CWStringArray &Src)
{
Empty();
for (int i = 0; i < Src.Size(); i++)
{
wchar_t *pSrc = (wchar_t *) Src.m_Array[i];
wchar_t *pCopy = (wchar_t *) LocalAlloc(LMEM_ZEROINIT, (wcslen(pSrc) + 1) * 2);
wcscpy(pCopy, pSrc);
m_Array.Add(pCopy);
}
return *this;
}
//***************************************************************************
//
// CWStringArray::Add
//
// Appends a new string to the end of the array.
//
// Parameters:
// <pSrc> The string to copy.
//
// Return value:
// The return values of CFlexArray::Add.
//
//***************************************************************************
int CWStringArray::Add(wchar_t *pSrc)
{
wchar_t *pNewStr = (wchar_t *) LocalAlloc(LMEM_ZEROINIT, (wcslen(pSrc) + 1) * 2);
wcscpy(pNewStr, pSrc);
return m_Array.Add(pNewStr);
}
//***************************************************************************
//
// CWStringArray::InsertAt
//
// Inserts a copy of a string in the array.
//
// Parameters:
// <nIndex> The 0-origin location at which to insert the string.
// <pSrc> The string to copy.
//
// Return values:
// The return values of CFlexArray::InsertAt
//
//***************************************************************************
int CWStringArray::InsertAt(int nIndex, wchar_t *pSrc)
{
wchar_t *pNewStr = (wchar_t *) LocalAlloc(LMEM_ZEROINIT, (wcslen(pSrc) + 1) * 2);
wcscpy(pNewStr, pSrc);
return m_Array.InsertAt(nIndex, pNewStr);
}
//***************************************************************************
//
// CWStringArray::RemoveAt
//
// Removes and deallocates the string at the specified location.
// Shrinks the array.
//
// Parameters:
// <nIndex> The 0-origin index of the 'doomed' string.
//
// Return value:
// Same as CFlexArray::RemoveAt.
//
//***************************************************************************
int CWStringArray::RemoveAt(int nIndex)
{
wchar_t *pDoomedString = (wchar_t *) m_Array[nIndex];
LocalFree(pDoomedString);
return m_Array.RemoveAt(nIndex);
}
//***************************************************************************
//
// CWStringArray::SetAt
//
// Replaces the string at the targeted location with the new one.
// The old string at the location is cleaned up.
//
// No range checking or out-of-memory checks at present.
//
// Parameters:
// <nIndex> The 0-origin location at which to replace the string.
// <pSrc> The string to copy.
//
// Return value:
// no_error
//
//***************************************************************************
int CWStringArray::SetAt(int nIndex, wchar_t *pSrc)
{
wchar_t *pDoomedString = (wchar_t *) m_Array[nIndex];
if (pDoomedString)
LocalFree(pDoomedString);
wchar_t *pNewStr = (wchar_t *) LocalAlloc(LMEM_ZEROINIT, (wcslen(pSrc) + 1) * 2);
wcscpy(pNewStr, pSrc);
m_Array[nIndex] = pNewStr;
return no_error;
}
//***************************************************************************
//
// CWStringArray::ReplaceAt
//
// Directly replaces the pointer at the specified location with the
// one in the parameter. No copy or cleanup.
//
// Parameters:
// <nIndex> The 0-origin location at which to replace.
// <pSrc> The new pointer to copy over the old one.
//
// Return value:
// no_error (No checking done at present).
//
//***************************************************************************
int CWStringArray::ReplaceAt(int nIndex, wchar_t *pSrc)
{
m_Array[nIndex] = pSrc;
return no_error;
}
//***************************************************************************
//
// CWStringArray::Empty
//
// Empties the array, deallocates all strings, and sets the apparent
// array size to zero.
//
//***************************************************************************
void CWStringArray::Empty()
{
for (int i = 0; i < m_Array.Size(); i++)
LocalFree(m_Array[i]);
m_Array.Empty();
}
//***************************************************************************
//
// CWStringArray::Sort
//
// Sorts the array according to UNICODE order.
// (Shell sort).
//
//***************************************************************************
void CWStringArray::Sort()
{
for (int nInterval = 1; nInterval < m_Array.Size() / 9; nInterval = nInterval * 3 + 1);
while (nInterval)
{
for (int iCursor = nInterval; iCursor < m_Array.Size(); iCursor++)
{
int iBackscan = iCursor;
while (iBackscan - nInterval >= 0 &&
_wcsicmp((const wchar_t *) m_Array[iBackscan],
(const wchar_t *) m_Array[iBackscan-nInterval]) < 0)
{
wchar_t *pTemp = (wchar_t *) m_Array[iBackscan - nInterval];
m_Array[iBackscan - nInterval] = m_Array[iBackscan];
m_Array[iBackscan] = pTemp;
iBackscan -= nInterval;
}
}
nInterval /= 3;
}
}
//***************************************************************************
//
// CWStringArray::Difference
//
// Set-theoretic difference operation on the arrays.
//
// Parameters:
// <Src1> First array (not modified).
// <Src2> Second array which is 'subtracted' from first (not modified).
// <Diff> Receives the difference. Should be an empty array on entry.
//
//***************************************************************************
void CWStringArray::Difference(
CWStringArray &Src1,
CWStringArray &Src2,
CWStringArray &Diff
)
{
for (int i = 0; i < Src1.Size(); i++)
if (Src2.FindStr(Src1[i], no_case) == -1)
Diff.Add(Src1[i]);
}
//***************************************************************************
//
// CWStringArray::Intersection
//
// Set-theoretic intersection operation on the arrays.
//
// Parameters:
// <Src1> First array (not modified).
// <Src2> Second array (not modified).
// <Diff> Receives the intersection. Should be an empty array on entry.
//***************************************************************************
void CWStringArray::Intersection(
CWStringArray &Src1,
CWStringArray &Src2,
CWStringArray &Output
)
{
for (int i = 0; i < Src1.Size(); i++)
if (Src2.FindStr(Src1[i], no_case) != -1)
Output.Add(Src1[i]);
}
//***************************************************************************
//
// CWStringArray::Union
//
// Set-theoretic union operation on the arrays.
//
// Parameters:
// <Src1> First array (not modified).
// <Src2> Second array (not modified).
// <Diff> Receives the union. Should be an empty array on entry.
//
//***************************************************************************
void CWStringArray::Union(
CWStringArray &Src1,
CWStringArray &Src2,
CWStringArray &Output
)
{
Output = Src1;
for (int i = 0; i < Src2.Size(); i++)
if (Output.FindStr(Src2[i], no_case) == not_found)
Output.Add(Src2[i]);
}