blob: 182d4b0636e0910bf264fa19b7ae28209b83b04f [file] [log] [blame]
/**
* This file has no copyright assigned and is placed in the Public Domain.
* This file is part of the mingw-w64 runtime package.
* No warranty is given; refer to the file DISCLAIMER.PD within this package.
*/
#ifndef _WRL_COREWRAPPERS_H_
#define _WRL_COREWRAPPERS_H_
#include <type_traits>
#include <windows.h>
#include <intsafe.h>
#include <winstring.h>
#include <roapi.h>
/* #include <wrl/def.h> */
#include <wrl/internal.h>
namespace Microsoft {
namespace WRL {
namespace Details {
struct Dummy {};
}
namespace Wrappers {
class HStringReference;
class HString {
public:
HString() throw() : hstr_(nullptr) {}
HString(HString&& o) throw() : hstr_(o.hstr_) {
o.hstr_ = nullptr;
}
HString(const HString&) = delete;
HString& operator=(const HString&) = delete;
operator HSTRING() const throw() {
return hstr_;
}
~HString() throw() {
Release();
}
HString& operator=(HString&& o) throw() {
Release();
hstr_ = o.hstr_;
o.hstr_ = nullptr;
return *this;
}
HRESULT Set(const wchar_t *s, unsigned int l) throw() {
Release();
return ::WindowsCreateString(s, l, &hstr_);
}
template <size_t s>
HRESULT Set(const wchar_t (&str)[s]) throw() {
static_assert(static_cast<size_t>(static_cast<UINT32>(s - 1)) == s - 1, "mismatch string length");
return Set(str, s - 1);
}
template <size_t s>
HRESULT Set(wchar_t (&strRef)[s]) throw() {
const wchar_t *str = static_cast<const wchar_t *>(strRef);
unsigned int l;
HRESULT hr = SizeTToUInt32(::wcslen(str), &l);
if (SUCCEEDED(hr))
hr = Set(str, l);
return hr;
}
template <typename T>
HRESULT Set(const T& s, typename ::std::enable_if<::std::is_convertible<const T&, const wchar_t *>::value, ::Microsoft::WRL::Details::Dummy>::type = ::Microsoft::WRL::Details::Dummy()) throw() {
HRESULT hr = S_OK;
const wchar_t *str = static_cast<PCWSTR>(s);
if (str != nullptr) {
unsigned int l;
hr = SizeTToUInt32(::wcslen(str), &l);
if (SUCCEEDED(hr))
hr = Set(str, l);
}
else
hr = Set(L"", 0);
return hr;
}
HRESULT Set(const HSTRING& s) throw() {
HRESULT hr = S_OK;
if (s == nullptr || s != hstr_) {
Release();
hr = ::WindowsDuplicateString(s, &hstr_);
}
return hr;
}
void Attach(HSTRING h) throw() {
::WindowsDeleteString(hstr_);
hstr_ = h;
}
HSTRING Detach() throw() {
HSTRING t = hstr_;
hstr_ = nullptr;
return t;
}
HSTRING* GetAddressOf() throw() {
Release();
return &hstr_;
}
HSTRING* ReleaseAndGetAddressOf() throw() {
Release();
return &hstr_;
}
HSTRING Get() const throw() {
return hstr_;
}
void Release() throw() {
::WindowsDeleteString(hstr_);
hstr_ = nullptr;
}
bool IsValid() const throw() {
return hstr_ != nullptr;
}
UINT32 Length() const throw() {
return ::WindowsGetStringLen(hstr_);
}
const wchar_t* GetRawBuffer(unsigned int *l) const {
return ::WindowsGetStringRawBuffer(hstr_, l);
}
HRESULT CopyTo(HSTRING *s) const throw() {
return ::WindowsDuplicateString(hstr_, s);
}
HRESULT Duplicate(const HString& o) throw() {
HSTRING l;
HRESULT hr = ::WindowsDuplicateString(o, &l);
return ReleaseAndAssignOnSuccess(hr, l, *this);
}
bool IsEmpty() const throw() {
return hstr_ == nullptr;
}
HRESULT Concat(const HString& s, HString& n) const throw() {
HSTRING l;
HRESULT hr = ::WindowsConcatString(hstr_, s, &l);
return ReleaseAndAssignOnSuccess(hr, l, n);
}
HRESULT TrimStart(const HString& t, HString& n) const throw() {
HSTRING l;
HRESULT hr = ::WindowsTrimStringStart(hstr_, t, &l);
return ReleaseAndAssignOnSuccess(hr, l, n);
}
HRESULT TrimEnd(const HString& t, HString& n) const throw() {
HSTRING l;
HRESULT hr = ::WindowsTrimStringEnd(hstr_, t, &l);
return ReleaseAndAssignOnSuccess(hr, l, n);
}
HRESULT Substring(UINT32 s, HString& n) const throw() {
HSTRING l;
HRESULT hr = ::WindowsSubstring(hstr_, s, &l);
return ReleaseAndAssignOnSuccess(hr, l, n);
}
HRESULT Substring(UINT32 s, UINT32 len, HString& n) const throw() {
HSTRING l;
HRESULT hr = ::WindowsSubstringWithSpecifiedLength(hstr_, s, len, &l);
return ReleaseAndAssignOnSuccess(hr, l, n);
}
HRESULT Replace(const HString& s1, const HString& s2, HString& n) const throw() {
HSTRING l;
HRESULT hr = ::WindowsReplaceString(hstr_, s1, s2, &l);
return ReleaseAndAssignOnSuccess(hr, l, n);
}
template<unsigned int s>
static HStringReference MakeReference(wchar_t const (&str)[s]) throw();
template<unsigned int s>
static HStringReference MakeReference(wchar_t const (&str)[s], unsigned int l) throw();
private:
static HRESULT ReleaseAndAssignOnSuccess(HRESULT hr, HSTRING n, HString& t) {
if (SUCCEEDED(hr)) {
*t.ReleaseAndGetAddressOf() = n;
}
return hr;
}
protected:
HSTRING hstr_;
};
class HStringReference {
private:
void Init(const wchar_t* str, unsigned int len) {
HRESULT hres = ::WindowsCreateStringReference(str, len, &header_, &hstr_);
if (FAILED(hres))
::Microsoft::WRL::Details::RaiseException(hres);
}
HStringReference() : hstr_(nullptr) {}
public:
HStringReference(const wchar_t* str, unsigned int len) throw() : hstr_(nullptr) {
Init(str, len);
}
template<unsigned int sizeDest>
explicit HStringReference(wchar_t const (&str)[sizeDest]) throw() : hstr_(nullptr) {
Init(str, sizeDest - 1);
}
template <size_t sizeDest>
explicit HStringReference(wchar_t (&strRef)[sizeDest]) throw() {
const wchar_t *str = static_cast<const wchar_t*>(strRef);
Init(str, ::wcslen(str));
}
template<typename T>
explicit HStringReference(const T &strRef) throw() : hstr_(nullptr) {
const wchar_t* str = static_cast<const wchar_t*>(strRef);
size_t len = ::wcslen(str);
if(static_cast<size_t>(static_cast<unsigned int>(len)) != len)
::Microsoft::WRL::Details::RaiseException(INTSAFE_E_ARITHMETIC_OVERFLOW);
Init(str, len);
}
HStringReference(const HStringReference &other) throw() : hstr_(nullptr) {
unsigned int len = 0;
const wchar_t* value = other.GetRawBuffer(&len);
Init(value, len);
}
~HStringReference() throw() {
hstr_ = nullptr;
}
HStringReference& operator=(const HStringReference &other) throw() {
unsigned int len = 0;
const wchar_t* value = other.GetRawBuffer(&len);
Init(value, len);
return *this;
}
HSTRING Get() const throw() {
return hstr_;
}
const wchar_t *GetRawBuffer(unsigned int *len) const {
return ::WindowsGetStringRawBuffer(hstr_, len);
}
HRESULT CopyTo(HSTRING *str) const throw() {
return ::WindowsDuplicateString(hstr_, str);
}
friend class HString;
protected:
HSTRING_HEADER header_;
HSTRING hstr_;
};
class RoInitializeWrapper {
public:
RoInitializeWrapper(RO_INIT_TYPE flags) {
hres = ::Windows::Foundation::Initialize(flags);
}
~RoInitializeWrapper() {
if(SUCCEEDED(hres))
::Windows::Foundation::Uninitialize();
}
operator HRESULT() {
return hres;
}
private:
HRESULT hres;
};
}
}
}
#endif