Leaked source code of windows server 2003
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.
 
 
 
 
 
 

476 lines
11 KiB

/******************************************************************************
Header File: String Array.CPP
Implements the String Array class- see the related header for the declaration
of this class.
This class will do arrays in chunks- if the total array exceeds the size of
one chunk, we chain more instances together, then use recursion to do the
work.
Copyright (c) 1996 by Microsoft Corporation
A Pretty Penny Enterprises Production
Change History:
11-01-96 [email protected] original version
12-04-96 [email protected] Added LoadString and IsEmpty to CString
Also fixed bug in Remove where
u > ChunkSize (wasn't exiting)
12-11-96 [email protected] Let CString do ANSI/UNICODE conversions
automagically to ease some API issues
01-07-97 [email protected] Fixed CStringArray::Empty and CUintArray::Empty
to NULL pointer to next chunk after deleting it. Led to GP faults
if we needed to use the chunk again.
******************************************************************************/
#include "ICMUI.H"
// Convert a UNICODE string to a new ANSI buffer
void CString::Flip(LPCWSTR lpstrIn, LPSTR& lpstrOut) {
if (!lpstrIn) {
lpstrOut = NULL;
return;
}
int iLength = WideCharToMultiByte(CP_ACP, 0, lpstrIn, -1, NULL, 0, NULL,
NULL);
if (!iLength) {
lpstrOut = NULL;
return;
}
lpstrOut = (LPSTR) malloc(++iLength);
if(lpstrOut) {
WideCharToMultiByte(CP_ACP, 0, lpstrIn, -1, lpstrOut, iLength, NULL,
NULL);
}
}
// Convert an ANSI string to a new UNICODE buffer
void CString::Flip(LPCSTR lpstrIn, LPWSTR& lpstrOut) {
if (!lpstrIn) {
lpstrOut = NULL;
return;
}
int iLength = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, lpstrIn, -1,
NULL, 0);
if (!iLength) {
lpstrOut = NULL;
return;
}
lpstrOut = (LPWSTR) malloc(++iLength * sizeof (WCHAR));
if(lpstrOut) {
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, lpstrIn, -1, lpstrOut,
iLength);
}
}
// Empty the string, and free all memory.
void CString::Empty() {
if (m_acContents)
free(m_acContents);
if (m_acConverted)
free(m_acConverted);
m_acContents = NULL;
m_acConverted = NULL;
m_bConverted = FALSE;
}
// Compare with other CString
BOOL CString::IsEqualString(CString& csRef1)
{
if (IsEmpty() || csRef1.IsEmpty())
return (FALSE);
return (_tcsicmp(m_acContents,(LPTSTR)csRef1) == 0);
}
CString::CString() {
m_acContents = NULL;
m_acConverted = NULL;
m_bConverted = FALSE;
}
CString::CString(const CString& csRef) {
m_acContents = csRef.m_acContents ? _tcsdup(csRef.m_acContents) : NULL;
m_acConverted = NULL;
m_bConverted = FALSE;
}
CString::CString(LPCTSTR lpstrRef) {
m_acContents = lpstrRef ? _tcsdup(lpstrRef) : NULL;
m_acConverted = NULL;
m_bConverted = FALSE;
}
CString::CString(LPCOSTR lpstrRef) {
m_acConverted = NULL;
m_bConverted = FALSE;
if (!lpstrRef) {
m_acContents = NULL;
return;
}
Flip(lpstrRef, m_acContents);
}
// Class destructor
CString::~CString() {
Empty();
}
// Report string in non-native encoding
CString::operator LPCOSTR() {
if (!m_bConverted) {
Flip(m_acContents, m_acConverted);
m_bConverted = TRUE;
}
return m_acConverted;
}
const CString& CString::operator =(const CString& csSrc) {
Empty();
m_acContents = csSrc.m_acContents ? _tcsdup(csSrc.m_acContents) : NULL;
return *this;
}
const CString& CString::operator =(LPCTSTR lpstrSrc) {
Empty();
m_acContents = lpstrSrc ? _tcsdup(lpstrSrc) : NULL;
return *this;
}
const CString& CString::operator =(LPCOSTR lpstrSrc) {
Empty();
Flip(lpstrSrc, m_acContents);
return *this;
}
CString CString::NameOnly() const {
TCHAR acName[_MAX_FNAME];
if (!m_acContents)
return *this;
_tsplitpath(m_acContents, NULL, NULL, acName, NULL);
return acName;
}
CString CString::NameAndExtension() const {
TCHAR acName[_MAX_FNAME], acExtension[_MAX_EXT];
if (!m_acContents)
return *this;
_tsplitpath(m_acContents, NULL, NULL, acName, acExtension);
lstrcat(acName, acExtension);
return acName;
}
void CString::Load(int id, HINSTANCE hi) {
if (!hi)
hi = CGlobals::Instance();
TCHAR acWork[MAX_PATH];
if(LoadString(hi, id, acWork, MAX_PATH) > 0)
*this = acWork;
else
*this = TEXT("");
}
// 03-20-1997 [email protected] Part of RAID 22289.
// Add a method for loading text from a windows handle
void CString::Load(HWND hwnd) {
Empty();
int iccNeeded = GetWindowTextLength(hwnd);
if (!iccNeeded)
return;
m_acContents = (LPTSTR) malloc(++iccNeeded * sizeof (TCHAR));
if(m_acContents) {
GetWindowText(hwnd, m_acContents, iccNeeded);
}
}
void CString::LoadAndFormat(int id, HINSTANCE hiWhere, BOOL bSystemMessage,
DWORD dwNumMsg, va_list *argList) {
Empty();
TCHAR acWork[1024];
CString csTemplate;
LPTSTR lpSource;
DWORD dwFlags;
if (bSystemMessage) {
lpSource = NULL;
dwFlags = FORMAT_MESSAGE_FROM_SYSTEM;
} else {
csTemplate.Load(id);
lpSource = csTemplate;
dwFlags = FORMAT_MESSAGE_FROM_STRING;
id = 0;
}
if (FormatMessage(dwFlags,lpSource, id, 0, acWork, 1024, argList)) {
*this = acWork;
}
}
CString operator +(const CString& csRef, LPCTSTR lpstrRef) {
if (!lpstrRef || !*lpstrRef)
return csRef;
if (csRef.IsEmpty())
return lpstrRef;
CString csReturn;
csReturn.m_acContents = (LPTSTR) malloc((1 + lstrlen(csRef.m_acContents) +
lstrlen(lpstrRef)) * sizeof(TCHAR));
if(csReturn.m_acContents) {
lstrcat(lstrcpy(csReturn.m_acContents, csRef.m_acContents), lpstrRef);
}
return csReturn;
}
// CStringArray classes- these manage an array of strings,
// but the methods are geared to list-style management.
// Borrow first element from next chunk
LPCTSTR CStringArray::Borrow() {
LPCTSTR lpstrReturn = m_aStore[0];
memcpy((LPSTR) m_aStore, (LPSTR) (m_aStore + 1),
(ChunkSize() - 1) * sizeof m_aStore[0]);
if (m_ucUsed > ChunkSize())
m_aStore[ChunkSize() - 1] = m_pcsaNext -> Borrow();
else
m_aStore[ChunkSize() - 1] = (LPCTSTR) NULL;
m_ucUsed--;
if (m_ucUsed <= ChunkSize() && m_pcsaNext) {
delete m_pcsaNext;
m_pcsaNext = NULL;
}
return lpstrReturn;
}
// ctor
CStringArray::CStringArray() {
m_ucUsed = 0;
m_pcsaNext = NULL;
}
// dtor
CStringArray::~CStringArray() {
Empty();
}
// Empty the list/array
void CStringArray::Empty() {
if (!m_ucUsed) return;
if (m_pcsaNext) {
delete m_pcsaNext;
m_pcsaNext = NULL;
}
m_ucUsed = 0;
}
unsigned CStringArray::Map(LPCTSTR lpstrRef) {
for (unsigned u = 0; u < m_ucUsed; u++)
if (!lstrcmpi(operator[](u), lpstrRef))
break;
return u;
}
// Add an item
void CStringArray::Add(LPCTSTR lpstrNew) {
if (m_ucUsed < ChunkSize()) {
m_aStore[m_ucUsed++] = lpstrNew;
return;
}
// Not enough space! Add another record, if there isn't one
if (!m_pcsaNext)
m_pcsaNext = new CStringArray;
// Add the string to the next array (recursive call!)
if (m_pcsaNext) {
m_pcsaNext -> Add(lpstrNew);
m_ucUsed++;
}
}
// define an indexing operator
CString& CStringArray::operator [](unsigned u) const {
_ASSERTE(u < m_ucUsed);
return u < ChunkSize() ?
(CString&)m_aStore[u] : m_pcsaNext -> operator[](u - ChunkSize());
}
// Remove the string at some index, shifting the rest down one slot
void CStringArray::Remove(unsigned u) {
if (u > m_ucUsed)
return;
if (u >= ChunkSize()) {
m_pcsaNext -> Remove(u - ChunkSize());
return;
}
memmove((LPSTR) (m_aStore + u), (LPSTR) (m_aStore + u + 1),
(ChunkSize() - (u + 1)) * sizeof m_aStore[0]);
if (m_ucUsed > ChunkSize())
m_aStore[ChunkSize() - 1] = m_pcsaNext -> Borrow();
else
m_aStore[ChunkSize() - 1] = (LPCTSTR) NULL;
m_ucUsed--;
if (m_ucUsed <= ChunkSize() && m_pcsaNext) {
delete m_pcsaNext;
m_pcsaNext = NULL;
}
}
// CUintArray class- this manages an array/list of unsigned integers
// The implementation is quite similar to the CStringArray's. Why
// bother to do it different, after all?
unsigned CUintArray::Borrow() {
unsigned uReturn = m_aStore[0];
memcpy((LPSTR) m_aStore, (LPSTR) (m_aStore + 1),
(ChunkSize() - 1) * sizeof m_aStore[0]);
if (m_ucUsed > ChunkSize())
m_aStore[ChunkSize() - 1] = m_pcuaNext -> Borrow();
else
m_aStore[ChunkSize() - 1] = 0;
m_ucUsed--;
if (m_ucUsed <= ChunkSize() && m_pcuaNext) {
delete m_pcuaNext;
m_pcuaNext = NULL;
}
return uReturn;
}
CUintArray::CUintArray() {
m_ucUsed = 0;
m_pcuaNext = NULL;
}
CUintArray::~CUintArray() {
Empty();
}
void CUintArray::Empty() {
if (!m_ucUsed) return;
if (m_pcuaNext) {
delete m_pcuaNext;
m_pcuaNext = NULL;
}
m_ucUsed = 0;
}
// Add an item
void CUintArray::Add(unsigned uNew) {
if (m_ucUsed < ChunkSize()) {
m_aStore[m_ucUsed++] = uNew;
return;
}
// Not enough space! Add another record, if there isn't one
if (!m_pcuaNext)
m_pcuaNext = new CUintArray;
// Add the item to the next array (recursive call!)
if (m_pcuaNext) {
m_pcuaNext -> Add(uNew);
m_ucUsed++;
}
}
unsigned CUintArray::operator [](unsigned u) const {
return u < m_ucUsed ? u < ChunkSize() ?
m_aStore[u] : m_pcuaNext -> operator[](u - ChunkSize()) : 0;
}
void CUintArray::Remove(unsigned u) {
if (u > m_ucUsed)
return;
if (u >= ChunkSize()) {
m_pcuaNext -> Remove(u - ChunkSize());
return;
}
memmove((LPSTR) (m_aStore + u), (LPSTR) (m_aStore + u + 1),
(ChunkSize() - (u + 1)) * sizeof m_aStore[0]);
if (m_ucUsed > ChunkSize())
m_aStore[ChunkSize() - 1] = m_pcuaNext -> Borrow();
else
m_aStore[ChunkSize() - 1] = 0;
m_ucUsed--;
if (m_ucUsed <= ChunkSize() && m_pcuaNext) {
delete m_pcuaNext;
m_pcuaNext = NULL;
}
}