|
|
/*++
Copyright (c) 1998 Microsoft Corporation
Module Name:
bsstring.h
Abstract:
This module defines the CBsString class. This class manages character arrays in a similar manner as the CString class in VC++. In fact, this class is a copy of the CString class with the MFC specific stuff ripped out since LTS doesn't use MTF. Added methods in addition to CString: c_str() - returns a C string pointer ala the STL string class size() - returns length of string ala the STL string class
Author:
Stefan R. Steiner [SSteiner] 1-Mar-1998
Revision History:
Stefan R. Steiner [SSteiner] 10-Apr-2000 Added fixed allocator code and resynced with MFC 6 SR-1 code
--*/
#ifndef __H_BSSTRING_
#define __H_BSSTRING_
#ifndef __cplusplus
#error requires C++ compilation
#endif
/////////////////////////////////////////////////////////////////////////////
// Other includes from standard "C" runtimes
#ifndef _INC_STRING
#include <string.h>
#endif
#ifndef _INC_STDIO
#include <stdio.h>
#endif
#ifndef _INC_STDLIB
#include <stdlib.h>
#endif
#ifndef _INC_TIME
#include <time.h>
#endif
#ifndef _INC_LIMITS
#include <limits.h>
#endif
#ifndef _INC_STDDEF
#include <stddef.h>
#endif
#ifndef _INC_STDARG
#include <stdarg.h>
#endif
#ifndef _INC_ASSERT
#include <assert.h>
#endif
#ifndef ASSERT
#define ASSERT assert
#endif
#include "bsfixalloc.h"
class CBsString;
//
// The purpose of this class is to generate a compiler error when different string classes
// are used in bad contexts (example: CBsWString used if _UNICODE is not defined)
//
// [aoltean] I introduce this small class to hide a class of LINT warnings.
//
class CBsStringErrorGenerator {}; // Private constructor
// CBsString only operates on string that are TCHAR arrays. Programs should use
// the following types to make sure they are getting what they are expecting.
#ifdef _UNICODE
#define CBsWString CBsString
#define CBsAString CBsStringErrorGenerator // trigger a compile time bug
#else
#define CBsAString CBsString
#define CBsWString CBsStringErrorGenerator // trigger a compile time bug
#endif
#include <tchar.h>
#ifndef BSAFXAPI
#define BSAFXAPI __cdecl
#define BSAFX_CDECL __cdecl
#endif
// FASTCALL is used for static member functions with little or no params
#ifndef FASTCALL
#define FASTCALL __fastcall
#endif
/////////////////////////////////////////////////////////////////////////////
// Turn off warnings for /W4
// To resume any of these warning: #pragma warning(default: 4xxx)
// which should be placed after the BSAFX include files
#ifndef ALL_WARNINGS
// warnings generated with common MFC/Windows code
#pragma warning(disable: 4127) // constant expression for TRACE/ASSERT
#pragma warning(disable: 4134) // message map member fxn casts
#pragma warning(disable: 4201) // nameless unions are part of C++
#pragma warning(disable: 4511) // private copy constructors are good to have
#pragma warning(disable: 4512) // private operator= are good to have
#pragma warning(disable: 4514) // unreferenced inlines are common
#pragma warning(disable: 4710) // private constructors are disallowed
#pragma warning(disable: 4705) // statement has no effect in optimized code
#pragma warning(disable: 4191) // pointer-to-function casting
// warnings caused by normal optimizations
#ifndef _DEBUG
#pragma warning(disable: 4701) // local variable *may* be used without init
#pragma warning(disable: 4702) // unreachable code caused by optimizations
#pragma warning(disable: 4791) // loss of debugging info in release version
#pragma warning(disable: 4189) // initialized but unused variable
#pragma warning(disable: 4390) // empty controlled statement
#endif
// warnings specific to _BSAFXDLL version
#ifdef _BSAFXDLL
#pragma warning(disable: 4204) // non-constant aggregate initializer
#endif
#ifdef _BSAFXDLL
#pragma warning(disable: 4275) // deriving exported class from non-exported
#pragma warning(disable: 4251) // using non-exported as public in exported
#endif
#endif //!ALL_WARNINGS
#ifdef _DEBUG
#define UNUSED(x)
#else
#define UNUSED(x) x
#endif
#define UNUSED_ALWAYS(x) x
/////////////////////////////////////////////////////////////////////////////
// Strings
#ifndef _OLEAUTO_H_
#ifdef OLE2ANSI
typedef LPSTR BSTR; #else
typedef LPWSTR BSTR;// must (semantically) match typedef in oleauto.h
#endif
#endif
struct CBsStringData { long nRefs; // reference count
int nDataLength; // length of data (including terminator)
int nAllocLength; // length of allocation
// TCHAR data[nAllocLength]
TCHAR* data() // TCHAR* to managed data
{ return (TCHAR*)(this+1); } };
class CBsString { public: // Constructors
// constructs empty CBsString
CBsString(); // copy constructor
CBsString(const CBsString& stringSrc); // from a single character
CBsString(TCHAR ch, int nRepeat = 1); // from an ANSI string (converts to TCHAR)
CBsString(LPCSTR lpsz); // from a UNICODE string (converts to TCHAR)
CBsString(LPCWSTR lpsz); // subset of characters from an ANSI string (converts to TCHAR)
CBsString(LPCSTR lpch, int nLength); // subset of characters from a UNICODE string (converts to TCHAR)
CBsString(LPCWSTR lpch, int nLength); // from unsigned characters
CBsString(const unsigned char* psz); CBsString(GUID guid);
// Attributes & Operations
// get data length
int GetLength() const; // TRUE if zero length
BOOL IsEmpty() const; // clear contents to empty
void Empty(); int size() const; // ala STL string class size()
// return single character at zero-based index
TCHAR GetAt(int nIndex) const; // return single character at zero-based index
TCHAR operator[](int nIndex) const; // set a single character at zero-based index
void SetAt(int nIndex, TCHAR ch); // return pointer to const string
operator LPCTSTR() const; const LPCTSTR c_str() const; // as a C string in STL string style
// overloaded assignment
// ref-counted copy from another CBsString
const CBsString& operator=(const CBsString& stringSrc); // set string content to single character
const CBsString& operator=(TCHAR ch); #ifdef _UNICODE
const CBsString& operator=(char ch); #endif
// copy string content from ANSI string (converts to TCHAR)
const CBsString& operator=(LPCSTR lpsz); // copy string content from UNICODE string (converts to TCHAR)
const CBsString& operator=(LPCWSTR lpsz); // copy string content from unsigned chars
const CBsString& operator=(const unsigned char* psz);
// string concatenation
// concatenate from another CBsString
const CBsString& operator+=(const CBsString& string);
// concatenate a single character
const CBsString& operator+=(TCHAR ch); #ifdef _UNICODE
// concatenate an ANSI character after converting it to TCHAR
const CBsString& operator+=(char ch); #endif
// concatenate a UNICODE character after converting it to TCHAR
const CBsString& operator+=(LPCTSTR lpsz);
friend CBsString BSAFXAPI operator+(const CBsString& string1, const CBsString& string2); friend CBsString BSAFXAPI operator+(const CBsString& string, TCHAR ch); friend CBsString BSAFXAPI operator+(TCHAR ch, const CBsString& string); #ifdef _UNICODE
friend CBsString BSAFXAPI operator+(const CBsString& string, char ch); friend CBsString BSAFXAPI operator+(char ch, const CBsString& string); #endif
friend CBsString BSAFXAPI operator+(const CBsString& string, LPCTSTR lpsz); friend CBsString BSAFXAPI operator+(LPCTSTR lpsz, const CBsString& string);
// string comparison
// straight character comparison
int Compare(LPCTSTR lpsz) const; // compare ignoring case
int CompareNoCase(LPCTSTR lpsz) const; // NLS aware comparison, case sensitive
int Collate(LPCTSTR lpsz) const; // NLS aware comparison, case insensitive
int CollateNoCase(LPCTSTR lpsz) const;
// simple sub-string extraction
// return nCount characters starting at zero-based nFirst
CBsString Mid(int nFirst, int nCount) const; // return all characters starting at zero-based nFirst
CBsString Mid(int nFirst) const; // return first nCount characters in string
CBsString Left(int nCount) const; // return nCount characters from end of string
CBsString Right(int nCount) const;
// characters from beginning that are also in passed string
CBsString SpanIncluding(LPCTSTR lpszCharSet) const; // characters from beginning that are not also in passed string
CBsString SpanExcluding(LPCTSTR lpszCharSet) const;
// upper/lower/reverse conversion
// NLS aware conversion to uppercase
void MakeUpper(); // NLS aware conversion to lowercase
void MakeLower(); // reverse string right-to-left
void MakeReverse();
// trimming whitespace (either side)
// remove whitespace starting from right edge
void TrimRight(); // remove whitespace starting from left side
void TrimLeft();
// trimming anything (either side)
// remove continuous occurrences of chTarget starting from right
void TrimRight(TCHAR chTarget); // remove continuous occcurrences of characters in passed string,
// starting from right
void TrimRight(LPCTSTR lpszTargets); // remove continuous occurrences of chTarget starting from left
void TrimLeft(TCHAR chTarget); // remove continuous occcurrences of characters in
// passed string, starting from left
void TrimLeft(LPCTSTR lpszTargets);
// advanced manipulation
// replace occurrences of chOld with chNew
int Replace(TCHAR chOld, TCHAR chNew); // replace occurrences of substring lpszOld with lpszNew;
// empty lpszNew removes instances of lpszOld
int Replace(LPCTSTR lpszOld, LPCTSTR lpszNew); // remove occurrences of chRemove
int Remove(TCHAR chRemove); // insert character at zero-based index; concatenates
// if index is past end of string
int Insert(int nIndex, TCHAR ch); // insert substring at zero-based index; concatenates
// if index is past end of string
int Insert(int nIndex, LPCTSTR pstr); // delete nCount characters starting at zero-based index
int Delete(int nIndex, int nCount = 1);
// searching
// find character starting at left, -1 if not found
int Find(TCHAR ch) const; // find character starting at right
int ReverseFind(TCHAR ch) const; // find character starting at zero-based index and going right
int Find(TCHAR ch, int nStart) const; // find first instance of any character in passed string
int FindOneOf(LPCTSTR lpszCharSet) const; // find first instance of substring
int Find(LPCTSTR lpszSub) const; // find first instance of substring starting at zero-based index
int Find(LPCTSTR lpszSub, int nStart) const;
// simple formatting
// printf-like formatting using passed string
void BSAFX_CDECL Format(LPCTSTR lpszFormat, ...); // printf-like formatting using variable arguments parameter
void FormatV(LPCTSTR lpszFormat, va_list argList);
#ifndef _UNICODE
// ANSI <-> OEM support (convert string in place)
// convert string from ANSI to OEM in-place
void AnsiToOem(); // convert string from OEM to ANSI in-place
void OemToAnsi(); #endif
#ifndef _BSAFX_NO_BSTR_SUPPORT
// OLE BSTR support (use for OLE automation)
// return a BSTR initialized with this CBsString's data
BSTR AllocSysString() const; // reallocates the passed BSTR, copies content of this CBsString to it
BSTR SetSysString(BSTR* pbstr) const; #endif
// Access to string implementation buffer as "C" character array
// get pointer to modifiable buffer at least as long as nMinBufLength
LPTSTR GetBuffer(int nMinBufLength); // release buffer, setting length to nNewLength (or to first nul if -1)
void ReleaseBuffer(int nNewLength = -1); // get pointer to modifiable buffer exactly as long as nNewLength
LPTSTR GetBufferSetLength(int nNewLength); // release memory allocated to but unused by string
void FreeExtra();
// Use LockBuffer/UnlockBuffer to turn refcounting off
// turn refcounting back on
LPTSTR LockBuffer(); // turn refcounting off
void UnlockBuffer();
// Implementation
public: ~CBsString(); int GetAllocLength() const;
protected: LPTSTR m_pchData; // Pointer to ref counted string data. This is actually
// a pointer to memory after the CBsStringData structure.
// implementation helpers
CBsStringData* GetData() const; void Init(); void AllocCopy(CBsString& dest, int nCopyLen, int nCopyIndex, int nExtraLen) const; void AllocBuffer(int nLen); void AssignCopy(int nSrcLen, LPCTSTR lpszSrcData); void ConcatCopy(int nSrc1Len, LPCTSTR lpszSrc1Data, int nSrc2Len, LPCTSTR lpszSrc2Data); void ConcatInPlace(int nSrcLen, LPCTSTR lpszSrcData); void CopyBeforeWrite(); void AllocBeforeWrite(int nLen); void Release(); static void PASCAL Release(CBsStringData* pData); static int PASCAL SafeStrlen(LPCTSTR lpsz); static void FASTCALL FreeData(CBsStringData* pData); };
// Compare helpers
bool BSAFXAPI operator==(const CBsString& s1, const CBsString& s2); bool BSAFXAPI operator==(const CBsString& s1, LPCTSTR s2); bool BSAFXAPI operator==(LPCTSTR s1, const CBsString& s2); bool BSAFXAPI operator!=(const CBsString& s1, const CBsString& s2); bool BSAFXAPI operator!=(const CBsString& s1, LPCTSTR s2); bool BSAFXAPI operator!=(LPCTSTR s1, const CBsString& s2); bool BSAFXAPI operator<(const CBsString& s1, const CBsString& s2); bool BSAFXAPI operator<(const CBsString& s1, LPCTSTR s2); bool BSAFXAPI operator<(LPCTSTR s1, const CBsString& s2); bool BSAFXAPI operator>(const CBsString& s1, const CBsString& s2); bool BSAFXAPI operator>(const CBsString& s1, LPCTSTR s2); bool BSAFXAPI operator>(LPCTSTR s1, const CBsString& s2); bool BSAFXAPI operator<=(const CBsString& s1, const CBsString& s2); bool BSAFXAPI operator<=(const CBsString& s1, LPCTSTR s2); bool BSAFXAPI operator<=(LPCTSTR s1, const CBsString& s2); bool BSAFXAPI operator>=(const CBsString& s1, const CBsString& s2); bool BSAFXAPI operator>=(const CBsString& s1, LPCTSTR s2); bool BSAFXAPI operator>=(LPCTSTR s1, const CBsString& s2);
// conversion helpers
int BSAFX_CDECL _wcstombsz(char* mbstr, const wchar_t* wcstr, size_t count); int BSAFX_CDECL _mbstowcsz(wchar_t* wcstr, const char* mbstr, size_t count);
// valid address test helpers
BOOL BSAFXAPI BsAfxIsValidString(LPCWSTR lpsz, int nLength = -1); BOOL BSAFXAPI BsAfxIsValidString(LPCSTR lpsz, int nLength = -1); BOOL BSAFXAPI BsAfxIsValidAddress(const void* lp, UINT nBytes, BOOL bReadWrite = TRUE);
// Globals
extern TCHAR bsafxChNil; const CBsString& BSAFXAPI BsAfxGetEmptyString(); #define bsafxEmptyString BsAfxGetEmptyString()
inline CBsStringData* CBsString::GetData() const { ASSERT(m_pchData != NULL); return ((CBsStringData*)m_pchData)-1; } inline void CBsString::Init() { m_pchData = bsafxEmptyString.m_pchData; } inline CBsString::CBsString(const unsigned char* lpsz) { Init(); *this = (LPCSTR)lpsz; } inline const CBsString& CBsString::operator=(const unsigned char* lpsz) { *this = (LPCSTR)lpsz; return *this; } #ifdef _UNICODE
inline const CBsString& CBsString::operator+=(char ch) { *this += (TCHAR)ch; return *this; } inline const CBsString& CBsString::operator=(char ch) { *this = (TCHAR)ch; return *this; } inline CBsString BSAFXAPI operator+(const CBsString& string, char ch) { return string + (TCHAR)ch; } inline CBsString BSAFXAPI operator+(char ch, const CBsString& string) { return (TCHAR)ch + string; } #endif
inline int CBsString::GetLength() const { return GetData()->nDataLength; } inline int CBsString::size() const { return GetData()->nDataLength; } inline int CBsString::GetAllocLength() const { return GetData()->nAllocLength; } inline BOOL CBsString::IsEmpty() const { return GetData()->nDataLength == 0; } inline CBsString::operator LPCTSTR() const { return m_pchData; } inline const LPCTSTR CBsString::c_str() const { return m_pchData; } inline int PASCAL CBsString::SafeStrlen(LPCTSTR lpsz) { return (lpsz == NULL) ? 0 : lstrlen(lpsz); }
// CBsString support (windows specific)
inline int CBsString::Compare(LPCTSTR lpsz) const { ASSERT(BsAfxIsValidString(lpsz)); return _tcscmp(m_pchData, lpsz); } // MBCS/Unicode aware
inline int CBsString::CompareNoCase(LPCTSTR lpsz) const { ASSERT(BsAfxIsValidString(lpsz)); return _tcsicmp(m_pchData, lpsz); } // MBCS/Unicode aware
// CBsString::Collate is often slower than Compare but is MBSC/Unicode
// aware as well as locale-sensitive with respect to sort order.
inline int CBsString::Collate(LPCTSTR lpsz) const { ASSERT(BsAfxIsValidString(lpsz)); return _tcscoll(m_pchData, lpsz); } // locale sensitive
inline int CBsString::CollateNoCase(LPCTSTR lpsz) const { ASSERT(BsAfxIsValidString(lpsz)); return _tcsicoll(m_pchData, lpsz); } // locale sensitive
inline TCHAR CBsString::GetAt(int nIndex) const { ASSERT(nIndex >= 0); ASSERT(nIndex < GetData()->nDataLength); return m_pchData[nIndex]; } inline TCHAR CBsString::operator[](int nIndex) const { // same as GetAt
ASSERT(nIndex >= 0); ASSERT(nIndex < GetData()->nDataLength); return m_pchData[nIndex]; } inline bool BSAFXAPI operator==(const CBsString& s1, const CBsString& s2) { return s1.Compare(s2) == 0; } inline bool BSAFXAPI operator==(const CBsString& s1, LPCTSTR s2) { return s1.Compare(s2) == 0; } inline bool BSAFXAPI operator==(LPCTSTR s1, const CBsString& s2) { return s2.Compare(s1) == 0; } inline bool BSAFXAPI operator!=(const CBsString& s1, const CBsString& s2) { return s1.Compare(s2) != 0; } inline bool BSAFXAPI operator!=(const CBsString& s1, LPCTSTR s2) { return s1.Compare(s2) != 0; } inline bool BSAFXAPI operator!=(LPCTSTR s1, const CBsString& s2) { return s2.Compare(s1) != 0; } inline bool BSAFXAPI operator<(const CBsString& s1, const CBsString& s2) { return s1.Compare(s2) < 0; } inline bool BSAFXAPI operator<(const CBsString& s1, LPCTSTR s2) { return s1.Compare(s2) < 0; } inline bool BSAFXAPI operator<(LPCTSTR s1, const CBsString& s2) { return s2.Compare(s1) > 0; } inline bool BSAFXAPI operator>(const CBsString& s1, const CBsString& s2) { return s1.Compare(s2) > 0; } inline bool BSAFXAPI operator>(const CBsString& s1, LPCTSTR s2) { return s1.Compare(s2) > 0; } inline bool BSAFXAPI operator>(LPCTSTR s1, const CBsString& s2) { return s2.Compare(s1) < 0; } inline bool BSAFXAPI operator<=(const CBsString& s1, const CBsString& s2) { return s1.Compare(s2) <= 0; } inline bool BSAFXAPI operator<=(const CBsString& s1, LPCTSTR s2) { return s1.Compare(s2) <= 0; } inline bool BSAFXAPI operator<=(LPCTSTR s1, const CBsString& s2) { return s2.Compare(s1) >= 0; } inline bool BSAFXAPI operator>=(const CBsString& s1, const CBsString& s2) { return s1.Compare(s2) >= 0; } inline bool BSAFXAPI operator>=(const CBsString& s1, LPCTSTR s2) { return s1.Compare(s2) >= 0; } inline bool BSAFXAPI operator>=(LPCTSTR s1, const CBsString& s2) { return s2.Compare(s1) <= 0; }
#endif // __H_BSSTRING_
|