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