1 /* 2 * Copyright (C) 2007, 2008 Apple Inc. All Rights Reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #ifndef COMVariantSetter_h 27 #define COMVariantSetter_h 28 29 #include <WebCore/BString.h> 30 #include <WebCore/COMPtr.h> 31 #include <wtf/Assertions.h> 32 #include <wtf/Forward.h> 33 34 template<typename T> struct COMVariantSetter {}; 35 36 template<typename T> struct COMVariantSetterBase 37 { 38 static inline VARENUM variantType(const T&) 39 { 40 return COMVariantSetter<T>::VariantType; 41 } 42 }; 43 44 template<> struct COMVariantSetter<WTF::String> : COMVariantSetterBase<WTF::String> 45 { 46 static const VARENUM VariantType = VT_BSTR; 47 48 static void setVariant(VARIANT* variant, const WTF::String& value) 49 { 50 ASSERT(V_VT(variant) == VT_EMPTY); 51 52 V_VT(variant) = VariantType; 53 V_BSTR(variant) = WebCore::BString(value).release(); 54 } 55 }; 56 57 template<> struct COMVariantSetter<bool> : COMVariantSetterBase<bool> 58 { 59 static const VARENUM VariantType = VT_BOOL; 60 61 static void setVariant(VARIANT* variant, bool value) 62 { 63 ASSERT(V_VT(variant) == VT_EMPTY); 64 65 V_VT(variant) = VariantType; 66 V_BOOL(variant) = value; 67 } 68 }; 69 70 template<> struct COMVariantSetter<unsigned long long> : COMVariantSetterBase<unsigned long long> 71 { 72 static const VARENUM VariantType = VT_UI8; 73 74 static void setVariant(VARIANT* variant, unsigned long long value) 75 { 76 ASSERT(V_VT(variant) == VT_EMPTY); 77 78 V_VT(variant) = VariantType; 79 V_UI8(variant) = value; 80 } 81 }; 82 83 template<> struct COMVariantSetter<int> : COMVariantSetterBase<int> 84 { 85 static const VARENUM VariantType = VT_I4; 86 87 static void setVariant(VARIANT* variant, int value) 88 { 89 ASSERT(V_VT(variant) == VT_EMPTY); 90 91 V_VT(variant) = VariantType; 92 V_I4(variant) = value; 93 } 94 }; 95 96 template<> struct COMVariantSetter<float> : COMVariantSetterBase<float> 97 { 98 static const VARENUM VariantType = VT_R4; 99 100 static void setVariant(VARIANT* variant, float value) 101 { 102 ASSERT(V_VT(variant) == VT_EMPTY); 103 104 V_VT(variant) = VariantType; 105 V_R4(variant) = value; 106 } 107 }; 108 109 template<typename T> struct COMVariantSetter<COMPtr<T> > : COMVariantSetterBase<COMPtr<T> > 110 { 111 static const VARENUM VariantType = VT_UNKNOWN; 112 113 static void setVariant(VARIANT* variant, const COMPtr<T>& value) 114 { 115 ASSERT(V_VT(variant) == VT_EMPTY); 116 117 V_VT(variant) = VariantType; 118 V_UNKNOWN(variant) = value.get(); 119 value->AddRef(); 120 } 121 }; 122 123 template<typename COMType, typename UnderlyingType> 124 struct COMIUnknownVariantSetter : COMVariantSetterBase<UnderlyingType> 125 { 126 static const VARENUM VariantType = VT_UNKNOWN; 127 128 static void setVariant(VARIANT* variant, const UnderlyingType& value) 129 { 130 ASSERT(V_VT(variant) == VT_EMPTY); 131 132 V_VT(variant) = VariantType; 133 V_UNKNOWN(variant) = COMType::createInstance(value); 134 } 135 }; 136 137 class COMVariant { 138 public: 139 COMVariant() 140 { 141 ::VariantInit(&m_variant); 142 } 143 144 template<typename UnderlyingType> 145 COMVariant(UnderlyingType value) 146 { 147 ::VariantInit(&m_variant); 148 COMVariantSetter<UnderlyingType>::setVariant(&m_variant, value); 149 } 150 151 ~COMVariant() 152 { 153 ::VariantClear(&m_variant); 154 } 155 156 COMVariant(const COMVariant& other) 157 { 158 ::VariantInit(&m_variant); 159 other.copyTo(&m_variant); 160 } 161 162 COMVariant& operator=(const COMVariant& other) 163 { 164 other.copyTo(&m_variant); 165 return *this; 166 } 167 168 void copyTo(VARIANT* dest) const 169 { 170 ::VariantCopy(dest, const_cast<VARIANT*>(&m_variant)); 171 } 172 173 VARENUM variantType() const { return static_cast<VARENUM>(V_VT(&m_variant)); } 174 175 private: 176 VARIANT m_variant; 177 }; 178 179 template<> struct COMVariantSetter<COMVariant> 180 { 181 static inline VARENUM variantType(const COMVariant& value) 182 { 183 return value.variantType(); 184 } 185 186 static void setVariant(VARIANT* variant, const COMVariant& value) 187 { 188 ASSERT(V_VT(variant) == VT_EMPTY); 189 190 value.copyTo(variant); 191 } 192 }; 193 194 #endif // COMVariantSetter 195