Changeset 6874 in vbox for trunk/include
- Timestamp:
- Feb 10, 2008 2:34:59 PM (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/com/array.h
r6851 r6874 28 28 #define ___VBox_com_array_h 29 29 30 #include <VBox/com/ptr.h> 31 30 32 /** @defgroup grp_COM_arrays COM/XPCOM Arrays 31 33 * @{ … … 125 127 * @endcode 126 128 * 127 * Implementation declarations and function bodies of attribute getters and 128 * setters are very similar to the examples shown above and therefore not 129 * explained separately. 129 * For interoperability with standard C++ containers, there is a template 130 * constructor that takes such a container as argument and performs a deep copy 131 * of its contents. This can be used in method implementations like this: 132 * @code 133 134 STDMETHODIMP Component::COMGETTER(Values) (ComSafeArrayOut (int, aValues)) 135 { 136 // ... assume there is a |std::list <int> mValues| data member 137 138 com::SafeArray <int> values (mValues); 139 values.detachTo (ComSafeArrayOutArg (aValues)); 140 141 return S_OK; 142 } 143 144 * @endcode 130 145 * 131 146 * The current implementation of the SafeArray layer supports all types normally 132 * allowed in XIDL as array element types (including 'wstring', 'uuid' types and 133 * interface pointers). However 'pointer-to' types (e.g. 'long *', 'wstrig *', 134 * 'IUnknown **') are not supported and therefore cannot be used as element 135 * types. 147 * allowed in XIDL as array element types (including 'wstring' and 'uuid'). 148 * However, 'pointer-to-...' types (e.g. 'long *', 'wstring *') are not 149 * supported and therefore cannot be used as element types. 150 * 151 * Arrays of interface pointers are also supported but they require to use a 152 * special SafeArray implementation, com::SafeIfacePointer, which takes the 153 * interface class name as a template argument (e.g. com::SafeIfacePointer 154 * <IUnknown>). This implementation functions identically to com::SafeArray. 136 155 */ 137 156 … … 193 212 static void Init (T &aElem) { aElem = 0; } 194 213 static void Uninit (T &aElem) { aElem = 0; } 195 196 /* Magic to workaround strict rules of par. 4.4.4 of the C++ standard. 197 * Then initial reason for this magic is that XPIDL declares input strings 214 static void Copy (const T &aFrom, T &aTo) { aTo = aFrom; } 215 216 /* Magic to workaround strict rules of par. 4.4.4 of the C++ standard (that 217 * in particular forbid casts of 'char **' to 'const char **'). Then initial 218 * reason for this magic is that XPIDL declares input strings 198 219 * (char/PRUnichar pointers) as const but doesn't do so for pointers to 199 220 * arrays. */ … … 202 223 }; 203 224 225 template <typename T> 226 struct SafeArrayTraits <T *> 227 { 228 // Arbitrary pointers are not supported 229 }; 230 204 231 template<> 205 232 struct SafeArrayTraits <PRUnichar *> … … 215 242 } 216 243 244 static void Copy (const PRUnichar * aFrom, PRUnichar * &aTo) 245 { 246 AssertCompile (sizeof (PRUnichar) == sizeof (OLECHAR)); 247 aTo = aFrom ? ::SysAllocString ((const OLECHAR *) aFrom) : NULL; 248 } 249 217 250 /* Magic to workaround strict rules of par. 4.4.4 of the C++ standard */ 218 251 static const PRUnichar **__asInParam_Arr (PRUnichar **aArr) … … 233 266 struct SafeArrayTraits 234 267 { 235 static VARTYPE VarType() { AssertMsgFailedReturn ("Not supported", VT_EMPTY) }268 // Arbitrary types are not supported 236 269 }; 237 270 … … 240 273 { 241 274 static VARTYPE VarType() { return VT_I4; } 275 static void Copy (LONG aFrom, LONG &aTo) { aTo = aFrom; } 242 276 }; 243 277 … … 246 280 { 247 281 static VARTYPE VarType() { return VT_UI4; } 282 static void Copy (ULONG aFrom, ULONG &aTo) { aTo = aFrom; } 248 283 }; 249 284 … … 252 287 { 253 288 static VARTYPE VarType() { return VT_BSTR; } 289 290 static void Copy (BSTR aFrom, BSTR &aTo) 291 { 292 aTo = aFrom ? ::SysAllocString ((const OLECHAR *) aFrom) : NULL; 293 } 254 294 }; 255 295 … … 284 324 * @note This class is not thread-safe. 285 325 */ 286 template <typename T >287 class SafeArray : p ublic SafeArrayTraits <T>326 template <typename T, class Traits = SafeArrayTraits <T> > 327 class SafeArray : protected Traits 288 328 { 289 329 public: … … 358 398 359 399 /** 400 * Creates a deep copy of the goven standard C++ container. 401 * 402 * @param aCntr Container object to copy. 403 * 404 * @param C Standard C++ container template class (normally deduced from 405 * @c aCntr). 406 */ 407 template <template <class> class C> 408 SafeArray (const C <T> & aCntr) 409 { 410 reset (aCntr.size()); 411 AssertReturnVoid (!isNull()); 412 413 int i = 0; 414 for (typename C <T>::const_iterator it = aCntr.begin(); 415 it != aCntr.end(); ++ it, ++ i) 416 #if defined (VBOX_WITH_XPCOM) 417 Copy (*it, m.arr [i]); 418 #else 419 Copy (*it, m.raw [i]); 420 #endif 421 } 422 423 /** 360 424 * Destroys this instance after calling #setNull() to release allocated 361 425 * resources. See #setNull() for more details. 362 426 */ 363 ~SafeArray() { setNull(); }427 virtual ~SafeArray() { setNull(); } 364 428 365 429 /** … … 376 440 * array itself is destroyed. 377 441 */ 378 v oid setNull() { m.uninit(); }442 virtual void setNull() { m.uninit(); } 379 443 380 444 /** … … 409 473 * memory for resizing. 410 474 */ 411 bool resize (size_t aNewSize)475 virtual bool resize (size_t aNewSize) 412 476 { 413 477 /// @todo Implement me! … … 423 487 * memory for resizing. 424 488 */ 425 bool reset (size_t aNewSize)489 virtual bool reset (size_t aNewSize) 426 490 { 427 491 m.uninit(); … … 532 596 * @param aArg Output method parameter to clone to. 533 597 */ 534 const SafeArray &cloneTo (ComSafeArrayOut (T, aArg)) const598 virtual const SafeArray &cloneTo (ComSafeArrayOut (T, aArg)) const 535 599 { 536 600 /// @todo Implement me! … … 553 617 * @param aArg Output method parameter to detach to. 554 618 */ 555 SafeArray &detachTo (ComSafeArrayOut (T, aArg))619 virtual SafeArray &detachTo (ComSafeArrayOut (T, aArg)) 556 620 { 557 621 AssertReturn (m.isWeak == false, *this); … … 611 675 static const SafeArray Null; 612 676 613 pr ivate:677 protected: 614 678 615 679 DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(SafeArray) … … 699 763 }; 700 764 765 //////////////////////////////////////////////////////////////////////////////// 766 767 #if defined (VBOX_WITH_XPCOM) 768 769 template <class I> 770 struct SafeIfaceArrayTraits 771 { 772 static void Init (I * &aElem) { aElem = NULL; } 773 static void Uninit (I * &aElem) 774 { 775 if (aElem) 776 { 777 aElem->Release(); 778 aElem = NULL; 779 } 780 } 781 782 static void Copy (I * aFrom, I * &aTo) 783 { 784 if (aFrom != NULL) 785 { 786 aTo = aFrom; 787 aTo->AddRef(); 788 } 789 else 790 aTo = NULL; 791 } 792 793 /* Magic to workaround strict rules of par. 4.4.4 of the C++ standard. */ 794 static I **__asInParam_Arr (I **aArr) { return aArr; } 795 static I **__asInParam_Arr (const I **aArr) { return const_cast <I **> (aArr); } 796 }; 797 798 #else /* defined (VBOX_WITH_XPCOM) */ 799 800 template <class I> 801 struct SafeIfaceArrayTraits 802 { 803 static VARTYPE VarType() { return VT_UNKNOWN; } 804 805 static void Copy (I * aFrom, I * &aTo) 806 { 807 if (aFrom != NULL) 808 { 809 aTo = aFrom; 810 aTo->AddRef(); 811 } 812 else 813 aTo = NULL; 814 } 815 }; 816 817 #endif /* defined (VBOX_WITH_XPCOM) */ 818 819 //////////////////////////////////////////////////////////////////////////////// 820 821 /** 822 * Version of com::SafeArray for arrays of interface pointers. 823 * 824 * Except that it manages arrays of interface pointers, the usage of this class 825 * is identical to com::SafeArray. 826 * 827 * @param I Interface class (no asterisk). 828 */ 829 template <class I> 830 class SafeIfaceArray : public SafeArray <I *, SafeIfaceArrayTraits <I> > 831 { 832 public: 833 834 typedef SafeArray <I *, SafeIfaceArrayTraits <I> > Base; 835 836 /** 837 * Creates a null array. 838 */ 839 SafeIfaceArray() {} 840 841 /** 842 * Creates a new array of the given size. All elements of the newly created 843 * array initialized with null values. 844 * 845 * @param aSize Initial number of elements in the array. Must be greater 846 * than 0. 847 * 848 * @note If this object remains null after construction it means that there 849 * was not enough memory for creating an array of the requested size. 850 * The constructor will also assert in this case. 851 */ 852 SafeIfaceArray (size_t aSize) { reset (aSize); } 853 854 /** 855 * Weakly attaches this instance to the existing array passed in a method 856 * parameter declared using the ComSafeArrayIn macro. When using this call, 857 * always wrap the parameter name in the ComSafeArrayOutArg macro call like 858 * this: 859 * <pre> 860 * SafeArray safeArray (ComSafeArrayInArg (aArg)); 861 * </pre> 862 * 863 * Note that this constructor doesn't take the ownership of the array. In 864 * particular, it means that operations that operate on the ownership (e.g. 865 * #detachTo()) are forbidden and will assert. 866 * 867 * @param aArg Input method parameter to attach to. 868 */ 869 SafeIfaceArray (ComSafeArrayIn (I *, aArg)) 870 { 871 #if defined (VBOX_WITH_XPCOM) 872 873 AssertReturnVoid (aArg != NULL); 874 875 Base::m.size = aArgSize; 876 Base::m.arr = aArg; 877 Base::m.isWeak = true; 878 879 #else /* defined (VBOX_WITH_XPCOM) */ 880 881 AssertReturnVoid (aArg != NULL); 882 SAFEARRAY *arg = *aArg; 883 884 if (arg) 885 { 886 AssertReturnVoid (arg->cDims == 1); 887 888 VARTYPE vt; 889 HRESULT rc = SafeArrayGetVartype (arg, &vt); 890 AssertComRCReturnVoid (rc); 891 AssertMsgReturnVoid (vt == VT_UNKNOWN, 892 ("Expected vartype VT_UNKNOWN, got %d.\n", 893 VarType(), vt)); 894 GUID guid; 895 rc = SafeArrayGetIID (arg, &guid); 896 AssertComRCReturnVoid (rc); 897 AssertMsgReturnVoid (InlineIsEqualGUID (_ATL_IIDOF (I), guid), 898 ("Expected IID {%Vuuid}, got {%Vuuid}.\n", 899 &_ATL_IIDOF (I), &guid)); 900 } 901 902 m.arr = arg; 903 m.isWeak = true; 904 905 AssertReturnVoid (accessRaw() != NULL); 906 907 #endif /* defined (VBOX_WITH_XPCOM) */ 908 } 909 910 /** 911 * Creates a deep copy of the given standard C++ container that stores 912 * interface pointers as objects of the ComPtr <I> class. 913 * 914 * @param aCntr Container object to copy. 915 * 916 * @param C Standard C++ container template class (normally deduced from 917 * @c aCntr). 918 * @param A Standard C++ allocator class (deduced from @c aCntr). 919 * @param OI Argument to the ComPtr template (deduced from @c aCntr). 920 */ 921 template <template <typename, typename> class C, class A, class OI> 922 SafeIfaceArray (const C <ComPtr <OI>, A> & aCntr) 923 { 924 typedef C <ComPtr <OI>, A> List; 925 926 reset (aCntr.size()); 927 AssertReturnVoid (!Base::isNull()); 928 929 int i = 0; 930 for (typename List::const_iterator it = aCntr.begin(); 931 it != aCntr.end(); ++ it, ++ i) 932 #if defined (VBOX_WITH_XPCOM) 933 Copy (*it, Base::m.arr [i]); 934 #else 935 Copy (*it, Base::m.raw [i]); 936 #endif 937 } 938 939 /** 940 * Creates a deep copy of the given standard C++ container that stores 941 * interface pointers as objects of the ComObjPtr <I> class. 942 * 943 * @param aCntr Container object to copy. 944 * 945 * @param C Standard C++ container template class (normally deduced from 946 * @c aCntr). 947 * @param A Standard C++ allocator class (deduced from @c aCntr). 948 * @param OI Argument to the ComObjPtr template (deduced from @c aCntr). 949 */ 950 template <template <typename, typename> class C, class A, class OI> 951 SafeIfaceArray (const C <ComObjPtr <OI>, A> & aCntr) 952 { 953 typedef C <ComObjPtr <OI>, A> List; 954 955 reset (aCntr.size()); 956 AssertReturnVoid (!Base::isNull()); 957 958 int i = 0; 959 for (typename List::const_iterator it = aCntr.begin(); 960 it != aCntr.end(); ++ it, ++ i) 961 #if defined (VBOX_WITH_XPCOM) 962 Copy (*it, Base::m.arr [i]); 963 #else 964 Copy (*it, Base::m.raw [i]); 965 #endif 966 } 967 968 /** 969 * Reinitializes this instance by preallocating space for the given number 970 * of elements. The previous array contents is lost. 971 * 972 * @param aNewSize New number of elements in the array. 973 * @return @c true on success and false if there is not enough 974 * memory for resizing. 975 */ 976 virtual bool reset (size_t aNewSize) 977 { 978 Base::m.uninit(); 979 980 #if defined (VBOX_WITH_XPCOM) 981 982 AssertReturn (aNewSize > 0, false); 983 984 Base::m.arr = (I **) nsMemory::Alloc (aNewSize * sizeof (I *)); 985 AssertReturn (Base::m.arr != NULL, false); 986 987 Base::m.size = aNewSize; 988 989 for (size_t i = 0; i < Base::m.size; ++ i) 990 Init (Base::m.arr [i]); 991 992 #else 993 994 AssertReturn (aNewSize > 0, false); 995 996 SAFEARRAYBOUND bound = { aNewSize, 0 }; 997 m.arr = SafeArrayCreateEx (VT_UNKNOWN, 1, &bound, 998 (PVOID) &_ATL_IIDOF (I)); 999 AssertReturn (m.arr != NULL, false); 1000 1001 AssertReturn (accessRaw() != NULL, false); 1002 1003 #endif 1004 return true; 1005 } 1006 }; 1007 701 1008 } /* namespace com */ 702 1009
Note:
See TracChangeset
for help on using the changeset viewer.