/*****************************************************************/ /** Microsoft Windows for Workgroups **/ /** Copyright (C) Microsoft Corp., 1991-1992 **/ /*****************************************************************/ /* string.cxx NLS/DBCS-aware string class: essential core methods This file contains those routines which every client of the string classes will always need. Most of the implementation has been exploded into other files, so that an app linking to string doesn't end up dragging the entire string runtime library along with it. FILE HISTORY: beng 10/23/90 Created johnl 12/11/90 Remodeled beyond all recognizable form beng 01/18/91 Most methods relocated into other files beng 02/07/91 Uses lmui.hxx beng 07/26/91 Replaced min with local inline gregj 03/30/93 Removed ISTR to separate module */ #include "npcommon.h" extern "C" { #include } #if defined(DEBUG) static const CHAR szFileName[] = __FILE__; #define _FILENAME_DEFINED_ONCE szFileName #endif #include #include /******************************************************************* NAME: NLS_STR::NLS_STR SYNOPSIS: Constructor for NLS_STR ENTRY: NLS_STR takes many (too many) ctor forms. EXIT: String constructed NOTES: The default constructor creates an empty string. HISTORY: beng 10/23/90 Created beng 04/26/91 Replaced 'CB' and USHORT with INT beng 07/22/91 Uses member-init ctor forms ********************************************************************/ NLS_STR::NLS_STR() : _pchData(0), _cbData(0), _cchLen(0), _fsFlags(0) { if ( !Alloc(1) ) return; *_pchData = '\0'; InitializeVers(); } NLS_STR::NLS_STR( INT cchInitLen ) : _pchData(0), _cbData(0), _cchLen(0), _fsFlags(0) { if (!Alloc(cchInitLen+1)) return; ::memsetf( _pchData, '\0', cchInitLen ); _cchLen = 0; InitializeVers(); } NLS_STR::NLS_STR( const CHAR * pchInit ) : _pchData(0), _cbData(0), _cchLen(0), _fsFlags(0) { if (pchInit == NULL) { if (!Alloc(1)) ReportError( WN_OUT_OF_MEMORY ); else { *_pchData = '\0'; } return; } INT iSourceLen = ::strlenf( pchInit ); if ( !Alloc( iSourceLen + 1 ) ) return; ::strcpyf( _pchData, pchInit ); _cchLen = iSourceLen; InitializeVers(); } NLS_STR::NLS_STR( const NLS_STR & nlsInit ) : _pchData(0), _cbData(0), _cchLen(0), _fsFlags(0) { UIASSERT( !nlsInit.QueryError() ); if (!Alloc( nlsInit.strlen()+1 ) ) return; ::memcpyf( _pchData, nlsInit.QueryPch(), nlsInit.strlen()+1 ); _cchLen = nlsInit.strlen(); InitializeVers(); } #ifdef EXTENDED_STRINGS NLS_STR::NLS_STR( const CHAR * pchInit, INT iTotalLen ) : _pchData(0), _cbData(0), _cchLen(0), _fsFlags(0) { if (pchInit == NULL) { if (!Alloc( 1 + iTotalLen )) return; *_pchData = '\0'; } else { _cchLen = ::strlenf( pchInit ); if ( _cchLen > iTotalLen ) { _cchLen = 0; ReportError( WN_OUT_OF_MEMORY ); return; } if ( !Alloc( iTotalLen ) ) { _cchLen = 0; return; } ::memcpyf( _pchData, pchInit, _cchLen+1 ); } InitializeVers(); } #endif // EXTENDED_STRINGS NLS_STR::NLS_STR( unsigned stralloc, CHAR *pchInit, INT cbSize ) : _pchData(0), _cbData(0), _cchLen(0), _fsFlags(SF_OWNERALLOC) { UIASSERT( stralloc == STR_OWNERALLOC || stralloc == STR_OWNERALLOC_CLEAR); UIASSERT( pchInit != NULL ); if ( stralloc == STR_OWNERALLOC_CLEAR ) { UIASSERT( cbSize > 0 ); *(_pchData = pchInit ) = '\0'; _cchLen = 0; } else { _pchData = pchInit; _cchLen = ::strlenf( pchInit ); } if ( cbSize == -1 ) _cbData = _cchLen + 1; else _cbData = cbSize; InitializeVers(); } #ifdef EXTENDED_STRINGS NLS_STR::NLS_STR( unsigned stralloc, CHAR *pchBuff, INT cbSize, const CHAR *pchInit ) : _pchData(0), _cbData(0), _cchLen(0), _fsFlags(SF_OWNERALLOC) { UIASSERT( stralloc == STR_OWNERALLOC ); UIASSERT( stralloc != STR_OWNERALLOC_CLEAR ); UIASSERT( pchBuff != NULL || pchInit != NULL ); UIASSERT( cbSize > 0 && ::strlenf( pchInit ) <= cbSize ); UNREFERENCED( stralloc ); _pchData = pchBuff; INT cbToCopy = min( ::strlenf( pchInit ), cbSize - 1 ); ::memcpyf( _pchData, pchInit, cbToCopy ); *(_pchData + cbToCopy) = '\0'; _cchLen = cbToCopy; _cbData = cbSize; InitializeVers(); } #endif /******************************************************************* NAME: NLS_STR::~NLS_STR SYNOPSIS: Destructor for NLS_STR ENTRY: EXIT: Storage deallocated, if not owner-alloc HISTORY: beng 10/23/90 Created beng 07/22/91 Zeroes only in debug version ********************************************************************/ NLS_STR::~NLS_STR() { if ( !IsOwnerAlloc() ) delete _pchData; #if defined(DEBUG) _pchData = NULL; _cchLen = 0; _cbData = 0; #endif } /******************************************************************* NAME: NLS_STR::Alloc SYNOPSIS: Common code for constructors. ENTRY: cb - number of bytes desired in string storage EXIT: Returns TRUE if successful: _pchData points to allocated storage of "cb" bytes. _cbData set to cb. Allocated storage set to 0xF2 in debug version Returns FALSE upon allocation failure. NOTES: HISTORY: beng 10/23/90 Created johnl 12/11/90 Updated as per code review beng 04/26/91 Changed USHORT parm to INT ********************************************************************/ BOOL NLS_STR::Alloc( INT cb ) { UIASSERT( cb != 0 ); _pchData = new CHAR[cb]; if (_pchData == NULL) { // For now, assume not enough memory. // ReportError(WN_OUT_OF_MEMORY); return FALSE; } #ifdef DEBUG ::memsetf(_pchData, 0xf2, cb); #endif _cbData = cb; return TRUE; } /******************************************************************* NAME: NLS_STR::Reset SYNOPSIS: Attempts to clear the error state of the string ENTRY: String is in error state EXIT: If recoverable, string is correct again RETURNS: TRUE if successful; FALSE otherwise NOTES: An operation on a string may fail, if this occurs, the error flag is set and you can't use the string until the flag is cleared. By calling Reset, you can clear the flag, thus allowing you to get access to the string again. The string will be in a consistent state. Reset will return FALSE if the string couldn't be restored (for example, after construction failure). HISTORY: Johnl 12/12/90 Created ********************************************************************/ BOOL NLS_STR::Reset() { UIASSERT( QueryError() ) ; // Make sure an error exists if ( QueryError() == WN_OUT_OF_MEMORY && _pchData != NULL ) { ReportError( WN_SUCCESS ); return TRUE; } return FALSE; }