359 lines
10 KiB
C++
359 lines
10 KiB
C++
/**********************************************************************/
|
||
/** Microsoft Windows NT **/
|
||
/** Copyright(c) Microsoft Corp., 1997 **/
|
||
/**********************************************************************/
|
||
|
||
/*
|
||
string.cxx
|
||
|
||
This module contains a light weight string class
|
||
|
||
|
||
FILE HISTORY:
|
||
4/8/97 michth created
|
||
|
||
*/
|
||
|
||
#include "precomp.hxx"
|
||
#include "aucommon.hxx"
|
||
|
||
|
||
/*******************************************************************
|
||
|
||
NAME: STRAU::STR
|
||
|
||
SYNOPSIS: Construct a string object
|
||
|
||
ENTRY: Optional object initializer
|
||
|
||
NOTES: If the object is not valid (i.e. !IsValid()) then GetLastError
|
||
should be called.
|
||
|
||
The object is guaranteed to construct successfully if nothing
|
||
or NULL is passed as the initializer.
|
||
|
||
********************************************************************/
|
||
|
||
// Inlined in stringau.hxx
|
||
|
||
|
||
VOID
|
||
STRAU::AuxInit( const LPSTR pInit )
|
||
{
|
||
BOOL fRet;
|
||
|
||
if ( pInit && (*pInit != '\0') )
|
||
{
|
||
INT cbCopy = (::strlen( pInit ) + 1) * sizeof(CHAR);
|
||
fRet = m_bufAnsi.Resize( cbCopy );
|
||
|
||
if ( fRet ) {
|
||
CopyMemory( m_bufAnsi.QueryPtr(), pInit, cbCopy );
|
||
m_cbMultiByteLen = (cbCopy)/sizeof(CHAR) - 1;
|
||
m_bUnicode = FALSE;
|
||
m_bInSync = FALSE;
|
||
} else {
|
||
m_bIsValid = FALSE;
|
||
}
|
||
|
||
} else {
|
||
Reset();
|
||
}
|
||
|
||
return;
|
||
} // STRAU::AuxInit()
|
||
|
||
|
||
VOID
|
||
STRAU::AuxInit( const LPWSTR pInit )
|
||
{
|
||
BOOL fRet;
|
||
|
||
if ( pInit && (*pInit != (WCHAR)'\0'))
|
||
{
|
||
INT cbCopy = (::wcslen( pInit) + 1) * sizeof(WCHAR);
|
||
fRet = m_bufUnicode.Resize( cbCopy );
|
||
|
||
if ( fRet ) {
|
||
CopyMemory( m_bufUnicode.QueryPtr(), pInit, cbCopy );
|
||
m_cchUnicodeLen = (cbCopy)/sizeof(WCHAR) - 1;
|
||
m_bUnicode = TRUE;
|
||
m_bInSync = FALSE;
|
||
} else {
|
||
m_bIsValid = FALSE;
|
||
}
|
||
|
||
} else {
|
||
Reset();
|
||
}
|
||
|
||
return;
|
||
} // STRAU::AuxInit()
|
||
|
||
|
||
/*******************************************************************
|
||
|
||
NAME: STRAU::AuxAppend
|
||
|
||
SYNOPSIS: Appends the string onto this one.
|
||
|
||
ENTRY: Object to append
|
||
********************************************************************/
|
||
|
||
|
||
BOOL STRAU::AuxAppend( const LPSTR pStr, UINT cbStr, BOOL fAddSlop )
|
||
{
|
||
DBG_ASSERT( pStr != NULL );
|
||
|
||
BOOL bReturn = m_bIsValid;
|
||
|
||
if (m_bIsValid) {
|
||
if (!m_bUnicode || (m_cchUnicodeLen == 0)) {
|
||
//
|
||
// Just append the ANSI string
|
||
//
|
||
//
|
||
// Only resize when we have to. When we do resize, we tack on
|
||
// some extra space to avoid extra reallocations.
|
||
//
|
||
// Note: QuerySize returns the requested size of the string buffer,
|
||
// *not* the strlen of the buffer
|
||
//
|
||
|
||
if ( m_bufAnsi.QuerySize() < ((m_cbMultiByteLen + cbStr + 1) * sizeof(CHAR)) )
|
||
{
|
||
bReturn = m_bufAnsi.Resize( ((m_cbMultiByteLen + cbStr + 1) * sizeof(CHAR)) + ((fAddSlop) ? STR_SLOP : 0) );
|
||
}
|
||
|
||
if (bReturn) {
|
||
// copy the exact string and append a null character
|
||
memcpy( (BYTE *) (((LPSTR)m_bufAnsi.QueryPtr()) + m_cbMultiByteLen),
|
||
pStr,
|
||
cbStr * sizeof(char));
|
||
m_cbMultiByteLen += cbStr;
|
||
*((CHAR *) m_bufAnsi.QueryPtr() + m_cbMultiByteLen) = '\0'; // append an explicit null char
|
||
m_bUnicode = FALSE;
|
||
m_bInSync = FALSE;
|
||
}
|
||
else {
|
||
m_bIsValid = FALSE;
|
||
}
|
||
}
|
||
else {
|
||
//
|
||
// Currently have a UNICODE string
|
||
// Need to convert to UNICODE and copy
|
||
// Use the ANSI buffer as temporary space
|
||
//
|
||
int iUnicodeLen = ConvertMultiByteToUnicode(pStr, &m_bufAnsi, cbStr);
|
||
if (STR_CONVERSION_SUCCEEDED(iUnicodeLen)) {
|
||
if ( m_bufUnicode.QuerySize() < ((m_cchUnicodeLen + iUnicodeLen + 1) * sizeof(WCHAR)) )
|
||
{
|
||
bReturn = m_bufUnicode.Resize( ((m_cchUnicodeLen + iUnicodeLen + 1) * sizeof(WCHAR)) + ((fAddSlop) ? STR_SLOP : 0) );
|
||
}
|
||
|
||
if (bReturn) {
|
||
// copy the exact string and append a null character
|
||
memcpy( (BYTE *) ((LPWSTR)(m_bufUnicode.QueryPtr()) + m_cchUnicodeLen),
|
||
m_bufAnsi.QueryPtr(),
|
||
(iUnicodeLen * sizeof(WCHAR)));
|
||
m_cchUnicodeLen += iUnicodeLen;
|
||
*((LPWSTR)m_bufUnicode.QueryPtr() + m_cchUnicodeLen) = (WCHAR)'\0'; // append an explicit null char
|
||
m_bInSync = FALSE;
|
||
}
|
||
else {
|
||
m_bIsValid = FALSE;
|
||
}
|
||
}
|
||
else {
|
||
m_bIsValid = FALSE;
|
||
}
|
||
}
|
||
}
|
||
return bReturn;
|
||
} // STRAU::AuxAppend()
|
||
|
||
|
||
BOOL STRAU::AuxAppend( const LPWSTR pStr, UINT cchStr, BOOL fAddSlop )
|
||
{
|
||
DBG_ASSERT( pStr != NULL );
|
||
|
||
BOOL bReturn = m_bIsValid;
|
||
int iUnicodeLen;
|
||
|
||
if (m_bIsValid) {
|
||
if (!m_bUnicode && !m_bInSync && (m_cbMultiByteLen != 0)) {
|
||
|
||
// Currently have an ANSI string
|
||
// Need to convert ANSI string to UNICODE before copy
|
||
//
|
||
iUnicodeLen = ConvertMultiByteToUnicode((LPSTR)m_bufAnsi.QueryPtr(), &m_bufUnicode, m_cbMultiByteLen);
|
||
if (STR_CONVERSION_SUCCEEDED(iUnicodeLen)) {
|
||
m_cchUnicodeLen = iUnicodeLen;
|
||
}
|
||
else {
|
||
bReturn = FALSE;
|
||
m_bIsValid = FALSE;
|
||
}
|
||
}
|
||
if (bReturn) {
|
||
//
|
||
// Only resize when we have to. When we do resize, we tack on
|
||
// some extra space to avoid extra reallocations.
|
||
//
|
||
// Note: QuerySize returns the requested size of the string buffer,
|
||
// *not* the strlen of the buffer
|
||
//
|
||
if ( m_bufUnicode.QuerySize() < ((m_cchUnicodeLen + cchStr + 1) * sizeof(WCHAR)) )
|
||
{
|
||
bReturn = m_bufUnicode.Resize( ((m_cchUnicodeLen + cchStr + 1) * sizeof(WCHAR)) + ((fAddSlop) ? STR_SLOP : 0) );
|
||
}
|
||
|
||
if (bReturn) {
|
||
// copy the exact string and append a null character
|
||
memcpy( (BYTE *) (((LPWSTR)m_bufUnicode.QueryPtr()) + m_cchUnicodeLen),
|
||
pStr,
|
||
(cchStr * sizeof(WCHAR)));
|
||
m_cchUnicodeLen += cchStr;
|
||
*((LPWSTR)m_bufUnicode.QueryPtr() + m_cchUnicodeLen) = (WCHAR)'\0'; // append an explicit null char
|
||
m_bInSync = FALSE;
|
||
m_bUnicode = TRUE;
|
||
}
|
||
else {
|
||
m_bIsValid = FALSE;
|
||
}
|
||
}
|
||
}
|
||
return bReturn;
|
||
} // STRAU::AuxAppend()
|
||
|
||
|
||
BOOL
|
||
STRAU::SetLen( IN DWORD cchLen)
|
||
{
|
||
BOOL bReturn = FALSE;
|
||
if (cchLen <= QueryCCH()) {
|
||
if (m_bUnicode || m_bInSync) {
|
||
*((LPWSTR)m_bufUnicode.QueryPtr() + cchLen) = (WCHAR)'\0';
|
||
m_cchUnicodeLen = cchLen;
|
||
}
|
||
if (!m_bUnicode || m_bInSync) {
|
||
LPSTR pszTerminateByte = (LPSTR)m_bufAnsi.QueryPtr();
|
||
WORD wPrimaryLangID = PRIMARYLANGID(GetSystemDefaultLangID());
|
||
if (wPrimaryLangID == LANG_JAPANESE ||
|
||
wPrimaryLangID == LANG_CHINESE ||
|
||
wPrimaryLangID == LANG_KOREAN)
|
||
{
|
||
char *pszTop = pszTerminateByte;
|
||
for (DWORD i = 0; i < QueryCCH(); i++) {
|
||
pszTerminateByte = CharNextExA(CP_ACP,
|
||
pszTerminateByte,
|
||
0);
|
||
}
|
||
m_cbMultiByteLen = DIFF(pszTerminateByte - pszTop);
|
||
}
|
||
else
|
||
{
|
||
pszTerminateByte += cchLen;
|
||
m_cbMultiByteLen = cchLen;
|
||
}
|
||
*pszTerminateByte = '\0';
|
||
}
|
||
bReturn = TRUE;
|
||
}
|
||
|
||
return bReturn;
|
||
}
|
||
|
||
|
||
LPTSTR
|
||
STRAU::QueryStr(BOOL bUnicode)
|
||
{
|
||
|
||
//
|
||
// This can fail. Return a null string for either UNICODE or ANSI
|
||
// So that clients expecting a valid pointer actually get one.
|
||
//
|
||
LPTSTR pszReturn = NULL;
|
||
int iNewStrLen;
|
||
|
||
if (m_bIsValid) {
|
||
if ((bUnicode != m_bUnicode) && (!m_bInSync)) {
|
||
//
|
||
// Need to Convert First
|
||
//
|
||
if (bUnicode) {
|
||
//
|
||
// Convert current string to UNICODE
|
||
//
|
||
iNewStrLen = ConvertMultiByteToUnicode((LPSTR)m_bufAnsi.QueryPtr(), &m_bufUnicode, m_cbMultiByteLen);
|
||
if (STR_CONVERSION_SUCCEEDED(iNewStrLen)) {
|
||
m_cchUnicodeLen = iNewStrLen;
|
||
m_bInSync = TRUE;
|
||
}
|
||
else {
|
||
m_bIsValid = FALSE;
|
||
}
|
||
}
|
||
else {
|
||
//
|
||
// Convert current string to Ansi
|
||
//
|
||
iNewStrLen = ConvertUnicodeToMultiByte((LPWSTR)m_bufUnicode.QueryPtr(), &m_bufAnsi, m_cchUnicodeLen);
|
||
if (STR_CONVERSION_SUCCEEDED(iNewStrLen)) {
|
||
m_cbMultiByteLen = iNewStrLen;
|
||
m_bInSync = TRUE;
|
||
}
|
||
else {
|
||
m_bIsValid = FALSE;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (m_bIsValid) {
|
||
if (bUnicode) {
|
||
pszReturn = (LPTSTR)m_bufUnicode.QueryPtr();
|
||
}
|
||
else {
|
||
pszReturn = (LPTSTR)m_bufAnsi.QueryPtr();
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
return pszReturn;
|
||
}
|
||
|
||
BOOL
|
||
STRAU::SafeCopy( const LPSTR pchInit )
|
||
{
|
||
BOOL bReturn = TRUE;
|
||
SaveState();
|
||
Reset();
|
||
if (pchInit != NULL) {
|
||
bReturn = AuxAppend(pchInit, ::strlen( pchInit ), FALSE );
|
||
if (!bReturn) {
|
||
RestoreState();
|
||
}
|
||
}
|
||
return bReturn;
|
||
}
|
||
|
||
|
||
BOOL
|
||
STRAU::SafeCopy( const LPWSTR pchInit )
|
||
{
|
||
BOOL bReturn = TRUE;
|
||
SaveState();
|
||
Reset();
|
||
if (pchInit != NULL) {
|
||
bReturn = AuxAppend( pchInit, ::wcslen( pchInit ), FALSE );
|
||
if (!bReturn) {
|
||
RestoreState();
|
||
}
|
||
}
|
||
return bReturn;
|
||
}
|
||
|
||
|