| /* |
| * Copyright (C) 2007, 2008 Apple Inc. All Rights Reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
| * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #ifndef COMVariantSetter_h |
| #define COMVariantSetter_h |
| |
| #include <WebCore/BString.h> |
| #include <WebCore/COMPtr.h> |
| #include <wtf/Assertions.h> |
| #include <wtf/Forward.h> |
| #include <wtf/Vector.h> |
| |
| template<typename T> struct COMVariantSetter {}; |
| |
| template<typename T> struct COMVariantSetterBase |
| { |
| static inline VARENUM variantType(const T&) |
| { |
| return COMVariantSetter<T>::VariantType; |
| } |
| }; |
| |
| template<> struct COMVariantSetter<WTF::String> : COMVariantSetterBase<WTF::String> |
| { |
| static const VARENUM VariantType = VT_BSTR; |
| |
| static void setVariant(VARIANT* variant, const WTF::String& value) |
| { |
| ASSERT(V_VT(variant) == VT_EMPTY); |
| |
| V_VT(variant) = VariantType; |
| V_BSTR(variant) = WebCore::BString(value).release(); |
| } |
| }; |
| |
| template<> struct COMVariantSetter<bool> : COMVariantSetterBase<bool> |
| { |
| static const VARENUM VariantType = VT_BOOL; |
| |
| static void setVariant(VARIANT* variant, bool value) |
| { |
| ASSERT(V_VT(variant) == VT_EMPTY); |
| |
| V_VT(variant) = VariantType; |
| V_BOOL(variant) = value; |
| } |
| }; |
| |
| template<> struct COMVariantSetter<unsigned long long> : COMVariantSetterBase<unsigned long long> |
| { |
| static const VARENUM VariantType = VT_UI8; |
| |
| static void setVariant(VARIANT* variant, unsigned long long value) |
| { |
| ASSERT(V_VT(variant) == VT_EMPTY); |
| |
| V_VT(variant) = VariantType; |
| V_UI8(variant) = value; |
| } |
| }; |
| |
| template<> struct COMVariantSetter<int> : COMVariantSetterBase<int> |
| { |
| static const VARENUM VariantType = VT_I4; |
| |
| static void setVariant(VARIANT* variant, int value) |
| { |
| ASSERT(V_VT(variant) == VT_EMPTY); |
| |
| V_VT(variant) = VariantType; |
| V_I4(variant) = value; |
| } |
| }; |
| |
| template<> struct COMVariantSetter<float> : COMVariantSetterBase<float> |
| { |
| static const VARENUM VariantType = VT_R4; |
| |
| static void setVariant(VARIANT* variant, float value) |
| { |
| ASSERT(V_VT(variant) == VT_EMPTY); |
| |
| V_VT(variant) = VariantType; |
| V_R4(variant) = value; |
| } |
| }; |
| |
| template<typename T> struct COMVariantSetter<COMPtr<T> > : COMVariantSetterBase<COMPtr<T> > |
| { |
| static const VARENUM VariantType = VT_UNKNOWN; |
| |
| static void setVariant(VARIANT* variant, const COMPtr<T>& value) |
| { |
| ASSERT(V_VT(variant) == VT_EMPTY); |
| |
| V_VT(variant) = VariantType; |
| V_UNKNOWN(variant) = value.get(); |
| value->AddRef(); |
| } |
| }; |
| |
| template<typename T> struct COMVariantSetter<Vector<T>> : COMVariantSetterBase<Vector<T>> { |
| static const VARTYPE VariantType = VT_ARRAY | COMVariantSetter<T>::VariantType; |
| |
| static void setVariant(VARIANT* variant, const Vector<T>& value) |
| { |
| ASSERT(V_VT(variant) == VT_EMPTY); |
| |
| SAFEARRAY* safeArray = ::SafeArrayCreateVector(COMVariantSetter<T>::VariantType, 0, value.size()); |
| for (LONG i = 0; i < value.size(); ++i) { |
| COMVariant item(value[i]); |
| ::SafeArrayPutElement(safeArray, &i, &item); |
| } |
| |
| V_VT(variant) = VariantType; |
| V_ARRAY(variant) = safeArray; |
| } |
| }; |
| |
| template<typename COMType, typename UnderlyingType> |
| struct COMIUnknownVariantSetter : COMVariantSetterBase<UnderlyingType> |
| { |
| static const VARENUM VariantType = VT_UNKNOWN; |
| |
| static void setVariant(VARIANT* variant, const UnderlyingType& value) |
| { |
| ASSERT(V_VT(variant) == VT_EMPTY); |
| |
| V_VT(variant) = VariantType; |
| V_UNKNOWN(variant) = COMType::createInstance(value); |
| } |
| }; |
| |
| class COMVariant { |
| public: |
| COMVariant() |
| { |
| ::VariantInit(&m_variant); |
| } |
| |
| template<typename UnderlyingType> |
| COMVariant(UnderlyingType value) |
| { |
| ::VariantInit(&m_variant); |
| COMVariantSetter<UnderlyingType>::setVariant(&m_variant, value); |
| } |
| |
| ~COMVariant() |
| { |
| ::VariantClear(&m_variant); |
| } |
| |
| COMVariant(const COMVariant& other) |
| { |
| ::VariantInit(&m_variant); |
| other.copyTo(&m_variant); |
| } |
| |
| COMVariant& operator=(const COMVariant& other) |
| { |
| other.copyTo(&m_variant); |
| return *this; |
| } |
| |
| VARIANT* operator&() |
| { |
| return &m_variant; |
| } |
| |
| VARIANT* operator->() |
| { |
| return &m_variant; |
| } |
| |
| void copyTo(VARIANT* dest) const |
| { |
| ::VariantCopy(dest, const_cast<VARIANT*>(&m_variant)); |
| } |
| |
| VARENUM variantType() const { return static_cast<VARENUM>(V_VT(&m_variant)); } |
| |
| private: |
| VARIANT m_variant; |
| }; |
| |
| template<> struct COMVariantSetter<COMVariant> |
| { |
| static inline VARENUM variantType(const COMVariant& value) |
| { |
| return value.variantType(); |
| } |
| |
| static void setVariant(VARIANT* variant, const COMVariant& value) |
| { |
| ASSERT(V_VT(variant) == VT_EMPTY); |
| |
| value.copyTo(variant); |
| } |
| }; |
| |
| #endif // COMVariantSetter |