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.

619 lines
14 KiB

  1. //+------------------------------------------------------------------------
  2. //
  3. // File: netolary.cxx
  4. //
  5. // Contents: Generic dynamic array class
  6. //
  7. // Classes: CADsAry
  8. //
  9. // History:
  10. //
  11. //-------------------------------------------------------------------------
  12. #include "procs.hxx"
  13. #pragma hdrstop
  14. // CADsAry class
  15. //+------------------------------------------------------------------------
  16. //
  17. // Member: CADsAry::~CADsAry
  18. //
  19. // Synopsis: Resizeable array destructor. Frees storage allocated for the
  20. // array.
  21. //
  22. //-------------------------------------------------------------------------
  23. CADsAry::~CADsAry( )
  24. {
  25. if (_pv)
  26. LocalFree(_pv);
  27. }
  28. //+------------------------------------------------------------------------
  29. //
  30. // Member: CADsAry::EnsureSize
  31. //
  32. // Synopsis: Ensures that the array is at least the given size. That is,
  33. // if EnsureSize(c) succeeds, then (c-1) is a valid index. Note
  34. // that the array maintains a separate count of the number of
  35. // elements logically in the array, which is obtained with the
  36. // Size/SetSize methods. The logical size of the array is never
  37. // larger than the allocated size of the array.
  38. //
  39. // Arguments: [cb] Element size
  40. // [c] New allocated size for the array.
  41. //
  42. // Returns: HRESULT
  43. //
  44. //-------------------------------------------------------------------------
  45. HRESULT
  46. CADsAry::EnsureSize(size_t cb, int c)
  47. {
  48. void * pv;
  49. if (c <= GetAlloced(cb))
  50. return NOERROR;
  51. // CONSIDER should we use a more sophisticated array-growing
  52. // algorithm?
  53. c = ((c - 1) & -8) + 8;
  54. ADsAssert(c > 0);
  55. if (!_pv)
  56. {
  57. pv = LocalAlloc(LMEM_FIXED, c * cb);
  58. }
  59. else
  60. {
  61. pv = LocalReAlloc(_pv, c * cb, LMEM_MOVEABLE);
  62. }
  63. if (!pv)
  64. RRETURN(E_OUTOFMEMORY);
  65. _pv = pv;
  66. return NOERROR;
  67. }
  68. #if 0
  69. //+------------------------------------------------------------------------
  70. //
  71. // Member: CADsAry::Append
  72. //
  73. // Synopsis: Appends the given pointer to the end of the array, incrementing
  74. // the array's logical size, and growing its allocated size if
  75. // necessary. This method should only be called for arrays of
  76. // pointers; AppendIndirect should be used for arrays of
  77. // non-pointers.
  78. //
  79. // Arguments: [pv] Pointer to append.
  80. //
  81. // Returns: HRESULT
  82. //
  83. //-------------------------------------------------------------------------
  84. HRESULT
  85. CADsAry::Append(void * pv)
  86. {
  87. HRESULT hr;
  88. ADsAssert(_cb == 4);
  89. hr = EnsureSize(_c + 1);
  90. if (hr)
  91. RRETURN(hr);
  92. * (void **) Deref(_c) = pv;
  93. _c++;
  94. return NOERROR;
  95. }
  96. #endif
  97. //+------------------------------------------------------------------------
  98. //
  99. // Member: CADsAry::AppendIndirect
  100. //
  101. // Synopsis: Appends the given element to the end of the array, incrementing
  102. // the array's logical size, and growing the array's allocated
  103. // size if necessary. Note that the element is passed with a
  104. // pointer, rather than directly.
  105. //
  106. // Arguments: [cb] -- Element size
  107. // [pv] -- Pointer to the element to be appended
  108. //
  109. // Returns: HRESULT
  110. //
  111. //-------------------------------------------------------------------------
  112. HRESULT
  113. CADsAry::AppendIndirect(size_t cb, void * pv)
  114. {
  115. HRESULT hr;
  116. hr = EnsureSize(cb, _c + 1);
  117. if (hr)
  118. RRETURN(hr);
  119. memcpy(Deref(cb, _c), pv, cb);
  120. _c++;
  121. return NOERROR;
  122. }
  123. //+------------------------------------------------------------------------
  124. //
  125. // Member: CADsAry::Delete
  126. //
  127. // Synopsis: Removes the i'th element of the array, shuffling all elements
  128. // that follow one slot towards the beginning of the array.
  129. //
  130. // Arguments: [cb] Element size
  131. // [i] Element to delete
  132. //
  133. //-------------------------------------------------------------------------
  134. void
  135. CADsAry::Delete(size_t cb, int i)
  136. {
  137. ADsAssert(i >= 0);
  138. ADsAssert(i < _c);
  139. memmove(((BYTE *) _pv) + (i * cb),
  140. ((BYTE *) _pv) + ((i + 1) * cb),
  141. (_c - i - 1) * cb);
  142. _c--;
  143. }
  144. //+------------------------------------------------------------------------
  145. //
  146. // Member: CADsAry::DeleteAll
  147. //
  148. // Synopsis: Efficient method for emptying array of any contents
  149. //
  150. //-------------------------------------------------------------------------
  151. void
  152. CADsAry::DeleteAll(void)
  153. {
  154. if (_pv)
  155. LocalFree(_pv);
  156. _pv = NULL;
  157. _c = 0;
  158. }
  159. #if 0
  160. //+------------------------------------------------------------------------
  161. //
  162. // Member: CADsAry::Insert
  163. //
  164. // Synopsis: Inserts a pointer pv at index i. The element previously at
  165. // index i, and all elements that follow it, are shuffled one
  166. // slot away towards the end of the array.
  167. // This method should only be called for arrays of
  168. // pointers; InsertIndirect should be used for arrays of
  169. // non-pointers.
  170. //
  171. //
  172. // Arguments: [i] Index to insert...
  173. // [pv] ...this pointer at
  174. //
  175. // Returns: HRESULT
  176. //
  177. //-------------------------------------------------------------------------
  178. HRESULT
  179. CADsAry::Insert(int i, void * pv)
  180. {
  181. HRESULT hr;
  182. hr = EnsureSize(cb, _c + 1);
  183. if (hr)
  184. RRETURN(hr);
  185. memmove(((BYTE *) _pv) + ((i + 1) * _cb),
  186. ((BYTE *) _pv) + (i * _cb),
  187. (_c - i ) * _cb);
  188. ((void **) _pv)[i] = pv;
  189. _c++;
  190. return NOERROR;
  191. }
  192. #endif
  193. //+------------------------------------------------------------------------
  194. //
  195. // Member: CADsAry::InsertIndirect
  196. //
  197. // Synopsis: Inserts a pointer pv at index i. The element previously at
  198. // index i, and all elements that follow it, are shuffled one
  199. // slot away towards the end of the array.Note that the
  200. // clement is passed with a pointer, rather than directly.
  201. //
  202. // Arguments: [cb] Element size
  203. // [i] Index to insert...
  204. // [pv] ...this pointer at
  205. //
  206. // Returns: HRESULT
  207. //
  208. //-------------------------------------------------------------------------
  209. HRESULT
  210. CADsAry::InsertIndirect(size_t cb, int i, void *pv)
  211. {
  212. HRESULT hr;
  213. hr = EnsureSize(cb, _c + 1);
  214. if (hr)
  215. RRETURN(hr);
  216. memmove(((BYTE *) _pv) + ((i + 1) * cb),
  217. ((BYTE *) _pv) + (i * cb),
  218. (_c - i ) * cb);
  219. memcpy(Deref(cb, i), pv, cb);
  220. _c++;
  221. return NOERROR;
  222. }
  223. //+------------------------------------------------------------------------
  224. //
  225. // Member: CADsAry::BringToFront
  226. //
  227. // Synopsis: Moves the i'th element to the front of the array, shuffling
  228. // intervening elements to make room.
  229. //
  230. // Arguments: [i]
  231. //
  232. //-------------------------------------------------------------------------
  233. void
  234. CADsAry::BringToFront(size_t cb, int i)
  235. {
  236. BYTE rgb[CADsAry_MAXELEMSIZE];
  237. ADsAssert(cb <= CADsAry_MAXELEMSIZE);
  238. memcpy(rgb, ((BYTE *) _pv) + (i * cb), cb);
  239. memmove(((BYTE *) _pv) + cb, _pv, i * cb);
  240. memcpy(_pv, rgb, cb);
  241. }
  242. //+------------------------------------------------------------------------
  243. //
  244. // Member: CADsAry::SendToBack
  245. //
  246. // Synopsis: Moves the i'th element to the back of the array (that is,
  247. // the largest index less than the logical size.) Any intervening
  248. // elements are shuffled out of the way.
  249. //
  250. // Arguments: [i]
  251. //
  252. //-------------------------------------------------------------------------
  253. void
  254. CADsAry::SendToBack(size_t cb, int i)
  255. {
  256. BYTE rgb[CADsAry_MAXELEMSIZE];
  257. ADsAssert(cb <= CADsAry_MAXELEMSIZE);
  258. memcpy(rgb, ((BYTE *) _pv) + (i * cb), cb);
  259. memmove(((BYTE *) _pv) + (i * cb),
  260. ((BYTE *) _pv) + ((i + 1) * cb),
  261. (_c - i - 1) * cb);
  262. memcpy(((BYTE *) _pv) + ((_c - 1) * cb), rgb, cb);
  263. }
  264. #if 0
  265. //+------------------------------------------------------------------------
  266. //
  267. // Member: CADsAry::Find
  268. //
  269. // Synopsis: Returns the index at which the given pointer is found, or -1
  270. // if it is not found. The pointer values are compared directly;
  271. // there is no compare function.
  272. //
  273. // Arguments: [pv] Pointer to find
  274. //
  275. // Returns: int; index of pointer, or -1 if not found
  276. //
  277. //-------------------------------------------------------------------------
  278. int
  279. CADsAry::Find(void * pv)
  280. {
  281. int i;
  282. void ** ppv;
  283. Assert(_cb == 4);
  284. for (i = 0, ppv = (void **) _pv; i < _c; i++, ppv++)
  285. {
  286. if (pv == *ppv)
  287. return i;
  288. }
  289. return -1;
  290. }
  291. #endif
  292. //+---------------------------------------------------------------------------
  293. //
  294. // Member: CADsAry::Copy
  295. //
  296. // Synopsis: Creates a copy from another CADsAry object.
  297. //
  298. // Arguments: [ary] -- Object to copy.
  299. // [fAddRef] -- Addref the elements on copy?
  300. //
  301. // Returns: HRESULT.
  302. //
  303. // Modifies: [this]
  304. //
  305. // History: 5-15-94 adams Created
  306. //
  307. //----------------------------------------------------------------------------
  308. HRESULT
  309. CADsAry::Copy(size_t cb, const CADsAry& ary, BOOL fAddRef)
  310. {
  311. int cbArray; // size of array
  312. IUnknown ** ppUnk; // elem to addref
  313. int i; // counter
  314. // avoid copy of self
  315. if (this == &ary)
  316. return S_OK;
  317. DeleteAll();
  318. if (ary._pv)
  319. {
  320. cbArray = ary._c * cb;
  321. _pv = LocalAlloc(LMEM_FIXED, cbArray);
  322. if (!_pv)
  323. RRETURN(E_OUTOFMEMORY);
  324. memcpy(_pv, ary._pv, cbArray);
  325. }
  326. _c = ary._c;
  327. if (fAddRef)
  328. {
  329. for (i = 0, ppUnk = (IUnknown **) _pv; i < _c; i++, ppUnk++)
  330. {
  331. (*ppUnk)->AddRef();
  332. }
  333. }
  334. return S_OK;
  335. }
  336. //+---------------------------------------------------------------------------
  337. //
  338. // Member: CADsAry::EnumElements
  339. //
  340. // Synopsis: Creates and returns an enumerator for the elements of the
  341. // array.
  342. //
  343. // Arguments: [iid] -- Type of the enumerator.
  344. // [ppv] -- Location to put enumerator.
  345. // [fAddRef] -- AddRef enumerated elements?
  346. // [fCopy] -- Create copy of this array for enumerator?
  347. // [fDelete] -- Delete this after no longer being used by
  348. // enumerators?
  349. //
  350. // Returns: HRESULT.
  351. //
  352. // History: 5-15-94 adams Created
  353. //
  354. //----------------------------------------------------------------------------
  355. HRESULT
  356. CADsAry::EnumElements(
  357. size_t cb,
  358. REFIID iid,
  359. void ** ppv,
  360. BOOL fAddRef,
  361. BOOL fCopy,
  362. BOOL fDelete)
  363. {
  364. HRESULT hr;
  365. ADsAssert(ppv);
  366. hr = CEnumGeneric::Create(
  367. cb,
  368. this,
  369. iid,
  370. fAddRef,
  371. fCopy,
  372. fDelete,
  373. (CEnumGeneric **)ppv);
  374. RRETURN(hr);
  375. }
  376. //+---------------------------------------------------------------------------
  377. //
  378. // Member: CADsAry::EnumElements
  379. //
  380. // Synopsis: Creates and returns an IEnumVARIANT enumerator for the elements
  381. // of the array.
  382. //
  383. // Arguments: [vt] -- Type of elements enumerated.
  384. // [ppv] -- Location to put enumerator.
  385. // [fCopy] -- Create copy of this array for enumerator?
  386. // [fDelete] -- Delete this after no longer being used by
  387. // enumerators?
  388. //
  389. // Returns: HRESULT.
  390. //
  391. // History: 5-15-94 adams Created
  392. //
  393. //----------------------------------------------------------------------------
  394. HRESULT
  395. CADsAry::EnumVARIANT(
  396. size_t cb,
  397. VARTYPE vt,
  398. IEnumVARIANT ** ppenum,
  399. BOOL fCopy,
  400. BOOL fDelete)
  401. {
  402. HRESULT hr;
  403. ADsAssert(ppenum);
  404. hr = CEnumVARIANT::Create(cb, this, vt, fCopy, fDelete, ppenum);
  405. RRETURN(hr);
  406. }
  407. //+------------------------------------------------------------------------
  408. //
  409. // Member: CADsAry::Deref
  410. //
  411. // Synopsis: Returns a pointer to the i'th element of the array. This
  412. // method is normally called by type-safe methods in derived
  413. // classes.
  414. //
  415. // Arguments: [i]
  416. //
  417. // Returns: void *
  418. //
  419. // BUGBUG: This function should be inline; however, since nothing is
  420. // inlined in debug builds, it requires an export, which
  421. // then doesn't apply in retail builds and breaks the retail
  422. // build. Near ship time, the def file will be fixed handle
  423. // inlining.
  424. //
  425. //-------------------------------------------------------------------------
  426. void *
  427. CADsAry::Deref(size_t cb, int i)
  428. {
  429. ADsAssert(i >= 0);
  430. ADsAssert(i < GetAlloced(cb));
  431. return ((BYTE *) _pv) + i * cb;
  432. };
  433. HRESULT
  434. CADsPtrAry::EnsureSize(int c)
  435. {
  436. return CADsAry::EnsureSize(sizeof(LPVOID), c);
  437. }
  438. HRESULT
  439. CADsPtrAry::Append(void * pv)
  440. {
  441. return CADsAry::AppendIndirect(sizeof(void *), &pv);
  442. }
  443. HRESULT
  444. CADsPtrAry::Insert(int i, void * pv)
  445. {
  446. return CADsAry::InsertIndirect(sizeof(void *), i, &pv);
  447. }
  448. int
  449. CADsPtrAry::Find(void * pv)
  450. {
  451. int i;
  452. void ** ppv;
  453. for (i = 0, ppv = (void **) _pv; i < _c; i++, ppv++)
  454. {
  455. if (pv == *ppv)
  456. return i;
  457. }
  458. return -1;
  459. }
  460. void
  461. CADsPtrAry::Delete(int i)
  462. {
  463. CADsAry::Delete(sizeof(void *), i);
  464. }
  465. void
  466. CADsPtrAry::BringToFront(int i)
  467. {
  468. CADsAry::BringToFront(sizeof(void *), i);
  469. }
  470. void
  471. CADsPtrAry::SendToBack(int i)
  472. {
  473. CADsAry::SendToBack(sizeof(void *), i);
  474. }
  475. HRESULT
  476. CADsPtrAry::Copy(const CADsAry& ary, BOOL fAddRef)
  477. {
  478. return CADsAry::Copy(sizeof(void *), ary, fAddRef);
  479. }
  480. HRESULT
  481. CADsPtrAry::EnumElements(
  482. REFIID iid,
  483. void ** ppv,
  484. BOOL fAddRef,
  485. BOOL fCopy,
  486. BOOL fDelete)
  487. {
  488. return CADsAry::EnumElements(
  489. sizeof(void *),
  490. iid,
  491. ppv,
  492. fAddRef,
  493. fCopy,
  494. fDelete);
  495. }
  496. HRESULT
  497. CADsPtrAry::EnumVARIANT(
  498. VARTYPE vt,
  499. IEnumVARIANT ** ppenum,
  500. BOOL fCopy,
  501. BOOL fDelete)
  502. {
  503. return CADsAry::EnumVARIANT(
  504. sizeof(void *),
  505. vt,
  506. ppenum,
  507. fCopy,
  508. fDelete);
  509. }