Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

358 lines
10 KiB

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