windows-nt/Source/XPSP1/NT/enduser/stuff/hhctrl/ctable.cpp
2020-09-26 16:20:57 +08:00

1213 lines
29 KiB
C++

// Copyright (C) Microsoft Corporation 1993-1997
#include "header.H"
#ifndef _CTABLE_INCLUDED
#include "ctable.h"
#endif
const int TABLE_ALLOC_SIZE = 4096; // allocate in page increments
const int MAX_POINTERS = (1024 * 1024); // 1 meg, 260,000+ strings
const int MAX_STRINGS = (10 * 1024 * 1024) - 4096L; // 10 megs
// Align on 32 bits for Intel, 64 bits for MIPS
#ifdef _X86_
const int ALIGNMENT = 4;
#else
const int ALIGNMENT = 8;
#endif
#ifdef _DEBUG
int g_cbTableAllocated;
int g_cbTableReserved;
int g_cTables;
#endif
CTable::CTable()
{
cbMaxBase = MAX_STRINGS;
cbMaxTable = MAX_POINTERS;
InitializeTable();
#ifdef _DEBUG
g_cTables++;
#endif
}
// Use this constructor to reduce reserved memory
CTable::CTable(int cbStrings)
{
cbMaxBase = cbStrings;
cbMaxTable = cbStrings / 4;
InitializeTable();
#ifdef _DEBUG
g_cTables++;
#endif
}
/***************************************************************************
FUNCTION: =
PURPOSE: Copies a table -- only works with tables containing ONLY
strings. Won't work with tables that combined data with
the strings.
PARAMETERS:
tblSrc
RETURNS:
COMMENTS:
MODIFICATION DATES:
26-Mar-1994 [ralphw]
***************************************************************************/
#pragma warning(disable:4172) // returning address of local variable or temporary
const CTable& CTable::operator =(const CTable& tblSrc)
{
Empty();
int srcpos = 1;
while (srcpos < tblSrc.endpos) {
if (endpos >= maxpos)
IncreaseTableBuffer();
if (endpos >= maxpos)
{
return NULL;
}
if ((ppszTable[endpos] =
TableMalloc((int)strlen(tblSrc.ppszTable[srcpos]) + 1)) == NULL) {
OOM();
return *this;
}
strcpy(ppszTable[endpos++], tblSrc.ppszTable[srcpos++]);
}
return *this;
}
/***************************************************************************
FUNCTION: ~CTable
PURPOSE: Close the table and free all memory associated with it
RETURNS:
COMMENTS:
MODIFICATION DATES:
26-Feb-1990 [ralphw]
27-Mar-1990 [ralphw]
Pass the address of the handle, so that we can set it to NULL.
This eliminates the chance of using a handle after it's memory
has been freed.
***************************************************************************/
CTable::~CTable()
{
Cleanup();
#ifdef _DEBUG
g_cTables--;
#endif
}
void CTable::Cleanup(void)
{
if (pszBase) {
VirtualFree(pszBase, cbStrings, MEM_DECOMMIT);
VirtualFree(pszBase, 0, MEM_RELEASE);
}
if (ppszTable) {
VirtualFree(ppszTable, cbPointers, MEM_DECOMMIT);
VirtualFree(ppszTable, 0, MEM_RELEASE);
}
if (m_pFreed)
lcClearFree(&m_pFreed);
#ifdef _DEBUG
g_cbTableAllocated -= (cbPointers + cbStrings);
g_cbTableReserved -= (cbMaxBase + cbMaxTable);
#endif
}
/***************************************************************************
FUNCTION: CTable::Empty
PURPOSE: Empties the current table by freeing all memory, then
recreating the table using the default size
PARAMETERS:
void
RETURNS:
COMMENTS:
MODIFICATION DATES:
22-Feb-1994 [ralphw]
***************************************************************************/
void CTable::Empty(void)
{
Cleanup();
InitializeTable();
}
/***************************************************************************
FUNCTION: GetString
PURPOSE: get a line from the table
RETURNS: FALSE if there are no more lines
COMMENTS:
If no strings have been placed into the table, the return value
is FALSE.
MODIFICATION DATES:
01-Jan-1990 [ralphw]
***************************************************************************/
BOOL CTable::GetString(PSTR pszDst)
{
*pszDst = 0; // clear the line no matter what happens
if (curpos >= endpos)
return FALSE;
strcpy(pszDst, (PCSTR) ppszTable[curpos++]);
return TRUE;
}
BOOL CTable::GetString(PSTR pszDst, int pos) const
{
*pszDst = 0; // clear the line no matter what happens
if (pos >= endpos || pos == 0)
return FALSE;
strcpy(pszDst, (PCSTR) ppszTable[pos]);
return TRUE;
}
BOOL CTable::GetIntAndString(int* plVal, PSTR pszDst)
{
*pszDst = 0; // clear the line no matter what happens
if (curpos >= endpos)
return FALSE;
*plVal = *(int *) ppszTable[curpos];
strcpy(pszDst, (PCSTR) ppszTable[curpos++] + sizeof(int));
return TRUE;
}
/***************************************************************************
FUNCTION: AddString
PURPOSE: Add a string to a table
RETURNS:
COMMENTS:
MODIFICATION DATES:
01-Jan-1990 [ralphw]
***************************************************************************/
int CTable::AddString(PCSTR pszString)
{
if (!pszString)
return 0;
if (endpos >= maxpos)
IncreaseTableBuffer();
if (endpos >= maxpos)
return 0;
if ((ppszTable[endpos] =
TableMalloc((int)strlen(pszString) + 1)) == NULL)
return 0;
strcpy(ppszTable[endpos], pszString);
return endpos++;
}
int CTable::AddString(PCWSTR pszString)
{
if (!pszString)
return 0;
if (endpos >= maxpos)
IncreaseTableBuffer();
if (endpos >= maxpos)
return 0;
if ((ppszTable[endpos] =
TableMalloc((int)lstrlenW(pszString) + 2)) == NULL)
return 0;
lstrcpyW((PWSTR) ppszTable[endpos], pszString);
return endpos++;
}
int CTable::AddData(int cb, const void* pdata)
{
if (endpos >= maxpos)
IncreaseTableBuffer();
if (endpos >= maxpos)
return 0;
if ((ppszTable[endpos] = TableMalloc(cb)) == NULL)
return 0;
if (pdata)
CopyMemory(ppszTable[endpos], pdata, cb);
return endpos++;
}
int CTable::AddIntAndString(int lVal, PCSTR pszString)
{
if (endpos >= maxpos)
IncreaseTableBuffer();
if (endpos >= maxpos)
return 0;
if ((ppszTable[endpos] =
TableMalloc((int)strlen(pszString) + 1 + (int)sizeof(int))) == NULL)
return 0;
*(int*) ppszTable[endpos] = lVal;
strcpy(ppszTable[endpos] + sizeof(int), pszString);
return endpos++;
}
/***************************************************************************
FUNCTION: IncreaseTableBuffer
PURPOSE: Called when we need more room for string pointers
PARAMETERS:
RETURNS:
COMMENTS:
MODIFICATION DATES:
23-Feb-1992 [ralphw]
***************************************************************************/
void CTable::IncreaseTableBuffer(void)
{
ASSERT(cbPointers < cbMaxTable);
if (!VirtualAlloc((PBYTE) ppszTable + cbPointers, TABLE_ALLOC_SIZE,
MEM_COMMIT, PAGE_READWRITE)) {
OOM();
return;
}
cbPointers += TABLE_ALLOC_SIZE;
#ifdef _DEBUG
g_cbTableAllocated += TABLE_ALLOC_SIZE;
#endif
maxpos = cbPointers / sizeof(PSTR);
}
/***************************************************************************
FUNCTION: TableMalloc
PURPOSE: Suballocate memory
RETURNS:
pointer to the memory
COMMENTS:
Instead of allocating memory for each string, memory is used from 4K
blocks. When the table is freed, all memory is freed as a single
unit. This has the advantage of speed for adding strings, speed for
freeing all strings, and low memory overhead to save strings.
MODIFICATION DATES:
26-Feb-1990 [ralphw]
26-Mar-1994 [ralphw]
Ported to 32-bits
***************************************************************************/
PSTR CTable::TableMalloc(int cb)
{
/*
* Align allocation request so that all allocations fall on an
* alignment boundary (32 bits for Intel, 64 bits for MIPS).
*/
cb = (cb & (ALIGNMENT - 1)) ?
cb / ALIGNMENT * ALIGNMENT + ALIGNMENT : cb;
if (m_pFreed) {
// First look for an exact match
for (int i = 0; i < m_cFreedItems; i++) {
ASSERT_COMMENT(m_pFreed[i].cb, "This memory has been used again -- it shouldn't be in the array");
if (cb > m_pFreed[i].cb)
break;
if (cb == m_pFreed[i].cb)
goto GotAMatch;
}
// Couldn't find an exact match, so find the first one that fits
for (i--; i >= 0; i--) {
ASSERT_COMMENT(m_pFreed[i].cb, "This memory has been used again -- it shouldn't be in the array");
if (cb < m_pFreed[i].cb) {
// If there's more then 32 bytes left, then suballoc
if (cb + 32 < m_pFreed[i].cb) {
PSTR psz = (PSTR) m_pFreed[i].pMem;
m_pFreed[i].pMem += cb;
m_pFreed[i].cb -= cb;
// Keep the sizes sorted
QSort(m_pFreed, m_cFreedItems, sizeof(TABLE_FREED_MEMORY),
CompareIntPointers);
return psz;
}
GotAMatch:
m_cFreedItems--;
PSTR psz = (PSTR) m_pFreed[i].pMem;
if (i < m_cFreedItems) {
MemMove(&m_pFreed[i], &m_pFreed[i + 1],
sizeof(TABLE_FREED_MEMORY) * (m_cFreedItems - i));
#ifdef _DEBUG
m_pFreed[m_cFreedItems].cb = 0;
#endif
}
#ifdef _DEBUG
else
m_pFreed[i].cb = 0;
#endif
return psz;
}
}
}
if (CurOffset + cb >= cbStrings) {
int cbNew = cbStrings + TABLE_ALLOC_SIZE;
while (cbNew < CurOffset + cb)
cbNew += TABLE_ALLOC_SIZE;
// We rely on VirtualAlloc to fail if cbStrings exceeds cbMaxBase
if(cbNew > cbMaxBase)
{
ASSERT_COMMENT(FALSE, "Table memory overflow");
return NULL;
}
if (!VirtualAlloc(pszBase + cbStrings, cbNew - cbStrings,
MEM_COMMIT, PAGE_READWRITE)) {
ASSERT_COMMENT(FALSE, "Table memory overflow");
OOM();
return NULL;
}
#ifdef _DEBUG
g_cbTableAllocated += (cbNew - cbStrings);
#endif
cbStrings = cbNew;
}
int offset = CurOffset;
CurOffset += cb;
return pszBase + offset;
}
/***************************************************************************
FUNCTION: SetPosition
PURPOSE: Sets the position for reading from the table
RETURNS:
COMMENTS:
MODIFICATION DATES:
26-Feb-1990 [ralphw]
16-Oct-1990 [ralphw]
If table position is to large, set to the end of the table,
not the last line.
***************************************************************************/
BOOL FASTCALL CTable::SetPosition(int pos)
{
if (pos >= endpos)
pos = endpos;
curpos = ((pos == 0) ? 1 : pos);
return TRUE;
}
/***************************************************************************
FUNCTION: CTable::IsHashInTable
PURPOSE: Find out if the hash number exists in the table
PARAMETERS:
hash
RETURNS:
COMMENTS:
Assumes case-insensitive hash number, and no collisions
MODIFICATION DATES:
05-Feb-1997 [ralphw]
***************************************************************************/
int CTable::IsHashInTable(HASH hash)
{
for (int i = 1; i < endpos; i++) {
if (hash == *(HASH *) ppszTable[i])
return i;
}
return 0;
}
/***************************************************************************
FUNCTION: IsStringInTable
PURPOSE: Determine if the string is already in the table
RETURNS: position if the string is already in the table,
0 if the string isn't found
COMMENTS:
The comparison is case-insensitive, and is considerably
slower then IsCSStringInTable
if lcid has been set, NLS string comparisons are used
MODIFICATION DATES:
02-Mar-1990 [ralphw]
***************************************************************************/
int CTable::IsStringInTable(PCSTR pszString) const
{
int i;
if (!lcid) {
/*
* Skip over as many strings as we can by just checking the first
* letter. This avoids the overhead of the _strcmpi() function call.
*/
char chLower = ToLower(*pszString);
char chUpper = ToUpper(*pszString);
for (i = 1; i < endpos; i++) {
if ((*ppszTable[i] == chLower || *ppszTable[i] == chUpper)
&& lstrcmpi(ppszTable[i], pszString) == 0)
return i;
}
}
else { // Use NLS string comparison
for (i = 1; i < endpos; i++) {
if (CompareStringA(lcid, fsCompareI | NORM_IGNORECASE,
pszString, -1, ppszTable[i], -1) == 1)
return i;
}
}
return 0;
}
/***************************************************************************
FUNCTION: CTable::IsCSStringInTable
PURPOSE: Case-sensitive search for a string in a table
PARAMETERS:
pszString
RETURNS:
COMMENTS:
MODIFICATION DATES:
12-Jun-1994 [ralphw]
***************************************************************************/
int CTable::IsCSStringInTable(PCSTR pszString) const
{
char szBuf[sizeof(DWORD) + 1];
DWORD cmp;
if (strlen(pszString) < sizeof(DWORD)) {
ZeroMemory(szBuf, sizeof(DWORD) + 1);
strcpy(szBuf, pszString);
cmp = *(DWORD*) szBuf;
}
else
cmp = *(DWORD*) pszString;
for (int i = 1; i < endpos; i++) {
if (cmp == *(DWORD*) ppszTable[i] &&
strcmp(ppszTable[i], pszString) == 0)
return i;
}
return 0;
}
int CTable::IsStringInTable(HASH hash, PCSTR pszString) const
{
for (int i = 1; i < endpos; i++) {
if (hash == *(HASH *) ppszTable[i] &&
// this avoids the very rare hash collision
strcmp(ppszTable[i] + sizeof(HASH), pszString) == 0)
return i;
}
return 0;
}
/***************************************************************************
FUNCTION: AddDblToTable
PURPOSE: Add two strings to the table
RETURNS:
COMMENTS:
This function checks to see if the second string has already been
added, and if so, it merely sets the pointer to the original string,
rather then allocating memory for a new copy of the string.
MODIFICATION DATES:
08-Mar-1991 [ralphw]
***************************************************************************/
int CTable::AddString(PCSTR pszStr1, PCSTR pszStr2)
{
int ui;
AddString(pszStr1);
if ((ui = IsSecondaryStringInTable(pszStr2)) != 0) {
if (endpos >= maxpos)
IncreaseTableBuffer();
ppszTable[endpos++] = ppszTable[ui];
return endpos - 1;
}
else {
return AddString(pszStr2);
}
}
/***************************************************************************
FUNCTION: IsPrimaryStringInTable
PURPOSE:
RETURNS:
COMMENTS:
MODIFICATION DATES:
03-Apr-1991 [ralphw]
***************************************************************************/
int CTable::IsPrimaryStringInTable(PCSTR pszString) const
{
int i;
/*
* Skip over as many strings as we can by just checking the first
* letter. This avoids the overhead of the _strcmpi() function call.
* Since the strings aren't necessarily alphabetized, we must trudge
* through the entire table using the _strcmpi() as soon as the first
* character matches.
*/
char chLower = ToLower(*pszString);
char chUpper = ToUpper(*pszString);
for (i = 1; i < endpos; i += 2) {
if (*ppszTable[i] == chLower || *ppszTable[i] == chUpper)
break;
}
for (; i < endpos; i += 2) {
if (lstrcmpi(ppszTable[i], pszString) == 0)
return i;
}
return 0;
}
/***************************************************************************
FUNCTION: IsSecondaryStringInTable
PURPOSE:
RETURNS:
COMMENTS:
MODIFICATION DATES:
03-Apr-1991 [ralphw]
***************************************************************************/
int CTable::IsSecondaryStringInTable(PCSTR pszString) const
{
int i;
/*
* Skip over as many strings as we can by just checking the first
* letter. This avoids the overhead of the _strcmpi() function call.
* Since the strings aren't necessarily alphabetized, we must trudge
* through the entire table using the _strcmpi() as soon as the first
* character matches.
*/
char chLower = ToLower(*pszString);
char chUpper = ToUpper(*pszString);
for (i = 2; i < endpos; i += 2) {
if (*ppszTable[i] == chLower || *ppszTable[i] == chUpper)
break;
}
for (; i < endpos; i += 2) {
if (lstrcmpi(ppszTable[i], pszString) == 0)
return i;
}
return 0;
}
/***************************************************************************
FUNCTION: SortTable
PURPOSE: Sort the current buffer
RETURNS:
COMMENTS:
MODIFICATION DATES:
01-Jan-1990 [ralphw]
***************************************************************************/
void CTable::SortTable(int sortoffset)
{
if (endpos < 3) // don't sort one entry
return;
m_sortoffset = sortoffset;
if (lcid) {
fsSortFlags = fsCompare;
doLcidSort(1, (int) endpos - 1);
}
else
doSort(1, (int) endpos - 1);
}
/***************************************************************************
FUNCTION: doSort
PURPOSE:
RETURNS:
COMMENTS:
Use QSORT algorithm
MODIFICATION DATES:
27-Mar-1990 [ralphw]
***************************************************************************/
void CTable::doSort(int left, int right)
{
int last;
if (left >= right) // return if nothing to sort
return;
// REVIEW: should be a flag before trying this -- we may already know
// that they won't be in order.
// Only sort if there are elements out of order.
j = right - 1;
while (j >= left) {
// REVIEW: strcmp is NOT case-sensitive!!!
if (strcmp(ppszTable[j] + m_sortoffset,
ppszTable[j + 1] + m_sortoffset) > 0)
break;
else
j--;
}
if (j < left)
return;
sTmp = (left + right) / 2;
pszTmp = ppszTable[left];
ppszTable[left] = ppszTable[sTmp];
ppszTable[sTmp] = pszTmp;
last = left;
for (j = left + 1; j <= right; j++) {
if (strcmp(ppszTable[j] + m_sortoffset,
ppszTable[left] + m_sortoffset) < 0) {
sTmp = ++last;
pszTmp = ppszTable[sTmp];
ppszTable[sTmp] = ppszTable[j];
ppszTable[j] = pszTmp;
}
}
pszTmp = ppszTable[left];
ppszTable[left] = ppszTable[last];
ppszTable[last] = pszTmp;
/*
* REVIEW: we need to add some sort of stack depth check to prevent
* overflow of the stack.
*/
if (left < last - 1)
doSort(left, last - 1);
if (last + 1 < right)
doSort(last + 1, right);
}
/***************************************************************************
FUNCTION: CTable::doLcidSort
PURPOSE: Sort using CompareStringA
PARAMETERS:
left
right
RETURNS:
COMMENTS:
MODIFICATION DATES:
03-Jun-1994 [ralphw]
***************************************************************************/
void CTable::doLcidSort(int left, int right)
{
int last;
#ifdef _DEBUG
static BOOL fWarned = FALSE;
if (!fWarned) {
char szBuf[256];
wsprintf(szBuf, "*** fsSortFlags == %u", fsSortFlags);
DBWIN(szBuf);
fWarned = TRUE;
}
#endif
if (left >= right) // return if nothing to sort
return;
// REVIEW: should be a flag before trying this -- we may already know
// that they won't be in order.
// Only sort if there are elements out of order.
j = right - 1;
while (j >= left) {
if (CompareStringA(lcid, fsSortFlags, ppszTable[j] + m_sortoffset, -1,
ppszTable[j + 1] + m_sortoffset, -1) > 2)
break;
else
j--;
}
if (j < left)
return;
sTmp = (left + right) / 2;
pszTmp = ppszTable[left];
ppszTable[left] = ppszTable[sTmp];
ppszTable[sTmp] = pszTmp;
last = left;
for (j = left + 1; j <= right; j++) {
if (CompareStringA(lcid, fsSortFlags, ppszTable[j] + m_sortoffset, -1,
ppszTable[left] + m_sortoffset, -1) < 2) {
sTmp = ++last;
pszTmp = ppszTable[sTmp];
ppszTable[sTmp] = ppszTable[j];
ppszTable[j] = pszTmp;
}
}
pszTmp = ppszTable[left];
ppszTable[left] = ppszTable[last];
ppszTable[last] = pszTmp;
if (left < last - 1)
doLcidSort(left, last - 1);
if (last + 1 < right)
doLcidSort(last + 1, right);
}
/***************************************************************************
FUNCTION: CTable::InitializeTable
PURPOSE: Initializes the table
PARAMETERS:
uInitialSize
RETURNS:
COMMENTS:
Called by constructor and Empty()
MODIFICATION DATES:
23-Feb-1994 [ralphw]
***************************************************************************/
void CTable::InitializeTable(void)
{
// Allocate memory for the strings
pszBase = (PSTR) VirtualAlloc(NULL, cbMaxBase, MEM_RESERVE,
PAGE_READWRITE);
if (!pszBase) {
ASSERT_COMMENT(FALSE, "Out of virtual address space");
OOM();
return;
}
if (!VirtualAlloc(pszBase, cbStrings = TABLE_ALLOC_SIZE, MEM_COMMIT,
PAGE_READWRITE))
OOM();
// Allocate memory for the string pointers
ppszTable = (PSTR *) VirtualAlloc(NULL, cbMaxTable, MEM_RESERVE,
PAGE_READWRITE);
if (!ppszTable) {
OOM();
return;
}
if (!VirtualAlloc(ppszTable, cbPointers = TABLE_ALLOC_SIZE, MEM_COMMIT,
PAGE_READWRITE))
OOM();
#ifdef _DEBUG
g_cbTableAllocated += (cbStrings + cbPointers);
g_cbTableReserved += (cbMaxBase + cbMaxTable);
#endif
curpos = 1; // set to one so that sorting works
endpos = 1;
maxpos = cbPointers / sizeof(PSTR);
CurOffset = 0;
lcid = 0;
m_pFreed = NULL;
}
void FASTCALL CTable::SetSorting(LCID lcid, DWORD fsCompareI, DWORD fsCompare)
{
this->lcid = lcid;
this->fsCompareI = fsCompareI;
this->fsCompare = fsCompare;
}
/***************************************************************************
FUNCTION: CTable::AddIndexHitString
PURPOSE: Add an index, a hit number, and a string
PARAMETERS:
index
hit
pszString
RETURNS:
COMMENTS:
MODIFICATION DATES:
27-Oct-1993 [ralphw]
***************************************************************************/
void CTable::AddIndexHitString(UINT index, UINT hit, PCSTR pszString)
{
if (endpos >= maxpos)
IncreaseTableBuffer();
if ((ppszTable[endpos] =
TableMalloc((int)strlen(pszString) + 1 + (int)sizeof(UINT) * 2)) == NULL)
return;
*(UINT*) ppszTable[endpos] = index;
*(UINT*) (ppszTable[endpos] + sizeof(UINT)) = hit;
strcpy(ppszTable[endpos++] + sizeof(UINT) * 2, pszString);
}
/***************************************************************************
FUNCTION: SortTablei
PURPOSE: Case-insensitive sort
RETURNS:
COMMENTS:
MODIFICATION DATES:
01-Jan-1990 [ralphw]
***************************************************************************/
void CTable::SortTablei(int sortoffset)
{
if (endpos < 3) // don't sort one entry
return;
m_sortoffset = sortoffset;
if (!lcid)
lcid = g_lcidSystem;
ASSERT(lcid);
fsSortFlags = fsCompareI | NORM_IGNORECASE;
doLcidSort(1, endpos - 1);
// REVIEW: what is this for?
#if 0
int pos;
for (pos = 1; pos < endpos - 2; pos++) {
if (strlen(ppszTable[pos]) ==
strlen(ppszTable[pos + 1]) &&
CompareStringA(lcid, fsCompare, ppszTable[pos] + m_sortoffset, -1,
ppszTable[pos + 1] + m_sortoffset, -1) == 3) {
PSTR pszTmp = ppszTable[pos];
ppszTable[pos] = ppszTable[pos + 1];
ppszTable[pos + 1] = pszTmp;
if (pos > 2)
pos -= 2;
}
}
#endif
}
UINT CTable::GetPosFromPtr(PCSTR psz)
{
int pos = 1;
do {
if (psz == ppszTable[pos])
return pos;
} while (++pos < endpos);
return 0;
}
/***************************************************************************
FUNCTION: ReplaceString
PURPOSE: Replaces the current string at the specified position with
a new string
RETURNS: TRUE if the function is successful, FALSE if an error occurred.
An error occurs if the specified position is beyond the end
of the table.
COMMENTS:
If the new string is the same size or smaller then the original
string, then it is copied over the original string. Otherwise,
a new string buffer is allocated, and the pointer for the specified
position is changed to point to the new buffer. Note that the old
string's memory is not freed -- it simply becomes unavailable.
MODIFICATION DATES:
08-Oct-1991 [ralphw]
Updated to transfer associated line number
***************************************************************************/
BOOL CTable::ReplaceString(const char * pszNewString, int pos)
{
if (pos > endpos)
return FALSE;
if (pos == 0)
pos = 1;
/*
* If the new string is larger then the old string, then allocate a
* new buffer for it.
*/
if (strlen(pszNewString) > (size_t) strlen(ppszTable[pos])) {
if ((ppszTable[pos] =
TableMalloc((int)strlen(pszNewString) + 1)) == NULL)
return FALSE;
}
strcpy(ppszTable[pos], pszNewString);
return TRUE;
}
void CTable::FreeMemory(PCSTR psz, int cb)
{
if (cb == -1)
cb = (int)strlen(psz) + 1;
/*
* Change the size of cb to match what would have been originally
* allocated. See TableMalloc().
*/
cb = (cb & (ALIGNMENT - 1)) ?
cb / ALIGNMENT * ALIGNMENT + ALIGNMENT : cb;
if (!m_pFreed) {
m_cFreedMax = 5;
m_cFreedItems = 0;
m_pFreed = (TABLE_FREED_MEMORY*) lcMalloc(m_cFreedMax * sizeof(TABLE_FREED_MEMORY));
}
else if (m_cFreedItems >= m_cFreedMax) {
m_cFreedMax += 5;
m_pFreed = (TABLE_FREED_MEMORY*) lcReAlloc(m_pFreed, m_cFreedMax * sizeof(TABLE_FREED_MEMORY));
}
m_pFreed[m_cFreedItems].cb = cb;
m_pFreed[m_cFreedItems].pMem = psz;
m_cFreedItems++;
// Keep the sizes sorted
QSort(m_pFreed, m_cFreedItems, sizeof(TABLE_FREED_MEMORY), CompareIntPointers);
}
//////////////////////////////////////////////////////////////////////////
// CWTable
//////////////////////////////////////////////////////////////////////////
void CWTable::_CWTable( UINT CodePage )
{
m_CodePage = CodePage;
}
CWTable::CWTable( UINT CodePage )
{
_CWTable( CodePage );
}
CWTable::CWTable(int cbStrings, UINT CodePage ) : CTable( cbStrings )
{
_CWTable( CodePage );
}
CWTable::~CWTable()
{
}
/***************************************************************************
FUNCTION: GetStringW
PURPOSE: Gets a Unicode version fo the stored string.
RETURNS: S_OK if the function is successful, S_FALSE otherwise.
COMMENTS: Stored string must be MBCS.
MODIFICATION DATES:
08-Sep-1998 [paulti]
***************************************************************************/
HRESULT CWTable::GetStringW( int pos, WCHAR* pwsz, int cch )
{
CHAR* psz = CTable::GetPointer( pos );
int iReturn = MultiByteToWideChar( m_CodePage, 0, psz, (int)strlen(psz), pwsz, cch );
if( iReturn == 0 )
return S_FALSE;
pwsz[iReturn] = 0;
return S_OK;
}
/***************************************************************************
FUNCTION: GetHashStringW
PURPOSE: Gets a Unicode versions of the string when the both a Hash
and a string pair are stored.
RETURNS: S_OK if the function is successful, S_FALSE otherwise.
COMMENTS: Stored string must be MBCS.
MODIFICATION DATES:
08-Sep-1998 [paulti]
***************************************************************************/
HRESULT CWTable::GetHashStringW( int pos, WCHAR* pwsz, int cch )
{
CHAR* psz = CTable::GetHashStringPointer( pos );
int iReturn = MultiByteToWideChar( m_CodePage, 0, psz, (int)strlen(psz), pwsz, cch );
if( iReturn == 0 )
return S_FALSE;
pwsz[iReturn] = 0;
return S_OK;
}