96c620e16a17a774d442b350c5207d5434db40f2
[WebKit-https.git] / WebKit / win / COMEnumVariant.h
1 /*\r
2  * Copyright (C) 2007 Apple Inc. All rights reserved.\r
3  *\r
4  * Redistribution and use in source and binary forms, with or without\r
5  * modification, are permitted provided that the following conditions\r
6  * are met:\r
7  *\r
8  * 1.  Redistributions of source code must retain the above copyright\r
9  *     notice, this list of conditions and the following disclaimer.\r
10  * 2.  Redistributions in binary form must reproduce the above copyright\r
11  *     notice, this list of conditions and the following disclaimer in the\r
12  *     documentation and/or other materials provided with the distribution.\r
13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of\r
14  *     its contributors may be used to endorse or promote products derived\r
15  *     from this software without specific prior written permission.\r
16  *\r
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY\r
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\r
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY\r
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\r
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\r
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\r
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
27  */\r
28 \r
29 #ifndef COMEnumVariant_h\r
30 #define COMEnumVariant_h\r
31 \r
32 #define NOMINMAX\r
33 #include <unknwn.h>\r
34 \r
35 #include <WebCore/BString.h>\r
36 #include <wtf/Assertions.h>\r
37 #include <wtf/Noncopyable.h>\r
38 \r
39 namespace WebCore {\r
40     class String;\r
41 }\r
42 \r
43 template<typename T> struct COMVariantSetter {};\r
44 \r
45 template<> struct COMVariantSetter<WebCore::String>\r
46 {\r
47     static void setVariant(VARIANT* variant, const WebCore::String& value)\r
48     {\r
49         ASSERT(V_VT(variant) == VT_EMPTY);\r
50 \r
51         V_VT(variant) = VT_BSTR;\r
52         V_BSTR(variant) = WebCore::BString(value).release();\r
53     }\r
54 };\r
55 \r
56 template<> struct COMVariantSetter<unsigned long long>\r
57 {\r
58     static void setVariant(VARIANT* variant, unsigned long long value)\r
59     {\r
60         ASSERT(V_VT(variant) == VT_EMPTY);\r
61 \r
62         V_VT(variant) = VT_UI8;\r
63         V_UI8(variant) = value;\r
64     }\r
65 };\r
66 \r
67 template<typename COMType, typename UnderlyingType>\r
68 struct COMIUnknownVariantSetter\r
69 {\r
70     static void setVariant(VARIANT* variant, const UnderlyingType& value)\r
71     {\r
72         ASSERT(V_VT(variant) == VT_EMPTY);\r
73 \r
74         V_VT(variant) = VT_UNKNOWN;\r
75         V_UNKNOWN(variant) = COMType::createInstance(value);\r
76     }\r
77 };\r
78 \r
79 template<typename ContainerType>\r
80 class COMEnumVariant : public IEnumVARIANT, Noncopyable {\r
81 public:\r
82     static COMEnumVariant* adopt(ContainerType&);\r
83     static COMEnumVariant* createInstance(const ContainerType&);\r
84 \r
85     // IUnknown\r
86     virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject);\r
87     virtual ULONG STDMETHODCALLTYPE AddRef();\r
88     virtual ULONG STDMETHODCALLTYPE Release();\r
89 \r
90     // IEnumVARIANT\r
91     virtual HRESULT STDMETHODCALLTYPE Next(ULONG celt, VARIANT* rgVar, ULONG* pCeltFetched);\r
92     virtual HRESULT STDMETHODCALLTYPE Skip(ULONG celt);\r
93     virtual HRESULT STDMETHODCALLTYPE Reset();\r
94     virtual HRESULT STDMETHODCALLTYPE Clone(IEnumVARIANT** ppEnum);\r
95 \r
96 private:\r
97     COMEnumVariant()\r
98         : m_refCount(0)\r
99     {\r
100     }\r
101 \r
102     COMEnumVariant(const ContainerType& container)\r
103         : m_refCount(0)\r
104         , m_container(container)       \r
105         , m_currentPos(m_container.begin())\r
106     {\r
107     }\r
108 \r
109     ~COMEnumVariant() {}\r
110 \r
111     ULONG m_refCount;\r
112 \r
113     ContainerType m_container;\r
114     typename ContainerType::const_iterator m_currentPos;\r
115 };\r
116 \r
117 // COMEnumVariant ------------------------------------------------------------------\r
118 template<typename ContainerType>\r
119 COMEnumVariant<typename ContainerType>* COMEnumVariant<ContainerType>::adopt(ContainerType& container) \r
120 {\r
121     COMEnumVariant* instance = new COMEnumVariant;\r
122     instance->m_container.swap(container);\r
123     instance->m_currentPos = instance->m_container.begin();\r
124     instance->AddRef();\r
125     return instance;\r
126 }\r
127 \r
128 template<typename ContainerType>\r
129 COMEnumVariant<typename ContainerType>* COMEnumVariant<ContainerType>::createInstance(const ContainerType& container)\r
130 {\r
131     COMEnumVariant* instance = new COMEnumVariant(container);\r
132     instance->AddRef();\r
133     return instance;\r
134 }\r
135 \r
136 // IUnknown ------------------------------------------------------------------------\r
137 template<typename ContainerType>\r
138 HRESULT STDMETHODCALLTYPE COMEnumVariant<ContainerType>::QueryInterface(REFIID riid, void** ppvObject)\r
139 {\r
140     *ppvObject = 0;\r
141     if (IsEqualGUID(riid, IID_IUnknown))\r
142         *ppvObject = static_cast<COMEnumVariant*>(this);\r
143     else if (IsEqualGUID(riid, IID_IEnumVARIANT))\r
144         *ppvObject = static_cast<COMEnumVariant*>(this);\r
145     else\r
146         return E_NOINTERFACE;\r
147 \r
148     AddRef();\r
149     return S_OK;\r
150 }\r
151 \r
152 template<typename ContainerType>\r
153 ULONG STDMETHODCALLTYPE COMEnumVariant<ContainerType>::AddRef()\r
154 {\r
155     return ++m_refCount;\r
156 }\r
157 \r
158 template<typename ContainerType>\r
159 ULONG STDMETHODCALLTYPE COMEnumVariant<ContainerType>::Release()\r
160 {\r
161     ULONG newRef = --m_refCount;\r
162     if (!newRef)\r
163         delete this;\r
164 \r
165     return newRef;\r
166 }\r
167 \r
168 // IEnumVARIANT --------------------------------------------------------------------\r
169 template<typename ContainerType>\r
170 HRESULT STDMETHODCALLTYPE COMEnumVariant<ContainerType>::Next(ULONG celt, VARIANT* rgVar, ULONG* pCeltFetched)\r
171 {\r
172     if (pCeltFetched)\r
173         *pCeltFetched = 0;\r
174     if (!rgVar)\r
175         return E_POINTER;\r
176     for (unsigned i = 0 ; i < celt; i++)\r
177         VariantInit(&rgVar[i]);\r
178 \r
179     for (unsigned i = 0; i < celt; i++) {\r
180         if (m_currentPos == m_container.end())\r
181             return S_FALSE;\r
182 \r
183         COMVariantSetter<ContainerType::ValueType>::setVariant(&rgVar[i], *m_currentPos);\r
184         ++m_currentPos;\r
185         if (pCeltFetched)\r
186             (*pCeltFetched)++;\r
187     }\r
188 \r
189     return S_OK;\r
190 }\r
191 \r
192 template<typename ContainerType>\r
193 HRESULT STDMETHODCALLTYPE COMEnumVariant<ContainerType>::Skip(ULONG celt) \r
194 {\r
195     for (unsigned i = 0; i < celt; i++) {\r
196         if (m_currentPos == m_container.end())\r
197             return S_FALSE;\r
198 \r
199         ++m_currentPos;\r
200     }\r
201     return S_OK;\r
202 }\r
203     \r
204 template<typename ContainerType>\r
205 HRESULT STDMETHODCALLTYPE COMEnumVariant<ContainerType>::Reset() \r
206 {\r
207     m_currentPos = m_container.begin();\r
208     return S_OK;\r
209 }\r
210     \r
211 template<typename ContainerType>\r
212 HRESULT STDMETHODCALLTYPE COMEnumVariant<ContainerType>::Clone(IEnumVARIANT** ppEnum)\r
213 {\r
214     if (!ppEnum)\r
215         return E_POINTER;\r
216 \r
217     *ppEnum = 0;\r
218     return E_NOTIMPL;\r
219 }\r
220 \r
221 #endif\r