Changeset 15042 in vbox for trunk/include/VBox
- Timestamp:
- Dec 5, 2008 1:38:10 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/com/array.h
r14045 r15042 359 359 //////////////////////////////////////////////////////////////////////////////// 360 360 361 struct SafeArrayTraitsBase 362 { 363 protected: 364 365 static SAFEARRAY *CreateSafeArray (VARTYPE aVarType, SAFEARRAYBOUND *aBound) 366 { return SafeArrayCreate (aVarType, 1, aBound); } 367 }; 368 361 369 /** 362 370 * Provides various helpers for SafeArray. … … 381 389 */ 382 390 template <typename T> 383 struct SafeArrayTraits 384 { 391 struct SafeArrayTraits : public SafeArrayTraitsBase 392 { 393 protected: 394 385 395 // Arbitrary types are treated as passed by value and each value is 386 396 // represented by a number of VT_Ix type elements where VT_Ix has the … … 425 435 426 436 template<> 427 struct SafeArrayTraits <LONG> 437 struct SafeArrayTraits <LONG> : public SafeArrayTraitsBase 428 438 { 429 439 protected: … … 437 447 438 448 template<> 439 struct SafeArrayTraits <ULONG> 449 struct SafeArrayTraits <ULONG> : public SafeArrayTraitsBase 440 450 { 441 451 protected: … … 449 459 450 460 template<> 451 struct SafeArrayTraits <LONG64> 461 struct SafeArrayTraits <LONG64> : public SafeArrayTraitsBase 452 462 { 453 463 protected: … … 461 471 462 472 template<> 463 struct SafeArrayTraits <ULONG64> 473 struct SafeArrayTraits <ULONG64> : public SafeArrayTraitsBase 464 474 { 465 475 protected: … … 473 483 474 484 template<> 475 struct SafeArrayTraits <BSTR> 485 struct SafeArrayTraits <BSTR> : public SafeArrayTraitsBase 476 486 { 477 487 protected: … … 488 498 489 499 template<> 490 struct SafeArrayTraits <GUID> 500 struct SafeArrayTraits <GUID> : public SafeArrayTraitsBase 491 501 { 492 502 protected: … … 505 515 506 516 static void Copy (GUID aFrom, GUID &aTo) { aTo = aFrom; } 517 }; 518 519 /** 520 * Helper for SafeArray::__asOutParam() that automatically updates m.raw after a 521 * non-NULL m.arr assignment. 522 */ 523 class OutSafeArrayDipper 524 { 525 OutSafeArrayDipper (SAFEARRAY **aArr, void **aRaw) 526 : arr (aArr), raw (aRaw) { Assert (*aArr == NULL && *aRaw == NULL); } 527 528 SAFEARRAY **arr; 529 void **raw; 530 531 template <class, class> friend class SafeArray; 532 533 public: 534 535 ~OutSafeArrayDipper() 536 { 537 if (*arr != NULL) 538 { 539 HRESULT rc = SafeArrayAccessData (*arr, raw); 540 AssertComRC (rc); 541 } 542 } 543 544 operator SAFEARRAY **() { return arr; } 507 545 }; 508 546 … … 551 589 * array initialized with null values. 552 590 * 553 * @param aSize Initial number of elements in the array. Must be greater 554 * than 0. 591 * @param aSize Initial number of elements in the array. 555 592 * 556 593 * @note If this object remains null after construction it means that there … … 558 595 * The constructor will also assert in this case. 559 596 */ 560 SafeArray (size_t aSize) { res et(aSize); }597 SafeArray (size_t aSize) { resize (aSize); } 561 598 562 599 /** … … 600 637 ("Expected vartype %d, got %d.\n", 601 638 VarType(), vt)); 639 640 rc = SafeArrayAccessData (arg, (void HUGEP **) &m.raw); 641 AssertComRCReturnVoid (rc); 602 642 } 603 643 … … 605 645 m.isWeak = true; 606 646 607 AssertReturnVoid (m.arr == NULL || accessRaw() != NULL);608 609 647 #endif /* defined (VBOX_WITH_XPCOM) */ 610 648 } … … 621 659 SafeArray (const C <T, A> & aCntr) 622 660 { 623 res et(aCntr.size());661 resize (aCntr.size()); 624 662 AssertReturnVoid (!isNull()); 625 663 … … 677 715 678 716 /** 717 * Appends a copy of the given element at the end of the array. 718 * 719 * The array size is increased by one by this method and the additional 720 * space is allocated as needed. 721 * 722 * This method is handy in cases where you want to assign a copy of the 723 * existing value to the array element, for example: 724 * <tt>Bstr string; array.push_back (string);</tt>. If you create a string 725 * just to put it to the array, you may find #appendedRaw() more useful. 726 * 727 * @param aElement Element to append. 728 * 729 * @return @c true on success and false if there is not enough 730 * memory for resizing. 731 */ 732 bool push_back (const T &aElement) 733 { 734 if (!ensureCapacity (size() + 1)) 735 return false; 736 737 #if defined (VBOX_WITH_XPCOM) 738 Copy (aElement, m.arr [m.size]); 739 ++ m.size; 740 #else 741 Copy (aElement, m.raw [size() - 1]); 742 #endif 743 return true; 744 } 745 746 /** 747 * Appends an empty element at the end of the array and returns a raw 748 * pointer to it suitable for assigning a raw value (w/o constructing a 749 * copy). 750 * 751 * The array size is increased by one by this method and the additional 752 * space is allocated as needed. 753 * 754 * Note that in case of raw assignment, value ownership (for types with 755 * dynamically allocated data and for interface pointers) is transferred to 756 * the safe array object. 757 * 758 * This method is handy for operations like 759 * <tt>Bstr ("foo").detacTo (array.appendedRaw());</tt>. Don't use it as 760 * l-value (<tt>array.appendedRaw() = SysAllocString (L"tralala");</tt>) 761 * since this doesn't check for a NULL condition; use #resize() and 762 * #setRawAt() instead. If you need to assign a copy of the existing value 763 * instead of transferring the ownership, look at #push_back(). 764 * 765 * @return Raw pointer to the added element or NULL if no memory. 766 */ 767 T *appendedRaw() 768 { 769 if (!ensureCapacity (size() + 1)) 770 return NULL; 771 772 #if defined (VBOX_WITH_XPCOM) 773 Init (m.arr [m.size]); 774 ++ m.size; 775 return &m.arr [m.size - 1]; 776 #else 777 /* nothing to do here, SafeArrayCreate() has performed element 778 * initialization */ 779 return &m.raw [size() - 1]; 780 #endif 781 } 782 783 /** 679 784 * Resizes the array preserving its contents when possible. If the new size 680 * is biggerthan the old size, new elements are initialized with null681 * values. If the new size is smallerthan the old size, the contents of the682 * array abovethe new size is lost.785 * is larget than the old size, new elements are initialized with null 786 * values. If the new size is less than the old size, the contents of the 787 * array beyond the new size is lost. 683 788 * 684 789 * @param aNewSize New number of elements in the array. … … 686 791 * memory for resizing. 687 792 */ 688 virtual bool resize (size_t aNewSize) 689 { 690 /// @todo Implement me! 691 NOREF (aNewSize); 692 AssertFailedReturn (false); 793 bool resize (size_t aNewSize) 794 { 795 if (!ensureCapacity (aNewSize)) 796 return false; 797 798 #if defined (VBOX_WITH_XPCOM) 799 800 if (m.size < aNewSize) 801 { 802 /* initialize the new elements */ 803 for (size_t i = m.size; i < aNewSize; ++ i) 804 Init (m.arr [i]); 805 } 806 807 m.size = aNewSize; 808 #else 809 /* nothing to do here, SafeArrayCreate() has performed element 810 * initialization */ 811 #endif 812 return true; 693 813 } 694 814 … … 701 821 * memory for resizing. 702 822 */ 703 virtualbool reset (size_t aNewSize)823 bool reset (size_t aNewSize) 704 824 { 705 825 m.uninit(); 706 707 #if defined (VBOX_WITH_XPCOM) 708 709 /* Note: for zero-sized arrays, we use the size of 1 because whether 710 * malloc(0) returns a null pointer or not (which is used in isNull()) 711 * is implementation-dependent according to the C standard. */ 712 713 m.arr = (T *) nsMemory::Alloc (RT_MAX (aNewSize, 1) * sizeof (T)); 714 AssertReturn (m.arr != NULL, false); 715 716 m.size = aNewSize; 717 718 for (size_t i = 0; i < m.size; ++ i) 719 Init (m.arr [i]); 720 721 #else 722 723 SAFEARRAYBOUND bound = { VarCount (aNewSize), 0 }; 724 m.arr = SafeArrayCreate (VarType(), 1, &bound); 725 AssertReturn (m.arr != NULL, false); 726 727 AssertReturn (accessRaw() != NULL, false); 728 729 #endif 730 return true; 826 return resize (aNewSize); 731 827 } 732 828 … … 743 839 return m.arr; 744 840 #else 745 return accessRaw();841 return m.raw; 746 842 #endif 747 843 } … … 755 851 return m.arr; 756 852 #else 757 return accessRaw();853 return m.raw; 758 854 #endif 759 855 } … … 775 871 return m.arr [aIdx]; 776 872 #else 777 778 AssertReturn (accessRaw() != NULL, *((T *) NULL)); 873 AssertReturn (m.raw != NULL, *((T *) NULL)); 779 874 return m.raw [aIdx]; 780 875 #endif … … 791 886 return m.arr [aIdx]; 792 887 #else 793 AssertReturn ( unconst (this)->accessRaw()!= NULL, *((T *) NULL));888 AssertReturn (m.raw != NULL, *((T *) NULL)); 794 889 return m.raw [aIdx]; 795 890 #endif … … 892 987 893 988 /** Internal function Never call it directly. */ 894 SAFEARRAY ** __asOutParam() { setNull(); return &m.arr; } 989 OutSafeArrayDipper __asOutParam() 990 { setNull(); return OutSafeArrayDipper (&m.arr, (void **) &m.raw); } 895 991 896 992 #endif /* defined (VBOX_WITH_XPCOM) */ … … 902 998 DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(SafeArray) 903 999 904 #if defined (VBOX_WITH_XPCOM) 905 #else /* defined (VBOX_WITH_XPCOM) */ 906 907 /** Requests access to the raw data pointer. */ 908 T *accessRaw() 909 { 910 if (m.arr && m.raw == NULL) 911 { 912 HRESULT rc = SafeArrayAccessData (m.arr, (void HUGEP **) &m.raw); 913 AssertComRCReturn (rc, NULL); 914 } 915 return m.raw; 916 } 917 918 #endif /* defined (VBOX_WITH_XPCOM) */ 1000 /** 1001 * Ensures that the array is big enough to contaon aNewSize elements. 1002 * 1003 * If the new size is greater than the current capacity, a new array is 1004 * allocated and elements from the old array are copied over. The size of 1005 * the array doesn't change, only the capacity increases (which is always 1006 * greater than the size). Note that the additionally allocated elements are 1007 * left uninitialized by this method. 1008 * 1009 * If the new size is less than the current size, the existing array is 1010 * truncated to the specified size and the elements outside the new array 1011 * boundary are freed. 1012 * 1013 * If the new size is the same as the current size, nothing happens. 1014 * 1015 * @param aNewSize New size of the array. 1016 * 1017 * @return @c true on success and @c false if not enough memory. 1018 */ 1019 bool ensureCapacity (size_t aNewSize) 1020 { 1021 AssertReturn (!m.isWeak, false); 1022 1023 #if defined (VBOX_WITH_XPCOM) 1024 1025 /* Note: we distinguish between a null array and an empty (zero 1026 * elements) array. Therefore we never use zero in malloc (even if 1027 * aNewSize is zero) to make sure we get a non-null pointer. */ 1028 1029 if (m.size == aNewSize && m.arr != NULL) 1030 return true; 1031 1032 /* allocate in 16-byte pieces */ 1033 size_t newCapacity = RT_MAX ((aNewSize + 15) / 16 * 16, 16); 1034 1035 if (m.capacity != newCapacity) 1036 { 1037 T *newArr = (T *) nsMemory::Alloc (RT_MAX (newCapacity, 1) * sizeof (T)); 1038 AssertReturn (newArr != NULL, false); 1039 1040 if (m.arr != NULL) 1041 { 1042 if (m.size > aNewSize) 1043 { 1044 /* truncation takes place, uninit exceeding elements and 1045 * shrink the size */ 1046 for (size_t i = aNewSize; i < m.size; ++ i) 1047 Uninit (m.arr [i]); 1048 1049 m.size = aNewSize; 1050 } 1051 1052 /* copy the old contents */ 1053 memcpy (newArr, m.arr, m.size * sizeof (T)); 1054 nsMemory::Free ((void *) m.arr); 1055 } 1056 1057 m.arr = newArr; 1058 } 1059 else 1060 { 1061 if (m.size > aNewSize) 1062 { 1063 /* truncation takes place, uninit exceeding elements and 1064 * shrink the size */ 1065 for (size_t i = aNewSize; i < m.size; ++ i) 1066 Uninit (m.arr [i]); 1067 1068 m.size = aNewSize; 1069 } 1070 } 1071 1072 m.capacity = newCapacity; 1073 1074 #else 1075 1076 SAFEARRAYBOUND bound = { VarCount (aNewSize), 0 }; 1077 HRESULT rc; 1078 1079 if (m.arr == NULL) 1080 { 1081 m.arr = CreateSafeArray (VarType(), &bound); 1082 AssertReturn (m.arr != NULL, false); 1083 } 1084 else 1085 { 1086 SafeArrayUnaccessData (m.arr); 1087 1088 rc = SafeArrayRedim (m.arr, &bound); 1089 AssertComRCReturn (rc == S_OK, false); 1090 } 1091 1092 rc = SafeArrayAccessData (m.arr, (void HUGEP **) &m.raw); 1093 AssertComRCReturn (rc, false); 1094 1095 #endif 1096 return true; 1097 } 919 1098 920 1099 struct Data … … 923 1102 : isWeak (false) 924 1103 #if defined (VBOX_WITH_XPCOM) 925 , size (0), arr (NULL)1104 , capacity (0), size (0), arr (NULL) 926 1105 #else 927 1106 , arr (NULL), raw (NULL) … … 943 1122 944 1123 nsMemory::Free ((void *) arr); 945 1124 } 1125 else 946 1126 isWeak = false; 947 } 1127 948 1128 arr = NULL; 949 1129 } 1130 1131 size = capacity = 0; 950 1132 951 1133 #else /* defined (VBOX_WITH_XPCOM) */ … … 963 1145 HRESULT rc = SafeArrayDestroy (arr); 964 1146 AssertComRCReturnVoid (rc); 965 1147 } 1148 else 966 1149 isWeak = false; 967 } 1150 968 1151 arr = NULL; 969 1152 } … … 975 1158 976 1159 #if defined (VBOX_WITH_XPCOM) 1160 PRUint32 capacity; 977 1161 PRUint32 size; 978 1162 T *arr; … … 1190 1374 aTo = NULL; 1191 1375 } 1376 1377 static SAFEARRAY *CreateSafeArray (VARTYPE aVarType, SAFEARRAYBOUND *aBound) 1378 { 1379 NOREF (aVarType); 1380 return SafeArrayCreateEx (VT_UNKNOWN, 1, aBound, (PVOID) &_ATL_IIDOF (I)); 1381 } 1192 1382 }; 1193 1383 … … 1227 1417 * The constructor will also assert in this case. 1228 1418 */ 1229 SafeIfaceArray (size_t aSize) { res et(aSize); }1419 SafeIfaceArray (size_t aSize) { resize (aSize); } 1230 1420 1231 1421 /** … … 1275 1465 ("Expected IID {%Vuuid}, got {%Vuuid}.\n", 1276 1466 &_ATL_IIDOF (I), &guid)); 1467 1468 rc = SafeArrayAccessData (arg, (void HUGEP **) &m.raw); 1469 AssertComRCReturnVoid (rc); 1277 1470 } 1278 1471 1279 1472 m.arr = arg; 1280 1473 m.isWeak = true; 1281 1282 AssertReturnVoid (accessRaw() != NULL);1283 1474 1284 1475 #endif /* defined (VBOX_WITH_XPCOM) */ … … 1301 1492 typedef C <ComPtr <OI>, A> List; 1302 1493 1303 res et(aCntr.size());1494 resize (aCntr.size()); 1304 1495 AssertReturnVoid (!Base::isNull()); 1305 1496 … … 1330 1521 typedef C <ComObjPtr <OI>, A> List; 1331 1522 1332 res et(aCntr.size());1523 resize (aCntr.size()); 1333 1524 AssertReturnVoid (!Base::isNull()); 1334 1525 … … 1342 1533 #endif 1343 1534 } 1344 1345 /**1346 * Reinitializes this instance by preallocating space for the given number1347 * of elements. The previous array contents is lost.1348 *1349 * @param aNewSize New number of elements in the array.1350 * @return @c true on success and false if there is not enough1351 * memory for resizing.1352 */1353 virtual bool reset (size_t aNewSize)1354 {1355 Base::m.uninit();1356 1357 #if defined (VBOX_WITH_XPCOM)1358 1359 /* Note: for zero-sized arrays, we use the size of 1 because whether1360 * malloc(0) returns a null pointer or not (which is used in isNull())1361 * is implementation-dependent according to the C standard. */1362 1363 Base::m.arr = (I **) nsMemory::Alloc (RT_MAX (aNewSize, 1) * sizeof (I *));1364 AssertReturn (Base::m.arr != NULL, false);1365 1366 Base::m.size = aNewSize;1367 1368 for (size_t i = 0; i < Base::m.size; ++ i)1369 Init (Base::m.arr [i]);1370 1371 #else1372 1373 SAFEARRAYBOUND bound = { (ULONG)aNewSize, 0 };1374 m.arr = SafeArrayCreateEx (VT_UNKNOWN, 1, &bound,1375 (PVOID) &_ATL_IIDOF (I));1376 AssertReturn (m.arr != NULL, false);1377 1378 AssertReturn (accessRaw() != NULL, false);1379 1380 #endif1381 return true;1382 }1383 1535 }; 1384 1536
Note:
See TracChangeset
for help on using the changeset viewer.