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.
879 lines
24 KiB
879 lines
24 KiB
/*++
|
|
|
|
Copyright (C) 1996-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
FLEXARRAY.CPP
|
|
|
|
Abstract:
|
|
|
|
CFlexArray and CWStringArray implementation.
|
|
|
|
These objects can operate from any allocator, and be constructed
|
|
on arbitrary memory blocks.
|
|
|
|
History:
|
|
|
|
11-Apr-96 a-raymcc Created.
|
|
24-Apr-96 a-raymcc Updated for CArena support.
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#include <stdio.h>
|
|
#include <flexarry.h>
|
|
#include <corex.h>
|
|
#include "strutils.h"
|
|
#include <statsync.h>
|
|
|
|
#define DUP_STRING_ARENA(dest,src) \
|
|
{ size_t tmpLenDoNotReuse = wcslen(src)+1; \
|
|
dest = (wchar_t*)CWin32DefaultArena::WbemMemAlloc(tmpLenDoNotReuse * 2); \
|
|
if (dest) StringCchCopyW(dest,tmpLenDoNotReuse , src); }
|
|
|
|
|
|
//***************************************************************************
|
|
//
|
|
// 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 nGrowByPercent
|
|
)
|
|
{
|
|
m_nExtent = nSize;
|
|
m_nSize = 0;
|
|
m_nGrowByPercent = nGrowByPercent;
|
|
if(nSize > 0)
|
|
{
|
|
m_pArray =
|
|
(void**)CWin32DefaultArena::WbemMemAlloc(sizeof(void *) * nSize);
|
|
|
|
// Check for allocation failures
|
|
if ( NULL == m_pArray )
|
|
{
|
|
m_nExtent = 0;
|
|
throw CX_MemoryException();
|
|
}
|
|
}
|
|
else
|
|
m_pArray = NULL;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CFlexArray::~CFlexArray
|
|
//
|
|
//***************************************************************************
|
|
// ok
|
|
CFlexArray::~CFlexArray()
|
|
{
|
|
CWin32DefaultArena::WbemMemFree(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_nGrowByPercent = 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_nGrowByPercent = Src.m_nGrowByPercent;
|
|
|
|
CWin32DefaultArena::WbemMemFree(m_pArray);
|
|
if(m_nExtent > 0)
|
|
{
|
|
m_pArray =
|
|
(void**)CWin32DefaultArena::WbemMemAlloc(sizeof(void *) * m_nExtent);
|
|
|
|
// Check for allocation failures
|
|
if ( NULL == m_pArray )
|
|
{
|
|
m_nExtent = m_nSize = 0;
|
|
throw CX_MemoryException();
|
|
}
|
|
|
|
}
|
|
else
|
|
m_pArray = NULL;
|
|
memcpy(m_pArray, Src.m_pArray, sizeof(void *) * m_nSize);
|
|
|
|
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;
|
|
|
|
// Account for the index being 0 based and size being 1 based
|
|
MoveMemory( &m_pArray[nIndex], &m_pArray[nIndex+1], ( ( m_nSize - nIndex ) - 1 ) * sizeof(void *) );
|
|
|
|
m_nSize--;
|
|
m_pArray[m_nSize] = 0;
|
|
|
|
return no_error;
|
|
}
|
|
|
|
int CFlexArray::EnsureExtent(int nExtent)
|
|
{
|
|
if(m_nExtent < nExtent)
|
|
{
|
|
if(m_pArray)
|
|
{
|
|
register void** pTmp = (void **) CWin32DefaultArena::WbemMemReAlloc(m_pArray, sizeof(void *) * nExtent);
|
|
if (pTmp == 0)
|
|
return out_of_memory;
|
|
m_nExtent = nExtent;
|
|
m_pArray = pTmp;
|
|
}
|
|
else
|
|
{
|
|
m_pArray = (void **) CWin32DefaultArena::WbemMemAlloc(sizeof(void *) * nExtent);
|
|
if (!m_pArray)
|
|
{
|
|
m_nExtent = 0;
|
|
return out_of_memory;
|
|
}
|
|
m_nExtent = nExtent;
|
|
}
|
|
}
|
|
|
|
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)
|
|
{
|
|
// TEMP: fix for sparse functionality in stdprov
|
|
// =============================================
|
|
|
|
while(nIndex > m_nSize)
|
|
Add(NULL);
|
|
|
|
// If the array is full, we need to expand it.
|
|
// ===========================================
|
|
|
|
if (m_nSize == m_nExtent) {
|
|
if (m_nGrowByPercent == 0)
|
|
return array_full;
|
|
register nTmpExtent = m_nExtent;
|
|
m_nExtent += 1;
|
|
m_nExtent *= (100 + m_nGrowByPercent);
|
|
m_nExtent /= 100;
|
|
|
|
if(m_pArray)
|
|
{
|
|
register void** pTmp = (void **) CWin32DefaultArena::WbemMemReAlloc(m_pArray, sizeof(void *) * m_nExtent);
|
|
if (pTmp == 0)
|
|
{
|
|
m_nExtent = nTmpExtent; //Change it back, otherwise the extent could constantly grow even though it keeps failing...
|
|
return out_of_memory;
|
|
}
|
|
m_pArray = pTmp;
|
|
}
|
|
else
|
|
{
|
|
m_pArray = (void **) CWin32DefaultArena::WbemMemAlloc(sizeof(void *) * m_nExtent);
|
|
|
|
if (!m_pArray)
|
|
{
|
|
m_nExtent = 0;
|
|
return out_of_memory;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 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.
|
|
// ==========================================================
|
|
|
|
// Account for nIndex being 0 based and m_nSize being 1 based
|
|
MoveMemory( &m_pArray[nIndex+1], &m_pArray[nIndex], ( m_nSize - nIndex ) * sizeof(void *) );
|
|
|
|
m_pArray[nIndex] = pSrc;
|
|
m_nSize++;
|
|
|
|
return no_error;
|
|
}
|
|
|
|
void CFlexArray::Sort()
|
|
{
|
|
if(m_pArray)
|
|
qsort((void*)m_pArray, m_nSize, sizeof(void*), CFlexArray::CompareEls);
|
|
}
|
|
|
|
int __cdecl CFlexArray::CompareEls(const void* pelem1, const void* pelem2)
|
|
{
|
|
return *(int*)pelem1 - *(int*)pelem2;
|
|
}
|
|
//***************************************************************************
|
|
//
|
|
// CFlexArray::DebugDump
|
|
//
|
|
//***************************************************************************
|
|
void CFlexArray::DebugDump()
|
|
{
|
|
printf("----CFlexArray Debug Dump----\n");
|
|
printf("m_pArray = 0x%p\n", m_pArray);
|
|
printf("m_nSize = %d\n", m_nSize);
|
|
printf("m_nExtent = %d\n", m_nExtent);
|
|
printf("m_nGrowByPercent = %d\n", m_nGrowByPercent);
|
|
|
|
for (int i = 0; i < m_nExtent; i++)
|
|
{
|
|
if (i < m_nSize)
|
|
printf("![%d] = %p\n", i, m_pArray[i]);
|
|
else
|
|
printf("?[%d] = %p\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 ( nRightCursor < m_nSize && m_pArray[nRightCursor] == 0 )
|
|
nRightCursor++;
|
|
if (nRightCursor == m_nSize)
|
|
break; // Short circuit, no more nonzero elements.
|
|
m_pArray[nLeftCursor] = m_pArray[nRightCursor];
|
|
m_pArray[nRightCursor] = 0;
|
|
}
|
|
}
|
|
|
|
Trim();
|
|
}
|
|
|
|
void CFlexArray::Trim()
|
|
{
|
|
while (m_nSize > 0 && m_pArray[m_nSize - 1] == NULL) 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()
|
|
{
|
|
CWin32DefaultArena::WbemMemFree(m_pArray);
|
|
m_pArray = NULL;
|
|
m_nSize = 0;
|
|
m_nExtent = 0;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CFlexArray::UnbindPtr
|
|
//
|
|
// Empties the array and returns the pointer to the data it contained
|
|
//
|
|
//***************************************************************************
|
|
|
|
void** CFlexArray::UnbindPtr()
|
|
{
|
|
void** pp = m_pArray;
|
|
m_pArray = NULL;
|
|
Empty();
|
|
return pp;
|
|
}
|
|
|
|
//
|
|
// an empty CFlexArray will take ownership
|
|
// of the memory of a second CFlexAray, empty-ing the source
|
|
//
|
|
///////////////////////////////////////////////////////////////////////
|
|
void CFlexArray::Bind(CFlexArray & Src)
|
|
{
|
|
if (this == &Src) return;
|
|
if (this->m_nSize > 0 || NULL != this->m_pArray) throw CX_Exception(); //cannot self delete hence invalid usage
|
|
this->m_nSize = Src.m_nSize;
|
|
Src.m_nSize = 0;
|
|
this->m_nExtent = Src.m_nExtent;
|
|
Src.m_nExtent = 0;
|
|
this->m_pArray = Src.m_pArray;
|
|
Src.m_pArray = NULL;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CFlexArray::CopyData
|
|
//
|
|
// Copies the data but not the settings of another flexarray
|
|
//
|
|
//***************************************************************************
|
|
|
|
int CFlexArray::CopyDataFrom(const CFlexArray& aOther)
|
|
{
|
|
// Check if there is enough room
|
|
// =============================
|
|
|
|
if(aOther.m_nSize > m_nExtent)
|
|
{
|
|
// Extend the array to the requisite size
|
|
// ======================================
|
|
|
|
if(m_pArray)
|
|
{
|
|
register void** pTmp = (void **) CWin32DefaultArena::WbemMemReAlloc(m_pArray, sizeof(void *) * aOther.m_nSize);
|
|
if (pTmp == 0)
|
|
return out_of_memory;
|
|
m_pArray = pTmp;
|
|
m_nExtent = aOther.m_nSize;
|
|
|
|
}
|
|
else
|
|
{
|
|
m_pArray = (void **) CWin32DefaultArena::WbemMemAlloc(sizeof(void *) * aOther.m_nSize);
|
|
if (!m_pArray)
|
|
{
|
|
m_nExtent = 0;
|
|
return out_of_memory;
|
|
}
|
|
m_nExtent = aOther.m_nSize;
|
|
}
|
|
}
|
|
|
|
// Copy the data
|
|
// =============
|
|
|
|
m_nSize = aOther.m_nSize;
|
|
memcpy(m_pArray, aOther.m_pArray, sizeof(void*) * m_nSize);
|
|
return no_error;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// 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)
|
|
{
|
|
CWin32DefaultArena::WbemMemFree(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(const wchar_t *pTarget, int nFlags)
|
|
{
|
|
if (nFlags == no_case) {
|
|
for (int i = 0; i < m_Array.Size(); i++)
|
|
if (wbem_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;
|
|
DUP_STRING_ARENA(pCopy, pSrc);
|
|
|
|
if ( !pCopy || m_Array.Add(pCopy) != CFlexArray::no_error )
|
|
{
|
|
throw CX_MemoryException();
|
|
}
|
|
}
|
|
|
|
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(const wchar_t *pSrc)
|
|
{
|
|
wchar_t *pNewStr;
|
|
DUP_STRING_ARENA(pNewStr, pSrc);
|
|
|
|
// Check for allocation failures
|
|
if ( NULL == pNewStr )
|
|
{
|
|
return out_of_memory;
|
|
}
|
|
|
|
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, const wchar_t *pSrc)
|
|
{
|
|
wchar_t *pNewStr;
|
|
DUP_STRING_ARENA(pNewStr, pSrc);
|
|
|
|
// Check for allocation failures
|
|
if ( NULL == pNewStr )
|
|
{
|
|
return out_of_memory;
|
|
}
|
|
|
|
int iRet = m_Array.InsertAt(nIndex, pNewStr);
|
|
|
|
if (iRet == array_full)
|
|
CWin32DefaultArena::WbemMemFree(pNewStr);
|
|
|
|
return iRet;
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//
|
|
// 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];
|
|
CWin32DefaultArena::WbemMemFree(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, const wchar_t *pSrc)
|
|
{
|
|
wchar_t *pNewStr;
|
|
DUP_STRING_ARENA(pNewStr, pSrc);
|
|
|
|
// Check for allocation failures
|
|
if ( NULL == pNewStr )
|
|
{
|
|
return out_of_memory;
|
|
}
|
|
|
|
wchar_t *pDoomedString = (wchar_t *) m_Array[nIndex];
|
|
if (pDoomedString)
|
|
CWin32DefaultArena::WbemMemFree(pDoomedString);
|
|
|
|
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++)
|
|
CWin32DefaultArena::WbemMemFree(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 &&
|
|
wbem_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)
|
|
{
|
|
if ( Diff.Add(Src1[i]) != no_error )
|
|
{
|
|
throw CX_MemoryException();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// 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)
|
|
{
|
|
if ( Output.Add(Src1[i]) != no_error )
|
|
{
|
|
throw CX_MemoryException();
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// 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)
|
|
{
|
|
if ( Output.Add(Src2[i]) != no_error )
|
|
{
|
|
throw CX_MemoryException();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// that's the fee to pay to have template __dllexport()-ed
|
|
//
|
|
void LinkerPleaseRemoveMe()
|
|
{
|
|
CLockableFlexArray<CStaticCritSec> a;
|
|
a.Lock();
|
|
a.Unlock();
|
|
}
|