|
|
// 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; }
|