VirtualBox

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

Last change on this file since 16560 was 14949, checked in by vboxsync, 15 years ago

Appended vim modeline to set tabstop and expand tabs (in the way
suggested by our coding guidelines).

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

© 2023 Oracle
ContactPrivacy policyTerms of Use