arraylist.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775
  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. Project Name:
  22. File Name : arraylist.h
  23. Author : Neal Kettler
  24. Start Date : Jan 19, 1997
  25. Last Update : Jan 19, 1997
  26. ------------------------------------------------------------------------------
  27. Array implementation of a list. Note: There are some freaky C++ memory tricks
  28. going on here. If you think there's a leak, see me before changing it.
  29. The way this works is that it allocates an array to hold 'N' items on the
  30. first list add. It doesn't call the constructors for those 'N' items until
  31. necessary (for efficiency). When an item is added to a slot then a new
  32. class is constructed inside the array element using the placement new operator
  33. and the class's copy constructor. When elements are removed the destructor
  34. is then manually called on this memory location.
  35. All data added to the list is copied so feel free to delete/destroy/modify
  36. the original after an add.
  37. You _must_ have a good copy constructor for any classes that you use this template
  38. for! A good copy constructor is one that won't blindly duplicate pointers
  39. that don't belong to them, etc...
  40. \****************************************************************************/
  41. #ifndef ARRAYLIST_HEADER
  42. #define ARRAYLIST_HEADER
  43. #include <stdio.h>
  44. #include <stdlib.h>
  45. #include <string.h>
  46. #include <assert.h>
  47. #include <new.h>
  48. #include <math.h>
  49. #include "wstypes.h"
  50. //
  51. // Usage: ArrayList<int> TheList;
  52. //
  53. template <class T>
  54. class ArrayList
  55. {
  56. public:
  57. ArrayList();
  58. ArrayList(ArrayList<T> &other);
  59. ~ArrayList();
  60. // Remove all entries from the lsit
  61. void clear(void);
  62. // Add a node after the zero based 'pos'
  63. bit8 add(IN T &node,sint32 pos);
  64. bit8 addTail(IN T &node);
  65. bit8 addHead(IN T &node);
  66. bit8 addSortedAsc(IN T &node); // Ascending
  67. bit8 addSortedDes(IN T &node); // Descending
  68. /*bit8 addNumSortedAsc(IN T &node); // Ascending
  69. bit8 addNumSortedDes(IN T &node); // Descending*/
  70. bit8 addMany(OUT T *outarray, sint32 pos, sint32 howmany);
  71. // Remove a node
  72. bit8 remove(OUT T &node,sint32 pos);
  73. bit8 remove(sint32 pos);
  74. bit8 removeHead(OUT T &node);
  75. bit8 removeTail(OUT T &node);
  76. sint32 removeMany(OUT T *outarray, sint32 pos, sint32 howmany);
  77. // Replace one obj with another
  78. bit8 replace(IN T &node, sint32 pos);
  79. // Get a node without removing from the list
  80. bit8 get(OUT T &node,sint32 pos) RO;
  81. bit8 getHead(OUT T &node) RO;
  82. bit8 getTail(OUT T &node) RO;
  83. // Get a pointer to the interally managed copy (careful!)
  84. bit8 getPointer(OUT T **node,sint32 pos) RO;
  85. // Get the number of entries in the list
  86. sint32 length(void) RO;
  87. // UNSAFE! for classes, see note below!
  88. bit8 setSize(sint32 newsize, IN T &filler);
  89. // Print information on the list
  90. void print(FILE *out);
  91. // assignment operator
  92. ArrayList<T> &operator=(IN ArrayList<T> &other);
  93. private:
  94. sint32 _sortedLookup(IN T &target, int ascending);
  95. sint32 Entries_; // Number of entries
  96. sint32 Slots_; // Number of available slots
  97. T *Vector_; // The actual memory where the list is held
  98. enum
  99. {
  100. INITIAL_SIZE = 10
  101. };
  102. bit8 growVector(void); // Expand the number of slots
  103. bit8 shrinkVector(void); // Reduce the number of slots
  104. };
  105. //Create the empty list
  106. template <class T>
  107. ArrayList<T>::ArrayList()
  108. {
  109. Entries_=0;
  110. Slots_=0;
  111. Vector_=NULL;
  112. }
  113. // copy constructor
  114. template <class T>
  115. ArrayList<T>::ArrayList(ArrayList<T> &other)
  116. {
  117. Entries_=0;
  118. Slots_=0;
  119. Vector_=NULL;
  120. (*this)=other;
  121. }
  122. //Free all the memory...
  123. template <class T>
  124. ArrayList<T>::~ArrayList()
  125. {
  126. clear(); // Remove the entries & call destructors on them
  127. delete[]((uint8*)Vector_); // this will prevent the destructors from
  128. // gettting called on elements not
  129. // containing valid objects.
  130. //fprintf(stderr,"Arraylist destructor\n");
  131. }
  132. // assignment operator
  133. template <class T>
  134. ArrayList<T> &ArrayList<T>::operator=(IN ArrayList<T> &other)
  135. {
  136. T node;
  137. clear();
  138. for (int i=0; i<other.length(); i++)
  139. {
  140. other.get(node,i);
  141. addTail(node);
  142. }
  143. return(*this);
  144. }
  145. // Remove all the entries and free the memory
  146. template <class T>
  147. void ArrayList<T>::clear()
  148. {
  149. for (int i=0; i<Entries_; i++)
  150. {
  151. (Vector_+i)->~T(); // Call the destructor manually. Don't try this
  152. // at home kiddies!
  153. }
  154. Entries_=0;
  155. }
  156. // ************************* UNSAFE UNSAFE UNSAFE *************************
  157. // Note - Don't call this on any type with a constructor/destructor since this
  158. // is really dumb and just puts a new one of filler in. Well, it's kindof safe
  159. // just be careful.
  160. // It's fine for simple classes like ints though..
  161. //
  162. // Add/remove entries in a stupid manner...
  163. //
  164. // **************************************************************************
  165. template <class T>
  166. bit8 ArrayList<T>::setSize(sint32 newsize, IN T &filler)
  167. {
  168. int oldEntries=Entries_;
  169. Entries_ = newsize;
  170. if (newsize<0)
  171. return(false);
  172. // Grow the vector as much as we need to
  173. while (newsize > Slots_)
  174. growVector();
  175. // Create new objects in the blank holes
  176. for (int i=oldEntries; i<Entries_; i++)
  177. {
  178. // Now put the replacement object in there...
  179. new((void *)(Vector_+i)) T(filler); // Trust me, this isn't a memory leak
  180. }
  181. // If we're at 33% usage or less, shrink the vector
  182. if ((Entries_*3) <= Slots_) // don't do while, because I think shrink will never goto 0
  183. shrinkVector();
  184. return(true);
  185. }
  186. // When adding into a position, the new node goes at the zero based slot
  187. // specified by pos. All other nodes get moved one slot down.
  188. template <class T>
  189. bit8 ArrayList<T>::add(IN T &node,sint32 pos)
  190. {
  191. if (pos > Entries_) // You can only access one of the end of the vector
  192. pos=Entries_;
  193. if (pos >= Slots_) // If we're at the end, grow the list
  194. growVector();
  195. if (Entries_ >= Slots_) // enuff space?
  196. growVector();
  197. // If we are insering into the middle or front of the list we have to
  198. // slide the old objects forward.
  199. if (pos < Entries_) // If there are elements after the add point
  200. memmove(Vector_+pos+1,Vector_+pos,sizeof(T)*(Entries_-pos)); // move them forward
  201. //fprintf(stderr,"Placement new to %p\n",(Vector_+pos));
  202. // This uses the placement new operator. placement new allows us to
  203. // specify the memory address for the new object. In this case we
  204. // want it at the 'pos' index into our array.
  205. new((void *)(Vector_+pos)) T((T &)node); // Trust me, this isn't a memory leak
  206. Entries_++; // one new entry
  207. return(TRUE);
  208. }
  209. // Add to the first node, all others get shifted down one slot
  210. template <class T>
  211. bit8 ArrayList<T>::addHead(IN T &node)
  212. {
  213. return(add(node,0));
  214. }
  215. // Append to the end of the list
  216. template <class T>
  217. bit8 ArrayList<T>::addTail(IN T &node)
  218. {
  219. return(add(node,length()));
  220. }
  221. // addSortedX only works (properly) if evrerything else in the list is added
  222. // using addSorted.
  223. template <class T>
  224. bit8 ArrayList<T>::addSortedAsc(IN T &node)
  225. {
  226. sint32 pos = _sortedLookup(node, 1);
  227. return(add(node, pos));
  228. }
  229. // addSortedX only works (properly) if evrerything else in the list is added
  230. // using addSorted.
  231. template <class T>
  232. bit8 ArrayList<T>::addSortedDes(IN T &node)
  233. {
  234. sint32 pos = _sortedLookup(node, 0);
  235. return(add(node, pos));
  236. }
  237. // This is the binary search used by addSorted
  238. template <class T>
  239. sint32 ArrayList<T>::_sortedLookup(IN T &target, int ascending)
  240. {
  241. int low, mid, high;
  242. T* lowtarget;
  243. T* hightarget;
  244. T* midtarget;
  245. // Trivial cases
  246. if( Entries_ == 0 )
  247. return 0;
  248. low = 0;
  249. high = Entries_ - 1;
  250. while( 1 )
  251. {
  252. assert( low <= high );
  253. mid = low + (int)(floor(((double)high - (double)low) / (double)2));
  254. getPointer(&lowtarget, low);
  255. getPointer(&hightarget, high);
  256. getPointer(&midtarget, mid);
  257. // Exact match
  258. if( *midtarget == target ) return mid;
  259. // Single element
  260. if( high == low )
  261. {
  262. if( ascending )
  263. {
  264. if( target <= *lowtarget )
  265. return low;
  266. else
  267. return low + 1;
  268. }
  269. else
  270. {
  271. if( target <= *lowtarget )
  272. return low + 1;
  273. else
  274. return low;
  275. }
  276. }
  277. // Two elemsnts
  278. if( (high - low) == 1 )
  279. {
  280. if( ascending )
  281. {
  282. if( target <= *lowtarget )
  283. return low;
  284. else if( target <= *hightarget )
  285. return high;
  286. else
  287. return high + 1;
  288. }
  289. else
  290. {
  291. if( target <= *hightarget )
  292. return high + 1;
  293. else if( target <= *lowtarget )
  294. return high;
  295. else
  296. return low;
  297. }
  298. }
  299. // Sorry, try again...
  300. if( ascending )
  301. {
  302. if( target < *midtarget )
  303. high = mid;
  304. else
  305. low = mid;
  306. }
  307. else
  308. {
  309. if( target < *midtarget )
  310. low = mid;
  311. else
  312. high = mid;
  313. }
  314. }
  315. }
  316. /*// addNumSortedX works in much the same way as addSortedX, except that I needed
  317. // it for a very specific thing. I needed a list of strings numerically sorted,
  318. // not alphabetically sorted. Furthermore these strings were composed of numbers
  319. // delimited by underscores. In the interest of keeping it generic, these
  320. // functions take as args a node, a delimiting character, and a count of the
  321. // number of fields to include in a sort. If this is the list of strings:
  322. //
  323. // 55_100, 2_5, 23_32, 98_445, 2_48, 8_88, 2_3, 2_4
  324. //
  325. // An alphabetical sort is:
  326. //
  327. // 2_3, 2_4, 2_48, 2_5, 55_100, 8_88, 98_445
  328. //
  329. // But a numerical sort by calling addNumSortedAsc(<whatever>, "_", 2) will result in:
  330. //
  331. // 2_3, 2_4, 2_5, 2_48, 8_88, 55_100, 98_445
  332. //
  333. // Yes...now that you mention it I am on crack...
  334. //
  335. template <class T>
  336. bit8 ArrayList<T>::addNumSortedAsc(IN T &node, char delim, int fields)
  337. {
  338. sint32 pos = _numSortedLookup(node, delim, fields, 1);
  339. return(add(node, pos));
  340. }
  341. // See addNumSortedAsc comment above.
  342. template <class T>
  343. bit8 ArrayList<T>::addSortedDes(IN T &node, char delim, int fields)
  344. {
  345. sint32 pos = _sortedLookup(node, delim, fields, 0);
  346. return(add(node, pos));
  347. }
  348. // This is the binary search used by addSorted
  349. template <class T>
  350. sint32 ArrayList<T>::_numSortedLookup(IN T &target, char delim, int fields, int ascending)
  351. {
  352. int low, mid, high;
  353. T* lowtarget;
  354. T* hightarget;
  355. T* midtarget;
  356. // Trivial case
  357. if( Entries_ == 0 )
  358. return 0;
  359. low = 0;
  360. high = Entries_;
  361. while( 1 )
  362. {
  363. assert( low <= high );
  364. mid = low + (int)(floor(((double)high - (double)low) / (double)2));
  365. getPointer(&lowtarget, low);
  366. getPointer(&hightarget, high);
  367. getPointer(&midtarget, mid);
  368. // Exact match
  369. if( *midtarget == target ) return mid;
  370. // Single element
  371. if( high == low )
  372. {
  373. if( ascending )
  374. {
  375. if( target <= *lowtarget )
  376. return low;
  377. else
  378. return low + 1;
  379. }
  380. else
  381. {
  382. if( target <= *lowtarget )
  383. return low + 1;
  384. else
  385. return low;
  386. }
  387. }
  388. // Two elemsnts
  389. if( (high - low) == 1 )
  390. {
  391. if( ascending )
  392. {
  393. if( target <= *lowtarget )
  394. return low;
  395. else
  396. return high;
  397. }
  398. else
  399. {
  400. if( target <= *lowtarget )
  401. return high;
  402. else
  403. return low;
  404. }
  405. }
  406. // Sorry, try again...
  407. if( ascending )
  408. {
  409. if( target < *midtarget )
  410. high = mid;
  411. else
  412. low = mid;
  413. }
  414. else
  415. {
  416. if( target < *midtarget )
  417. low = mid;
  418. else
  419. high = mid;
  420. }
  421. }
  422. }*/
  423. //
  424. // Delete an item at this index and construct a new one in it's place
  425. //
  426. template <class T>
  427. bit8 ArrayList<T>::replace(IN T &node, sint32 pos)
  428. {
  429. if (Entries_==0)
  430. return(FALSE);
  431. if (pos<0)
  432. pos=0;
  433. if (pos >= Entries_)
  434. pos=Entries_-1;
  435. (Vector_+pos)->~T(); // Call the destructor manually. Don't try this
  436. // at home kiddies!
  437. // Now put the replacement object in there...
  438. new((void *)(Vector_+pos)) T(node); // Trust me, this isn't a memory leak
  439. return(TRUE);
  440. }
  441. // Remove at the zero based index specified by 'pos'. When removing from
  442. // a slot, all others get shifted up by one.
  443. template <class T>
  444. bit8 ArrayList<T>::remove(sint32 pos)
  445. {
  446. if (Entries_==0)
  447. return(FALSE);
  448. if (pos<0)
  449. pos=0;
  450. if (pos >= Entries_)
  451. pos=Entries_-1;
  452. (Vector_+pos)->~T(); // Call the destructor manually. Don't try this
  453. // at home kiddies!
  454. memmove(Vector_+pos,Vector_+pos+1,sizeof(T)*(Entries_-pos-1));
  455. Entries_--;
  456. // If we're at 33% usage or less, shrink the vector
  457. if ( (Entries_*3) <= Slots_)
  458. shrinkVector();
  459. return(TRUE);
  460. }
  461. // Remove at the zero based index specified by 'pos'. When removing from
  462. // a slot, all others get shifted up by one.
  463. template <class T>
  464. bit8 ArrayList<T>::remove(OUT T &node, sint32 pos)
  465. {
  466. bit8 retval;
  467. retval=get(node,pos);
  468. if (retval==FALSE)
  469. return(FALSE);
  470. return(remove(pos));
  471. }
  472. // Remove the first node of the list
  473. template <class T>
  474. bit8 ArrayList<T>::removeHead(OUT T &node)
  475. {
  476. return(remove(node,0));
  477. }
  478. // Remove the last node of the list
  479. template <class T>
  480. bit8 ArrayList<T>::removeTail(OUT T &node)
  481. {
  482. return(remove(node,Entries_-1));
  483. }
  484. // get a pointer to the internally managed object. Try and avoid this, but
  485. // sometimes efficiency requires it...
  486. // get a copy of an item
  487. template <class T>
  488. bit8 ArrayList<T>::getPointer(OUT T **node,sint32 pos) RO
  489. {
  490. if ((pos < 0)||(pos >= Entries_))
  491. return(FALSE);
  492. *node=&(Vector_[pos]);
  493. return(TRUE);
  494. }
  495. // get a copy of an item
  496. template <class T>
  497. bit8 ArrayList<T>::get(OUT T &node,sint32 pos) RO
  498. {
  499. if ((pos < 0)||(pos >= Entries_))
  500. return(FALSE);
  501. node=Vector_[pos];
  502. return(TRUE);
  503. }
  504. // get a copy of the first node of the list
  505. template <class T>
  506. bit8 ArrayList<T>::getHead(OUT T &node) RO
  507. {
  508. return(get(node,0));
  509. }
  510. // get a copy of the last node
  511. template <class T>
  512. bit8 ArrayList<T>::getTail(OUT T &node) RO
  513. {
  514. return(get(node,Entries_-1));
  515. }
  516. // just for debugging
  517. template <class T>
  518. void ArrayList<T>::print(FILE *out)
  519. {
  520. fprintf(out,"--------------------\n");
  521. //for (int i=0; i<Entries_; i++)
  522. // Vector_[i].print();
  523. fprintf(out,"Entries: %d Slots: %d sizeof(T): %d\n",Entries_,Slots_,
  524. sizeof(T));
  525. fprintf(out,"--------------------\n");
  526. }
  527. // Return the current length of the list
  528. template <class T>
  529. sint32 ArrayList<T>::length(void) RO
  530. {
  531. return(Entries_);
  532. }
  533. // Grow the vector by a factor of 2X
  534. template <class T>
  535. bit8 ArrayList<T>::growVector(void)
  536. {
  537. if (Entries_ < Slots_) // Don't grow until we're at 100% usage
  538. return(FALSE);
  539. int newSlots=Entries_*2;
  540. if(newSlots < INITIAL_SIZE)
  541. newSlots=INITIAL_SIZE;
  542. //fprintf(stderr,"Growing vector to: %d\n",newSlots);
  543. // The goofy looking new below prevents operator new from getting called
  544. // unnecessarily. This is severall times faster than allocating all of
  545. // the slots as objects and then calling the assignment operator on them
  546. // when they actually get used.
  547. //
  548. T *newVector=(T *)(new uint8[newSlots * sizeof(T)]);
  549. memset(newVector,0,newSlots * sizeof(T)); // zero just to be safe
  550. if (Vector_ != NULL)
  551. memcpy(newVector,Vector_,Entries_*sizeof(T));
  552. delete[]((uint8 *)Vector_); // Get rid of the old vector without calling
  553. // destructors
  554. Vector_=newVector;
  555. Slots_=newSlots;
  556. return(TRUE);
  557. }
  558. // Shrink the vector by a factor of 2X
  559. template <class T>
  560. bit8 ArrayList<T>::shrinkVector(void)
  561. {
  562. //fprintf(stderr,"Shrink called\n");
  563. // Don't need to shrink until usage goes below 33%
  564. if ( (Entries_*3) > Slots_)
  565. return(FALSE);
  566. int newSlots=Slots_/2;
  567. if(newSlots < INITIAL_SIZE) // never shrink past initial size
  568. newSlots=INITIAL_SIZE;
  569. if (newSlots >= Slots_) // don't need to shrink
  570. return(FALSE);
  571. //fprintf(stderr,"Shrinking vector to: %d\n",newSlots);
  572. // The goofy looking new below prevents operator new from getting called
  573. // unnecessarily. This is severall times faster than allocating all of
  574. // the slots as objects and then calling the assignment operator on them
  575. // when they actually get used.
  576. //
  577. T *newVector=(T *)(new uint8[newSlots * sizeof(T)]);
  578. if (Vector_ != NULL) // Vector_ better not be NULL!
  579. memcpy(newVector,Vector_,Entries_*sizeof(T));
  580. delete[]((uint8 *)Vector_); // Get rid of the old vector without calling
  581. // destructors
  582. Vector_=newVector;
  583. Slots_=newSlots;
  584. return(TRUE);
  585. }
  586. // Implementation was missing from source code. This function is based on the build
  587. // artifact DLL in the archive and similar functions in this header file.
  588. // Compiles, but not tested. LFeenanEA - January 27th 2025
  589. template <class T>
  590. sint32 ArrayList<T>::removeMany(OUT T *outarray, sint32 pos, sint32 howmany)
  591. {
  592. if (Entries_==0)
  593. return(FALSE);
  594. if (pos<0)
  595. pos=0;
  596. if (pos>=Entries_)
  597. pos=Entries_-1;
  598. if (pos+howmany>Entries_)
  599. assert(0);
  600. for (int i=0; i<howmany; i++)
  601. {
  602. if (outarray)
  603. outarray[i]=Vector_[pos+i];
  604. }
  605. memmove(Vector_+pos,Vector_+pos+howmany,sizeof(T)*(Entries_-pos-howmany));
  606. Entries_-=howmany;
  607. // If we're at 33% usage or less, shrink the vector
  608. if ((Entries_*3) <= Slots_) // don't do while, because I think shrink will never goto 0
  609. shrinkVector();
  610. return(howmany);
  611. }
  612. // Implementation was missing from source code. This function is based on the build
  613. // artifact DLL in the archive and similar functions in this header file.
  614. // Compiles, but not tested. LFeenanEA - January 27th 2025
  615. template <class T>
  616. bit8 ArrayList<T>::addMany(IN T *inarray, sint32 pos, sint32 howmany)
  617. {
  618. if (pos > Entries_) // You can only access one of the end of the vector
  619. pos=Entries_;
  620. // Grow the vector as much as we need to
  621. while (howmany+Entries_ >= Slots_)
  622. growVector();
  623. // If we are insering into the middle or front of the list we have to
  624. // slide the old objects forward.
  625. if (pos < Entries_) // If there are elements after the add point
  626. memmove(Vector_+pos+howmany,Vector_+pos,sizeof(T)*(Entries_-pos)); // move them forward
  627. // This uses the placement new operator. placement new allows us to
  628. // specify the memory address for the new object. In this case we
  629. // want it at the 'pos' index into our array.
  630. for (int i=0; i<howmany; i++)
  631. {
  632. new((void *)(Vector_+i)) T(inarray[i]); // Trust me, this isn't a memory leak
  633. }
  634. Entries_+=howmany;
  635. return(TRUE);
  636. }
  637. #endif