//----------------------------------------------------------------------------
// Borland WinSys Library
// Copyright (c) 1994, 1996 by Borland International, All Rights Reserved
//
/// \file
/// Definition of class TString, a flexible universal string envelope class.
/// Facilitates efficient construction and assignment of many string types
//----------------------------------------------------------------------------
#if !defined(OWL_STRING_H)
#define OWL_STRING_H
#include <owl/private/defs.h>
#if defined(BI_HAS_PRAGMA_ONCE)
# pragma once
#endif
#include <owl/private/ole2inc.h>
#include <owl/private/memory.h>
#include <owl/module.h>
#include <owl/lclstrng.h>
namespace owl {
/// \cond NoSuppressDoxygenWarning
#include <owl/preclass.h>
/// \endcond
//
/// \class TSysStr
// ~~~~~ ~~~~~~~
/// System string (BSTR) encapsulation. Also gives BSTRs a unique type
/// Always assumes ownership of the BSTR, use Relinquish to take BSTR away.
//
class _OWLCLASS TSysStr {
public:
TSysStr() : P(0) {}
TSysStr(const BSTR p) : P(p) {}
TSysStr(const TSysStr& src) : P(TOleAuto::SysAllocString(src.P)) {}
~TSysStr() {if (P) TOleAuto::SysFreeString(P);}
int operator !() const {return P == 0;}
operator const BSTR() const {return P;}
operator BSTR() {return P;}
TSysStr& operator =(BSTR p) {if (P) TOleAuto::SysFreeString(P); P = p; return *this;}
operator BSTR *() {if (P) {TOleAuto::SysFreeString(P); P = 0;} return &P;}
BSTR Relinquish() {BSTR p = P; P = 0; return p;}
protected:
BSTR P;
private:
void* operator new(size_t) noexcept {return nullptr;} // prohibit use of new, delete, etc
void operator delete(void*) {}
};
class _OWLCLASS TUString;
//
/// \class TString
// ~~~~~ ~~~~~~~
/// Reference to reference counted string object TUString
/// Lightweight reference object consisting of a pointer to actual object
/// Facilitates copying and assignment with minimal string reallocations
//
class _OWLCLASS TString {
public:
/// Construct a TString from any type of string
// !CQ the assumption that a const char* is non-volatile is bogus!
//
TString(const char * s = 0);
TString(const wchar_t* s);
TString(BSTR s, bool loan);
TString(TSysStr& s, bool loan);
TString(const tstring& s);
TString(TUString* s);
TString(const TString& src);
~TString();
// Information
//
int Length() const; ///< The length in characters of this string
bool IsNull() const; ///< Is the string NULL?
bool IsWide() const; ///< Are the string contents any kind of wide?
// Assign any type of string into this TString
//
TString& operator =(const TString& s);
TString& operator =(const tstring& s);
TString& operator =(const char * s);
TString& operator =(char* s);
TString& operator =(const wchar_t* s);
TString& operator =(wchar_t* s);
// Convert this TString into the desired string type & return pointer into
// this TString
//
operator const char *() const;
operator char*();
operator const wchar_t*() const;
operator wchar_t*();
BSTR AsBSTR() const;
// Relinquish ownership and return contents of this TString. Caller then
// owns the string & must delete or free it.
// !CQ currently returns a copy & then frees its copy on destruction
//
BSTR RelinquishSysStr() const;
wchar_t* RelinquishWide() const;
char* RelinquishNarrow() const;
tchar* Relinquish() const;
// Language related
//
TLangId GetLangId();
void SetLangId(TLangId id);
protected:
TUString* S;
};
//
// Provide ANSI to Wide conversion when OLE requires wide chars
// Allocate a unicode BSTR from an ANSI char*
//
# define OleStr(s) ::owl::TString(s)
# define OleText(s) L##s
inline BSTR SysAllocString(const char * str) {
return TOleAuto::SysAllocString((wchar_t*)(const wchar_t*)TString(str));
}
//----------------------------------------------------------------------------
//
/// \class TUString
// ~~~~~ ~~~~~~~~
/// Privately used by TString to manage string pointers
/// This is a reference counted union of various string representatons
/// Constructors/destructors are private to enforce reference count model
/// Create functions are used to facilitate rapid allocation schemes
/// Null pointers are never stored; instead a static null object is ref'd
//
class _OWLCLASS TUString {
public:
static TUString* Create(const char * str);
static TUString* Create(char* str);
static TUString* Create(const wchar_t* str);
static TUString* Create(wchar_t* str);
static TUString* Create(TSysStr& str, bool loan, TLangId lang = 0);
static TUString* Create(BSTR str, bool loan, TLangId lang = 0);
static TUString* Create(const tstring& str);
TUString* Assign(const TUString& s);
TUString* Assign(const tstring& s);
TUString* Assign(const char * s);
TUString* Assign(char* s);
TUString* Assign(const wchar_t* s);
TUString* Assign(wchar_t* s);
TUString* Assign(BSTR str, TLangId lang);
operator const char *() const;
operator char*();
operator const wchar_t*() const;
operator wchar_t*();
TUString& operator ++(); ///< Preincrement operator only
TUString& operator --(); ///< Predecrement operator only
int Length() const; ///< Return appropriate string length
bool IsNull() const; ///< Is the string a null string?
bool IsWide() const; ///< Are the string contents any kind of wide?
TLangId Lang;
void RevokeBstr(BSTR s); ///< Used to restore if Created with loan==true
void ReleaseBstr(BSTR s); ///< Used to unhook if Created with loan==true
static wchar_t* ConvertAtoW(const char* src, size_t len = (size_t)-1);
static char* ConvertWtoA(const wchar_t* src, size_t len = (size_t)-1);
static BSTR ConvertAtoBSTR(const char* src);
BSTR ConvertToBSTR();
#if defined(BI_COMP_MSC) // MSC can't handle the dtor being private
public:
#else
private:
#endif
~TUString() {Free();}
private:
// !CQ the assumption that a const char* is non-volatile is bogus!
TUString(const char & str);
TUString(char& str);
TUString(const wchar_t& str);
TUString(wchar_t& str);
TUString(TSysStr& str, bool loan, TLangId lang);
TUString(BSTR str, bool loan, TLangId lang);
TUString(const tstring& str);
void Free();
tstring& GetOWLString();
const tstring& GetOWLString() const;
void AllocOWLString(const tstring& as);
char* ChangeToCopy();
wchar_t* ChangeToWCopy();
enum TKind {
isNull,
isConst, isCopy,
isWConst, isWCopy,
isBstr, isExtBstr,
isString,
#if 0 // if alighn greater then 2
} Kind : 16;
int16 RefCnt;
#else
} Kind;
int RefCnt;
#endif
union {
const char * Const; ///< Passed-in string, NOT owned here, read-only
char* Copy; ///< Local copy, must be deleted, read-write
const wchar_t* WConst; ///< Unicode version of Const (Win32)
wchar_t* WCopy; ///< Unicode version of Copy (Win32)
BSTR Bstr; ///< Copy of pointer, owned here
char StringMem[sizeof(tstring)]; ///< Placeholder for string:: object
};
static TUString Null; // Null TString references this
TUString() : Lang(0),Kind(isNull),RefCnt(1),Const(0) {} // for Null object
friend class TString; // Envelope string class
};
/// \cond NoSuppressDoxygenWarning
#include <owl/posclass.h>
/// \endcond
//----------------------------------------------------------------------------
// Inlines
//
//
/// Construct a TString from a character array
//
inline TString::TString(const char * s)
:
S(TUString::Create(s))
{
}
//
/// Construct a TString from a wide character array
//
inline TString::TString(const wchar_t* s)
:
S(TUString::Create(s))
{
}
//
/// Construct a TString from a BSTR (OLE String)
//
inline TString::TString(BSTR s, bool loan)
:
S(TUString::Create(s, loan))
{
}
//
/// Construct a TString from a System string (BSTR)
//
inline TString::TString(TSysStr& s, bool loan)
:
S(TUString::Create(s, loan))
{
}
//
/// Construct a TString from a string
//
inline TString::TString(const tstring& s)
:
S(TUString::Create(s))
{
}
//
/// Construct a TString from a TUString
//
inline TString::TString(TUString* s)
:
S(s)
{
}
//
/// Construct a TString from a TString (Copy Constructor)
//
inline TString::TString(const TString& src)
:
S(src.S)
{
++*S;
}
//
// Destruct a TString (actually decrements a reference counter)
//
inline TString::~TString()
{
--*S;
}
//
// Return the length of the string
//
inline int TString::Length() const
{
return S->Length();
}
//
/// Return true if string is empty
//
inline bool TString::IsNull() const
{
return S->IsNull();
}
//
/// Return true if string uses wide character set
//
inline bool TString::IsWide() const
{
return S->IsWide();
}
//
/// Copy contents of TString s into this string
//
inline TString& TString::operator =(const TString& s)
{
S = S->Assign(*s.S); return *this;
}
//
/// Copy contents of string s into this string
//
inline TString& TString::operator =(const tstring& s)
{
S = S->Assign(s); return *this;
}
//
/// Copy contents of const char* s into this string
//
inline TString& TString::operator =(const char * s)
{
S = S->Assign(s); return *this;
}
//
/// Copy contents of char* s into this string
//
inline TString& TString::operator =(char* s)
{
S = S->Assign(s); return *this;
}
//
/// Copy contents of const wchar_t* s into this string
//
inline TString& TString::operator =(const wchar_t* s)
{
S = S->Assign(s); return *this;
}
//
/// Copy contents of wchar_t* s into this string
//
inline TString& TString::operator =(wchar_t* s)
{
S = S->Assign(s); return *this;
}
//
/// Return string as a const char *
//
inline TString::operator const char *() const
{
return S->operator const char *();
}
//
/// Return string as a char*
//
inline TString::operator char*()
{
return S->operator char*();
}
//
/// Return string as a const wchar_t*
//
inline TString::operator const wchar_t*() const
{
return S->operator const wchar_t*();
}
//
/// Return string as a wchar_t*
//
inline TString::operator wchar_t*()
{
return S->operator wchar_t*();
}
//
/// Return a BSTR object owned by 'this' (not by the caller)
//
inline BSTR TString::AsBSTR() const
{
return S->ConvertToBSTR();
}
//
/// Return a pointer (BSTR) to a copy of the string
//
inline BSTR TString::RelinquishSysStr() const
{
return TOleAuto::SysAllocString((wchar_t*)(const wchar_t*)*S);
}
//
/// Return a pointer (wchar_t*) to a copy of the string
//
inline wchar_t* TString::RelinquishWide() const
{
return strnewdup((const wchar_t*)*S);
}
//
/// Return a pointer (char*) to a copy of the string
//
inline char* TString::RelinquishNarrow() const
{
return strnewdup((const char*)*S);
}
//
/// Return a pointer (tchar*) to a copy of the string
//
inline tchar* TString::Relinquish() const
{
#if !defined(UNICODE)
return RelinquishNarrow();
#else
return RelinquishWide();
#endif
}
//
/// Get Language Id of this string
//
inline TLangId TString::GetLangId()
{
return S->Lang;
}
//
/// Set Language Id of this string
//
inline void TString::SetLangId(TLangId id)
{
S->Lang = id;
}
//----------------------------------------------------------------------------
//
/// Increment reference counter for this string
//
inline TUString& TUString::operator ++()
{
++RefCnt;
return *this;
}
//
/// Decrement reference counter for this string
//
inline TUString& TUString::operator --()
{
if (--RefCnt != 0)
return *this;
delete this;
return Null;
}
//
/// Return true if string is empty
//
inline bool TUString::IsNull() const
{
return Kind == isNull;
}
//
/// Return true if string uses wide character set
//
inline bool TUString::IsWide() const
{
return Kind == isWConst || Kind == isWCopy || Kind == isBstr || Kind == isExtBstr;
}
inline tstring& TUString::GetOWLString()
{
CHECK(Kind == isString);
return *reinterpret_cast<tstring*>(StringMem);
}
inline const tstring& TUString::GetOWLString() const
{
CHECK(Kind == isString);
return *reinterpret_cast<const tstring*>(StringMem);
}
inline void TUString::AllocOWLString(const tstring& as)
{
new(StringMem) tstring(as);
}
} // OWL namespace
#endif // OWL_STRING_H
↑ V690 The 'TSysStr' class implements a copy constructor, but lacks the copy assignment operator. It is dangerous to use such a class.