// conversion_error
class conversion_error
{};
// no_convert
template<typename dest_char, typename src_char>
class no_convert
{
private: // Нельзя использовать
no_convert(const src_char*, unsigned) {}
operator const dest_char*() const { return 0; }
unsigned size() const { return 0; }
};
// identity_convert<ch>
template<typename ch>
class identity_convert
{
public:
identity_convert(const ch* psSource, unsigned nSize) : m_psData(psSource), m_nSize(nSize) {}
operator const ch*() const { return m_psData; }
unsigned size() const { return m_nSize; }
private:
const ch* m_psData;
unsigned m_nSize;
};
// a2w_convert
class a2w_convert
{
public:
a2w_convert(const char* psSource, unsigned nSize)
{
if (nSize == 0)
{
m_nSize = 0;
m_psData = new wchar_t[0];
} else
{
unsigned nRequestedSize =
::MultiByteToWideChar(CP_ACP, 0, psSource, nSize, NULL, 0);
if (!nRequestedSize)
throw conversion_error();
m_psData = new wchar_t[nRequestedSize];
unsigned nTranslatedSize =
::MultiByteToWideChar(
CP_ACP, 0, psSource, nSize, m_psData, nRequestedSize);
if (nRequestedSize != nTranslatedSize)
{
delete[] m_psData;
throw conversion_error();
}
m_nSize = nTranslatedSize;
}
}
~a2w_convert() { delete[] m_psData; }
operator const wchar_t*() const { return m_psData; }
unsigned size() const { return m_nSize; }
private:
wchar_t* m_psData;
unsigned m_nSize;
};
// w2a_convert
class w2a_convert
{
public:
w2a_convert(const wchar_t* psSource, unsigned nSize)
{
if (nSize == 0)
{
m_nSize = 0;
m_psData = new char[0];
} else
{
unsigned nRequestedSize =
::WideCharToMultiByte(
CP_ACP, 0, psSource, nSize, NULL, 0, NULL, NULL);
if (!nRequestedSize)
throw conversion_error();
m_psData = new char[nRequestedSize];
unsigned nTranslatedSize =
::WideCharToMultiByte(
CP_ACP, 0, psSource, nSize, m_psData, nRequestedSize, NULL,
NULL);
if (nRequestedSize != nTranslatedSize)
{
delete[] m_psData;
throw conversion_error();
}
m_nSize = nTranslatedSize;
}
}
~w2a_convert() { delete[] m_psData; }
operator const char*() const { return m_psData; }
unsigned size() const { return m_nSize; }
private:
char* m_psData;
unsigned m_nSize;
};
// str_convert_traits<dest_char, src_char>
template<typename dest_char, typename src_char>
class str_convert_traits
{
public:
typedef no_convert<dest_char, src_char> convert;
};
// специализация: str_convert_traits<char, char>
template<>
class str_convert_traits<char, char>
{
public:
typedef identity_convert<char> convert;
};
// специализация: str_convert_traits<wchar_t, wchar_t>
template<>
class str_convert_traits<wchar_t, wchar_t>
{
public:
typedef identity_convert<wchar_t> convert;
};
// специализация: str_convert_traits<wchar_t, char>
template<>
class str_convert_traits<wchar_t, char>
{
public:
typedef a2w_convert convert;
};
// специализация: str_convert_traits<char, wchar_t>
template<>
class str_convert_traits<char, wchar_t>
{
public:
typedef w2a_convert convert;
};
// converting_string<string, convert>
template<typename string, typename convert>
class converting_string :
public string
{
public:
converting_string(const convert& convert) : string(convert, convert.size()) {}
};
// bstr_converting_string<string, tr>
template<typename string, typename tr = str_convert_traits<string::value_type, OLECHAR> >
class bstr_converting_string : public converting_string<string, tr::convert>
{
public:
bstr_converting_string(const OLECHAR* psSource, UINT nSourceSize) :
converting_string<string, tr::convert>(tr::convert(psSource, nSourceSize)) {}
};
////////////////////////////////////////////////////////////////////////////////
// basic_bstr_in_string<string>
template<typename string>
class basic_bstr_in_string : public bstr_converting_string<string>
{
public:
basic_bstr_in_string(BSTR bstrInParameter) : bstr_converting_string<string>(bstrInParameter, ::SysStringLen(bstrInParameter)) {}
string& operator=(const string& rhs) { return string::operator=(rhs); }
string& operator=(const string::value_type* s) { return string::operator=(s); }
string& operator=(string::value_type c) { return string::operator=(c); }
};
typedef basic_bstr_in_string<std::wstring> bstr_in_wstring;
typedef basic_bstr_in_string<std::string> bstr_in_string;
typedef basic_bstr_in_string<std::basic_string<TCHAR> > bstr_in_tstring;
////////////////////////////////////////////////////////////////////////////////
// basic_bstr_out_string<string>
template<typename string>
class basic_bstr_out_string : public string
{
public:
basic_bstr_out_string(BSTR* pbstrOutParameter, const string::value_type *s, const string::allocator_type& a = string::allocator_type()) :
m_pbstrOutParameter(pbstrOutParameter), string(s, a) {}
basic_bstr_out_string(BSTR* pbstrOutParameter, const string::value_type *s, string::size_type n, const string::allocator_type& a = string::allocator_type()) :
m_pbstrOutParameter(pbstrOutParameter), string(s, n, a) {}
basic_bstr_out_string(BSTR* pbstrOutParameter, const string& rhs) :
m_pbstrOutParameter(pbstrOutParameter), string(rhs) {}
basic_bstr_out_string(BSTR* pbstrOutParameter, const string& rhs, string::size_type pos, string::size_type n, const string::allocator_type& a = string::allocator_type()) :
m_pbstrOutParameter(pbstrOutParameter), string(rhs, pos, n, a) {}
basic_bstr_out_string(BSTR* pbstrOutParameter, string::size_type n, string::value_type c, const string::allocator_type& a = string::allocator_type()) :
m_pbstrOutParameter(pbstrOutParameter), string(n, c, a) {}
basic_bstr_out_string(BSTR* pbstrOutParameter, const string::allocator_type& a = string::allocator_type()) :
m_pbstrOutParameter(pbstrOutParameter), string(a) {}
template<typename CInIt>
basic_bstr_out_string(BSTR* pbstrOutParameter, CInIt first, CInIt last, const string::allocator_type& a = string::allocator_type()) :
m_pbstrOutParameter(pbstrOutParameter), string(first, last, a) {}
~basic_bstr_out_string()
{
if (!length())
{
*m_pbstrOutParameter = NULL;
return;
}
try
{
str_convert_traits<OLECHAR, value_type>::convert convert(
data(), length());
*m_pbstrOutParameter = ::SysAllocStringLen(convert, convert.size());
} catch (...)
{
*m_pbstrOutParameter = NULL;
}
}
string& operator=(const string& rhs) { return string::operator=(rhs); }
string& operator=(const string::value_type* s) { return string::operator=(s); }
string& operator=(string::value_type c) { return string::operator=(c); }
private:
BSTR* m_pbstrOutParameter;
};
typedef basic_bstr_out_string<std::wstring> bstr_out_wstring;
typedef basic_bstr_out_string<std::string> bstr_out_string;
typedef basic_bstr_out_string<std::basic_string<TCHAR> > bstr_out_tstring;
Впервые написано около двух лет назад, сейчас восстановлено по памяти, кажется, должно работать. "Заточено" под MSVC++. Единственное серьезное "но", как мне кажется, — традиционный для MSVC++ вопрос с bad_alloc.