VirtualBox

source: vbox/trunk/src/VBox/Main/include/Collection.h@ 5999

Last change on this file since 5999 was 5999, checked in by vboxsync, 17 years ago

The Giant CDDL Dual-License Header Change.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 20.4 KB
Line 
1/** @file
2 *
3 * VirtualBox collection templates
4 */
5
6/*
7 * Copyright (C) 2006-2007 innotek GmbH
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#ifndef ____H_COLLECTION
19#define ____H_COLLECTION
20
21#include "VBox/com/defs.h"
22#include "VirtualBoxBase.h"
23
24#include <list>
25#include <vector>
26
27/**
28 * Template class to create a non-thread safe implementation of the
29 * enumerator over the read-only collection that stores safe interface pointers
30 * using std::vector. The enumerator is attached to an existing std::vector
31 * storing EnumItem instances, optionally making a copy.
32 *
33 * The template also inherits the VirtualBoxSupportErrorInfoImpl template and
34 * therefore provides the error info support.
35 *
36 * @param IEnum
37 * enumerator interface to implement. This interface must define
38 * HasMore (BOOL *) and GetNext (IEnumItem **).
39 * @param IEnumItem
40 * enumerator item interface. Pointers of this type are returned
41 * by GetNext().
42 * @param EnumItem
43 * actual enumerator item class. Instances of this class
44 * are stored in the std::vector passed as an argument to
45 * init(). This class must be a ComPtrBase<> template instantiation
46 * or derived from such instantiation.
47 * @param ComponentClass
48 * the only role of this class is to have the following member:
49 * |public: static const wchar_t *getComponentName()|, that returns the
50 * component name (see VirtualBoxSupportErrorInfoImpl template for more info).
51 */
52template <class IEnum, class IEnumItem, class EnumItem, class ComponentClass>
53class ATL_NO_VTABLE IfaceVectorEnumerator :
54 public VirtualBoxSupportErrorInfoImpl <IfaceVectorEnumerator <IEnum, IEnumItem,
55 EnumItem, ComponentClass>, IEnum>,
56#ifdef RT_OS_WINDOWS
57 public CComObjectRootEx <CComSingleThreadModel>,
58#else
59 public CComObjectRootEx,
60#endif
61 public IEnum
62{
63 Q_OBJECT
64
65public:
66
67 typedef std::vector <EnumItem> Vector;
68
69 DECLARE_NOT_AGGREGATABLE(IfaceVectorEnumerator)
70
71 DECLARE_PROTECT_FINAL_CONSTRUCT()
72
73 BEGIN_COM_MAP(IfaceVectorEnumerator)
74 COM_INTERFACE_ENTRY(ISupportErrorInfo)
75 COM_INTERFACE_ENTRY(IEnum)
76 END_COM_MAP()
77
78 IfaceVectorEnumerator()
79 {
80 parent = NULL;
81 vec = NULL;
82 allocated = true;
83 }
84
85 virtual ~IfaceVectorEnumerator()
86 {
87 if (vec && allocated)
88 delete vec;
89 if (parent)
90 parent->Release();
91 }
92
93 // public initializer/uninitializer for internal purposes only
94 void init (IUnknown *p, const Vector &v, bool readonly = true)
95 {
96 parent = p;
97 if (parent)
98 parent->AddRef();
99 if (readonly)
100 vec = &v;
101 else
102 vec = new Vector (v);
103 allocated = !readonly;
104 iter = vec->begin();
105 }
106
107 STDMETHOD(HasMore) (BOOL *more)
108 {
109 if (!more)
110 return E_POINTER;
111 *more = iter != vec->end();
112 return S_OK;
113 }
114
115 STDMETHOD(GetNext) (IEnumItem **next)
116 {
117 if (!next)
118 return E_POINTER;
119 *next = NULL;
120 if (iter == vec->end())
121 return this->setError (E_UNEXPECTED, VirtualBoxBase::translate (
122 "IfaceVectorEnumerator", "No more elements"));
123 typename Vector::value_type item = *iter;
124 ++iter;
125 return item.queryInterfaceTo (next);
126 }
127
128 // for VirtualBoxSupportErrorInfoImpl
129 inline static const wchar_t *getComponentName() {
130 return ComponentClass::getComponentName();
131 }
132
133private:
134
135 IUnknown *parent;
136 const Vector *vec;
137 bool allocated;
138 typename Vector::const_iterator iter;
139};
140
141/**
142 * Template class to create a non-thread safe implementation of the
143 * read-only collection that stores interface pointers. The collection is
144 * initialized from the std::list storing CollItem instances by copying
145 * (i.e. making a snapshot of) all list items to std::vector for
146 * optimized random access.
147 *
148 * The template also inherits the VirtualBoxSupportErrorInfoImpl template and
149 * therefore provides the error info support.
150 *
151 * @param IColl
152 * collection interface to implement. This interface must define
153 * Count(ULONG *), GetItemAt (ULONG, ICollItem**) and Enumerate (IEnum **).
154 * @param ICollItem
155 * collection item interface. Pointers of this type are returned by
156 * GetItemAt().
157 * @param IEnum
158 * enumerator interface. Pointers of this type are returned by Enumerate().
159 * @param CollItem
160 * actual collection item class. Instances of this class
161 * are stored in the std::list passed as an argument to
162 * init() and in the internal std::vector. This class must be a
163 * ComPtrBase<> template instantiation or derived from such instantiation.
164 * @param Enum
165 * enumerator implementation class used to construct a new enumerator.
166 * This class must be a IfaceVectorEnumerator<> template instantiation
167 * with IEnum and IEnumItem arguments exactly the same as in this template,
168 * and with EnumItem argument exactly the same as this template's
169 * CollItem argument.
170 * @param ComponentClass
171 * the only role of this class is to have the following member:
172 * |public: static const wchar_t *getComponentName()|, that returns the
173 * component name (see VirtualBoxSupportErrorInfoImpl template for more info).
174 */
175template <class IColl, class ICollItem, class IEnum, class CollItem, class Enum,
176 class ComponentClass>
177class ATL_NO_VTABLE ReadonlyIfaceVector :
178 public VirtualBoxSupportErrorInfoImpl <ReadonlyIfaceVector <IColl, ICollItem,
179 IEnum, CollItem, Enum, ComponentClass>, IColl>,
180#ifdef RT_OS_WINDOWS
181 public CComObjectRootEx <CComSingleThreadModel>,
182#else
183 public CComObjectRootEx,
184#endif
185 public IColl
186{
187 Q_OBJECT
188
189public:
190
191 typedef std::vector <CollItem> Vector;
192 typedef std::list <CollItem> List;
193
194 DECLARE_NOT_AGGREGATABLE(ReadonlyIfaceVector)
195
196 DECLARE_PROTECT_FINAL_CONSTRUCT()
197
198 BEGIN_COM_MAP(ReadonlyIfaceVector)
199 COM_INTERFACE_ENTRY(ISupportErrorInfo)
200 COM_INTERFACE_ENTRY(IColl)
201 END_COM_MAP()
202
203 // public initializer/uninitializer for internal purposes only
204
205 void init (const List &l)
206 {
207 // create a copy of the list
208 vec = Vector (l.begin(), l.end());
209 }
210
211 template <class Key>
212 void init (const std::map <Key, CollItem> &m)
213 {
214 // create a copy of the map
215 for (typename std::map <Key, CollItem>::const_iterator it = m.begin();
216 it != m.end(); ++ it)
217 vec.push_back (it->second);
218 }
219
220 STDMETHOD(COMGETTER(Count)) (ULONG *count)
221 {
222 if (!count)
223 return E_POINTER;
224 *count = (ULONG) vec.size();
225 return S_OK;
226 }
227
228 STDMETHOD(GetItemAt) (ULONG index, ICollItem **item)
229 {
230 if (!item)
231 return E_POINTER;
232 *item = NULL;
233 if (index >= vec.size())
234 return this->setError (E_INVALIDARG, VirtualBoxBase::translate (
235 "ReadonlyIfaceVector", "The specified index is out of range"));
236 return vec [index].queryInterfaceTo (item);
237 }
238
239 STDMETHOD(Enumerate) (IEnum **enumerator)
240 {
241 if (!enumerator)
242 return E_POINTER;
243 *enumerator = NULL;
244 ComObjPtr <Enum> enumObj;
245 HRESULT rc = enumObj.createObject();
246 if (SUCCEEDED (rc))
247 {
248 enumObj->init ((IColl *) this, vec);
249 rc = enumObj.queryInterfaceTo (enumerator);
250 }
251 return rc;
252 }
253
254 // for VirtualBoxSupportErrorInfoImpl
255 inline static const wchar_t *getComponentName() {
256 return ComponentClass::getComponentName();
257 }
258
259protected:
260
261 Vector vec;
262};
263
264/**
265 * This macro declares an enumerator class and a collection class that stores
266 * elements of the given class @a itemcls that implements the given
267 * interface @a iface
268 *
269 * The the @a itemcls class must be either a ComObjPtr or a ComPtr template
270 * instantiation with the argument being a class that implements the @a iface
271 * interface.
272 *
273 * The namespace of the collection class remains opened after
274 * this macro is expanded (i.e. no closing brace with semicolon), which
275 * allows to declare extra collection class members. This namespace
276 * must be closed by the COM_DECL_READONLY_ENUM_AND_COLLECTION_EX_END macro.
277 *
278 * For example, given |ComObjPtr <OSomeItem>|, |ISomeItem|| and |OSomeItem|
279 * arguments, this macro will generate the following code:
280 *
281 * <code>
282 * class OSomeItemEnumerator : public
283 * IfaceVectorEnumerator <ISomeItemEnumerator, ISomeItem, ComObjPtr <OSomeItem>,
284 * OSomeItemEnumerator>
285 * {...};
286 * class SomeItemCollection : public
287 * ReadonlyIfaceVector <ISomeItemCollection, ISomeItem, ComObjPtr <OSomeItem>,
288 * OSomeItemEnumerator, OSomeItemCollection>
289 * {...};
290 * </code>
291 *
292 * i.e. it assumes that ISomeItemEnumerator, ISomeItem and ISomeItemCollection
293 * are existing interfaces, and OSomeItem implements the ISomeItem interface.
294 * It also assumes, that std::list passed to SomeItemCollection::init()
295 * stores objects of the @a itemcls class (|ComObjPtr <OSomeItem>| in the
296 * example above).
297 *
298 * See descriptions of the above IfaceVectorEnumerator and
299 * ReadonlyIfaceVector templates for more info.
300 *
301 * The generated class also inherits the VirtualBoxSupportTranslation template,
302 * providing the support for translation of string constants within class
303 * members.
304 *
305 * The macro is best to be placed in the header after SomeItem class
306 * declaration. The COM_DECL_READONLY_ENUM_AND_COLLECTION_EX_END macro must
307 * follow all extra member declarations of the collection class, or right
308 * after this macro if the collection doesn't have extra members.
309 *
310 * @param itemcls Either ComObjPtr or ComPtr for the class that implements
311 * the given interface of items to be stored in the
312 * collection
313 * @param iface Interface of items implemented by the @a itemcls class
314 * @param prefix Prefix to apply to generated enumerator and collection
315 * names.
316 */
317#define COM_DECL_READONLY_ENUM_AND_COLLECTION_EX_BEGIN(itemcls, iface, prefix) \
318 class prefix##Enumerator \
319 : public IfaceVectorEnumerator \
320 <iface##Enumerator, iface, itemcls, prefix##Enumerator> \
321 , public VirtualBoxSupportTranslation <prefix##Enumerator> \
322 { \
323 NS_DECL_ISUPPORTS \
324 public: static const wchar_t *getComponentName() { \
325 return WSTR_LITERAL (prefix) L"Enumerator"; \
326 } \
327 }; \
328 class prefix##Collection \
329 : public ReadonlyIfaceVector \
330 <iface##Collection, iface, iface##Enumerator, itemcls, prefix##Enumerator, \
331 prefix##Collection> \
332 , public VirtualBoxSupportTranslation <prefix##Collection> \
333 { \
334 NS_DECL_ISUPPORTS \
335 public: static const wchar_t *getComponentName() { \
336 return WSTR_LITERAL (prefix) L"Collection"; \
337 }
338
339/**
340 * This macro is a counterpart to COM_DECL_READONLY_ENUM_AND_COLLECTION_EX_BEGIN
341 * and must be always used to finalize the collection declaration started
342 * by that macro.
343 *
344 * Currently the macro just expands to the closing brace with semicolon,
345 * but this might change in the future.
346 */
347#define COM_DECL_READONLY_ENUM_AND_COLLECTION_EX_END(itemcls, iface, prefix) \
348 };
349
350/**
351 * This is a "shortcut" macro, for convenience. It expands exactly to:
352 * <code>
353 * COM_DECL_READONLY_ENUM_AND_COLLECTION_EX_BEGIN(itemcls, iface, prefix)
354 * COM_DECL_READONLY_ENUM_AND_COLLECTION_EX_END(itemcls, iface, prefix)
355 * </code>
356 */
357#define COM_DECL_READONLY_ENUM_AND_COLLECTION_EX(itemcls, iface, prefix) \
358 COM_DECL_READONLY_ENUM_AND_COLLECTION_EX_BEGIN (itemcls, iface, prefix) \
359 COM_DECL_READONLY_ENUM_AND_COLLECTION_EX_END (itemcls, iface, prefix)
360
361/**
362 * This macro declares an enumerator class and a collection class for the
363 * given item class @a c.
364 *
365 * It's a convenience macro that deduces all arguments to the
366 * COM_DECL_READONLY_ENUM_AND_COLLECTION_EX_BEGIN macro from a single @a c
367 * class name argument. Given a class named |SomeItem|, this macro is
368 * equivalent to
369 * <code>
370 * COM_DECL_READONLY_ENUM_AND_COLLECTION_EX_BEGIN (ComObjPtr <SomeItem>, ISomeItem, SomeItem)
371 * </code>
372 * and will generate the following code:
373 * <code>
374 * class OSomeItemEnumerator : public
375 * IfaceVectorEnumerator <ISomeItemEnumerator, ISomeItem, ComObjPtr <SomeItem>,
376 * SomeItemEnumerator>
377 * {...};
378 * class SomeItemCollection : public
379 * ReadonlyIfaceVector <ISomeItemCollection, ISomeItem, ComObjPtr <SomeItem>,
380 * SomeItemEnumerator, SomeItemCollection>
381 * {...};
382 * </code>
383 *
384 * See COM_DECL_READONLY_ENUM_AND_COLLECTION_EX_BEGIN for the detailed
385 * description.
386 *
387 * The macro is best to be placed in the header after SomeItem class
388 * declaration. The COM_DECL_READONLY_ENUM_AND_COLLECTION_END macro must follow
389 * all extra member declarations of the collection class, or right after this
390 * macro if the collection doesn't have extra members.
391 *
392 * @param c Component class implementing the interface of items to be stored
393 * in the collection
394 */
395#define COM_DECL_READONLY_ENUM_AND_COLLECTION_BEGIN(c) \
396 COM_DECL_READONLY_ENUM_AND_COLLECTION_EX_BEGIN (ComObjPtr <c>, I##c, c)
397
398/**
399 * This macro is a counterpart to COM_DECL_READONLY_ENUM_AND_COLLECTION_BEGIN
400 * and must be always used to finalize the collection declaration started
401 * by that macro.
402 *
403 * This is a "shortcut" macro that expands exactly to:
404 * <code>
405 * COM_DECL_READONLY_ENUM_AND_COLLECTION_EX_END (ComObjPtr <c>, I##c, c)
406 * </code>
407 */
408#define COM_DECL_READONLY_ENUM_AND_COLLECTION_END(c) \
409 COM_DECL_READONLY_ENUM_AND_COLLECTION_EX_END (ComObjPtr <c>, I##c, c)
410
411/**
412 * This is a "shortcut" macro, for convenience. It expands exactly to:
413 * <code>
414 * COM_DECL_READONLY_ENUM_AND_COLLECTION_BEGIN(c)
415 * COM_DECL_READONLY_ENUM_AND_COLLECTION_END(c)
416 * </code>
417 */
418#define COM_DECL_READONLY_ENUM_AND_COLLECTION(c) \
419 COM_DECL_READONLY_ENUM_AND_COLLECTION_BEGIN(c) \
420 COM_DECL_READONLY_ENUM_AND_COLLECTION_END(c)
421
422/**
423 * This macro declares an enumerator class and a collection class for the
424 * given item interface @a iface prefixed with the given @a prefix.
425 *
426 * It's a convenience macro that deduces all arguments to the
427 * COM_DECL_READONLY_ENUM_AND_COLLECTION_EX_BEGIN macro from the two given
428 * @a iface and @a prefix arguments. Given an interface named |ISomeItem|,
429 * and a prefix SomeItem this macro is equivalent to
430 * <code>
431 * COM_DECL_READONLY_ENUM_AND_COLLECTION_EX_BEGIN (ComPtr <ISomeItem>, ISomeItem, SomeItem)
432 * </code>
433 * and will generate the following code:
434 * <code>
435 * class OSomeItemEnumerator : public
436 * IfaceVectorEnumerator <ISomeItemEnumerator, ISomeItem, ComPtr <ISomeItem>,
437 * SomeItemEnumerator>
438 * {...};
439 * class SomeItemCollection : public
440 * ReadonlyIfaceVector <ISomeItemCollection, ISomeItem, ComPtr <ISomeItem>,
441 * SomeItemEnumerator, SomeItemCollection>
442 * {...};
443 * </code>
444 *
445 * See COM_DECL_READONLY_ENUM_AND_COLLECTION_EX_BEGIN for the detailed
446 * description.
447 *
448 * The macro is best to be placed in the header after SomeItem class
449 * declaration. The COM_DECL_READONLY_ENUM_AND_COLLECTION_AS_END macro must follow
450 * all extra member declarations of the collection class, or right after this
451 * macro if the collection doesn't have extra members.
452 *
453 * @param prefix Prefix prepended to the generated collection and
454 * enumerator classes
455 * @param iface Interface class
456 */
457#define COM_DECL_READONLY_ENUM_AND_COLLECTION_AS_BEGIN(prefix, iface) \
458 COM_DECL_READONLY_ENUM_AND_COLLECTION_EX_BEGIN (ComPtr <iface>, iface, prefix)
459
460/**
461 * This macro is a counterpart to COM_DECL_READONLY_ENUM_AND_COLLECTION_AS_BEGIN
462 * and must be always used to finalize the collection declaration started
463 * by that macro.
464 *
465 * This is a "shortcut" macro that expands exactly to:
466 * <code>
467 * COM_DECL_READONLY_ENUM_AND_COLLECTION_EX_END (ComObjPtr <c>, I##c, c)
468 * </code>
469 */
470#define COM_DECL_READONLY_ENUM_AND_COLLECTION_AS_END(prefix, iface) \
471 COM_DECL_READONLY_ENUM_AND_COLLECTION_EX_END (ComPtr <iface>, iface, prefix)
472
473/**
474 * This is a "shortcut" macro, for convenience. It expands exactly to:
475 * <code>
476 * COM_DECL_READONLY_ENUM_AND_COLLECTION_AS_BEGIN(c)
477 * COM_DECL_READONLY_ENUM_AND_COLLECTION_AS_END(c)
478 * </code>
479 */
480#define COM_DECL_READONLY_ENUM_AND_COLLECTION_AS(prefix, iface) \
481 COM_DECL_READONLY_ENUM_AND_COLLECTION_AS_BEGIN (prefix, iface) \
482 COM_DECL_READONLY_ENUM_AND_COLLECTION_AS_END (prefix, iface)
483
484#ifdef RT_OS_WINDOWS
485
486#define COM_IMPL_READONLY_ENUM_AND_COLLECTION_EX(itemcls, iface, prefix)
487#define COM_IMPL_READONLY_ENUM_AND_COLLECTION(c)
488#define COM_IMPL_READONLY_ENUM_AND_COLLECTION_AS(prefix, iface)
489
490#else // !RT_OS_WINDOWS
491
492/**
493 * This macro defines nsISupports implementations (i.e. QueryInterface(),
494 * AddRef() and Release()) for the enumerator and collection classes
495 * declared by the COM_DECL_READONLY_ENUM_AND_COLLECTION_EX,
496 * COM_DECL_READONLY_ENUM_AND_COLLECTION_EX_BEGIN and
497 * COM_DECL_READONLY_ENUM_AND_COLLECTION_EX macros.
498 *
499 * See COM_DECL_READONLY_ENUM_AND_COLLECTION_EX_BEGIN for the detailed
500 * description.
501 *
502 * The macro should be placed in one of the source files.
503 *
504 * @note
505 * this macro is XPCOM-specific and not necessary for MS COM,
506 * so expands to nothing on Win32.
507 *
508 * @param itemcls Either ComObjPtr or ComPtr for the class that implements
509 * the given interface of items to be stored in the
510 * collection
511 * @param iface Interface of items implemented by the @a itemcls class
512 * @param prefix Prefix to apply to generated enumerator and collection
513 * names.
514 */
515#define COM_IMPL_READONLY_ENUM_AND_COLLECTION_EX(itemcls, iface, prefix) \
516 NS_DECL_CLASSINFO(prefix##Collection) \
517 NS_IMPL_THREADSAFE_ISUPPORTS1_CI(prefix##Collection, iface##Collection) \
518 NS_DECL_CLASSINFO(prefix##Enumerator) \
519 NS_IMPL_THREADSAFE_ISUPPORTS1_CI(prefix##Enumerator, iface##Enumerator)
520
521/**
522 * This macro defines nsISupports implementations (i.e. QueryInterface(),
523 * AddRef() and Release()) for the enumerator and collection classes
524 * declared by the COM_DECL_READONLY_ENUM_AND_COLLECTION,
525 * COM_DECL_READONLY_ENUM_AND_COLLECTION_BEGIN and
526 * COM_DECL_READONLY_ENUM_AND_COLLECTION_END macros.
527 *
528 * See COM_DECL_READONLY_ENUM_AND_COLLECTION_BEGIN for the detailed
529 * description.
530 *
531 * The macro should be placed in one of the source files.
532 *
533 * @note
534 * this macro is XPCOM-specific and not necessary for MS COM,
535 * so expands to nothing on Win32.
536 *
537 * @param c Component class implementing the interface of items to be stored
538 * in the collection
539 */
540#define COM_IMPL_READONLY_ENUM_AND_COLLECTION(c) \
541 COM_IMPL_READONLY_ENUM_AND_COLLECTION_EX (0, I##c, c)
542
543/**
544 * This macro defines nsISupports implementations (i.e. QueryInterface(),
545 * AddRef() and Release()) for the enumerator and collection classes
546 * declared by the COM_DECL_READONLY_ENUM_AND_COLLECTION_AS,
547 * COM_DECL_READONLY_ENUM_AND_COLLECTION_AS_BEGIN and
548 * COM_DECL_READONLY_ENUM_AND_COLLECTION_AS_END macros.
549 *
550 * See COM_DECL_READONLY_ENUM_AND_COLLECTION_AS_BEGIN for the detailed
551 * description.
552 *
553 * The macro should be placed in one of the source files.
554 *
555 * @note
556 * this macro is XPCOM-specific and not necessary for MS COM,
557 * so expands to nothing on Win32.
558 *
559 * @param prefix Prefix prepended to the generated collection and
560 * enumerator classes
561 * @param iface Interface class
562 */
563#define COM_IMPL_READONLY_ENUM_AND_COLLECTION_AS(prefix, iface) \
564 COM_IMPL_READONLY_ENUM_AND_COLLECTION_EX (0, iface, prefix)
565
566#endif // !RT_OS_WINDOWS
567
568#endif // ____H_COLLECTION
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette