Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

557 lines
20 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Forms
  4. // Copyright (C) Microsoft Corporation, 1992 - 1996.
  5. //
  6. // File: formsary.hxx
  7. //
  8. // Contents: CImplAry* classes
  9. //
  10. // Stolen from Trident
  11. //
  12. //----------------------------------------------------------------------------
  13. //+------------------------------------------------------------------------
  14. //
  15. // This is the implementation of the generic resizeable array classes. There
  16. // are four array classes:
  17. //
  18. // CPtrAry<ELEM> --
  19. //
  20. // Dynamic array class which is optimized for sizeof(ELEM) equal
  21. // to 4. The array is initially empty with no space or memory allocated
  22. // for data.
  23. //
  24. // CDataAry<ELEM> --
  25. //
  26. // Same as CPtrAry but where sizeof(ELEM) is != 4 and less than 128.
  27. //
  28. // CStackPtrAry<ELEM, N> --
  29. //
  30. // Dynamic array class optimized for sizeof(ELEM) equal to 4.
  31. // Space for N elements is allocated as member data of the class. If
  32. // this class is created on the stack, then space for N elements will
  33. // be created on the stack. The class can grow beyond N elements, at
  34. // which point memory will be allocated for the array data.
  35. //
  36. // CStackDataAry<ELEM, N> --
  37. //
  38. // Same as CStackPtrAry, but where sizeof(ELEM) is != 4 and less than 128.
  39. //
  40. //
  41. // All four classes have virtually the same methods, and are used the same.
  42. // The only difference is that the DataAry classes have AppendIndirect and
  43. // InsertIndirect, while the PtrAry classes use Append and Insert. The reason
  44. // for the difference is that the Indirect methods take a pointer to the data,
  45. // while the non-indirect methods take the actual data as an argument.
  46. //
  47. // The Stack arrays (CStackPtrAry and CStackDataAry) are used to pre-allocate
  48. // space for elements in the array. This is useful if you create the array on
  49. // the stack and you know that most of the time the array will be less than
  50. // a certain number of elements. Creating one of these arrays on the stack
  51. // allocates the array on the stack as well, preventing a separate memory
  52. // allocation. Only if the array grows beyond the initial size will any
  53. // additional memory be allocated.
  54. //
  55. // The fastest and most efficient way of looping through all elements in
  56. // the array is as follows:
  57. //
  58. // ELEM * pElem;
  59. // int i;
  60. //
  61. // for (i = aryElems.Size(), pElem = aryElems;
  62. // i > 0;
  63. // i--, pElem++)
  64. // {
  65. // (*pElem)->DoSomething();
  66. // }
  67. //
  68. // This loop syntax has been shown to be the fastest and produce the smallest
  69. // code. Here's an example using a real data type:
  70. //
  71. // CStackPtrAry<CSite*, 16> arySites;
  72. // CSite **ppSite;
  73. // int i;
  74. //
  75. // // Populate the array.
  76. // ...
  77. //
  78. // // Now loop through every element in the array.
  79. // for (i = arySites.Size(), ppSite = arySites;
  80. // i > 0;
  81. // i--, ppSite++)
  82. // {
  83. // (*ppSite)->DoSomething();
  84. // }
  85. //
  86. // METHOD DESCRIPTIONS:
  87. //
  88. // Commonly used methods:
  89. //
  90. // Size() Returns the number of elements currently stored
  91. // in the array.
  92. //
  93. // operator [] Returns the given element in the array.
  94. //
  95. // Item(int i) Returns the given element in the array.
  96. //
  97. // operator ELEM* Allows the array class to be cast to a pointer
  98. // to ELEM. Returns a pointer to the first element
  99. // in the array. (Same as a Base() method).
  100. //
  101. // Append(ELEM e) Adds a new pointer to the end of the array,
  102. // growing the array if necessary. Only valid
  103. // for arrays of pointers (CPtrAry, CStackPtrAry).
  104. //
  105. // AppendIndirect(ELEM *pe, ELEM** ppePlaced)
  106. // As Append, for non-pointer arrays
  107. // (CDataAry, CStackDataAry).
  108. // pe [in] - Pointer to element to add to array. The
  109. // data is copied into the array. Can be
  110. // NULL, in which case the new element is
  111. // initialized to all zeroes.
  112. // ppePlaced [out] - Returns pointer to the new
  113. // element. Can be NULL.
  114. //
  115. // Insert(int i, ELEM e)
  116. // Inserts a new element (e) at the given index (i)
  117. // in the array, growing the array if necessary. Any
  118. // elements at or following the index are moved
  119. // out of the way.
  120. //
  121. // InsertIndirect(int i, ELEM *pe)
  122. // As Insert, for non-pointer arrays
  123. // (CDataAry, CStackDataAry).
  124. //
  125. // Find(ELEM e) Returns the index at which a given element (e)
  126. // is found (CPtrAry, CStackPtrAry).
  127. //
  128. // FindIndirect(ELEM *pe)
  129. // As Find, for non-pointer arrays
  130. // (CDataAry, CStackDataAry).
  131. //
  132. // DeleteAll() Empties the array and de-allocates associated
  133. // memory.
  134. //
  135. // Delete(int i) Deletes an element of the array, moving any
  136. // elements that follow it to fill
  137. //
  138. // DeleteMultiple(int start, int end)
  139. // Deletes a range of elements from the array,
  140. // moving to fill. [start] and [end] are the indices
  141. // of the start and end elements (inclusive).
  142. //
  143. // DeleteByValue(ELEM e)
  144. // Delete the element matching the given value.
  145. //
  146. // DeleteByValueIndirect(ELEM *pe)
  147. // As DeleteByValue, for non-pointer arrays.
  148. // (CDataAry, CStackDataAry).
  149. //
  150. //
  151. // Less commonly used methods:
  152. //
  153. // EnsureSize(long c) If you know how many elements you are going to put
  154. // in the array before you actually do it, you can use
  155. // EnsureSize to allocate the memory all at once instead
  156. // of relying on Append(Indirect) to grow the array. This
  157. // can be much more efficient (by causing only a single
  158. // memory allocation instead of many) than just using
  159. // Append(Indirect). You pass in the number of elements
  160. // that memory should be allocated for. Note that this
  161. // does not affect the "Size" of the array, which is
  162. // the number of elements currently stored in it.
  163. //
  164. // SetSize(int c) Sets the "Size" of the array, which is the number
  165. // of elements currently stored in it. SetSize will not
  166. // allocate memory if you're growing the array.
  167. // EnsureSize must be called first to reserve space if
  168. // the array is growing. Setting the size smaller does
  169. // not de-allocate memory, it just chops off the
  170. // elements at the end of the array.
  171. //
  172. // Grow(int c) Equivalent to calling EnsureSize(c) followed by
  173. // SetSize(c).
  174. //
  175. // ReleaseAll() (CPtrAry and CStackPtrAry only) Calls Release()
  176. // on each element in the array and empties the array.
  177. //
  178. // ReleaseAndDelete(int idx)
  179. // (CPtrAry and CStackPtrAry only) Calls Release() on
  180. // the given element and removes it from the array.
  181. //
  182. // (See the class definitions below for signatures of the following
  183. // methods and src\core\cdutil\formsary.cxx for argument
  184. // descriptions)
  185. //
  186. // CopyAppend Appends data from another array (of the same type)
  187. // to the end.
  188. //
  189. // Copy Copies data from another array (of the same type)
  190. // into this array, replacing any existing data.
  191. //
  192. // CopyAppendIndirect Appends data from a C-style array of element data
  193. // to the end of this array.
  194. //
  195. // CopyIndirect Copies elements from a C-style array into this array
  196. // replacing any existing data.
  197. //
  198. // EnumElements Create an enumerator which supports the given
  199. // interface ID for the contents of the array
  200. //
  201. // EnumVARIANT Create an IEnumVARIANT enumerator.
  202. //
  203. // operator void * Allow the CImplAry class to be cast
  204. // to a (void *). Avoid using if possible - use
  205. // the type-safe operator ELEM * instead.
  206. //
  207. // ClearAndReset Obsolete. Do not use.
  208. //
  209. //
  210. //----------------------------------------------------------------------------
  211. //----------------------------------------------------------------------------
  212. //
  213. // Class: CImplAry
  214. //
  215. // Purpose: Base implementation of all the dynamic array classes.
  216. //
  217. // Interface:
  218. //
  219. // Deref Returns a pointer to an element of the array;
  220. // should only be used by derived classes. Use the
  221. // type-safe methods operator[] or Item() instead.
  222. //
  223. // GetAlloced Get number of elements allocated
  224. //
  225. // Members: _c Current size of the array
  226. // _pv Buffer storing the elements
  227. //
  228. // Note: The CImplAry class only supports arrays of elements
  229. // whose size is less than 128.
  230. //
  231. //-------------------------------------------------------------------------
  232. class CImplAry
  233. {
  234. friend class CImplPtrAry;
  235. private:
  236. DECLARE_MEMALLOC_NEW_DELETE();
  237. public:
  238. ~CImplAry();
  239. inline int Size() const { return _c; } // UNIX: long->int for min() macro
  240. inline void SetSize(int c) { _c = c; }
  241. inline operator void *() { return PData(); }
  242. void DeleteAll();
  243. // BUGBUG -- This method should be protected, but I don't want to convert
  244. // existing code that uses it. (lylec)
  245. void * Deref(size_t cb, int i);
  246. #if DBG == 1
  247. BOOL _fCheckLock ; // If set with TraceTag CImplAryLock then any change
  248. // (addition or deletion to the DataAry will generate an assert.
  249. void LockCheck(BOOL fState)
  250. { _fCheckLock = fState; }
  251. #else
  252. void LockCheck(BOOL)
  253. { }
  254. #endif
  255. NO_COPY(CImplAry);
  256. protected:
  257. // Methods which are wrapped by inline subclass methods
  258. CImplAry();
  259. HRESULT EnsureSize(size_t cb, long c);
  260. HRESULT Grow(size_t cb, int c);
  261. HRESULT AppendIndirect(size_t cb, void * pv, void ** ppvPlaced=NULL);
  262. HRESULT InsertIndirect(size_t cb, int i, void * pv);
  263. int FindIndirect(size_t cb, void *);
  264. void Delete(size_t cb, int i);
  265. BOOL DeleteByValueIndirect(size_t cb, void *pv);
  266. void DeleteMultiple(size_t cb, int start, int end);
  267. HRESULT CopyAppend(size_t cb, const CImplAry& ary, BOOL fAddRef);
  268. HRESULT Copy(size_t cb, const CImplAry& ary, BOOL fAddRef);
  269. HRESULT CopyIndirect(size_t cb, int c, void * pv, BOOL fAddRef);
  270. ULONG GetAlloced(size_t cb);
  271. HRESULT EnumElements(
  272. size_t cb,
  273. REFIID iid,
  274. void ** ppv,
  275. BOOL fAddRef,
  276. BOOL fCopy = TRUE,
  277. BOOL fDelete = TRUE);
  278. HRESULT EnumVARIANT(
  279. size_t cb,
  280. VARTYPE vt,
  281. IEnumVARIANT ** ppenum,
  282. BOOL fCopy = TRUE,
  283. BOOL fDelete = TRUE);
  284. inline BOOL UsingStackArray()
  285. { return _fDontFree; }
  286. UINT GetStackSize()
  287. { Assert(_fStack);
  288. return *(UINT*)((BYTE*)this + sizeof(CImplAry)); }
  289. void * GetStackPtr()
  290. { Assert(_fStack);
  291. return (void*)((BYTE*)this + sizeof(CImplAry) + sizeof(int)); }
  292. unsigned long _fStack :1 ; // Set if we're a stack-based array.
  293. unsigned long _fDontFree :1 ; // Cleared if _pv points to alloced memory.
  294. unsigned long _c :30 ; // Count of elements
  295. void * _pv;
  296. inline void * & PData() { return _pv; }
  297. };
  298. //+------------------------------------------------------------------------
  299. //
  300. // Member: CImplAry::CImplAry
  301. //
  302. //+------------------------------------------------------------------------
  303. inline
  304. CImplAry::CImplAry()
  305. {
  306. memset(this, 0, sizeof(CImplAry));
  307. }
  308. //+------------------------------------------------------------------------
  309. //
  310. // Member: CImplAry::Deref
  311. //
  312. // Synopsis: Returns a pointer to the i'th element of the array. This
  313. // method is normally called by type-safe methods in derived
  314. // classes.
  315. //
  316. // Arguments: i
  317. //
  318. // Returns: void *
  319. //
  320. //-------------------------------------------------------------------------
  321. inline void *
  322. CImplAry::Deref(size_t cb, int i)
  323. {
  324. Assert(i >= 0);
  325. Assert(ULONG( i ) < GetAlloced(cb));
  326. return ((BYTE *) PData()) + i * cb;
  327. }
  328. //+------------------------------------------------------------------------
  329. //
  330. // Class: CImplPtrAry (ary)
  331. //
  332. // Purpose: Subclass used for arrays of pointers. In this case, the
  333. // element size is known to be sizeof(void *). Normally, the
  334. // CPtrAry template is used to define a specific concrete
  335. // implementation of this class, to hold a specific type of
  336. // pointer.
  337. //
  338. // See documentation above for use.
  339. //
  340. //-------------------------------------------------------------------------
  341. class CImplPtrAry : public CImplAry
  342. {
  343. protected:
  344. DECLARE_MEMALLOC_NEW_DELETE();
  345. CImplPtrAry() : CImplAry() {};
  346. HRESULT Append(void * pv);
  347. HRESULT Insert(int i, void * pv);
  348. int Find(void * pv);
  349. BOOL DeleteByValue(void *pv);
  350. HRESULT CopyAppend(const CImplAry& ary, BOOL fAddRef);
  351. HRESULT Copy(const CImplAry& ary, BOOL fAddRef);
  352. HRESULT CopyIndirect(int c, void * pv, BOOL fAddRef);
  353. public:
  354. HRESULT ClearAndReset();
  355. HRESULT EnsureSize(long c);
  356. HRESULT Grow(int c);
  357. void Delete(int i);
  358. void DeleteMultiple(int start, int end);
  359. void ReleaseAll();
  360. void ReleaseAndDelete(int idx);
  361. };
  362. //+---------------------------------------------------------------------------
  363. //
  364. // Class: CDataAry
  365. //
  366. // Purpose: This template class declares a concrete derived class
  367. // of CImplAry.
  368. //
  369. // See documentation above for use.
  370. //
  371. //----------------------------------------------------------------------------
  372. template <class ELEM>
  373. class CDataAry : public CImplAry
  374. {
  375. public:
  376. DECLARE_MEMALLOC_NEW_DELETE();
  377. CDataAry() : CImplAry() { }
  378. operator ELEM *() { return (ELEM *)PData(); }
  379. CDataAry(const CDataAry &);
  380. ELEM & Item(int i) { return *(ELEM*)Deref(sizeof(ELEM), i); }
  381. HRESULT EnsureSize(long c)
  382. { return CImplAry::EnsureSize(sizeof(ELEM), c); }
  383. HRESULT Grow(int c)
  384. { return CImplAry::Grow(sizeof(ELEM), c); }
  385. HRESULT AppendIndirect(ELEM * pe, ELEM ** ppePlaced=NULL)
  386. { return CImplAry::AppendIndirect(sizeof(ELEM), (void*)pe, (void**)ppePlaced); }
  387. ELEM * Append()
  388. { ELEM * pElem; return AppendIndirect( NULL, & pElem ) ? NULL : pElem; }
  389. HRESULT InsertIndirect(int i, ELEM * pe)
  390. { return CImplAry::InsertIndirect(sizeof(ELEM), i, (void*)pe); }
  391. int FindIndirect(ELEM * pe)
  392. { return CImplAry::FindIndirect(sizeof(ELEM), (void*)pe); }
  393. void Delete(int i)
  394. { CImplAry::Delete(sizeof(ELEM), i); }
  395. BOOL DeleteByValueIndirect(ELEM *pe)
  396. { return CImplAry::DeleteByValueIndirect(sizeof(ELEM), (void*)pe); }
  397. void DeleteMultiple(int start, int end)
  398. { CImplAry::DeleteMultiple(sizeof(ELEM), start, end); }
  399. HRESULT CopyAppend(const CDataAry<ELEM>& ary, BOOL fAddRef)
  400. { return CImplAry::Copy(sizeof(ELEM), ary, fAddRef); }
  401. HRESULT Copy(const CDataAry<ELEM>& ary, BOOL fAddRef)
  402. { return CImplAry::Copy(sizeof(ELEM), ary, fAddRef); }
  403. HRESULT CopyIndirect(int c, ELEM * pv, BOOL fAddRef)
  404. { return CImplAry::CopyIndirect(sizeof(ELEM), c, (void*)pv, fAddRef); }
  405. };
  406. //+---------------------------------------------------------------------------
  407. //
  408. // Class: CPtrAry
  409. //
  410. // Purpose: This template class declares a concrete derived class
  411. // of CImplPtrAry.
  412. //
  413. // See documentation above for use.
  414. //
  415. //----------------------------------------------------------------------------
  416. template <class ELEM>
  417. class CPtrAry : public CImplPtrAry
  418. {
  419. public:
  420. DECLARE_MEMALLOC_NEW_DELETE();
  421. CPtrAry() : CImplPtrAry() { Assert(sizeof(ELEM) == sizeof(void*)); }
  422. operator ELEM *() { return (ELEM *)PData(); }
  423. CPtrAry(const CPtrAry &);
  424. ELEM & Item(int i) { return *(ELEM*)Deref(sizeof(ELEM), i); }
  425. HRESULT Append(ELEM e)
  426. { return CImplPtrAry::Append((void*)e); }
  427. HRESULT Insert(int i, ELEM e)
  428. { return CImplPtrAry::Insert(i, (void*)e); }
  429. BOOL DeleteByValue(ELEM e)
  430. { return CImplPtrAry::DeleteByValue((void*)e); }
  431. int Find(ELEM e)
  432. { return CImplPtrAry::Find((void*)e); }
  433. HRESULT CopyAppend(const CPtrAry<ELEM>& ary, BOOL fAddRef)
  434. { return CImplPtrAry::Copy(ary, fAddRef); }
  435. HRESULT Copy(const CPtrAry<ELEM>& ary, BOOL fAddRef)
  436. { return CImplPtrAry::Copy(ary, fAddRef); }
  437. HRESULT CopyIndirect(int c, ELEM *pe, BOOL fAddRef)
  438. { return CImplPtrAry::CopyIndirect(c, (void*)pe, fAddRef); }
  439. };
  440. //+---------------------------------------------------------------------------
  441. //
  442. // Class: CStackDataAry
  443. //
  444. // Purpose: Declares a CDataAry that has initial storage on the stack.
  445. // N elements are declared on the stack, and the array will
  446. // grow dynamically beyond that if necessary.
  447. //
  448. // See documentation above for use.
  449. //
  450. //----------------------------------------------------------------------------
  451. template <class ELEM, int N>
  452. class CStackDataAry : public CDataAry<ELEM>
  453. {
  454. public:
  455. DECLARE_MEMALLOC_NEW_DELETE();
  456. CStackDataAry() : CDataAry<ELEM>()
  457. {
  458. _cStack = N;
  459. _fStack = TRUE;
  460. _fDontFree = TRUE;
  461. PData() = (void *) & _achTInit;
  462. }
  463. protected:
  464. int _cStack; // Must be first data member.
  465. char _achTInit[N*sizeof(ELEM)];
  466. };
  467. //+---------------------------------------------------------------------------
  468. //
  469. // Class: CStackPtrAry
  470. //
  471. // Purpose: Same as CStackDataAry except for pointer types.
  472. //
  473. // See documentation above for use.
  474. //
  475. //----------------------------------------------------------------------------
  476. template <class ELEM, int N>
  477. class CStackPtrAry : public CPtrAry<ELEM>
  478. {
  479. public:
  480. DECLARE_MEMALLOC_NEW_DELETE();
  481. CStackPtrAry() : CPtrAry<ELEM>()
  482. {
  483. _cStack = N;
  484. _fStack = TRUE;
  485. _fDontFree = TRUE;
  486. PData() = (void *) & _achTInit;
  487. }
  488. protected:
  489. int _cStack; // Must be first data member.
  490. char _achTInit[N*sizeof(ELEM)];
  491. };