From 76424950e373d3b04ac3dd13019151bfba3e8423 Mon Sep 17 00:00:00 2001 From: sumuel Date: Mon, 17 Aug 2026 20:44:55 +0000 Subject: Add the files --- src/common/windows/variant.hpp | 164 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 src/common/windows/variant.hpp (limited to 'src/common/windows/variant.hpp') diff --git a/src/common/windows/variant.hpp b/src/common/windows/variant.hpp new file mode 100644 index 0000000..58e46b7 --- /dev/null +++ b/src/common/windows/variant.hpp @@ -0,0 +1,164 @@ +#include +#include +#include +#include +#include +#include +#include + +template +struct FFBaseVariant : TVariant { + bool hasValue() { + return this->vt != VT_EMPTY; + } + + explicit operator bool() { + return this->hasValue(); + } + + template + T get() { + // boolean + if constexpr (std::is_same_v) { + assert(this->vt == VT_BOOL); + return this->boolVal != VARIANT_FALSE; + } + + // signed + else if constexpr (std::is_same_v) { + assert(this->vt == VT_I1); + return this->cVal; + } else if constexpr (std::is_same_v) { + assert(this->vt == VT_I2); + return this->iVal; + } else if constexpr (std::is_same_v) { + assert(this->vt == VT_I4 || this->vt == VT_INT); + return this->intVal; + } else if constexpr (std::is_same_v) { + assert(this->vt == VT_I8); + return this->llVal; + } + + // unsigned + else if constexpr (std::is_same_v) { + assert(this->vt == VT_UI1); + return this->bVal; + } else if constexpr (std::is_same_v) { + assert(this->vt == VT_UI2); + return this->uiVal; + } else if constexpr (std::is_same_v) { + assert(this->vt == VT_UI4 || this->vt == VT_UINT); + return this->uintVal; + } else if constexpr (std::is_same_v) { + assert(this->vt == VT_UI8); + return this->ullVal; + } + + // decimal + else if constexpr (std::is_same_v) { + assert(this->vt == VT_R4); + return this->fltVal; + } else if constexpr (std::is_same_v) { + assert(this->vt == VT_R8); + return this->dblVal; + } + + // string + else if constexpr (std::is_same_v) { + assert(this->vt == VT_LPSTR); + return this->pcVal; + } else if constexpr (std::is_same_v) { + assert(this->vt == VT_BSTR || this->vt == VT_LPWSTR); + if (this->vt == VT_LPWSTR) { + return this->bstrVal; + } else { + return { this->bstrVal, SysStringLen(this->bstrVal) }; + } + } + + // array signed + else if constexpr (std::is_same_v>) { + assert(this->vt & VT_ARRAY); + assert((this->vt & ~VT_ARRAY) == VT_I1); + return std::make_pair((int8_t*) this->parray->pvData, this->parray->cDims); + } else if constexpr (std::is_same_v>) { + assert(this->vt & VT_ARRAY); + assert((this->vt & ~VT_ARRAY) == VT_I2); + return std::make_pair((int16_t*) this->parray->pvData, this->parray->cDims); + } else if constexpr (std::is_same_v>) { + assert(this->vt & VT_ARRAY); + assert((this->vt & ~VT_ARRAY) == VT_I4); + return std::make_pair((int32_t*) this->parray->pvData, this->parray->cDims); + } else if constexpr (std::is_same_v>) { + assert(this->vt & VT_ARRAY); + assert((this->vt & ~VT_ARRAY) == VT_I8); + return std::make_pair((int64_t*) this->parray->pvData, this->parray->cDims); + } + + // array unsigned + else if constexpr (std::is_same_v>) { + assert(this->vt & VT_ARRAY); + assert((this->vt & ~VT_ARRAY) == VT_UI1); + return std::make_pair((uint8_t*) this->parray->pvData, this->parray->cDims); + } else if constexpr (std::is_same_v>) { + assert(this->vt & VT_ARRAY); + assert((this->vt & ~VT_ARRAY) == VT_UI2); + return std::make_pair((uint16_t*) this->parray->pvData, this->parray->cDims); + } else if constexpr (std::is_same_v>) { + assert(this->vt & VT_ARRAY); + assert((this->vt & ~VT_ARRAY) == VT_UI4); + return std::make_pair((uint32_t*) this->parray->pvData, this->parray->cDims); + } else if constexpr (std::is_same_v>) { + assert(this->vt & VT_ARRAY); + assert((this->vt & ~VT_ARRAY) == VT_UI8); + return std::make_pair((uint64_t*) this->parray->pvData, this->parray->cDims); + } else { + assert(false && "unsupported type"); + __builtin_unreachable(); + } + } +}; + +struct FFWmiVariant : FFBaseVariant { + FFWmiVariant(const FFWmiVariant&) = delete; + FFWmiVariant(FFWmiVariant&&); // don't define it to enforce NRVO optimization + explicit FFWmiVariant() { + VariantInit(this); + } + explicit FFWmiVariant(std::initializer_list strings); + ~FFWmiVariant() { + VariantClear(this); + } +}; +static_assert(sizeof(FFWmiVariant) == sizeof(VARIANT), ""); + +struct FFPropVariant : FFBaseVariant { + FFPropVariant(const FFPropVariant&) = delete; + FFPropVariant(FFPropVariant&&); // don't define it to enforce NRVO optimization + explicit FFPropVariant() { + PropVariantInit(this); + } + ~FFPropVariant() { + PropVariantClear(this); + } +}; +static_assert(sizeof(FFPropVariant) == sizeof(PROPVARIANT), ""); + +namespace { +// Provide our bstr_t to avoid libstdc++ dependency +struct bstr_t { + explicit bstr_t(const wchar_t* str) noexcept : _bstr(SysAllocString(str)) {} + ~bstr_t(void) noexcept { + SysFreeString(_bstr); + } + explicit operator const wchar_t*(void) const noexcept { + return _bstr; + } + operator BSTR(void) const noexcept { + return _bstr; + } + + private: + BSTR _bstr; +}; +} // namespace -- cgit v1.2.3