PageRenderTime 42ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/src/List.h

http://github.com/gunnarbeutner/shroudbnc
C Header | 348 lines | 173 code | 54 blank | 121 comment | 39 complexity | 2d829b875601bdb95cd57861c59c699e MD5 | raw file
Possible License(s): GPL-2.0
  1. /*******************************************************************************
  2. * shroudBNC - an object-oriented framework for IRC *
  3. * Copyright (C) 2005-2014 Gunnar Beutner *
  4. * *
  5. * This program is free software; you can redistribute it and/or *
  6. * modify it under the terms of the GNU General Public License *
  7. * as published by the Free Software Foundation; either version 2 *
  8. * of the License, or (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, write to the Free Software *
  17. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
  18. *******************************************************************************/
  19. #ifndef LIST_H
  20. #define LIST_H
  21. typedef enum list_error_e {
  22. List_ReadOnly,
  23. List_ItemNotFound
  24. } list_error_t;
  25. template <typename Type>
  26. struct link_t {
  27. Type Value;
  28. bool Valid;
  29. link_t<Type> *Next;
  30. link_t<Type> *Previous;
  31. };
  32. template <typename Type>
  33. class CList;
  34. template <typename Type>
  35. class CListCursor;
  36. template <typename Type>
  37. CListCursor<Type> GetCursorHelper(CList<Type> *List);
  38. /**
  39. * CList
  40. *
  41. * A linked list.
  42. */
  43. template <typename Type>
  44. class CList {
  45. private:
  46. link_t<Type> *m_Head; /**< first element */
  47. link_t<Type> *m_Tail; /**< last element */
  48. mutable unsigned int m_Locks; /**< number of locks held */
  49. public:
  50. typedef class CListCursor<Type> Cursor;
  51. #ifndef SWIG
  52. /**
  53. * CList
  54. *
  55. * Constructs an empty list.
  56. */
  57. CList(void) {
  58. m_Head = NULL;
  59. m_Tail = NULL;
  60. m_Locks = 0;
  61. }
  62. /**
  63. * ~CList
  64. *
  65. * Destroys a list.
  66. */
  67. ~CList(void) {
  68. Clear();
  69. }
  70. #endif /* SWIG */
  71. /**
  72. * Insert
  73. *
  74. * Inserts a new item into the list.
  75. *
  76. * @param Item the item which is to be inserted
  77. */
  78. RESULT<link_t<Type> *> Insert(Type Item) {
  79. link_t<Type> *Element;
  80. Element = (link_t<Type> *)malloc(sizeof(link_t<Type>));
  81. if (Element == NULL) {
  82. THROW(link_t<Type> *, Generic_OutOfMemory, "Out of memory.");
  83. }
  84. Element->Next = NULL;
  85. if (m_Tail != NULL) {
  86. Element->Previous = m_Tail;
  87. m_Tail->Next = Element;
  88. m_Tail = Element;
  89. } else {
  90. m_Head = Element;
  91. m_Tail = Element;
  92. Element->Previous = NULL;
  93. }
  94. Element->Value = Item;
  95. Element->Valid = true;
  96. RETURN(link_t<Type> *, Element);
  97. }
  98. /**
  99. * Remove
  100. *
  101. * Removes an item from the list.
  102. *
  103. * @param Item the item which is to be removed
  104. */
  105. RESULT<bool> Remove(Type Item) {
  106. bool ReturnValue = false;
  107. link_t<Type> *Current = m_Head;
  108. while (Current != NULL) {
  109. if (memcmp(&(Current->Value), &Item, sizeof(Item))) {
  110. Remove(Current);
  111. RETURN(bool, true);
  112. }
  113. }
  114. THROW(bool, Vector_ItemNotFound, "Item could not be found.");
  115. }
  116. /**
  117. * Remove
  118. *
  119. * Removes an item from the list
  120. *
  121. * @param Item the item's link_t which is to be removed
  122. */
  123. void Remove(link_t<Type> *Item) {
  124. if (Item == NULL) {
  125. return;
  126. }
  127. if (m_Locks > 0) {
  128. Item->Valid = false;
  129. #ifdef _DEBUG
  130. memset(&(Item->Value), 0, sizeof(Item->Value));
  131. #endif /* _DEBUG */
  132. } else {
  133. if (Item->Next != NULL) {
  134. Item->Next->Previous = Item->Previous;
  135. }
  136. if (Item->Previous != NULL) {
  137. Item->Previous->Next = Item->Next;
  138. }
  139. if (Item == m_Head) {
  140. m_Head = Item->Next;
  141. }
  142. if (Item == m_Tail) {
  143. m_Tail = Item->Previous;
  144. }
  145. free(Item);
  146. }
  147. }
  148. /**
  149. * GetHead
  150. *
  151. * Returns the head of the linked list.
  152. */
  153. link_t<Type> *GetHead(void) const {
  154. return m_Head;
  155. }
  156. /**
  157. * Clear
  158. *
  159. * Removes all items from the list.
  160. */
  161. void Clear(void) {
  162. link_t<Type> *Current = m_Head;
  163. link_t<Type> *Next = NULL;
  164. while (Current != NULL) {
  165. Next = Current->Next;
  166. free(Current);
  167. Current = Next;
  168. }
  169. m_Head = NULL;
  170. m_Tail = NULL;
  171. }
  172. /**
  173. * Lock
  174. *
  175. * Locks the list so items are delay-deleted.
  176. */
  177. void Lock(void) {
  178. m_Locks++;
  179. }
  180. /**
  181. * Unlock
  182. *
  183. * Unlocks the list.
  184. */
  185. void Unlock(void) {
  186. assert(m_Locks > 0);
  187. m_Locks--;
  188. if (m_Locks == 0) {
  189. link_t<Type> *Current, *Next;
  190. Current = m_Head;
  191. while (Current != NULL) {
  192. Next = Current->Next;
  193. if (!Current->Valid) {
  194. Remove(Current);
  195. }
  196. Current = Next;
  197. }
  198. }
  199. }
  200. };
  201. /**
  202. * CListCursor
  203. *
  204. * Used for safely iterating over CList objects.
  205. */
  206. template <typename Type>
  207. class CListCursor {
  208. private:
  209. link_t<Type> *m_Current; /**< the current item */
  210. CList<Type> *m_List; /**< the list */
  211. public:
  212. /**
  213. * CListCursor
  214. *
  215. * Initializes a new cursor.
  216. *
  217. * @param List the list object
  218. */
  219. explicit CListCursor(CList<Type> *List) {
  220. m_List = List;
  221. List->Lock();
  222. m_Current = List->GetHead();
  223. while (m_Current != NULL && !m_Current->Valid) {
  224. m_Current = m_Current->Next;
  225. }
  226. }
  227. /**
  228. * ~CListCursor
  229. *
  230. * Destroys a cursor.
  231. */
  232. ~CListCursor(void) {
  233. m_List->Unlock();
  234. }
  235. /**
  236. * operator *
  237. *
  238. * Retrieves the current object.
  239. */
  240. Type& operator *(void) {
  241. return m_Current->Value;
  242. }
  243. /**
  244. * operator ->
  245. *
  246. * Retrieves the current object.
  247. */
  248. Type* operator ->(void) {
  249. return &(m_Current->Value);
  250. }
  251. /**
  252. * Remove
  253. *
  254. * Removes the current item.
  255. */
  256. void Remove(void) {
  257. m_List->Remove(m_Current);
  258. }
  259. /**
  260. * Proceed
  261. *
  262. * Proceeds in the linked list.
  263. */
  264. void Proceed(void) {
  265. if (m_Current == NULL) {
  266. return;
  267. }
  268. m_Current = m_Current->Next;
  269. while (m_Current != NULL && !m_Current->Valid) {
  270. m_Current = m_Current->Next;
  271. }
  272. }
  273. /**
  274. * IsValid
  275. *
  276. * Checks whether the end of the list has been reached.
  277. */
  278. bool IsValid(void) {
  279. return (m_Current != NULL);
  280. }
  281. /**
  282. * IsRemoved
  283. *
  284. * Checks whether the current item has been removed.
  285. */
  286. bool IsRemoved(void) {
  287. if (m_Current == NULL) {
  288. return true;
  289. } else {
  290. return !m_Current->Valid;
  291. }
  292. }
  293. };
  294. #endif /* LIST_H */