Annotation of gpl/axl/src/axl_list.c, revision 1.1.1.1
1.1 misho 1: /*
2: * LibAxl: Another XML library
3: * Copyright (C) 2006 Advanced Software Production Line, S.L.
4: *
5: * This program is free software; you can redistribute it and/or
6: * modify it under the terms of the GNU Lesser General Public License
7: * as published by the Free Software Foundation; either version 2.1 of
8: * 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 Lesser General Public License for more details.
14: *
15: * You should have received a copy of the GNU Lesser General Public
16: * License along with this program; if not, write to the Free
17: * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18: * 02111-1307 USA
19: *
20: * You may find a copy of the license under this software is released
21: * at COPYING file. This is LGPL software: you are welcome to
22: * develop proprietary applications using this library without any
23: * royalty or fee but returning back any change, improvement or
24: * addition in the form of source code, project image, documentation
25: * patches, etc.
26: *
27: * For commercial support on build XML enabled solutions contact us:
28: *
29: * Postal address:
30: * Advanced Software Production Line, S.L.
31: * Edificio Alius A, Oficina 102,
32: * C/ Antonio Suarez Nº 10,
33: * Alcalá de Henares 28802 Madrid
34: * Spain
35: *
36: * Email address:
37: * info@aspl.es - http://www.aspl.es/xml
38: */
39:
40: #include <axl_decl.h>
41: #include <axl_list.h>
42: #include <axl_log.h>
43: #include <axl_stream.h>
44:
45: #define LOG_DOMAIN "axl-list"
46:
47: typedef struct _axlListNode axlListNode;
48:
49: struct _axlList {
50: /* functions used by the list to properly order elements
51: * inside it and how they are destroyed */
52: axlEqualFunc are_equal;
53: axlDestroyFunc destroy_data;
54:
55: /* pointers to the list content */
56: axlListNode * first_node;
57: axlListNode * last_node;
58:
59: /* list length */
60: int length;
61:
62: /* memory management functions */
63: axlListNode ** preallocated;
64: int available;
65: int allocated;
66: };
67:
68: struct _axlListNode {
69: axlListNode * previous;
70: axlListNode * next;
71: axlPointer data;
72: };
73:
74: struct _axlListCursor {
75: axlList * list;
76: axlListNode * current;
77: };
78:
79: /**
80: * \defgroup axl_list_module Axl List: A configurable double-linked list used across the library.
81: */
82:
83: /**
84: * \addtogroup axl_list_module
85: * @{
86: */
87:
88: /**
89: * @internal
90: *
91: * Internal are equal handler implementation for the axl list module
92: * that always return 0.
93: */
94: int __axl_list_always_true (axlPointer a, axlPointer b)
95: {
96: return 0;
97: }
98:
99: /**
100: * @internal
101: *
102: * Preallocates nodes to be used to store data on the lists.
103: *
104: * @param list The list where the preallocation operation will be
105: * performed.
106: */
107: void __axl_list_allocate_nodes (axlList * list)
108: {
109: int iterator;
110:
111: list->available = 1;
112: list->allocated += list->available;
113:
114: /* allocate enough memory to hold all nodes already
115: * allocated */
116: if (list->preallocated == NULL)
117: list->preallocated = axl_new (axlListNode *, list->allocated);
118: else
119: list->preallocated = realloc (list->preallocated, (sizeof (axlListNode *)) * list->allocated);
120:
121: /* allocate a node for each available position */
122: for (iterator = 0; iterator < list->available; iterator++) {
123: list->preallocated[iterator] = axl_new (axlListNode, 1);
124: }
125:
126: return;
127: }
128:
129: /**
130: * @internal
131: *
132: * Disposes the node provided, reusing on the next operation
133: * requested.
134: */
135: void __axl_list_dispose_node (axlList * list, axlListNode * node)
136: {
137: /* store the node to be usable again */
138: list->preallocated [list->available] = node;
139:
140: /* increase current available nodes */
141: list->available++;
142:
143: return;
144: }
145:
146: /**
147: * @internal
148: *
149: * Returns a reference to an list node to be used.
150: */
151: axlListNode * __axl_list_get_next_node_available (axlList * list)
152: {
153: axlListNode * node;
154:
155: /* check that there are nodes available */
156: if (list->available == 0)
157: __axl_list_allocate_nodes (list);
158:
159: /* get the next node available */
160: node = list->preallocated[list->available - 1];
161: list->available--;
162:
163: /* clean node */
164: node->next = NULL;
165: node->previous = NULL;
166: node->data = NULL;
167:
168: return node;
169: }
170:
171:
172: /**
173: * @brief Creates a new \ref axlList, using provided handlers.
174: *
175: * An \ref axlList is a double linked list, with the hability to
176: * recognize elements inside its list by providing the \ref
177: * axlEqualFunc "are_equal" function and the ability to release
178: * memory allocated by the data stored by providing a \ref
179: * axlDestroyFunc "destroy_data" handler.
180: *
181: * The destroy handler is a optional value. If not provided, any
182: * automatic deallocation function will not provided.
183: *
184: * The "are equal" handler is not optinal. You must provide it to make
185: * the list work. In the case you don't like a ordering feature you
186: * can provide an are equal that just return 0 when elements are equal
187: * and always -1 for the rest of the cases if element should be
188: * appended or 1 if the element should be prepended.
189: *
190: * The list is not prepared to be managed at the same type by several
191: * threads. If the list is created and then used by several threads it
192: * will work properly. However, if several threads add and removes
193: * elements at the same time rainy days will come and you'll get funny
194: * behaviours.
195: *
196: * To create the list you must provide two function that performs some
197: * minimal functions required by the list o properly order the data
198: * inside the list and how this data is deallocated (this is
199: * optional).
200: *
201: * For example, to create a list that will hold strings dinamically
202: * allocated you can use:
203: * \code
204: * axlList * list = axl_list_new (axl_list_equal_string, axl_free);
205: * \endcode
206: *
207: * For a list that will holds integer values you can use: \ref
208: * axl_list_equal_int.
209: *
210: * Previous list will cause all strings inside to be deallocated once
211: * called to \ref axl_list_free. If you don't like this, do not
212: * provide the deallocation function.
213: *
214: * You can always use the following function to make the list to allways
215: * add all data at the end of the list: \ref axl_list_always_return_1,
216: * which, as its names indicates, allways return 1, causing the item
217: * to be added at the end of the list. See \ref axlEqualFunc
218: * documentation to know more about creating ordenation functions.
219: *
220: * Now you have your list created, you can use the following functions
221: * to add items:
222: *
223: * - \ref axl_list_add
224: * - \ref axl_list_add_at
225: * - \ref axl_list_prepend
226: * - \ref axl_list_append
227: *
228: * Once you have inserted some data, you can use the following piece
229: * of code to perform an iteration:
230: *
231: * \code
232: * int iterator = 0;
233: * while (iterator < axl_list_length (list)) {
234: * // get the data at the given position
235: * data = axl_list_get_nth (list, iterator);
236: *
237: * // update the iterator
238: * iterator++;
239: * }
240: * \endcode
241: *
242: * However, it is preferred to use the \ref axlListCursor, which is
243: * far more efficient. See the following function to get more
244: * information: \ref axl_list_cursor_new.
245: *
246: * In general, if you are going to perform a lookup for a single item
247: * you can use \ref axl_list_lookup (by providing a handler) or \ref
248: * axl_list_get_nth if you know the position.
249: *
250: *
251: * @param are_equal The equal function to be used by the list to find
252: * and order elements inside the list.
253: *
254: * @param destroy_data An optional handler to destroy nodes in the
255: * case the list is unrefered.
256: *
257: * @return A newly allocated list, that must be destroy by calling to
258: * \ref axl_list_free.
259: */
260: axlList * axl_list_new (axlEqualFunc are_equal, axlDestroyFunc destroy_data)
261: {
262: axlList * result;
263:
264: axl_return_val_if_fail (are_equal, NULL);
265:
266: result = axl_new (axlList, 1);
267: result->are_equal = are_equal;
268: result->destroy_data = destroy_data;
269:
270: /* preallocate memory for nodes */
271: /* __axl_list_allocate_nodes (result); */
272:
273: return result;
274: }
275:
276: /**
277: * @brief Allows to reconfigure the destroy function to be used on
278: * this list. This function can be useful to disable the destroy
279: * function associated to the list.
280: *
281: * @param list The list to reconfigure or disable (NULL) the destroy function.
282: *
283: * @param destroy_data The reference to the destroy function to be
284: * used or NULL to disable it.
285: */
286: void axl_list_set_destroy_func (axlList * list, axlDestroyFunc destroy_data)
287: {
288: axl_return_if_fail (list);
289: list->destroy_data = destroy_data;
290: return;
291: }
292:
293: /**
294: * @brief Allows to copy the provided list, returning a newly
295: * allocated structure.
296: *
297: * The copy process can also perform a deep copy for all data stored
298: * inside the \ref axlList. However, for this purpose it is required
299: * to provide a duplication function that is able to implement the
300: * duplication operation over the data received.
301: *
302: * This handler is optional, and in the case it is not provided, the
303: * list returned will be a copy having reference to the content
304: * stored.
305: *
306: * NOTE: the function also copy the destroy and equal function
307: * configured at \ref axl_list_new. If you want to disable destroy
308: * function on the copy returned you must use \ref
309: * axl_list_set_destroy_func, passing NULL as destroy handler.
310: *
311: * @param list The list to copy.
312: * @param func The duplication function used to perform a deep copy (optional handler).
313: *
314: * @return A newly allocated \ref axlList with the same configuration
315: * as the one provided.
316: */
317: axlList * axl_list_copy (axlList * list, axlDuplicateFunc func)
318: {
319: axlList * result;
320: int iterator;
321: axlPointer data;
322:
323: axl_return_val_if_fail (list, NULL);
324:
325: /* create a new axl list */
326: result = axl_list_new (list->are_equal, list->destroy_data);
327:
328: /* if the duplicate function is NULL, remove the destroy
329: * function */
330: if (func == NULL)
331: result->destroy_data = NULL;
332:
333: /* add all elements */
334: iterator = 0;
335: while (iterator < axl_list_length (list)) {
336: /* get data pointer from the list */
337: data = axl_list_get_nth (list, iterator);
338:
339: /* try to make a copy */
340: if (func != NULL)
341: data = func (data);
342:
343: /* add the data to the new list */
344: axl_list_add (result, data);
345:
346: /* update index */
347: iterator++;
348: }
349:
350: return result;
351: }
352:
353: /**
354: * @brief Equal function that is prepared to receive two strings a
355: * return if they are equal.
356: *
357: * This function is provided as a convenience implementation for the
358: * \ref axl_list_new function, allowing to store strings inside the
359: * given list.
360: *
361: * The function will return 0 if the string are equal and 1 if
362: * not. This will cause strings to be append at the end of the list.
363: *
364: * @param a The first string to compare.
365: * @param b The second string to compare.
366: */
367: int axl_list_equal_string (axlPointer a, axlPointer b)
368: {
369: int length;
370:
371: axl_return_val_if_fail (a, 1);
372: axl_return_val_if_fail (b, 1);
373:
374: /* get length */
375: length = strlen (a);
376:
377: /* check first that both strings have the same length */
378: if (length != strlen (b))
379: return 1;
380:
381: if (axl_stream_cmp (a, b, length))
382: return 0;
383: /* differs */
384: return 1;
385: }
386:
387: /**
388: * @brief Equal function that is preprated to receive to integers and
389: * return if they are equal.
390: *
391: * It is assumed that integers are stored in the list using the
392: * following:
393: * \code
394: * axl_list_add (list, INT_TO_PTR (integer));
395: * \endcode
396: *
397: * You can use this function to create an \ref axlList that stores
398: * integer values as follows:
399: * \code
400: * list = axl_list_new (axl_list_equal_int, NULL);
401: * \endcode
402: *
403: * The list created with this function will order data from litter to
404: * greater values.
405: *
406: *
407: * @param a A reference to the first integer.
408: * @param b A reference to the second integer.
409: *
410: * @return 0 if values received are equal, and 1 if b is greater than
411: * b. Otherwise -1 is returned.
412: */
413: int axl_list_equal_int (axlPointer a, axlPointer b)
414: {
415: /* especial case where a 0 is stored */
416: if (PTR_TO_INT (a) == PTR_TO_INT (b))
417: return 0;
418: else if (PTR_TO_INT (a) < PTR_TO_INT (b))
419: return -1;
420: else
421: return 1;
422: }
423:
424: /**
425: * @brief An equal function that could be used to make elements to be
426: * stored inside an \ref axlList at the end as the are added, without
427: * replacing any previously added item.
428: *
429: *
430: * If it is needed to create a list that stores elements at the end as
431: * they are added, this function could be used as the \ref
432: * axlEqualFunc, while calling to axl_list_new.
433: *
434: * @param a First item.
435: * @param b Second item.
436: *
437: * @return The function always return 1.
438: *
439: * NOTE: If you use this function and your intention is to remove
440: * items (without calling to axl_list_free) you must use \ref
441: * axl_list_remove_ptr or \ref axl_list_unlink_ptr since \ref
442: * axl_list_remove and \ref axl_list_unlink relays on the equal
443: * function to find and remove the item. Because this function never
444: * return 0, the item is never removed.
445: */
446: int axl_list_always_return_1 (axlPointer a, axlPointer b)
447: {
448: return 1;
449: }
450:
451: /**
452: * @brief Allows to store a new element inside the list, using the
453: * provided data.
454: *
455: * The function will fail to perform any action if a null reference is
456: * provided to the function.
457: *
458: * @param list The list where the element will be added.
459: *
460: * @param pointer The pointer to store.
461: *
462: * NOTE: The function uses the equal function defined at \ref
463: * axl_list_new. If the function shows that the item to be added is
464: * already added (because the equal function returns 0, then the item
465: * won't be added.
466: *
467: */
468: void axl_list_add (axlList * list, axlPointer pointer)
469: {
470: axlListNode * new_node;
471: axlListNode * node;
472: axlListNode * node2;
473:
474:
475: /* perform some environment checkings */
476: axl_return_if_fail (list);
477:
478: new_node = __axl_list_get_next_node_available (list);
479: new_node->data = pointer;
480:
481: /* check basic case */
482: if (list->first_node == NULL) {
483: list->first_node = new_node;
484: list->last_node = new_node;
485: list->length = 1;
486: return;
487: }
488:
489: /* complex case */
490: node = list->first_node;
491: node2 = list->last_node;
492:
493: /* lookup */
494: while ((node != NULL) || (node2 != NULL)) {
495: /* lookup the head */
496: if (node != NULL) {
497: switch (list->are_equal (node->data, pointer)) {
498: case -1:
499: /* the node should be added before node */
500: new_node->next = node;
501: new_node->previous = node->previous;
502: node->previous = new_node;
503:
504: /* if new previous is null do not update it */
505: if (new_node->previous != NULL)
506: new_node->previous->next = new_node;
507: else
508: list->first_node = new_node;
509:
510: /* update list length */
511: list->length ++;
512: return;
513: case 0:
514: /* the node found is equal, do not perform any operation */
515: return;
516: case 1:
517: default:
518: /* the node should be added after */
519: node = node->next;
520: break;
521: }
522: } /* end if */
523:
524: /* lookup from the tail */
525: if (node2 != NULL) {
526: switch (list->are_equal (node2->data, pointer)) {
527: case -1:
528: default:
529: /* the node should be added before node */
530: node2 = node2->previous;
531: break;
532: case 0:
533:
534: /* the node found is equal, do not perform any operation */
535: return;
536: case 1:
537: /* the node should be added after */
538: new_node->previous = node2;
539: new_node->next = node2->next;
540: node2->next = new_node;
541:
542: /* do not update if next is NULL */
543: if (new_node->next != NULL)
544: new_node->next->previous = new_node;
545: else
546: list->last_node = new_node;
547:
548: /* update length size */
549: list->length ++;
550: return;
551: }
552: } /* end if */
553: } /* end while */
554:
555: /* nothing more to do */
556: return;
557: }
558:
559: /**
560: * @brief Allows to adds the provided item to the given list at the
561: * selected position.
562: *
563: * The function will perform an indexed addition, using the value
564: * <b>position</b>, by-passing current list configuration (\ref
565: * axl_list_new).
566: *
567: * If the position is greater than the length of the list, the item is
568: * added at the end of the list. If the position is 0, the item is
569: * added at the begin (equivalent to call \ref axl_list_prepend).
570: *
571: * If an item is found at the provided position, the element is added
572: * before the already found.
573: *
574: * @param list The list where the addition operation will be performed.
575: *
576: * @param pointer The item to add to the list.
577: *
578: * @param position Position where the addition operation will be
579: * performed. Values allowed ranges from 0 up to list length - 1.
580: */
581: void axl_list_add_at (axlList * list, axlPointer pointer, int position)
582: {
583: int iterator;
584: axlListNode * node;
585: axlListNode * new_node;
586:
587: /* check incoming values */
588: axl_return_if_fail (list);
589:
590: /* check if we have a prepend operation */
591: if (position <= 0) {
592: __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "adding item using prepend");
593: /* prepend */
594: axl_list_prepend (list, pointer);
595:
596: return;
597: }
598: /* check if we have an append operation */
599: if (position >= list->length) {
600: __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "adding item using append (position=%d >= length=%d)",
601: position, list->length);
602: /* append */
603: axl_list_append (list, pointer);
604:
605: return;
606: }
607:
608: /* allocate a new node */
609: new_node = __axl_list_get_next_node_available (list);
610: new_node->data = pointer;
611:
612:
613: __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "looking node position: %d", position);
614:
615: /* basic case isn't reached here (remove first and last
616: * cases) */
617: iterator = 1;
618: node = list->first_node->next;
619: while (iterator < position) {
620:
621: /* get the next element */
622: node = node->next;
623:
624: /* update the iterator */
625: iterator++;
626: }
627:
628: __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "adding item at: %d", iterator);
629:
630: /* add the element */
631: new_node->previous = node->previous;
632: if (node->previous != NULL)
633: node->previous->next = new_node;
634:
635: new_node->next = node;
636: node->previous = new_node;
637:
638: /* update number of items inside */
639: list->length++;
640: return;
641: }
642:
643: /**
644: * @brief Allows to add a node to the provided list, at the first
645: * position, without taking into consideration current \ref axlList
646: * configuration (\ref axlEqualFunc at \ref axl_list_new).
647: *
648: * @param list The list where the data will be added at the first
649: * position.
650: *
651: * @param pointer The pointer to add.
652: */
653: void axl_list_prepend (axlList * list, axlPointer pointer)
654: {
655: axlListNode * new_node;
656:
657: axl_return_if_fail (list);
658:
659: /* simulate adding the node at the first position */
660: new_node = __axl_list_get_next_node_available (list);
661: new_node->data = pointer;
662:
663: /* make the new node the be the first one */
664: if (list->first_node == NULL) {
665: list->first_node = new_node;
666: list->last_node = new_node;
667: }else {
668: list->first_node->previous = new_node;
669: new_node->next = list->first_node;
670: list->first_node = new_node;
671: }
672:
673: /* update number of items inside */
674: list->length++;
675:
676: return;
677: }
678:
679:
680: /**
681: * @brief Allows to add a node to the provided list, at the last
682: * position, without taking into consideration current \ref axlList
683: * configuration (\ref axlEqualFunc at \ref axl_list_new).
684: *
685: * @param list The list where the data will be added at the last
686: * position.
687: *
688: * @param pointer The pointer to add.
689: */
690: void axl_list_append (axlList * list, axlPointer pointer)
691: {
692: axlListNode * new_node;
693:
694: axl_return_if_fail (list);
695:
696: /* simulate adding the node at the first position */
697: new_node = __axl_list_get_next_node_available (list);
698: new_node->data = pointer;
699:
700: /* make the new node the be the first one */
701: if (list->last_node == NULL) {
702: list->first_node = new_node;
703: list->last_node = new_node;
704: }else {
705: list->last_node->next = new_node;
706: new_node->previous = list->last_node;
707: list->last_node = new_node;
708: }
709:
710: /* update number of items inside */
711: list->length++;
712:
713: return;
714: }
715:
716: /**
717: * @internal Internal list lookup using a linear search, checking all
718: * items inside the list taking into considerations hints provided by
719: * equal function.
720: *
721: * @param list The list where the linear search will be performed.
722: * @param pointer The pointer that is being looked up.
723: *
724: * @return A reference to the internal axl list node containing the
725: * pointer.
726: */
727: axlListNode * axl_list_internal_linear_lookup (axlList * list,
728: axlPointer pointer)
729: {
730: axlListNode * node;
731:
732: axl_return_val_if_fail (list, NULL);
733:
734: /* complex case */
735: node = list->first_node;
736:
737: /* lookup */
738: while (node != NULL) {
739: if (list->are_equal (node->data, pointer) == 0)
740: return node;
741:
742: /* the node should be after this one */
743: node = node->next;
744:
745: } /* end while */
746:
747: return NULL;
748: }
749:
750: /**
751: * @internal Internal list lookup using a linear search, checking all
752: * items inside the list withtout taking into considerations hints
753: * provided by equal function (search by pointer).
754: *
755: * @param list The list where the linear search will be performed.
756: * @param pointer The pointer that is being looked up.
757: *
758: * @return A reference to the internal axl list node containing the
759: * pointer.
760: */
761: axlListNode * axl_list_internal_linear_lookup_ptr (axlList * list,
762: axlPointer pointer)
763: {
764: axlListNode * node;
765:
766: axl_return_val_if_fail (list, NULL);
767:
768: /* complex case */
769: node = list->first_node;
770:
771: /* lookup */
772: while (node && node->data != pointer) {
773: /* the node should be after this one */
774: node = node->next;
775: } /* end while */
776:
777: /* return current result */
778: return node;
779: }
780:
781: /**
782: * @internal
783: * @brief Internal lookup function to locate the axlListNode that contains the pointer.
784: *
785: *
786: * @param list The list where the lookup will be performed.
787: * @param pointer The pointer data to lookup.
788: *
789: * @return A reference to the \ref axlListNode or NULL if no pointer
790: * is found.
791: */
792: axlListNode * axl_list_internal_lookup (axlList * list, axlPointer pointer)
793: {
794: axlListNode * node;
795: axlListNode * node2;
796:
797: axl_return_val_if_fail (list, NULL);
798: axl_return_val_if_fail (pointer, NULL);
799:
800: /* complex case */
801: node = list->first_node;
802: node2 = list->last_node;
803:
804: /* lookup */
805: while ((node != NULL) || (node2 != NULL)) {
806: /* lookup the head */
807: if (node != NULL) {
808: switch (list->are_equal (node->data, pointer)) {
809: case -1:
810: default:
811: /* node should be before the node
812: * found. So we are not going to find
813: * a node that is lower, the element
814: * is not in the list.
815: */
816: return NULL;
817: case 0:
818: return node;
819: case 1:
820: /* the node should be after this one */
821: node = node->next;
822: break;
823: }
824: } /* end if */
825:
826: /* lookup from the tail */
827: if (node2 != NULL) {
828: switch (list->are_equal (node2->data, pointer)) {
829: case -1:
830: /* the node should be added before node */
831: node2 = node2->next;
832: break;
833: case 0:
834: return node2;
835: case 1:
836: default:
837: /* it seems that the node should be
838: * found after this node but this is
839: * not going to be possible. The node is not in the list.
840: */
841: return NULL;
842: }
843: } /* end if */
844: } /* end while */
845:
846: return NULL;
847: }
848:
849:
850: /**
851: * @internal
852: *
853: * @brief Allows to lookup the pointer stored, inside the provided
854: * list, on the given position.
855: *
856: * @param list The list where the operation will be performed.
857: * @param position The position to lookup for stored data.
858: *
859: * @return A reference or NULL if fails.
860: */
861: axlListNode * axl_list_internal_get_nth (axlList * list, int position)
862: {
863: axlListNode * node;
864: int iterator = 0;
865:
866: axl_return_val_if_fail (list, NULL);
867: axl_return_val_if_fail (position >= 0 && position < list->length, NULL);
868:
869: /* iterate until the node is found */
870: node = list->first_node;
871: while (node != NULL && (iterator != position)) {
872: iterator ++;
873: node = node->next;
874: }
875:
876: /* return data found */
877: if (iterator == position)
878: return node;
879: return NULL;
880: }
881:
882: /* remove the selected node */
883: void __axl_list_common_remove_selected_node (axlList * list, axlListNode * node,
884: axl_bool alsoRemove)
885: {
886: axlPointer pointer;
887:
888: /* do not remove anything if a null reference is received */
889: if (node == NULL)
890: return;
891:
892: /* get a reference to the pointer */
893: pointer = node->data;
894:
895: if (node->previous == NULL)
896: list->first_node = node->next;
897: else
898: node->previous->next = node->next;
899:
900: if (node->next == NULL)
901: list->last_node = node->previous;
902: else
903: node->next->previous = node->previous;
904:
905: /* release user space allocated memory
906: * if defined destroy function */
907: if (alsoRemove && (list->destroy_data != NULL))
908: list->destroy_data (pointer);
909:
910: /* release memory allocated by the node */
911: __axl_list_dispose_node (list, node);
912:
913: /* decrease list length */
914: list->length--;
915:
916: /* nothing more to do */
917: return;
918: }
919:
920: /**
921: * @internal
922: *
923: * Internal support for axl_list_remove and axl_list_unlink
924: * function. The function perform a node removing, the one that
925: * contains the node pointed by the provided pointer, and making a
926: * node deallocation according to the configuration of the
927: * <b>alsoRemove</b>.
928: *
929: * @param list The list where the operation will be performed.
930: *
931: * @param pointer The pointer to remove
932: *
933: * @param alsoRemove Also call to destroy function.
934: *
935: * @param byPtr Makes the linear search to be done by pointer.
936: */
937: void axl_list_common_remove (axlList * list, axlPointer pointer, axl_bool alsoRemove, axl_bool byPtr)
938: {
939: axlListNode * node;
940:
941: axl_return_if_fail (list);
942:
943: /* complex case */
944: if (byPtr)
945: node = axl_list_internal_linear_lookup_ptr (list, pointer);
946: else
947: node = axl_list_internal_linear_lookup (list, pointer);
948: if (node == NULL) {
949: __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "unable to find item by pointer (0x%x)",
950: pointer);
951: return;
952: }
953:
954: /* remove the selected node */
955: __axl_list_common_remove_selected_node (list, node, alsoRemove);
956:
957: return;
958: }
959:
960:
961: /**
962: * @brief Allows to remove the given pointer from the list.
963: *
964: * The element referenced by <b>pointer</b> will be removed from the
965: * list, include the memory allocated if a destroy function were
966: * provided.
967: *
968: * If it is required to remove a pointer from the list, without
969: * calling to the destroy function, you can use \ref axl_list_unlink.
970: *
971: * The function will fail to work if references provided are NULL.
972: *
973: * @param list The list where the removal operation will be performed.
974: * @param pointer The pointer where the
975: *
976: * NOTE: The function uses the current equal function configured. A
977: * not properly configured equal function will make this function to
978: * not remove the item selected. If you are trying to remove by
979: * pointer, you can use \ref axl_list_remove_ptr.
980: */
981: void axl_list_remove (axlList * list, axlPointer pointer)
982: {
983:
984: /* perform a complete removing */
985: axl_list_common_remove (list, pointer,
986: /* alsoRemove */
987: axl_true,
988: /* byPtr */
989: axl_false);
990:
991: return;
992: }
993:
994: /**
995: * @internal Implementation that removes or unlinks a selected node at
996: * a particular position.
997: */
998: void __axl_list_remove_at_common (axlList * list, int position, axl_bool remove_node)
999: {
1000: axlListNode * node;
1001: int iterator = 0;
1002:
1003: axl_return_if_fail (list);
1004:
1005: /* find the item by position */
1006: node = list->first_node;
1007:
1008: /* lookup */
1009: while (node) {
1010: /* return selected node */
1011: if (iterator == position)
1012: break;
1013:
1014: /* the node should be after this one */
1015: node = node->next;
1016:
1017: /* next iterator */
1018: iterator++;
1019: } /* end while */
1020:
1021: if (node) {
1022: /* remove selected node */
1023: __axl_list_common_remove_selected_node (list, node, remove_node);
1024: } /* end if */
1025: return;
1026: }
1027:
1028: /**
1029: * @brief Allows to remove a particular item inside the list at a
1030: * selected position.
1031: *
1032: * This function also deallocates the memory used by the node located
1033: * at the particular position. In the case only a removal operation is
1034: * required use \ref axl_list_unlink_at.
1035: *
1036: * @param list The list where the remove operation will take place.
1037: *
1038: * @param position The position where the removal operation will take
1039: * place. Position values ranges from 0 up to (N - 1).
1040: */
1041: void axl_list_remove_at (axlList * list, int position)
1042: {
1043: /* call to common implementation */
1044: __axl_list_remove_at_common (list, position, axl_true);
1045: return;
1046: }
1047:
1048: /**
1049: * @brief Allows to remove the provided pointer from the list (calling
1050: * to the destroy function defined).
1051: *
1052: * Unlike \ref axl_list_remove, which removes the element selected by
1053: * using the equal function configured at \ref axl_list_new, this
1054: * function allows to perform a remove operation by pointer.
1055: *
1056: * @param list The list on which the operation is performed.
1057: *
1058: * @param pointer The pointer to remove from the list.
1059: */
1060: void axl_list_remove_ptr (axlList * list, axlPointer pointer)
1061: {
1062: /* perform a complete removing */
1063: axl_list_common_remove (list, pointer,
1064: /* alsoRemove */
1065: axl_true,
1066: /* byPtr */
1067: axl_true);
1068: }
1069:
1070: /**
1071: * @brief Removes the given pointer from the list, without calling the
1072: * destroy function, even when it is configured.
1073: *
1074: * @param list The list where the operation will be performed.
1075: *
1076: * @param pointer The pointer to remove.
1077: */
1078: void axl_list_unlink (axlList * list, axlPointer pointer)
1079: {
1080: /* perform a complete removing */
1081: axl_list_common_remove (list, pointer,
1082: /* alsoRemove */
1083: axl_false,
1084: /* byPtr */
1085: axl_false);
1086:
1087: return;
1088: }
1089:
1090: /**
1091: * @brief Allows to remove the provided item from the axl list
1092: * withtout using the equal function provided (remove by pointer) and
1093: * without calling to the associated destroy function.
1094: *
1095: * @param list The list where the operation will be implemented.
1096: *
1097: * @param pointer the pointer to remove from the list without calling
1098: * to the destroy function.
1099: */
1100: void axl_list_unlink_ptr (axlList * list, axlPointer pointer)
1101: {
1102:
1103: /* perform an unlink operation, without using equal
1104: * function */
1105: /* perform a complete removing */
1106: axl_list_common_remove (list, pointer,
1107: /* alsoRemove */
1108: axl_false,
1109: /* byPtr */
1110: axl_true);
1111:
1112: return;
1113: }
1114:
1115: /**
1116: * @brief Allows to unlink a particular item inside the list at a
1117: * selected position.
1118: *
1119: * This function DO NOT deallocates the memory used by the node located
1120: * at the particular position. In the case a complete removal operation is
1121: * required use \ref axl_list_remove_at.
1122: *
1123: * @param list The list where the unlink operation will take place.
1124: *
1125: * @param position The position where the unlink operation will take
1126: * place. Position values ranges from 0 up to (N - 1).
1127: */
1128: void axl_list_unlink_at (axlList * list, int position)
1129: {
1130: /* call to common implementation */
1131: __axl_list_remove_at_common (list, position, axl_false);
1132: return;
1133: }
1134:
1135:
1136: /**
1137: * @brief Allows to remove the first element, calling to the destroy
1138: * function if defined.
1139: *
1140: * @param list The list where the first element will be removed.
1141: */
1142: void axl_list_remove_first (axlList * list)
1143: {
1144:
1145: axl_return_if_fail (list);
1146:
1147: /* do not perform any operation if no node is stored */
1148: if (list->first_node == NULL)
1149: return;
1150:
1151: /* remove the selected node */
1152: __axl_list_common_remove_selected_node (list, list->first_node, axl_true);
1153:
1154: return;
1155: }
1156:
1157: /**
1158: * @brief Allows to remove the first element from the list without
1159: * calling to the destroy function, even with it is defined.
1160: *
1161: * @param list The list where the first element will be removed.
1162: */
1163: void axl_list_unlink_first (axlList * list)
1164: {
1165:
1166: axl_return_if_fail (list);
1167:
1168: /* do not perform any operation if no node is stored */
1169: if (list->first_node == NULL)
1170: return;
1171:
1172: /* remove the selected node */
1173: __axl_list_common_remove_selected_node (list, list->first_node, axl_false);
1174:
1175: return;
1176: }
1177:
1178: /**
1179: * @brief Allows to remove the last element, calling to the destroy
1180: * function if defined.
1181: *
1182: * @param list The list where the last element will be removed.
1183: */
1184: void axl_list_remove_last (axlList * list)
1185: {
1186: axl_return_if_fail (list);
1187:
1188: /* do not perform any operation if no node is stored */
1189: if (list->last_node == NULL)
1190: return;
1191:
1192: /* remove the selected node */
1193: __axl_list_common_remove_selected_node (list, list->last_node, axl_true);
1194:
1195: return;
1196: }
1197:
1198: /**
1199: * @brief Allows to remove the last element from the list without
1200: * calling to the destroy function, even with it is defined.
1201: *
1202: * @param list The list where the last element will be removed.
1203: */
1204: void axl_list_unlink_last (axlList * list)
1205: {
1206: axl_return_if_fail (list);
1207:
1208: /* do not perform any operation if no node is stored */
1209: if (list->last_node == NULL)
1210: return;
1211:
1212: /* remove the selected node */
1213: __axl_list_common_remove_selected_node (list, list->last_node, axl_false);
1214:
1215: return;
1216: }
1217:
1218: /**
1219: * @brief Allows to check if the given pointer is stored on the given
1220: * list.
1221: *
1222: * @param list The list where the lookup will be performed.
1223: *
1224: * @param pointer The pointer to lookup.
1225: *
1226: * @return \ref axl_true if the element is stored on the list,
1227: * otherwise axl_false is returned. The function will fail to lookup
1228: * if a NULL reference is received, either the list or the pointer.
1229: */
1230: axl_bool axl_list_exists (axlList * list, axlPointer pointer)
1231: {
1232: axl_return_val_if_fail (list, axl_false);
1233: axl_return_val_if_fail (pointer, axl_false);
1234:
1235: if (axl_list_internal_lookup (list, pointer) != NULL)
1236: return axl_true;
1237: return axl_false;
1238: }
1239:
1240: /**
1241: * @brief Allows to check if the provided list is empty (no element
1242: * stored).
1243: *
1244: * @param list The list to check for emptyness.
1245: *
1246: * @return axl_true if the list is empty, axl_false if not. The function
1247: * return axl_false in the case a null reference is provided.
1248: */
1249: axl_bool axl_list_is_empty (axlList * list)
1250: {
1251: axl_return_val_if_fail (list, axl_false);
1252:
1253: /* check if the first node is defined */
1254: return (list->first_node == NULL);
1255: }
1256:
1257: /**
1258: * @brief Allows to check if the given pointer is stored on the given position.
1259: *
1260: * @param list The list where the operation will be run.
1261: * @param pointer The pointer to check.
1262: * @param position The position where is expected to find the pointer.
1263: *
1264: * @return axl_true if the given data, referenced by the pointer, is
1265: * stored on the given position.
1266: */
1267: axl_bool axl_list_exists_at (axlList * list, axlPointer pointer, int position)
1268: {
1269: axlListNode * node;
1270:
1271: node = axl_list_internal_get_nth (list, position);
1272: if (node != NULL) {
1273: if (! list->are_equal (node->data, pointer))
1274: return axl_true;
1275: }
1276: return axl_false;
1277: }
1278:
1279: /**
1280: * @brief Returns the first element stored on the list.
1281: *
1282: *
1283: * @param list The list where the first element stored will be
1284: * returned.
1285: *
1286: * @return An \ref axlPointer containing the data stored on the list.
1287: */
1288: axlPointer axl_list_get_first (axlList * list)
1289: {
1290: axl_return_val_if_fail (list, NULL);
1291:
1292: if (list->first_node == NULL)
1293: return NULL;
1294: return list->first_node->data;
1295: }
1296:
1297: /**
1298: * @brief Returns the last element stored on the list.
1299: *
1300: * @param list The list where the last element will be returned.
1301: *
1302: * @return An \ref axlPointer reference containing the last stored
1303: * value.
1304: */
1305: axlPointer axl_list_get_last (axlList * list)
1306: {
1307: axl_return_val_if_fail (list, NULL);
1308:
1309: if (list->last_node == NULL)
1310: return NULL;
1311: return list->last_node->data;
1312: }
1313:
1314: /**
1315: * @brief Allows to get current pointer stored at the given position.
1316: *
1317: * @param list The list where the data will be retrieved.
1318: *
1319: * @param position A value ranging from 0 up to the the list lenght -
1320: * 1.
1321: *
1322: * @return The \ref axlPointer stored on the given position or NULL if
1323: * fail.
1324: */
1325: axlPointer axl_list_get_nth (axlList * list, int position)
1326: {
1327: axlListNode * node;
1328:
1329: node = axl_list_internal_get_nth (list, position);
1330: if (node != NULL)
1331: return node->data;
1332: return NULL;
1333: }
1334:
1335: /**
1336: * @brief Allows to perform a linear lookup on the list provided,
1337: * givin a function that is used to now the object to return due to
1338: * the lookup.
1339: *
1340: * The function can also be used as a foreach function. The following
1341: * example shows how to launch the function and perform a tasks on the
1342: * lookup function:
1343: * \code
1344: * // perform the lookup
1345: * return axl_list_lookup (list, __find_item, name);
1346: *
1347: * // the lookup function
1348: * axl_bool __find_item (axlPointer _element, axlPointer data)
1349: * {
1350: * SomeItem * element = _element;
1351: * char * name = data;
1352: *
1353: * // check the name
1354: * if (axl_cmp (element->name, name))
1355: * return axl_true;
1356: *
1357: * // it is not the element
1358: * return axl_false;
1359: * }
1360: * \endcode
1361: *
1362: * In the case you create a list to hold string values, you can use
1363: * \ref axl_list_find_string as lookup function predefined to perform
1364: * the search.
1365: *
1366: * @param list The list where the lookup will be performed.
1367: *
1368: * @param func The function to use to perform the lookup.
1369: *
1370: * @param data User defined data that will be passed to the func provided.
1371: *
1372: * @return A pointer to the object found or NULL if no item was found.
1373: */
1374: axlPointer axl_list_lookup (axlList * list, axlLookupFunc func, axlPointer data)
1375: {
1376: axlListNode * node;
1377: axl_return_val_if_fail (list, NULL);
1378: axl_return_val_if_fail (func, NULL);
1379:
1380: /* get the first pointer */
1381: node = list->first_node;
1382: do {
1383: /* if the next node to check is NULL, terminate the
1384: * lookup. */
1385: if (node == NULL)
1386: return NULL;
1387:
1388: /* check if the node found is the one looked up */
1389: if (func (node->data, data))
1390: return node->data;
1391:
1392: /* seems not, update to the next reference */
1393: node = node->next;
1394:
1395: }while (1);
1396:
1397: /* return no node found */
1398: return NULL;
1399: }
1400:
1401: /**
1402: * @brief Helper function that could be used at \ref axl_list_lookup if
1403: * the list created only contains strings.
1404: *
1405: * Use this function as a parameter for the lookup function at \ref
1406: * axl_list_lookup.
1407: *
1408: * @param element The element at the list, in this case, an string value.
1409: *
1410: * @param data The data provided at \ref axl_list_lookup, in this
1411: * case, the value we are looking.
1412: *
1413: * @return \ref axl_true if the string was found, \ref axl_false if not.
1414: */
1415: axl_bool axl_list_find_string (axlPointer element, axlPointer data)
1416: {
1417: /* if the string received is null, just return axl_false */
1418: if (data == NULL)
1419: return axl_false;
1420:
1421: /* return the comparison status */
1422: return axl_cmp ((char *) element, (char *) data);
1423: }
1424:
1425: /**
1426: * @brief Allows to get current list length.
1427: *
1428: * @param list The list to operate.
1429: *
1430: * @return The list length or -1 if fail (the list reference received
1431: * is null).
1432: */
1433: int axl_list_length (axlList * list)
1434: {
1435: axl_return_val_if_fail (list, -1);
1436: return list->length;
1437: }
1438:
1439: /**
1440: * @brief Allows to destroy the given list, and all user space
1441: * associated memory if a destroy handler was provided.
1442: *
1443: * @param list The list to destroy
1444: */
1445: void axl_list_free (axlList * list)
1446: {
1447: axlListNode * node;
1448: axlListNode * node2;
1449: int iterator;
1450:
1451: /* if a null reference is received do not oper */
1452: if (list == NULL)
1453: return;
1454:
1455: node = list->first_node;
1456: while (node != NULL) {
1457: if (list->destroy_data != NULL) {
1458: list->destroy_data (node->data);
1459: }
1460: node2 = node;
1461: node = node->next;
1462:
1463: axl_free (node2);
1464: }
1465:
1466: /* allocate a node for each available position */
1467: for (iterator = 0; iterator < list->available; iterator++) {
1468: axl_free (list->preallocated[iterator]);
1469: }
1470:
1471: /* free the array */
1472: axl_free (list->preallocated);
1473:
1474: /* free the list itself */
1475: axl_free (list);
1476:
1477: return;
1478: }
1479:
1480: /* @} */
1481:
1482: /**
1483: * \defgroup axl_list_cursor_module Axl List Cursor: Iterator support for the Axl List
1484: */
1485:
1486: /**
1487: * \addtogroup axl_list_cursor_module
1488: * @{
1489: */
1490:
1491: /**
1492: * @brief Allows to get a cursor to iterate the list in a linear and
1493: * efficient way.
1494: *
1495: * The \ref axlListCursor could be used to iterate an \ref axlList in
1496: * an efficient way because it stores current state (position). Then
1497: * using the following functions you can modify the state (current
1498: * position to get):
1499: *
1500: * - \ref axl_list_cursor_first
1501: * - \ref axl_list_cursor_last
1502: * - \ref axl_list_cursor_next
1503: * - \ref axl_list_cursor_previous
1504: *
1505: * Finally, a function is provided to get the data stored at a
1506: * particular position, pointed by the current status of the cursor:
1507: *
1508: * - \ref axl_list_cursor_get
1509: *
1510: * You are allowed to remove elements from the list (\ref axlList)
1511: * having a cursor created (\ref axlListCursor), using \ref
1512: * axl_list_cursor_unlink.
1513: *
1514: * Here is an example:
1515: * \code
1516: * axlPointer value;
1517: * axlListCursor * cursor;
1518: *
1519: * // create the cursor
1520: * cursor = axl_list_cursor_new (list);
1521: *
1522: * // while there are more elements
1523: * while (axl_list_cursor_has_item (cursor)) {
1524: *
1525: * // get the value
1526: * value = axl_list_cursor_get (cursor);
1527: *
1528: *
1529: * // get the next
1530: * axl_list_cursor_next (cursor);
1531: *
1532: * // update the iterator
1533: * iterator++;
1534: *
1535: * }
1536: *
1537: * // free the cursor
1538: * axl_list_cursor_free (cursor);
1539: * \endcode
1540: *
1541: * @param list The list that the new cursor (\ref axlListCursor) will
1542: * provide access.
1543: *
1544: * @return A newly created \ref axlListCursor used to iterate the
1545: * list. Once finished you must call to \ref axl_list_cursor_free.
1546: */
1547: axlListCursor * axl_list_cursor_new (axlList * list)
1548: {
1549: axlListCursor * cursor;
1550:
1551: axl_return_val_if_fail (list, NULL);
1552:
1553: /* create the cursor */
1554: cursor = axl_new (axlListCursor, 1);
1555:
1556: /* initial configuration */
1557: cursor->list = list;
1558: cursor->current = list->first_node;
1559:
1560: return cursor;
1561: }
1562:
1563: /**
1564: * @brief Allows to configure the cursor to point to the first item of
1565: * the list (if there are any).
1566: *
1567: * @param cursor The cursor that is required to be configured to point the first item.
1568: */
1569: void axl_list_cursor_first (axlListCursor * cursor)
1570: {
1571: axl_return_if_fail (cursor);
1572:
1573: if (cursor->list->length == 0) {
1574: cursor->current = NULL;
1575: return;
1576: } /* end if */
1577:
1578: /* set the first node */
1579: cursor->current = cursor->list->first_node;
1580:
1581: return;
1582: }
1583:
1584: /**
1585: * @brief Allows to configure the cursor to point to the last item of
1586: * the list (if there are any).
1587: *
1588: * @param cursor The cursor that is required to be configured to point
1589: * to the last item.
1590: */
1591: void axl_list_cursor_last (axlListCursor * cursor)
1592: {
1593: axl_return_if_fail (cursor);
1594:
1595: /* set the first node */
1596: cursor->current = cursor->list->last_node;
1597:
1598: return;
1599: }
1600:
1601: /**
1602: * @brief Allows to configure the cursor to point to the next item of
1603: * the list (if there are any).
1604: *
1605: * @param cursor The cursor that is required to be configured to point
1606: * to the next item.
1607: */
1608: void axl_list_cursor_next (axlListCursor * cursor)
1609: {
1610: axl_return_if_fail (cursor);
1611:
1612: /* set the next node */
1613: if (cursor->current != NULL)
1614: cursor->current = cursor->current->next;
1615:
1616: return;
1617: }
1618:
1619: /**
1620: * @brief Allows to configure the cursor to point to the previous item
1621: * of the list (if there are any).
1622: *
1623: * @param cursor The cursor that is required to be configured to point
1624: * to the previous item.
1625: */
1626: void axl_list_cursor_previous (axlListCursor * cursor)
1627: {
1628: axl_return_if_fail (cursor);
1629:
1630: /* set the next node */
1631: if (cursor->current != NULL)
1632: cursor->current = cursor->current->previous;
1633:
1634: return;
1635: }
1636:
1637: /**
1638: * @brief Allows to check if there are more elements next to the
1639: * current element pointed by the cursor.
1640: *
1641: * @param cursor The cursor that is required to return if there are
1642: * next items.
1643: *
1644: * @return \ref axl_true if more items are found, otherwise \ref axl_false is
1645: * returned.
1646: */
1647: axl_bool axl_list_cursor_has_next (axlListCursor * cursor)
1648: {
1649: axl_return_val_if_fail (cursor, axl_false);
1650:
1651: /* check for empty list */
1652: if (cursor->current == NULL)
1653: return axl_false;
1654:
1655: /* return if the next element isn't null */
1656: return (cursor->current->next != NULL);
1657: }
1658:
1659: /**
1660: * @brief Allows to check if there are more elements next to the
1661: * current element pointed by the cursor.
1662: *
1663: * @param cursor The cursor that is required to return if there are
1664: * next items.
1665: *
1666: * @return \ref axl_true if more items are found, otherwise \ref axl_false is
1667: * returned.
1668: */
1669: axl_bool axl_list_cursor_has_previous (axlListCursor * cursor)
1670: {
1671: axl_return_val_if_fail (cursor, axl_false);
1672:
1673: /* check for empty list */
1674: if (cursor->current == NULL)
1675: return axl_false;
1676:
1677: /* return if the next element isn't null */
1678: return (cursor->current->previous != NULL);
1679: }
1680:
1681: /**
1682: * @brief Allows to know if the current position has items.
1683: *
1684: * @param cursor The cursor that is requested to return if a call to
1685: * \ref axl_list_cursor_get will return data.
1686: *
1687: * @return \ref axl_true if the list that is iterated can return data at
1688: * the current position, otherwise \ref axl_false is returned.
1689: */
1690: axl_bool axl_list_cursor_has_item (axlListCursor * cursor)
1691: {
1692: axl_return_val_if_fail (cursor, axl_false);
1693:
1694: /* return if there are current */
1695: return (cursor->current != NULL);
1696: }
1697:
1698: /**
1699: * @brief Allows to remove current element pointed by the cursor,
1700: * maintainig internal state of the cursor.
1701: *
1702: * The function won't call to the destroy function asociated to the
1703: * list. If you want the item stored to be also destroyed call \ref
1704: * axl_list_cursor_remove.
1705: *
1706: * @param cursor The cursor pointing to the item inside the list that
1707: * must be removed.
1708: */
1709: void axl_list_cursor_unlink (axlListCursor * cursor)
1710: {
1711: axlListNode * node;
1712:
1713: axl_return_if_fail (cursor);
1714:
1715: /* if current cursor is pointing nowhere, just do nothing */
1716: if (cursor->current == NULL)
1717: return;
1718:
1719: /* remember node */
1720: node = cursor->current;
1721:
1722: /* configure the cursor to point to the next element (or the previous if the next element is null) */
1723: cursor->current = (node->next != NULL) ? node->next : node->previous;
1724:
1725: /* call to unlik */
1726: __axl_list_common_remove_selected_node (cursor->list, node, axl_false);
1727:
1728: return;
1729: }
1730:
1731: /**
1732: * @brief Allows to remove current element pointed by the cursor,
1733: * maintainig internal state of the cursor, calling to the destroy
1734: * function associated in the list.
1735: *
1736: * The function will call to the destroy function asociated to the
1737: * list. If you don't want the item stored to be also destroyed call \ref
1738: * axl_list_cursor_unlink.
1739: *
1740: * @param cursor The cursor pointing to the item inside the list that
1741: * must be removed.
1742: */
1743: void axl_list_cursor_remove (axlListCursor * cursor)
1744: {
1745: axlListNode * node;
1746:
1747: axl_return_if_fail (cursor);
1748:
1749: /* if current cursor is pointing nowhere, just do nothing */
1750: if (cursor->current == NULL)
1751: return;
1752:
1753: /* remember node */
1754: node = cursor->current;
1755:
1756: /* configure the cursor to point to the next element (or the previous if the next element is null) */
1757: cursor->current = (node->next != NULL) ? node->next : node->previous;
1758:
1759: /* call to remove */
1760: __axl_list_common_remove_selected_node (cursor->list, node, axl_true);
1761:
1762: return;
1763: }
1764:
1765: /**
1766: * @brief Allows to get current data at the current cursor state.
1767: *
1768: * @param cursor The cursor that will be used to return the data
1769: * located at the list, using cursor current state.
1770: */
1771: axlPointer axl_list_cursor_get (axlListCursor * cursor)
1772: {
1773: axl_return_val_if_fail (cursor, NULL);
1774:
1775: /* nothing to return if current is NULL */
1776: if (cursor->current == NULL)
1777: return NULL;
1778:
1779: /* return data */
1780: return cursor->current->data;
1781: }
1782:
1783: /**
1784: * @brief Allows to get the reference to the list that is associated
1785: * to the cursor received.
1786: *
1787: * @param cursor The cursor that is required to return the list associated.
1788: *
1789: * @return A reference to the list being iterated or NULL if fails.
1790: */
1791: axlList * axl_list_cursor_list (axlListCursor * cursor)
1792: {
1793: /* check incoming cursor */
1794: axl_return_val_if_fail (cursor, NULL);
1795:
1796: /* return the list */
1797: return cursor->list;
1798: }
1799:
1800: /**
1801: * @brief Deallocates memory used by the cursor.
1802: *
1803: * @param cursor The cursor to be deallocated.
1804: */
1805: void axl_list_cursor_free (axlListCursor * cursor)
1806: {
1807: axl_return_if_fail (cursor);
1808:
1809: /* free the cursor */
1810: axl_free (cursor);
1811:
1812: return;
1813: }
1814:
1815: /* @} */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>