[interp] Small fixes (#11667)
[mono-project.git] / mono / metadata / mono-mlist.c
blob80bd991b92f2870c3763988db1148f1787998c03
1 /**
2 * \file
3 * Managed object list implementation
5 * Author:
6 * Paolo Molaro (lupus@ximian.com)
8 * Copyright 2006-2009 Novell, Inc (http://www.novell.com)
9 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
12 #include <config.h>
13 #include "mono/metadata/mono-mlist.h"
14 #include "mono/metadata/appdomain.h"
15 #include "mono/metadata/class-internals.h"
16 #include "mono/metadata/object-internals.h"
19 static
20 MonoMList* mono_mlist_alloc_checked (MonoObject *data, MonoError *error);
23 /* matches the System.MonoListItem object*/
24 struct _MonoMList {
25 MonoObject object;
26 MonoMList *next;
27 MonoObject *data;
30 /*
31 * note: we only allocate in the root domain: this lists are
32 * not exposed to managed code
34 static MonoVTable *monolist_item_vtable = NULL;
36 /**
37 * mono_mlist_alloc:
38 * \param data object to use as data
39 * Allocates a new managed list node with \p data as the contents.
40 * A managed list node also represents a singly-linked list.
41 * Managed lists are garbage collected, so there is no free routine
42 * and the user is required to keep references to the managed list
43 * to prevent it from being garbage collected.
45 MonoMList*
46 mono_mlist_alloc (MonoObject *data)
48 ERROR_DECL (error);
49 MonoMList *result = mono_mlist_alloc_checked (data, error);
50 mono_error_cleanup (error);
51 return result;
54 /**
55 * mono_mlist_alloc_checked:
56 * \param data object to use as data
57 * \param error set on error
58 * Allocates a new managed list node with \p data as the contents. A
59 * managed list node also represents a singly-linked list. Managed
60 * lists are garbage collected, so there is no free routine and the
61 * user is required to keep references to the managed list to prevent
62 * it from being garbage collected. On failure returns NULL and sets
63 * \p error.
65 MonoMList*
66 mono_mlist_alloc_checked (MonoObject *data, MonoError *error)
68 error_init (error);
69 MonoMList* res;
70 if (!monolist_item_vtable) {
71 MonoClass *klass = mono_class_load_from_name (mono_defaults.corlib, "System", "MonoListItem");
72 monolist_item_vtable = mono_class_vtable_checked (mono_get_root_domain (), klass, error);
73 mono_error_assert_ok (error);
75 res = (MonoMList*)mono_object_new_specific_checked (monolist_item_vtable, error);
76 return_val_if_nok (error, NULL);
77 MONO_OBJECT_SETREF_INTERNAL (res, data, data);
78 return res;
81 /**
82 * mono_mlist_get_data:
83 * \param list the managed list node
84 * Get the object stored in the list node \p list.
86 MonoObject*
87 mono_mlist_get_data (MonoMList* list)
89 return list->data;
92 /**
93 * mono_mlist_set_data:
94 * \param list the managed list node
95 * Set the object content in the list node \p list.
97 void
98 mono_mlist_set_data (MonoMList* list, MonoObject *data)
100 MONO_OBJECT_SETREF_INTERNAL (list, data, data);
104 * mono_mlist_set_next:
105 * \param list a managed list node
106 * \param next list node that will be next for the \p list node.
107 * Set next node for \p list to \p next.
109 MonoMList *
110 mono_mlist_set_next (MonoMList* list, MonoMList *next)
112 if (!list)
113 return next;
115 MONO_OBJECT_SETREF_INTERNAL (list, next, next);
116 return list;
120 * mono_mlist_length:
121 * \param list the managed list
122 * Get the number of items in the list \p list.
123 * Since managed lists are singly-linked, this operation takes O(n) time.
126 mono_mlist_length (MonoMList* list)
128 int len = 0;
129 while (list) {
130 list = list->next;
131 ++len;
133 return len;
137 * mono_mlist_next:
138 * \param list the managed list node
139 * Returns the next managed list node starting from \p list.
141 MonoMList*
142 mono_mlist_next (MonoMList* list)
144 return list->next;
148 * mono_mlist_last:
149 * \param list the managed list node
150 * Returns the last managed list node in list \p list.
151 * Since managed lists are singly-linked, this operation takes O(n) time.
153 MonoMList*
154 mono_mlist_last (MonoMList* list)
156 if (list) {
157 while (list->next)
158 list = list->next;
159 return list;
161 return NULL;
165 * mono_mlist_prepend:
166 * \param list the managed list
167 * \param data the object to add to the list
168 * Allocate a new list node with \p data as content and prepend it
169 * to the list \p list. \p list can be NULL.
171 MonoMList*
172 mono_mlist_prepend (MonoMList* list, MonoObject *data)
174 ERROR_DECL (error);
175 MonoMList *result = mono_mlist_prepend_checked (list, data, error);
176 mono_error_cleanup (error);
177 return result;
181 * mono_mlist_prepend_checked:
182 * \param list the managed list
183 * \param data the object to add to the list
184 * \param error set on error
185 * Allocate a new list node with \p data as content and prepend it to
186 * the list \p list. \p list can be NULL. On failure returns NULL and sets
187 * \p error.
189 MonoMList*
190 mono_mlist_prepend_checked (MonoMList* list, MonoObject *data, MonoError *error)
192 error_init (error);
193 MonoMList* res = mono_mlist_alloc_checked (data, error);
194 return_val_if_nok (error, NULL);
196 if (list)
197 MONO_OBJECT_SETREF_INTERNAL (res, next, list);
198 return res;
202 * mono_mlist_append:
203 * \param list the managed list
204 * \param data the object to add to the list
205 * Allocate a new list node with \p data as content and append it
206 * to the list \p list. \p list can be NULL.
207 * Since managed lists are singly-linked, this operation takes O(n) time.
209 MonoMList*
210 mono_mlist_append (MonoMList* list, MonoObject *data)
212 ERROR_DECL (error);
213 MonoMList *result = mono_mlist_append_checked (list, data, error);
214 mono_error_cleanup (error);
215 return result;
219 * mono_mlist_append_checked:
220 * \param list the managed list
221 * \param data the object to add to the list
222 * \param error set on error
223 * Allocate a new list node with \p data as content and append it
224 * to the list \p list. \p list can be NULL.
225 * Since managed lists are singly-linked, this operation takes O(n) time.
226 * On failure returns NULL and sets \p error.
228 MonoMList*
229 mono_mlist_append_checked (MonoMList* list, MonoObject *data, MonoError *error)
231 error_init (error);
232 MonoMList* res = mono_mlist_alloc_checked (data, error);
233 return_val_if_nok (error, NULL);
235 if (list) {
236 MonoMList* last = mono_mlist_last (list);
237 MONO_OBJECT_SETREF_INTERNAL (last, next, res);
238 return list;
239 } else {
240 return res;
244 static MonoMList*
245 find_prev (MonoMList* list, MonoMList *item)
247 MonoMList* prev = NULL;
248 while (list) {
249 if (list == item)
250 break;
251 prev = list;
252 list = list->next;
254 return prev;
258 * mono_mlist_remove_item:
259 * \param list the managed list
260 * \param data the object to remove from the list
261 * Remove the list node \p item from the managed list \p list.
262 * Since managed lists are singly-linked, this operation can take O(n) time.
264 MonoMList*
265 mono_mlist_remove_item (MonoMList* list, MonoMList *item)
267 MonoMList* prev;
268 if (list == item) {
269 list = item->next;
270 item->next = NULL;
271 return list;
273 prev = find_prev (list, item);
274 if (prev) {
275 MONO_OBJECT_SETREF_INTERNAL (prev, next, item->next);
276 item->next = NULL;
277 return list;
278 } else {
279 /* not found */
280 return list;