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.
 
 
 
 
 
 

324 lines
5.8 KiB

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1999 - 1999
//
// File: combstr.h
//
//--------------------------------------------------------------------------
#ifndef COMBSTR_H
#define COMBSTR_H
#ifndef BOOL_H
#include <bool.h>
#endif
#ifndef STRCONV_H
#include <strconv.h>
#endif
namespace microsoft {
namespace com {
class bstr
//REVIEW: need to add support for copy-on-write iterators.
{
public: bstr() throw()
: m_Data(NULL)
{
}
public: bstr(const bstr& s) throw()
: m_Data(s.m_Data)
{
_AddRef();
}
public: bstr(const char* s) throw()
: m_Data(new Data(s))
{
ASSERT(m_Data);
}
public: bstr(const wchar_t* s) throw()
: m_Data(new Data(s))
{
}
public: ~bstr() throw()
{
_Free();
}
public: bstr& operator=(const bstr& s) throw()
{
_Free();
m_Data = s.m_Data;
_AddRef();
return *this;
}
public: bstr& operator=(const char* s) throw()
{
_Free();
m_Data = new Data(s);
return *this;
}
public: bstr& operator=(const wchar_t* s) throw()
{
_Free();
m_Data = new Data(s);
return *this;
}
public: bstr& operator+=(const bstr& s) throw()
{
Data* newData = new Data(*this, s);
ASSERT(newData);
_Free();
m_Data = newData;
return *this;
}
public: bstr operator+(const bstr& s) const throw()
{
bstr b = *this;
b += s;
return b;
}
public: operator const wchar_t*() const throw()
{
return m_Data ? m_Data->GetWString() : NULL;
}
public: operator const char*() const throw()
{
return m_Data ? m_Data->GetString() : NULL;
}
public: bool operator!() const throw()
{
return m_Data ? !m_Data->GetWString() : true;
}
public: bool operator==(const bstr& str) const throw()
{
return _Compare(str) == 0;
}
public: bool operator!=(const bstr& str) const throw()
{
return _Compare(str) != 0;
}
public: bool operator<(const bstr& str) const throw()
{
return _Compare(str) < 0;
}
public: bool operator>(const bstr& str) const throw()
{
return _Compare(str) > 0;
}
public: bool operator<=(const bstr& str) const throw()
{
return _Compare(str) <= 0;
}
public: bool operator>=(const bstr& str) const throw()
{
return _Compare(str) >= 0;
}
public: BSTR copy() const throw()
{
return m_Data ? m_Data->Copy() : NULL;
}
public: unsigned int length() const throw()
{
return m_Data ? m_Data->length() : 0;
}
//REVIEW: create size(of)()
private: class Data
{
public: Data(const char* s) throw()
: m_str(NULL), m_RefCount(1)
{
if (s)
{
m_wstr = str2BSTR(s);
ASSERT(m_wstr);
}
else m_wstr = NULL;
}
public: Data(const wchar_t* s) throw()
: m_str(NULL), m_RefCount(1)
{
if (s)
{
m_wstr = wcs2BSTR(s);
ASSERT(m_wstr);
}
else m_wstr = NULL;
}
public: Data(const bstr& s1, const bstr& s2)
: m_str(NULL), m_RefCount(1)
{
const unsigned int l1 = s1.length();
const unsigned int l2 = s2.length();
m_wstr=SysAllocStringLen(s1, l1+l2);
ASSERT(m_wstr);
memcpy(m_wstr+l1, static_cast<const wchar_t*>(s2), l2+1);
}
public: unsigned long AddRef() throw()
{
ASSERT(m_RefCount);
InterlockedIncrement(reinterpret_cast<long*>(&m_RefCount));
return m_RefCount;
}
public: unsigned long Release() throw()
{
ASSERT(m_RefCount);
//REVIEW: may not want InterlockedDecrement for simple speed cases?
if (!InterlockedDecrement(reinterpret_cast<long*>(&m_RefCount)))
delete this;
return m_RefCount;
}
public: operator const wchar_t*() const throw()
{
return m_wstr;
}
public: operator const char*() const throw()
{
return GetString();
}
public: const wchar_t* GetWString() const throw()
{
return m_wstr;
}
public: const char* GetString() const throw()
{
if (!m_str && m_wstr)
{
USES_STRCONV;
const unsigned int len=SysStringLen(m_wstr)+1;
#if _MSC_VER >= 1100
m_str = new char[len];
ASSERT(m_str);
memcpy(m_str, WCS2STR(m_wstr), len);
#else //REVIEW: Strip after v5 ships
const_cast<Data*>(this)->m_str = new char[len];
ASSERT(m_str);
memcpy(const_cast<Data*>(this)->m_str, WCS2STR(m_wstr), len);
#endif // _MSC_VER >= 1100
}
return m_str;
}
public: BSTR Copy() const throw()
{
return m_wstr ? SysAllocStringLen(m_wstr, SysStringLen(m_wstr)) : NULL;
}
public: unsigned int length()
{
return m_wstr ? SysStringLen(m_wstr) : 0;
}
private: wchar_t* m_wstr;
private: mutable char* m_str;
private: unsigned long m_RefCount;
private: Data()
// Never allow default construction
{
}
private: Data(const Data& s) throw()
// Never allow copy
: m_str(NULL), m_RefCount(1)
{
if (s.m_wstr)
{
m_wstr = SysAllocStringLen(s.m_wstr, SysStringLen(s.m_wstr));
ASSERT(m_wstr);
}
else m_wstr = NULL;
}
private: ~Data()
// Prevent deletes from outside. Release() must be used.
// ASSERT if the count is not 0
{
ASSERT(!m_RefCount);
_Free();
}
private: void _Free()
{
if (m_wstr)
SysFreeString(m_wstr);
if (m_str)
delete m_str;
}
}; // class Data
private: Data* m_Data;
private: void _AddRef()
{
if (m_Data)
m_Data->AddRef();
}
private: void _Free() throw()
{
if (m_Data)
{
m_Data->Release();
m_Data = NULL;
}
}
private: int _Compare(const bstr& str) const throw()
{
if (m_Data == str.m_Data)
return 0;
if (!m_Data && str.m_Data)
return -1;
if (m_Data && !str.m_Data)
return 1;
#ifndef OLE2ANSI
return wcscmp(*m_Data, str);
#else
return strcmp(*m_Data, str);
#endif
}
}; // class bstr
} // namespace com
} // namespace microsoft
#ifndef MICROSOFT_NAMESPACE_ON
using namespace microsoft;
#ifndef COM_NAMESPACE_ON
using namespace com;
#endif // COM_NAMESPACE_ON
#endif // MICROSOFT_NAMESPACE_ON
#endif // COMBSTR_H