2020-09-30 16:53:49 +02:00

270 lines
6.3 KiB
C++

// StringProperty.cpp: implementation of the CStringProperty class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "StringProperty.h"
#include "utils.h"
#define TRACE 0?0:
CDictionary CStringPropertySection::m_Dictionary;
CStringPropertySection::CStringPropertySection()
{
m_UsedItems=0; // make this an array and re-alloc it - like the CDPA ! Gosh.
m_ItemSize=RUN_SIZE;
m_Items=new LINKSTRING[m_ItemSize];
}
//
// Finds the Value from the KEY, returns NULL if the KEY isn't used.
//
LPCTSTR CStringPropertySection::Get(LPCTSTR szPropID)
{
int iEntry;
if( Find( szPropID, &iEntry ) )
return (LPCTSTR)m_Items[iEntry].pszValue;
return NULL;
}
#define _MEM_DEBUG
#ifdef _MEM_DEBUG
DWORD g_KeyAlloc;
DWORD g_ValueAlloc;
#endif
//
// Associats a value (perhaps new) to a given key.
//
BOOL CStringPropertySection::Set(LPCTSTR szPropID, LPCTSTR szValue)
{
int iEntry;
if( Find( szPropID, &iEntry ) == FALSE )
{
if( m_UsedItems == m_ItemSize )
{
// re allocate the buffer bigger.
m_ItemSize*=2;
PLINKSTRING pNew=new LINKSTRING[m_ItemSize];
CopyMemory(pNew, m_Items, sizeof(LINKSTRING) * m_UsedItems );
delete m_Items;
m_Items=pNew;
}
iEntry=m_UsedItems++;
m_Items[iEntry].idKey=m_Dictionary.GetID( szPropID );
}
else
{
delete m_Items[iEntry].pszValue;
}
DWORD dwLen=lstrlen(szValue)+1;
#ifdef _MEM_DEBUG
g_ValueAlloc+=dwLen;
#endif
m_Items[iEntry].pszValue=new TCHAR[dwLen];
CopyMemory( m_Items[iEntry].pszValue, szValue, dwLen*sizeof(TCHAR) );
return TRUE;
}
//
// Finds a string in the table.
// The KEY of the thing you are finding
// An OUT pointer to the LINKSTRING structure
// which item in the LINKSTRING structure can be used.
//
BOOL CStringPropertySection::Find( LPCTSTR szPropID, int * pEntry)
{
UINT uiPropID = m_Dictionary.GetID( szPropID ); // this is the ID for this string.
for(UINT i=0;i<m_UsedItems;i++)
{
if( uiPropID == m_Items[i].idKey )
{
*pEntry=i;
return TRUE;
}
}
*pEntry=0;
return FALSE;
}
CStringPropertySection::~CStringPropertySection()
{
Purge();
delete m_Items;
m_Items=NULL;
}
void CStringPropertySection::Purge()
{
for(UINT i=0;i<m_UsedItems;i++)
{
m_Items[i].idKey=0;
delete m_Items[i].pszValue;
m_Items[i].pszValue=NULL;
}
m_UsedItems=0;
}
//
// Looks for the existance of a property szPropID
// if present and set to YES, returns dwResult (default of TRUE).
// otherwise returns defValue
//
DWORD CStringPropertySection::YesNo(LPCTSTR szPropID, DWORD dwNotPresent, DWORD dwYes)
{
return YesNo( szPropID, dwNotPresent, FALSE, dwYes );
}
DWORD CStringPropertySection::YesNo(LPCTSTR szPropID, DWORD dwNotPresent, DWORD dwNo, DWORD dwYes)
{
LPCTSTR req=(LPCTSTR)Get(szPropID);
if( req == NULL )
return dwNotPresent;
if( req && lstrcmpi(req,TEXT("YES"))==0)
return dwYes;
return dwNo;
}
DWORD CStringPropertySection::ValueOf(LPCTSTR szPropID, DWORD dwDefault)
{
LPCTSTR req=(LPCTSTR)Get(szPropID);
// return req?_ttoi( req ):dwDefault;
return req?StringToInt(req):dwDefault;
}
////////////////////////////////////////////////////////////////////////////////////////////////
//
// Dictionary.
// maps strings to UINTS, in a case insensitive manner.
//
////////////////////////////////////////////////////////////////////////////////////////////////
CDictionary::CDictionary()
{
for(int i=0;i<DIC_TABLE_SIZE;i++)
m_Table[i]=NULL;
}
UINT CDictionary::GetID(LPCTSTR szPropID)
{
//
// Has the string, find the bucket.
//
DWORD dwStrLen=lstrlen(szPropID)+1;
DWORD hash=Hash(szPropID, dwStrLen);
PLINKDICSTRING * pFoundPointer = &m_Table[hash];
PLINKDICSTRING pFound=*pFoundPointer;
int iNumber=0+1;
while( pFound )
{
int used=pFound->cbUsed;
for( int i=0;i<used;i++)
{
iNumber++;
if( lstrcmpi( pFound->pszKey[i], szPropID) == 0 )
return pFound->ID[i];
}
//
// If we have space in this run, use it up.
//
if( used < DIC_RUN_SIZE )
break;
// Next bucket
pFoundPointer=&pFound->pNext;
pFound=*pFoundPointer;
}
if( pFound == NULL )
{
pFound = new LINKDICSTRING;
ZeroMemory( pFound, sizeof(LINKDICSTRING) );
*pFoundPointer=pFound;
TRACE(TEXT("Dic at 0x%08x\n"), pFound );
}
//
// Make the ID out of the bucket we are in, and the item we're adding.
//
int iEntry=pFound->cbUsed++;
pFound->ID[iEntry]=hash<<8 | iNumber;
#ifdef _MEM_DEBUG
g_ValueAlloc+=dwStrLen;
#endif
pFound->pszKey[iEntry]=new TCHAR[dwStrLen];
CopyMemory( pFound->pszKey[iEntry], szPropID, dwStrLen*sizeof(TCHAR) );
return pFound->ID[iEntry];
}
LPCTSTR CDictionary::GetString(UINT ID)
{
int iBucket=ID >> 8;
// for( int iBucket=0;iBucket<DIC_TABLE_SIZE;iBucket++)
{
PLINKDICSTRING pLinkString=m_Table[iBucket];
int i=0;
while( pLinkString )
{
int used=pLinkString->cbUsed;
for( int i=0;i<used;i++)
{
if( pLinkString->ID[i] == ID )
return pLinkString->pszKey[i];
}
pLinkString=( pLinkString->pNext );
}
}
return 0;
}
//
// Case insensitive hash.
//
DWORD CDictionary::Hash( LPCTSTR szString, DWORD dwStrLen )
{
TCHAR szChar=toupper( *szString );
return (dwStrLen * szChar) % DIC_TABLE_SIZE;
}
CDictionary::~CDictionary()
{
Purge();
}
void CDictionary::Purge()
{
for(int i=0;i<DIC_TABLE_SIZE;i++)
{
PLINKDICSTRING pNext;
PLINKDICSTRING pEntry = m_Table[i];
while( pEntry )
{
for(int ti=0;ti<pEntry->cbUsed;ti++)
{
pEntry->ID[ti]=0;
delete pEntry->pszKey[ti];
pEntry->pszKey[ti]=NULL;
}
pNext= pEntry->pNext;
delete pEntry;
TRACE(TEXT("Dic @ 0x%08x\n"), pEntry );
pEntry=pNext;
}
m_Table[i]=NULL;
}
}