simplevec.h 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : WWLib *
  23. * *
  24. * $Archive:: /Commando/Code/wwlib/simplevec.h $*
  25. * *
  26. * Original Author:: Greg Hjelstrom *
  27. * *
  28. * $Author:: Greg_h $*
  29. * *
  30. * $Modtime:: 5/16/01 10:42a $*
  31. * *
  32. * $Revision:: 16 $*
  33. * *
  34. *---------------------------------------------------------------------------------------------*
  35. * Functions: *
  36. * SimpleVecClass<T>::SimpleVecClass -- Constructor *
  37. * SimpleVecClass<T>::~SimpleVecClass -- Destructor *
  38. * SimpleVecClass<T>::Resize -- resize the array *
  39. * SimpleVecClass<T>::Uninitialised_Grow -- upscale the array, don't copy contents *
  40. * SimpleDynVecClass<T>::~SimpleDynVecClass -- Destructor *
  41. * SimpleDynVecClass<T>::SimpleDynVecClass -- Constructor *
  42. * SimpleDynVecClass<T>::Resize -- Resize the array *
  43. * SimpleDynVecClass<T>::Add -- Add an item to the end of the array *
  44. * SimpleDynVecClass<T>::Delete -- Delete an item from the array *
  45. * SimpleDynVecClass<T>::Delete_Range -- delete several items from the array *
  46. * SimpleDynVecClass<T>::Delete_All -- delete all items from the array *
  47. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  48. #if defined(_MSC_VER)
  49. #pragma once
  50. #endif
  51. #ifndef SIMPLEVEC_H
  52. #define SIMPLEVEC_H
  53. #include "always.h"
  54. #include <assert.h>
  55. #include <string.h> // for memmove
  56. #if (_MSC_VER >= 1200)
  57. #pragma warning (push)
  58. #pragma warning (disable:4702) // disabling the "unreachable code" warning.
  59. #endif
  60. /**
  61. ** SimpleVecClass
  62. ** This is a template similar to VectorClass (found in Vector.h) except that it is designed
  63. ** specifically to work with data types that are "memcopy-able".
  64. ** DON'T USE THIS TEMPLATE IF YOUR CLASS REQUIRES A DESTRUCTOR!!!
  65. */
  66. template <class T> class SimpleVecClass
  67. {
  68. public:
  69. SimpleVecClass(int size = 0);
  70. virtual ~SimpleVecClass(void);
  71. T & operator[](int index) { assert(index < VectorMax); return(Vector[index]); }
  72. T const & operator[](int index) const { assert(index < VectorMax); return(Vector[index]); }
  73. int Length(void) const { return VectorMax; }
  74. virtual bool Resize(int newsize);
  75. virtual bool Uninitialised_Grow(int newsize);
  76. void Zero_Memory(void) { if (Vector != NULL) { memset(Vector,0,VectorMax * sizeof(T)); } }
  77. protected:
  78. T * Vector;
  79. int VectorMax;
  80. };
  81. /***********************************************************************************************
  82. * SimpleVecClass<T>::SimpleVecClass -- Constructor *
  83. * *
  84. * INPUT: *
  85. * size - initial size of the vector *
  86. * *
  87. * OUTPUT: *
  88. * *
  89. * WARNINGS: *
  90. * *
  91. * HISTORY: *
  92. * 1/25/00 gth : Created. *
  93. *=============================================================================================*/
  94. template<class T>
  95. inline SimpleVecClass<T>::SimpleVecClass(int size) :
  96. Vector(NULL),
  97. VectorMax(0)
  98. {
  99. if (size > 0) {
  100. Resize(size);
  101. }
  102. }
  103. /***********************************************************************************************
  104. * SimpleVecClass<T>::~SimpleVecClass -- Destructor *
  105. * *
  106. * INPUT: *
  107. * *
  108. * OUTPUT: *
  109. * *
  110. * WARNINGS: *
  111. * *
  112. * HISTORY: *
  113. * 1/25/00 gth : Created. *
  114. *=============================================================================================*/
  115. template<class T>
  116. inline SimpleVecClass<T>::~SimpleVecClass(void)
  117. {
  118. if (Vector != NULL) {
  119. delete[] Vector;
  120. Vector = NULL;
  121. VectorMax = 0;
  122. }
  123. }
  124. /***********************************************************************************************
  125. * SimpleVecClass<T>::Resize -- resize the array *
  126. * *
  127. * INPUT: *
  128. * *
  129. * OUTPUT: *
  130. * *
  131. * WARNINGS: *
  132. * *
  133. * HISTORY: *
  134. * 1/25/00 gth : Created. *
  135. *=============================================================================================*/
  136. template<class T>
  137. inline bool SimpleVecClass<T>::Resize(int newsize)
  138. {
  139. if (newsize == VectorMax) {
  140. return true;
  141. }
  142. if (newsize > 0) {
  143. /*
  144. ** Allocate a new vector of the size specified. The default constructor
  145. ** will be called for every object in this vector.
  146. */
  147. T * newptr = new T[newsize];
  148. /*
  149. ** If there is an old vector, then it must be copied (as much as is feasible)
  150. ** to the new vector.
  151. */
  152. if (Vector != NULL) {
  153. /*
  154. ** Mem copy as much of the old vector into the new vector as possible.
  155. */
  156. int copycount = (newsize < VectorMax) ? newsize : VectorMax;
  157. memcpy(newptr,Vector,copycount * sizeof(T));
  158. /*
  159. ** Delete the old vector.
  160. */
  161. delete[] Vector;
  162. Vector = NULL;
  163. }
  164. /*
  165. ** Assign the new vector data to this class.
  166. */
  167. Vector = newptr;
  168. VectorMax = newsize;
  169. } else {
  170. /*
  171. ** Delete entire vector and reset counts
  172. */
  173. VectorMax = 0;
  174. if (Vector != NULL) {
  175. delete[] Vector;
  176. Vector = NULL;
  177. }
  178. }
  179. return true;
  180. }
  181. /***********************************************************************************************
  182. * SimpleVecClass<T>::Uninitialised_Grow -- resize the array if current array is too small. *
  183. * Note that it the function doesn't copy the contents so if resising occurs (contents are *
  184. * assumed uninitialised after the call). *
  185. * *
  186. * INPUT: *
  187. * *
  188. * OUTPUT: *
  189. * *
  190. * WARNINGS: *
  191. * *
  192. * HISTORY: *
  193. * 6/6/00 jani : Created. *
  194. *=============================================================================================*/
  195. template<class T>
  196. inline bool SimpleVecClass<T>::Uninitialised_Grow(int newsize)
  197. {
  198. if (newsize <= VectorMax) {
  199. return true;
  200. }
  201. if (newsize > 0) {
  202. /*
  203. ** Allocate a new vector of the size specified. The default constructor
  204. ** will be called for every object in this vector.
  205. */
  206. delete[] Vector;
  207. Vector = new T[newsize];
  208. VectorMax=newsize;
  209. }
  210. return true;
  211. }
  212. /**
  213. ** SimpleDynVecClass
  214. ** This is also a template designed to work with simple data types. It is designed to work
  215. ** just like DynamicVectorClass except that it assumes that the data type used can be
  216. ** legally mem-copied.
  217. ** DON'T USE THIS TEMPLATE IF YOUR CLASS REQUIRES A DESTRUCTOR!!!
  218. **
  219. ** The automatic resizing behavior for this class is a little different than DynamicVectorClass.
  220. ** When the vector needs to be resized, it grows by 25% and if it ever shrinks to 75% usage,
  221. ** it resizes downwards. In addition, when adding objects, you can pass in a "next-size-hint"
  222. ** which is the minimum size the vector will need to be once you are done adding your set of
  223. ** objects. This will cause it to resize to at least that size if it needs to resize. Just
  224. ** leave the parameter at its default value for default behavior.
  225. */
  226. template <class T> class SimpleDynVecClass : public SimpleVecClass<T>
  227. {
  228. public:
  229. SimpleDynVecClass(int size = 0);
  230. virtual ~SimpleDynVecClass(void);
  231. // Array-like access (does not grow)
  232. int Count(void) const { return(ActiveCount); }
  233. T & operator[](int index) { assert(index < ActiveCount); return(Vector[index]); }
  234. T const & operator[](int index) const { assert(index < ActiveCount); return(Vector[index]); }
  235. // Change maximum size of vector
  236. virtual bool Resize(int newsize);
  237. // Add object to vector (growing as necessary).
  238. bool Add(T const & object,int new_size_hint = 0);
  239. // Add room for multiple object to vector. Pointer to first slot added is returned.
  240. T * Add_Multiple( int number_to_add );
  241. // Delete objects from the vector
  242. bool Delete(int index,bool allow_shrink = true);
  243. bool Delete(T const & object,bool allow_shrink = true);
  244. bool Delete_Range(int start,int count,bool allow_shrink = true);
  245. void Delete_All(bool allow_shrink = true);
  246. protected:
  247. bool Grow(int new_size_hint);
  248. bool Shrink(void);
  249. int Find_Index(T const & object);
  250. int ActiveCount;
  251. };
  252. /***********************************************************************************************
  253. * SimpleDynVecClass<T>::SimpleDynVecClass -- Constructor *
  254. * *
  255. * INPUT: *
  256. * size - initial size of the allocated vector *
  257. * *
  258. * OUTPUT: *
  259. * *
  260. * WARNINGS: *
  261. * *
  262. * HISTORY: *
  263. * 1/25/00 gth : Created. *
  264. *=============================================================================================*/
  265. template<class T>
  266. inline SimpleDynVecClass<T>::SimpleDynVecClass(int size) :
  267. SimpleVecClass<T>(size),
  268. ActiveCount(0)
  269. {
  270. }
  271. /***********************************************************************************************
  272. * SimpleDynVecClass<T>::~SimpleDynVecClass -- Destructor *
  273. * *
  274. * INPUT: *
  275. * *
  276. * OUTPUT: *
  277. * *
  278. * WARNINGS: *
  279. * *
  280. * HISTORY: *
  281. * 1/25/00 gth : Created. *
  282. *=============================================================================================*/
  283. template<class T>
  284. inline SimpleDynVecClass<T>::~SimpleDynVecClass(void)
  285. {
  286. if (Vector != NULL) {
  287. delete[] Vector;
  288. Vector = NULL;
  289. }
  290. }
  291. /***********************************************************************************************
  292. * SimpleDynVecClass<T>::Resize -- Resize the array *
  293. * *
  294. * INPUT: *
  295. * newsize - new desired size of the array *
  296. * *
  297. * OUTPUT: *
  298. * *
  299. * WARNINGS: *
  300. * *
  301. * HISTORY: *
  302. * 1/25/00 gth : Created. *
  303. *=============================================================================================*/
  304. template<class T>
  305. inline bool SimpleDynVecClass<T>::Resize(int newsize)
  306. {
  307. if (SimpleVecClass<T>::Resize(newsize)) {
  308. if (Length() < ActiveCount) ActiveCount = Length();
  309. return(true);
  310. }
  311. return(false);
  312. }
  313. /***********************************************************************************************
  314. * SimpleDynVecClass<T>::Add -- Add an item to the end of the array *
  315. * *
  316. * INPUT: *
  317. * object - object to add to the array *
  318. * *
  319. * OUTPUT: *
  320. * *
  321. * WARNINGS: *
  322. * *
  323. * HISTORY: *
  324. * 1/25/00 gth : Created. *
  325. *=============================================================================================*/
  326. template<class T>
  327. inline bool SimpleDynVecClass<T>::Add(T const & object,int new_size_hint)
  328. {
  329. if (ActiveCount >= VectorMax) {
  330. /*
  331. ** We are out of space so tell the vector to grow
  332. */
  333. if (!Grow(new_size_hint)) {
  334. return false;
  335. }
  336. }
  337. /*
  338. ** There is room for the new object now. Add it to the end of the object vector.
  339. */
  340. (*this)[ActiveCount++] = object;
  341. return true;
  342. }
  343. /***********************************************************************************************
  344. * SimpleDynVecClass<T>::Add_Multiple -- Add room for multiple object to vector. *
  345. * *
  346. * INPUT: number of object slots to add *
  347. * *
  348. * OUTPUT: pointer to first slot added is returned. *
  349. * *
  350. * WARNINGS: *
  351. * *
  352. * HISTORY: *
  353. * 1/25/01 bmg : Created. *
  354. *=============================================================================================*/
  355. template<class T>
  356. inline T * SimpleDynVecClass<T>::Add_Multiple( int number_to_add )
  357. {
  358. int index = ActiveCount;
  359. ActiveCount += number_to_add;
  360. if (ActiveCount >= VectorMax) {
  361. /*
  362. ** We are out of space so tell the vector to grow
  363. */
  364. Grow( ActiveCount );
  365. }
  366. return &Vector[index];
  367. }
  368. /***********************************************************************************************
  369. * SimpleDynVecClass<T>::Delete -- Delete an item from the array *
  370. * *
  371. * This causes the items below the specified index to be mem-moved up. *
  372. * *
  373. * INPUT: *
  374. * index - index of the entry to delete *
  375. * allow_shrink - should the vector be allowed to resize *
  376. * *
  377. * OUTPUT: *
  378. * *
  379. * WARNINGS: *
  380. * *
  381. * HISTORY: *
  382. * 1/25/00 gth : Created. *
  383. *=============================================================================================*/
  384. template<class T>
  385. inline bool SimpleDynVecClass<T>::Delete(int index,bool allow_shrink)
  386. {
  387. assert(index < ActiveCount);
  388. /*
  389. ** If there are any objects past the index that was deleted, memcopy
  390. ** those objects to collapse the array. NOTE: again, this template
  391. ** cannot be used for classes that cannot be memcopied!!
  392. */
  393. if (index < ActiveCount-1) {
  394. memmove(&(Vector[index]),&(Vector[index+1]),(ActiveCount - index - 1) * sizeof(T));
  395. }
  396. ActiveCount--;
  397. /*
  398. ** We deleted something so we may need to shrink
  399. */
  400. if (allow_shrink) {
  401. Shrink();
  402. }
  403. return true;
  404. }
  405. /***********************************************************************************************
  406. * SimpleDynVecClass<T>::Delete -- Remove the specified object from the vector. *
  407. * *
  408. * This routine will delete the object referenced from the vector. All objects in the *
  409. * vector that follow the one deleted will be moved "down" to fill the hole. *
  410. * *
  411. * INPUT: object -- Reference to the object in this vector that is to be deleted. *
  412. * allow_shrink -- should the vector be allowed to shrink if it is wasting space? *
  413. * *
  414. * OUTPUT: bool; Was the object deleted successfully? *
  415. * *
  416. * WARNINGS: *
  417. * *
  418. * HISTORY: *
  419. * 03/10/1995 JLB : Created. *
  420. *=============================================================================================*/
  421. template<class T>
  422. inline bool SimpleDynVecClass<T>::Delete(T const & object,bool allow_shrink)
  423. {
  424. int id = Find_Index(object);
  425. if (id != -1) {
  426. return(Delete(id),allow_shrink);
  427. }
  428. return(false);
  429. }
  430. /***********************************************************************************************
  431. * SimpleDynVecClass<T>::Delete_Range -- delete several items from the array *
  432. * *
  433. * This causes the items below the specified index range to be mem-moved up. *
  434. * *
  435. * INPUT: *
  436. * start - starting index to delete *
  437. * count - number of entries to delete *
  438. * allow_shrink - should the vector be allowed to shrink *
  439. * *
  440. * OUTPUT: *
  441. * *
  442. * WARNINGS: *
  443. * *
  444. * HISTORY: *
  445. * 1/25/00 gth : Created. *
  446. *=============================================================================================*/
  447. template<class T>
  448. inline bool SimpleDynVecClass<T>::Delete_Range(int start,int count,bool allow_shrink)
  449. {
  450. assert(start >= 0);
  451. assert(start <= ActiveCount - count);
  452. /*
  453. ** If there are any objects past the index that was deleted, memcopy
  454. ** those objects to collapse the array. NOTE: again, this template
  455. ** cannot be used for classes that cannot be memcopied!!
  456. */
  457. if (start < ActiveCount - count) {
  458. memmove(&(Vector[start]),&(Vector[start + count]),(ActiveCount - start - count) * sizeof(T));
  459. }
  460. ActiveCount -= count;
  461. /*
  462. ** We deleted something so we may need to shrink
  463. */
  464. if (allow_shrink) {
  465. Shrink();
  466. }
  467. return true;
  468. }
  469. /***********************************************************************************************
  470. * SimpleDynVecClass<T>::Delete_All -- delete all items from the array *
  471. * *
  472. * Internally, this just resets the ActiveCount... *
  473. * *
  474. * INPUT: *
  475. * *
  476. * OUTPUT: *
  477. * *
  478. * WARNINGS: *
  479. * *
  480. * HISTORY: *
  481. * 1/25/00 gth : Created. *
  482. *=============================================================================================*/
  483. template<class T>
  484. inline void SimpleDynVecClass<T>::Delete_All(bool allow_shrink)
  485. {
  486. ActiveCount = 0;
  487. /*
  488. ** We deleted something so we may need to shrink
  489. */
  490. if (allow_shrink) {
  491. Shrink();
  492. }
  493. }
  494. /***********************************************************************************************
  495. * SimpleDynVecClass<T>::Grow -- increase the size of the array *
  496. * *
  497. * Internally, this just resets the ActiveCount... *
  498. * *
  499. * INPUT: *
  500. * *
  501. * OUTPUT: *
  502. * *
  503. * WARNINGS: *
  504. * *
  505. * HISTORY: *
  506. * 1/25/00 gth : Created. *
  507. *=============================================================================================*/
  508. template<class T>
  509. inline bool SimpleDynVecClass<T>::Grow(int new_size_hint)
  510. {
  511. /*
  512. ** Vector should grow to 25% bigger, grow at least 4 elements,
  513. ** and grow at least up to the user's new_size_hint
  514. */
  515. int new_size = MAX(Length() + Length()/4,Length() + 4);
  516. new_size = MAX(new_size,new_size_hint);
  517. return Resize(new_size);
  518. }
  519. /***********************************************************************************************
  520. * SimpleDynVecClass<T>::Shrink -- reduce the size of the array *
  521. * *
  522. * Internally, this just resets the ActiveCount... *
  523. * *
  524. * INPUT: *
  525. * *
  526. * OUTPUT: *
  527. * *
  528. * WARNINGS: *
  529. * *
  530. * HISTORY: *
  531. * 1/25/00 gth : Created. *
  532. *=============================================================================================*/
  533. template<class T>
  534. inline bool SimpleDynVecClass<T>::Shrink(void)
  535. {
  536. /*
  537. ** Shrink the array if it is wasting more than 25%
  538. */
  539. if (ActiveCount < VectorMax/4) {
  540. return Resize(ActiveCount);
  541. }
  542. return true;
  543. }
  544. /***********************************************************************************************
  545. * SimpleDynVecClass<T>::Find_Index -- Find matching value in the dynamic vector. *
  546. * *
  547. * Use this routine to find a matching object (by value) in the vector. Unlike the base *
  548. * class ID function of similar name, this one restricts the scan to the current number *
  549. * of valid objects. *
  550. * *
  551. * INPUT: object -- A reference to the object that a match is to be found in the *
  552. * vector. *
  553. * *
  554. * OUTPUT: Returns with the index number of the object that is equivalent to the one *
  555. * specified. If no equivalent object could be found then -1 is returned. *
  556. * *
  557. * WARNINGS: none *
  558. * *
  559. * HISTORY: *
  560. * 03/13/1995 JLB : Created. *
  561. *=============================================================================================*/
  562. template<class T>
  563. inline int SimpleDynVecClass<T>::Find_Index(T const & object)
  564. {
  565. for (int index = 0; index < Count(); index++) {
  566. if ((*this)[index] == object) return(index);
  567. }
  568. return(-1);
  569. }
  570. #if (_MSC_VER >= 1200)
  571. #pragma warning (pop)
  572. #endif
  573. #endif // SIMPLEVEC_H