1 /* 2 * Copyright (C) 2007 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 COMEnumVariant_h 27 #define COMEnumVariant_h 28 29 #define NOMINMAX 30 #include <unknwn.h> 31 32 33 #include "COMVariantSetter.h" 34 35 template<typename ContainerType> 36 class COMEnumVariant : public IEnumVARIANT { 37 WTF_MAKE_NONCOPYABLE(COMEnumVariant); 38 public: 39 static COMEnumVariant* adopt(ContainerType&); 40 static COMEnumVariant* createInstance(const ContainerType&); 41 42 // IUnknown 43 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject); 44 virtual ULONG STDMETHODCALLTYPE AddRef(); 45 virtual ULONG STDMETHODCALLTYPE Release(); 46 47 // IEnumVARIANT 48 virtual HRESULT STDMETHODCALLTYPE Next(ULONG celt, VARIANT* rgVar, ULONG* pCeltFetched); 49 virtual HRESULT STDMETHODCALLTYPE Skip(ULONG celt); 50 virtual HRESULT STDMETHODCALLTYPE Reset(); 51 virtual HRESULT STDMETHODCALLTYPE Clone(IEnumVARIANT** ppEnum); 52 53 private: 54 COMEnumVariant() 55 : m_refCount(0) 56 { 57 } 58 59 COMEnumVariant(const ContainerType& container) 60 : m_refCount(0) 61 , m_container(container) 62 , m_currentPos(m_container.begin()) 63 { 64 } 65 66 ~COMEnumVariant() {} 67 68 ULONG m_refCount; 69 70 ContainerType m_container; 71 typename ContainerType::const_iterator m_currentPos; 72 }; 73 74 // COMEnumVariant ------------------------------------------------------------------ 75 template<typename ContainerType> 76 COMEnumVariant<typename ContainerType>* COMEnumVariant<ContainerType>::adopt(ContainerType& container) 77 { 78 COMEnumVariant* instance = new COMEnumVariant; 79 instance->m_container.swap(container); 80 instance->m_currentPos = instance->m_container.begin(); 81 instance->AddRef(); 82 return instance; 83 } 84 85 template<typename ContainerType> 86 COMEnumVariant<typename ContainerType>* COMEnumVariant<ContainerType>::createInstance(const ContainerType& container) 87 { 88 COMEnumVariant* instance = new COMEnumVariant(container); 89 instance->AddRef(); 90 return instance; 91 } 92 93 // IUnknown ------------------------------------------------------------------------ 94 template<typename ContainerType> 95 HRESULT STDMETHODCALLTYPE COMEnumVariant<ContainerType>::QueryInterface(REFIID riid, void** ppvObject) 96 { 97 *ppvObject = 0; 98 if (IsEqualGUID(riid, IID_IUnknown)) 99 *ppvObject = static_cast<COMEnumVariant*>(this); 100 else if (IsEqualGUID(riid, IID_IEnumVARIANT)) 101 *ppvObject = static_cast<COMEnumVariant*>(this); 102 else 103 return E_NOINTERFACE; 104 105 AddRef(); 106 return S_OK; 107 } 108 109 template<typename ContainerType> 110 ULONG STDMETHODCALLTYPE COMEnumVariant<ContainerType>::AddRef() 111 { 112 return ++m_refCount; 113 } 114 115 template<typename ContainerType> 116 ULONG STDMETHODCALLTYPE COMEnumVariant<ContainerType>::Release() 117 { 118 ULONG newRef = --m_refCount; 119 if (!newRef) 120 delete this; 121 122 return newRef; 123 } 124 125 // IEnumVARIANT -------------------------------------------------------------------- 126 template<typename ContainerType> 127 HRESULT STDMETHODCALLTYPE COMEnumVariant<ContainerType>::Next(ULONG celt, VARIANT* rgVar, ULONG* pCeltFetched) 128 { 129 if (pCeltFetched) 130 *pCeltFetched = 0; 131 if (!rgVar) 132 return E_POINTER; 133 for (unsigned i = 0 ; i < celt; i++) 134 VariantInit(&rgVar[i]); 135 136 for (unsigned i = 0; i < celt; i++) { 137 if (m_currentPos == m_container.end()) 138 return S_FALSE; 139 140 COMVariantSetter<ContainerType::ValueType>::setVariant(&rgVar[i], *m_currentPos); 141 ++m_currentPos; 142 if (pCeltFetched) 143 (*pCeltFetched)++; 144 } 145 146 return S_OK; 147 } 148 149 template<typename ContainerType> 150 HRESULT STDMETHODCALLTYPE COMEnumVariant<ContainerType>::Skip(ULONG celt) 151 { 152 for (unsigned i = 0; i < celt; i++) { 153 if (m_currentPos == m_container.end()) 154 return S_FALSE; 155 156 ++m_currentPos; 157 } 158 return S_OK; 159 } 160 161 template<typename ContainerType> 162 HRESULT STDMETHODCALLTYPE COMEnumVariant<ContainerType>::Reset() 163 { 164 m_currentPos = m_container.begin(); 165 return S_OK; 166 } 167 168 template<typename ContainerType> 169 HRESULT STDMETHODCALLTYPE COMEnumVariant<ContainerType>::Clone(IEnumVARIANT** ppEnum) 170 { 171 if (!ppEnum) 172 return E_POINTER; 173 174 *ppEnum = 0; 175 return E_NOTIMPL; 176 } 177 178 #endif 179