PageRenderTime 46ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/mono/metadata/mono-mlist.c

https://bitbucket.org/danipen/mono
C | 219 lines | 115 code | 16 blank | 88 comment | 15 complexity | 672b44d8d7c56133ece3120b43b84e70 MD5 | raw file
Possible License(s): Unlicense, Apache-2.0, LGPL-2.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0
  1. /*
  2. * mono-mlist.c: Managed object list implementation
  3. *
  4. * Author:
  5. * Paolo Molaro (lupus@ximian.com)
  6. *
  7. * Copyright 2006-2009 Novell, Inc (http://www.novell.com)
  8. */
  9. #include "mono/metadata/mono-mlist.h"
  10. #include "mono/metadata/appdomain.h"
  11. #include "mono/metadata/class-internals.h"
  12. /* matches the System.MonoListItem object*/
  13. struct _MonoMList {
  14. MonoObject object;
  15. MonoMList *next;
  16. MonoObject *data;
  17. };
  18. /*
  19. * note: we only allocate in the root domain: this lists are
  20. * not exposed to managed code
  21. */
  22. static MonoVTable *monolist_item_vtable = NULL;
  23. /**
  24. * mono_mlist_alloc:
  25. * @data: object to use as data
  26. *
  27. * Allocates a new managed list node with @data as the contents.
  28. * A managed list node also represents a singly-linked list.
  29. * Managed lists are garbage collected, so there is no free routine
  30. * and the user is required to keep references to the managed list
  31. * to prevent it from being garbage collected.
  32. */
  33. MonoMList*
  34. mono_mlist_alloc (MonoObject *data)
  35. {
  36. MonoMList* res;
  37. if (!monolist_item_vtable) {
  38. MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System", "MonoListItem");
  39. monolist_item_vtable = mono_class_vtable (mono_get_root_domain (), klass);
  40. g_assert (monolist_item_vtable);
  41. }
  42. res = (MonoMList*)mono_object_new_fast (monolist_item_vtable);
  43. MONO_OBJECT_SETREF (res, data, data);
  44. return res;
  45. }
  46. /**
  47. * mono_mlist_get_data:
  48. * @list: the managed list node
  49. *
  50. * Get the object stored in the list node @list.
  51. */
  52. MonoObject*
  53. mono_mlist_get_data (MonoMList* list)
  54. {
  55. return list->data;
  56. }
  57. /**
  58. * mono_mlist_set_data:
  59. * @list: the managed list node
  60. *
  61. * Set the object content in the list node @list.
  62. */
  63. void
  64. mono_mlist_set_data (MonoMList* list, MonoObject *data)
  65. {
  66. MONO_OBJECT_SETREF (list, data, data);
  67. }
  68. /**
  69. * mono_mlist_set_next:
  70. * @list: a managed list node
  71. * @next: list node that will be next for the @list node.
  72. *
  73. * Set next node for @list to @next.
  74. */
  75. MonoMList *
  76. mono_mlist_set_next (MonoMList* list, MonoMList *next)
  77. {
  78. if (!list)
  79. return next;
  80. MONO_OBJECT_SETREF (list, next, next);
  81. return list;
  82. }
  83. /**
  84. * mono_mlist_length:
  85. * @list: the managed list
  86. *
  87. * Get the number of items in the list @list.
  88. * Since managed lists are singly-linked, this operation takes O(n) time.
  89. */
  90. int
  91. mono_mlist_length (MonoMList* list)
  92. {
  93. int len = 0;
  94. while (list) {
  95. list = list->next;
  96. ++len;
  97. }
  98. return len;
  99. }
  100. /**
  101. * mono_mlist_next:
  102. * @list: the managed list node
  103. *
  104. * Returns the next managed list node starting from @list.
  105. */
  106. MonoMList*
  107. mono_mlist_next (MonoMList* list)
  108. {
  109. return list->next;
  110. }
  111. /**
  112. * mono_mlist_last:
  113. * @list: the managed list node
  114. *
  115. * Returns the last managed list node in list @list.
  116. * Since managed lists are singly-linked, this operation takes O(n) time.
  117. */
  118. MonoMList*
  119. mono_mlist_last (MonoMList* list)
  120. {
  121. if (list) {
  122. while (list->next)
  123. list = list->next;
  124. return list;
  125. }
  126. return NULL;
  127. }
  128. /**
  129. * mono_mlist_prepend:
  130. * @list: the managed list
  131. * @data: the object to add to the list
  132. *
  133. * Allocate a new list node with @data as content and prepend it
  134. * to the list @list. @list can be NULL.
  135. */
  136. MonoMList*
  137. mono_mlist_prepend (MonoMList* list, MonoObject *data)
  138. {
  139. MonoMList* res = mono_mlist_alloc (data);
  140. if (list)
  141. MONO_OBJECT_SETREF (res, next, list);
  142. return res;
  143. }
  144. /**
  145. * mono_mlist_append:
  146. * @list: the managed list
  147. * @data: the object to add to the list
  148. *
  149. * Allocate a new list node with @data as content and append it
  150. * to the list @list. @list can be NULL.
  151. * Since managed lists are singly-linked, this operation takes O(n) time.
  152. */
  153. MonoMList*
  154. mono_mlist_append (MonoMList* list, MonoObject *data)
  155. {
  156. MonoMList* res = mono_mlist_alloc (data);
  157. if (list) {
  158. MonoMList* last = mono_mlist_last (list);
  159. MONO_OBJECT_SETREF (last, next, res);
  160. return list;
  161. } else {
  162. return res;
  163. }
  164. }
  165. static MonoMList*
  166. find_prev (MonoMList* list, MonoMList *item)
  167. {
  168. MonoMList* prev = NULL;
  169. while (list) {
  170. if (list == item)
  171. break;
  172. prev = list;
  173. list = list->next;
  174. }
  175. return prev;
  176. }
  177. /**
  178. * mono_mlist_remove_item:
  179. * @list: the managed list
  180. * @data: the object to remove from the list
  181. *
  182. * Remove the list node @item from the managed list @list.
  183. * Since managed lists are singly-linked, this operation can take O(n) time.
  184. */
  185. MonoMList*
  186. mono_mlist_remove_item (MonoMList* list, MonoMList *item)
  187. {
  188. MonoMList* prev;
  189. if (list == item) {
  190. list = item->next;
  191. item->next = NULL;
  192. return list;
  193. }
  194. prev = find_prev (list, item);
  195. if (prev) {
  196. MONO_OBJECT_SETREF (prev, next, item->next);
  197. item->next = NULL;
  198. return list;
  199. } else {
  200. /* not found */
  201. return list;
  202. }
  203. }