afList.h
上传用户:kaiguan
上传日期:2007-10-28
资源大小:1074k
文件大小:15k
源码类别:

其他游戏

开发平台:

Visual C++

  1. #ifndef AF_LIST
  2. #define AF_LIST
  3. #include <assert.h>
  4. #include <string.h>
  5. #include "afLog.h"
  6. /// afList is a template class for storing simple objects directly in the list (no pointers)
  7. /**
  8.  *  See also: plPtrList
  9.  */
  10. #pragma warning( disable: 4514 )
  11. template <class TYPE>
  12. class afList
  13. {
  14. public:   
  15. afList();
  16. afList(const afList<TYPE> &other);
  17.  virtual 
  18. ~afList();
  19. /// Returns the number of objects currently stored in the list
  20. int
  21. getSize() const  { return actualItemCount; }
  22. /// Returns true if the list is empty
  23. bool
  24. isEmpty() const  { return actualItemCount==0; }
  25. /// Checks if the index is valid
  26. bool
  27. checkIndex(int index) const;
  28. /// Sets how many elements the list grows when growing is done
  29. void
  30. setGrowingSize(int size)  { growingSize = size; }
  31. /// Lets the list grow 'size' elemens
  32. bool
  33. enlargeList(int size=-1);
  34. /// Enlarge the lists by a given size and set the lists size
  35. bool
  36. enlargeListSet(int size=-1);
  37. /// Enlarges/Reduces the list to a given size.
  38. int
  39. setSize(int nSize);
  40. /// Adds one element to the head of the list (SLOW)
  41. virtual int
  42. addHead(const TYPE& item);
  43. /// Adds one element to the tail of the list
  44. virtual int
  45. addTail(const TYPE& item);
  46. /// Adds the last element of the list to the list again
  47. virtual int
  48. addTailAgain();
  49. /// Adds 'nSize' elements to the tail of the list
  50. virtual int
  51. addTail(const TYPE* item,int nSize);
  52. /// Inserts one element after the given index (SLOW)
  53. virtual int
  54. insertAfter(int index,const TYPE& item);
  55. /// Inserts one element before the given index (SLOW)
  56. virtual int
  57. insertBefore(int index,const TYPE& item);
  58. /// Takes 'nSize' elements starting at the given address and copies them into the list
  59. virtual bool
  60. setList(const TYPE* item,int nSize);
  61. /// Overwrites one element
  62. virtual bool
  63. setAt(int index,const TYPE& item);
  64. /// Replaces the indices of the 2 items
  65. virtual bool
  66. replaceIndices(int nIndexA,int nIndexB);
  67. /// Replaces the first found element which is equal to 'old'  with 'item'
  68. virtual bool
  69. replace(const TYPE& old,const TYPE& item);
  70. /// Replaces all elements which are equal to 'old' with 'item'
  71. virtual bool
  72. replaceAll(const TYPE& old,const TYPE& item);
  73. /// Returns the first element of the list
  74. /**
  75.  *  Returns false if the list is empty
  76.  */
  77. bool
  78. getHead(TYPE& item) const;
  79. /// Returns the first element of the list
  80. TYPE&
  81. getHead() const;
  82. /// Returns the last element of the list
  83. /**
  84.  *  Returns false if the list is empty
  85.  */
  86. bool
  87. getTail(TYPE& item) const;
  88. /// Returns the last element of the list
  89. TYPE&
  90. getTail() const;
  91. /// Returns the element at the given position
  92. /**
  93.  *  Returns false if the list is empty
  94.  */
  95. bool
  96. getAt(int index,TYPE& item) const;
  97. /// Returns the element at the given position
  98. TYPE&
  99. getAt(int index) const;
  100. /// Removing the first element of the list (SLOW)
  101. bool
  102. removeHead();
  103. /// Removing the last element of the list
  104. bool
  105. removeTail();
  106. /// Removes the first element in the list which is equal to 'item'
  107. bool
  108. removeItem(const TYPE& item);
  109. /// Removes the element a position 'index'
  110. virtual bool
  111. removeIndex(int index);
  112. /// Empties the list.
  113. virtual bool
  114. removeAll();
  115. /// Finds the first element which is equal to 'item'
  116. int
  117. find(const TYPE& item);
  118. /// Finds the first element which is equal to 'item' and positioned after 'after'
  119. int
  120. findAfter(const TYPE& item,int after);
  121. /// Finds the first element which is equal to 'item' and positioned before 'before'
  122. int
  123. findBefore(const TYPE& item,int before);
  124. /// Returns a part of the list
  125. virtual afList*
  126. getSubList(int from,int to);
  127. /// Gives direct access to the list members
  128.     TYPE& 
  129. operator[](unsigned index) const { return getAt(index); }
  130. /// Copies a list from another list
  131.     inline afList<TYPE>&
  132. operator=(const afList<TYPE>& other);
  133. /// Compares two lists
  134. /**
  135.  *  Each item is compared. (therefore TYPE must have an operator==).
  136.  *  If all items are ident, true is returned.
  137.  */
  138. friend inline bool 
  139. operator==(const afList&, const afList&)  { return false; }
  140. protected:
  141. int growingSize;
  142. int actualBlockSize;
  143. int actualItemCount;
  144. TYPE* array;
  145. bool reserveBlockSize(int size);
  146. protected:
  147. bool //raises an error
  148. raiseError(const char* nError) const
  149. {  afLog::error(nError);  return false;  }
  150. };
  151. template <class TYPE> inline
  152. afList<TYPE>::afList<TYPE>()
  153. {
  154. array = NULL;
  155. actualBlockSize = 0;
  156. actualItemCount = 0;
  157. growingSize = 16;
  158. enlargeList();
  159. }
  160. template <class TYPE> inline
  161. afList<TYPE>::afList<TYPE>(const afList<TYPE> &other)
  162. {
  163. afList<TYPE>();
  164. *this = other;
  165. }
  166. template <class TYPE> inline
  167. afList<TYPE>::~afList()
  168. {
  169. bool ret = removeAll();
  170. ret;
  171. if(array)
  172. delete [] array;
  173. assert(ret);
  174. }
  175. template <class TYPE> inline bool 
  176. afList<TYPE>::enlargeList(int size)
  177. {
  178. TYPE* tempList;
  179. if (size == -1)
  180. size = growingSize;
  181. try
  182. {
  183. tempList = new TYPE[actualBlockSize + size];
  184. // memcpy(tempList,array,actualBlockSize*sizeof(TYPE));
  185. for (int i=0; i < actualItemCount;++i)
  186. tempList[i] = array[i];
  187. //for (; i < ( actualBlockSize+size );++i)
  188. // tempList[i] = NULL;
  189. if (array!=NULL)
  190. delete [] array;
  191. array = tempList;
  192. actualBlockSize += size;
  193. }
  194. catch(...)
  195. {
  196. return raiseError("in enlargeList");
  197. }
  198. return true;
  199. }
  200. template <class TYPE> inline bool 
  201. afList<TYPE>::enlargeListSet(int size)
  202. {
  203. if (enlargeList(size))
  204. {
  205. actualItemCount = actualBlockSize;
  206. return true;
  207. }
  208. return false;
  209. }
  210. template <class TYPE> inline int
  211. afList<TYPE>::setSize(int nSize)
  212. {
  213. if(array!=NULL)
  214. delete [] array;
  215. int size;
  216. if (nSize<1)
  217. size = growingSize;
  218. else
  219. size = (nSize-(nSize%growingSize)) + growingSize;
  220. array = new TYPE[size];
  221. actualItemCount = nSize;
  222. return actualItemCount;
  223. }
  224. template <class TYPE> inline bool 
  225. afList<TYPE>::reserveBlockSize(int size)
  226. {
  227. if (actualBlockSize < actualItemCount+size)
  228. return enlargeList();
  229. return true;
  230. }
  231. template <class TYPE> inline bool 
  232. afList<TYPE>::checkIndex(int index) const
  233. {
  234. if (index<0 || index > actualItemCount-1)
  235. return false;
  236. return true;
  237. }
  238. template <class TYPE> inline int
  239. afList<TYPE>::addHead(const TYPE& item)
  240. {
  241. if (!reserveBlockSize(1))
  242. return -1;
  243. try
  244. {
  245. memmove((void*)(reinterpret_cast<unsigned>(array)+sizeof(TYPE)),
  246. array,actualItemCount*sizeof(TYPE));
  247. array[0] = item;
  248. ++actualItemCount;
  249. }
  250. catch(...)
  251. {
  252. return raiseError("in addHead");
  253. }
  254. return 0;
  255. }
  256. template <class TYPE> inline int 
  257. afList<TYPE>::addTail(const TYPE& item)
  258. if (!reserveBlockSize(1)) 
  259. return -1;
  260. try
  261. {
  262. array[actualItemCount] = item;
  263. ++actualItemCount;
  264. }
  265. catch(...)
  266. {
  267. return raiseError("in addTail");
  268. }
  269. return (actualItemCount-1);
  270. }
  271. template <class TYPE> inline int 
  272. afList<TYPE>::addTail(const TYPE* item,int nSize)
  273. if (!reserveBlockSize(nSize)) 
  274. return -1;
  275. try
  276. {
  277. for (int i=0;i<nSize;++i)
  278. array[actualItemCount+i] = item[i];
  279. actualItemCount += nSize;
  280. }
  281. catch(...)
  282. {
  283. return raiseError("in addTail");
  284. }
  285. return (actualItemCount-1);
  286. }
  287. template <class TYPE> inline int 
  288. afList<TYPE>::addTailAgain()
  289. {
  290. if(actualItemCount>0)
  291. {
  292. TYPE item = array[actualItemCount-1]; // need to copy since a list grow could screw the reference
  293. return addTail(item);
  294. }
  295. else
  296. return -1;
  297. }
  298. template <class TYPE> inline int 
  299. afList<TYPE>::insertAfter(int index,const TYPE& item)
  300. {
  301. if (!checkIndex(index))
  302. {
  303. raiseError("IndexError");
  304. return -1;
  305. }
  306. if (index == actualItemCount-1)
  307. return addTail(item);
  308. else
  309. {
  310. if (!reserveBlockSize(1))
  311. return -1;
  312. try
  313. {
  314. memmove((void*)(reinterpret_cast<unsigned>(array)+(index+2)*sizeof(TYPE)),
  315. (void*)(reinterpret_cast<unsigned>(array)+(index+1)*sizeof(TYPE)),
  316. (actualItemCount-index-1)*sizeof(TYPE));
  317. array[index+1] = item;
  318. ++actualItemCount;
  319. }
  320. catch(...)
  321. {
  322. raiseError("in InsertAfter");
  323. return -1;
  324. }
  325. }
  326. return (index+1);
  327. }
  328. template <class TYPE> inline int 
  329. afList<TYPE>::insertBefore(int index,const TYPE& item)
  330. {
  331. if (!checkIndex(index))
  332. {
  333. raiseError("IndexError");
  334. return -1;
  335. }
  336. if (index == 0)
  337. return addHead(item);
  338. else
  339. {
  340. if (!reserveBlockSize(1))
  341. return -1;
  342. try
  343. {
  344. memmove((void*)(reinterpret_cast<unsigned>(array)+(index+1)*sizeof(TYPE)),
  345. (void*)(reinterpret_cast<unsigned>(array)+(index)*sizeof(TYPE)),
  346. (actualItemCount-index)*sizeof(TYPE));
  347. array[index] = item;
  348. ++actualItemCount;
  349. }
  350. catch(...)
  351. {
  352. raiseError("in InsertBefore");
  353. return -1;
  354. }
  355. }
  356. return (index-1);
  357. }
  358. template <class TYPE> inline bool 
  359. afList<TYPE>::setList(const TYPE* item,int nSize)
  360. {
  361. if(array!=NULL)
  362. delete [] array;
  363. int size;
  364. if (nSize<1)
  365. size = growingSize;
  366. else
  367. size = (nSize-(nSize%growingSize)) + growingSize;
  368. array = new TYPE[size];
  369. memmove((void*)reinterpret_cast<unsigned>(array),
  370. (void*)reinterpret_cast<unsigned>(item),
  371. (nSize)*sizeof(TYPE));
  372. actualItemCount = nSize;
  373. return true;
  374. }
  375. template <class TYPE> inline bool 
  376. afList<TYPE>::setAt(int index,const TYPE& item)
  377. {
  378. if (!checkIndex(index))
  379. return raiseError("IndexError");
  380. try
  381. {
  382. array[index] = item;
  383. }
  384. catch(...)
  385. {
  386. return raiseError("in SetAt");
  387. }
  388. return true;
  389. }
  390. template <class TYPE> inline bool
  391. afList<TYPE>::replaceIndices(int nIndexA,int nIndexB)
  392. {
  393. if (!checkIndex(nIndexA))
  394. return false;
  395. if (!checkIndex(nIndexB))
  396. return false;
  397. TYPE item = array[nIndexA];
  398. array[nIndexA] = array[nIndexB];
  399. array[nIndexB] = item;
  400. return true;
  401. }
  402. template <class TYPE> inline bool 
  403. afList<TYPE>::replace(const TYPE& old,const TYPE& item)
  404. {
  405. bool ret = false;
  406. for (int i=0; i < actualItemCount; ++i)
  407. if (array[i] == old)
  408. {
  409. array[i] = item;
  410. ret = true;
  411. break;
  412. }
  413. return ret;
  414. }
  415. template <class TYPE> inline bool 
  416. afList<TYPE>::replaceAll(const TYPE& old,const TYPE& item)
  417. {
  418. bool ret = false;
  419. for (int i=0; i < actualItemCount; ++i)
  420. if (array[i] == old)
  421. {
  422. array[i] = item;
  423. ret = true;
  424. }
  425. return ret;
  426. }
  427. template <class TYPE> inline bool 
  428. afList<TYPE>::getHead(TYPE& item) const
  429. {
  430. if (actualItemCount>0)
  431. {
  432. raiseError("Item not found");
  433. return false;
  434. }
  435. try
  436. {
  437. item = array[0];
  438. }
  439. catch(...)
  440. {
  441. raiseError("in GetHead");
  442. return false;
  443. }
  444. return true;
  445. }
  446. template <class TYPE> inline TYPE&
  447. afList<TYPE>::getHead() const
  448. {
  449. if(actualItemCount<1)
  450. raiseError("Item not found");
  451. try
  452. {
  453. return array[0];
  454. }
  455. catch(...)
  456. {
  457. raiseError("in GetHead");
  458. }
  459. }
  460. template <class TYPE> inline bool 
  461. afList<TYPE>::getTail(TYPE& item) const
  462. {
  463. if (actualItemCount<1)
  464. {
  465. raiseError("Item not found");
  466. return false;
  467. }
  468. try
  469. {
  470. item = array[actualItemCount-1];
  471. }
  472. catch(...)
  473. {
  474. raiseError("in GetTail");
  475. return false;
  476. }
  477. return true;
  478. }
  479. template <class TYPE> inline TYPE&
  480. afList<TYPE>::getTail()  const
  481. {
  482. if(actualItemCount<1)
  483. raiseError("Item not found");
  484. try
  485. {
  486. return array[actualItemCount-1];
  487. }
  488. catch(...)
  489. {
  490. raiseError("in GetTail");
  491. }
  492. }
  493. template <class TYPE> inline bool
  494. afList<TYPE>::getAt(int index,TYPE& item) const
  495. {
  496. if (!checkIndex(index))
  497. {
  498. raiseError("IndexError");
  499. assert(1);
  500. return false;
  501. }
  502. try
  503. {
  504. item = array[index];
  505. }
  506. catch(...)
  507. {
  508. raiseError("in Get At");
  509. return false;
  510. }
  511. return true;
  512. }
  513. template <class TYPE> inline TYPE&
  514. afList<TYPE>::getAt(int index) const
  515. {
  516. if (!checkIndex(index))
  517. raiseError("IndexError");
  518. try
  519. {
  520. return array[index];
  521. }
  522. catch(...)
  523. {
  524. raiseError("in Get At");
  525. }
  526. //will never occure because of raiseError
  527. //it just prevent a compiler-warning
  528. return array[index];
  529. }
  530. template <class TYPE> inline bool 
  531. afList<TYPE>::removeHead()
  532. {
  533. return removeIndex(0);
  534. }
  535. template <class TYPE> inline bool 
  536. afList<TYPE>::removeTail()
  537. {
  538. //return removeIndex(actualItemCount-1);
  539. if(actualItemCount>0)
  540. {
  541. actualItemCount--;
  542. return true;
  543. }
  544. else
  545. return raiseError("in removeTail");
  546. }
  547. template <class TYPE> inline bool 
  548. afList<TYPE>::removeItem(const TYPE& item)
  549. {
  550. int index;
  551. index = find(item);
  552. if (index < 0)
  553. return false;
  554. return removeIndex(index);
  555. }
  556. template <class TYPE> inline bool 
  557. afList<TYPE>::removeIndex(int index)
  558. {
  559. if (!checkIndex(index))
  560. return raiseError("IndexError");
  561. try
  562. {
  563. memmove((void*)(reinterpret_cast<unsigned>(array)+(index)*sizeof(TYPE)),
  564. (void*)(reinterpret_cast<unsigned>(array)+(index+1)*sizeof(TYPE)),
  565. (actualItemCount-index-1)*sizeof(TYPE));
  566. --actualItemCount;
  567. }
  568. catch(...)
  569. {
  570. return raiseError("in removeIndex");
  571. }
  572. return true;
  573. }
  574. template <class TYPE> inline bool 
  575. afList<TYPE>::removeAll()
  576. {
  577. try
  578. {
  579. actualItemCount = 0;
  580. }
  581. catch(...)
  582. {
  583. return raiseError("in RemoveAll");
  584. }
  585. return true;
  586. }
  587. template <class TYPE> inline int 
  588. afList<TYPE>::find(const TYPE& item)
  589. {
  590. int ret = -1;
  591. try
  592. {
  593. for (int i=0; i < actualItemCount; ++i)
  594. if (item == array[i])
  595. {
  596. ret = i;
  597. break;
  598. }
  599. }
  600. catch(...)
  601. {
  602. return raiseError("in Find");
  603. }
  604. return ret;
  605. }
  606. template <class TYPE> inline int 
  607. afList<TYPE>::findAfter(const TYPE& item,int after)
  608. {
  609. int ret = -1;
  610. int index = after+1;
  611. if (!checkIndex(index))
  612. return raiseError("IndexError");
  613. try
  614. {
  615. for (int i=index; i < actualItemCount; ++i)
  616. if (item == array[i])
  617. {
  618. ret = i;
  619. break;
  620. }
  621. }
  622. catch(...)
  623. {
  624. return raiseError("in FindAfter");
  625. }
  626. return ret;
  627. }
  628. template <class TYPE> inline int 
  629. afList<TYPE>::findBefore(const TYPE& item,int before)
  630. {
  631. int ret = -1;
  632. int index = before-1;
  633. if (!checkIndex(index))
  634. return raiseError("IndexError");
  635. try
  636. {
  637. for (int i=0; i < before; ++i)
  638. if (item == array[i])
  639. {
  640. ret = i;
  641. break;
  642. }
  643. }
  644. catch(...)
  645. {
  646. return raiseError("in FindBefore");
  647. }
  648. return ret;
  649. }
  650. template <class TYPE> inline afList<TYPE>* 
  651. afList<TYPE>::getSubList(int from,int to)
  652. {
  653. if (!checkIndex(from))
  654. {
  655. raiseError("IndexError");
  656. return NULL;
  657. }
  658. if (!checkIndex(to))
  659. {
  660. raiseError("IndexError");
  661. return NULL;
  662. }
  663. if (from < to)
  664. {
  665. raiseError("IndexError");
  666. return NULL;
  667. }
  668. afList<TYPE> *ret = new afList<TYPE>;
  669. try
  670. {
  671. for (int i=from; i < to; ++i)
  672. ret->addTail(array[i]);
  673. }
  674. catch(...)
  675. {
  676. delete ret;
  677. raiseError("in GetSubList");
  678. return NULL;
  679. }
  680. return ret;
  681. }
  682. template <class TYPE> inline afList<TYPE>&
  683. afList<TYPE>::operator=(const afList<TYPE>& other)
  684. {
  685. removeAll();
  686. if (array!=NULL)
  687. delete [] array;
  688. if (other.array == NULL || other.actualItemCount==0)
  689. {
  690. array = NULL;
  691. actualBlockSize = 0;
  692. actualItemCount = 0;
  693. enlargeList();
  694. }
  695. else
  696. {
  697. array = new TYPE[other.actualItemCount];
  698. memmove((void*)(reinterpret_cast<unsigned>(array)),
  699. (void*)(reinterpret_cast<unsigned>(other.array)),
  700. (other.actualItemCount)*sizeof(TYPE));
  701. actualItemCount = other.actualItemCount;
  702. actualBlockSize = actualItemCount;
  703. }
  704. /*
  705. for (int i=0;i<other.GetSize();++i)
  706. AddTail(other[i]);
  707. */
  708. return *this;
  709. }
  710. typedef afList<int> afIntList;
  711. #endif