mirror of https://github.com/tongzx/nt5src
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
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
|