X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Futil%2Fcontainer_slist.c;h=7b85dc87760780239eeab9720e1e030f64cc97fb;hb=e62ce5b19244ae28472bf0e02b19c3f905f1ee0a;hp=c279bb2eaf8af799573c320f8dce5bebf5eaf8e0;hpb=d5f3c16326273625b37cd0f2d5b4716ac650f51d;p=oweals%2Fgnunet.git diff --git a/src/util/container_slist.c b/src/util/container_slist.c index c279bb2ea..7b85dc877 100644 --- a/src/util/container_slist.c +++ b/src/util/container_slist.c @@ -27,24 +27,57 @@ #include "platform.h" #include "gnunet_container_lib.h" +#define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) + +/** + * Element in our linked list. + */ struct GNUNET_CONTAINER_SList_Elem { + /** + * This is a linked list. + */ + struct GNUNET_CONTAINER_SList_Elem *next; + + /** + * Application data stored at this element. + */ void *elem; + + /** + * Number of bytes stored in elem. + */ size_t len; - int disp; - struct GNUNET_CONTAINER_SList_Elem *next; + + /** + * Disposition of the element. + */ + enum GNUNET_CONTAINER_SListDisposition disp; }; + +/** + * Handle to a singly linked list + */ struct GNUNET_CONTAINER_SList { - struct GNUNET_CONTAINER_SList_Elem head; + /** + * Head of the linked list. + */ + struct GNUNET_CONTAINER_SList_Elem *head; + + /** + * Tail of the linked list. + */ + struct GNUNET_CONTAINER_SList_Elem *tail; + + /** + * Number of elements in the list. + */ + unsigned int length; }; -struct GNUNET_CONTAINER_SList_Iterator -{ - struct GNUNET_CONTAINER_SList_Elem *last; - struct GNUNET_CONTAINER_SList_Elem *elem; -}; + /** * Create a new element that is to be inserted into the list @@ -55,24 +88,28 @@ struct GNUNET_CONTAINER_SList_Iterator * @return a new element */ static struct GNUNET_CONTAINER_SList_Elem * -create_elem (int disp, const void *buf, size_t len) +create_elem (enum GNUNET_CONTAINER_SListDisposition disp, const void *buf, + size_t len) { struct GNUNET_CONTAINER_SList_Elem *e; - e = GNUNET_malloc (sizeof (struct GNUNET_CONTAINER_SList_Elem)); - e->disp = disp; - if (disp == GNUNET_MEM_DISP_TRANSIENT) - { - e->elem = GNUNET_malloc (len); - memcpy (e->elem, buf, len); - } + if (disp == GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT) + { + e = GNUNET_malloc (sizeof (struct GNUNET_CONTAINER_SList_Elem) + len); + memcpy (&e[1], buf, len); + e->elem = (void *) &e[1]; + } else + { + e = GNUNET_malloc (sizeof (struct GNUNET_CONTAINER_SList_Elem)); e->elem = (void *) buf; + } + e->disp = disp; e->len = len; - return e; } + /** * Add a new element to the list * @param l list @@ -81,16 +118,71 @@ create_elem (int disp, const void *buf, size_t len) * @param len length of the buffer */ void -GNUNET_CONTAINER_slist_add (struct GNUNET_CONTAINER_SList *l, int disp, +GNUNET_CONTAINER_slist_add (struct GNUNET_CONTAINER_SList *l, + enum GNUNET_CONTAINER_SListDisposition disp, const void *buf, size_t len) { struct GNUNET_CONTAINER_SList_Elem *e; e = create_elem (disp, buf, len); - e->next = l->head.next; - l->head.next = e; + e->next = l->head; + l->head = e; + if (l->tail == NULL) + l->tail = e; + l->length++; +} + +/** + * Add a new element to the end of the list + * @param l list + * @param disp memory disposition + * @param buf payload buffer + * @param len length of the buffer + */ +void +GNUNET_CONTAINER_slist_add_end (struct GNUNET_CONTAINER_SList *l, + enum GNUNET_CONTAINER_SListDisposition disp, + const void *buf, size_t len) +{ + struct GNUNET_CONTAINER_SList_Elem *e; + + e = create_elem (disp, buf, len); + if (l->tail != NULL) + l->tail->next = e; + if (l->head == NULL) + l->head = e; + l->tail = e; + l->length++; +} + + +/** + * Append a singly linked list to another + * @param dst list to append to + * @param src source + */ +void +GNUNET_CONTAINER_slist_append (struct GNUNET_CONTAINER_SList *dst, + struct GNUNET_CONTAINER_SList *src) +{ + struct GNUNET_CONTAINER_SList_Iterator i; + + for (i = GNUNET_CONTAINER_slist_begin (src); + GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES; + GNUNET_CONTAINER_slist_next (&i)) + + { + GNUNET_CONTAINER_slist_add (dst, + (i.elem->disp == + GNUNET_CONTAINER_SLIST_DISPOSITION_STATIC) ? + GNUNET_CONTAINER_SLIST_DISPOSITION_STATIC : + GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, + i.elem->elem, i.elem->len); + } + GNUNET_CONTAINER_slist_iter_destroy (&i); } + /** * Create a new singly linked list * @return the new list @@ -98,17 +190,10 @@ GNUNET_CONTAINER_slist_add (struct GNUNET_CONTAINER_SList *l, int disp, struct GNUNET_CONTAINER_SList * GNUNET_CONTAINER_slist_create () { - struct GNUNET_CONTAINER_SList *ret; - - ret = GNUNET_malloc (sizeof (struct GNUNET_CONTAINER_SList)); - if (NULL == ret) - return NULL; - - memset (&ret->head, 0, sizeof (struct GNUNET_CONTAINER_SList)); - - return ret; + return GNUNET_malloc (sizeof (struct GNUNET_CONTAINER_SList)); } + /** * Destroy a singly linked list * @param l the list to be destroyed @@ -120,22 +205,24 @@ GNUNET_CONTAINER_slist_destroy (struct GNUNET_CONTAINER_SList *l) GNUNET_free (l); } + /** * Return the beginning of a list * @param l list * @return iterator pointing to the beginning */ -const struct GNUNET_CONTAINER_SList_Iterator * -GNUNET_CONTAINER_slist_begin (const struct GNUNET_CONTAINER_SList *l) +struct GNUNET_CONTAINER_SList_Iterator +GNUNET_CONTAINER_slist_begin (struct GNUNET_CONTAINER_SList *l) { - struct GNUNET_CONTAINER_SList_Iterator *ret; + struct GNUNET_CONTAINER_SList_Iterator ret; - ret = GNUNET_malloc (sizeof (struct GNUNET_CONTAINER_SList_Iterator)); - ret->elem = l->head.next; - ret->last = (struct GNUNET_CONTAINER_SList_Elem *) &l->head; + memset (&ret, 0, sizeof (ret)); + ret.elem = l->head; + ret.list = l; return ret; } + /** * Clear a list * @param l list @@ -143,25 +230,30 @@ GNUNET_CONTAINER_slist_begin (const struct GNUNET_CONTAINER_SList *l) void GNUNET_CONTAINER_slist_clear (struct GNUNET_CONTAINER_SList *l) { - struct GNUNET_CONTAINER_SList_Elem *e, *n; + struct GNUNET_CONTAINER_SList_Elem *e; + struct GNUNET_CONTAINER_SList_Elem *n; - e = l->head.next; + e = l->head; while (e != NULL) - { - if (e->disp != GNUNET_MEM_DISP_STATIC) - GNUNET_free (e->elem); - n = e->next; - GNUNET_free (e); - e = n; - } - l->head.next = NULL; + { + n = e->next; + if (e->disp == GNUNET_CONTAINER_SLIST_DISPOSITION_DYNAMIC) + GNUNET_free (e->elem); + GNUNET_free (e); + e = n; + } + l->head = NULL; + l->tail = NULL; + l->length = 0; } + /** * Check if a list contains a certain element + * * @param l list * @param buf payload buffer to find - * @param lenght of the payload + * @param len length of the payload (number of bytes in buf) */ int GNUNET_CONTAINER_slist_contains (const struct GNUNET_CONTAINER_SList *l, @@ -169,13 +261,13 @@ GNUNET_CONTAINER_slist_contains (const struct GNUNET_CONTAINER_SList *l, { struct GNUNET_CONTAINER_SList_Elem *e; - for (e = l->head.next; e != NULL; e = e->next) - if (e->len == len && memcmp (buf, e->elem, len) == 0) + for (e = l->head; e != NULL; e = e->next) + if ((e->len == len) && (memcmp (buf, e->elem, len) == 0)) return GNUNET_YES; - return GNUNET_NO; } + /** * Count the elements of a list * @param l list @@ -184,17 +276,13 @@ GNUNET_CONTAINER_slist_contains (const struct GNUNET_CONTAINER_SList *l, int GNUNET_CONTAINER_slist_count (const struct GNUNET_CONTAINER_SList *l) { - int n; - struct GNUNET_CONTAINER_SList_Elem *e; - - for (n = 0, e = l->head.next; e != NULL; e = e->next) - n++; - - return n; + return l->length; } + /** * Remove an element from the list + * * @param i iterator that points to the element to be removed */ void @@ -203,13 +291,20 @@ GNUNET_CONTAINER_slist_erase (struct GNUNET_CONTAINER_SList_Iterator *i) struct GNUNET_CONTAINER_SList_Elem *next; next = i->elem->next; - i->last->next = next; - if (i->elem->disp != GNUNET_MEM_DISP_STATIC) + if (i->last != NULL) + i->last->next = next; + else + i->list->head = next; + if (next == NULL) + i->list->tail = i->last; + if (i->elem->disp == GNUNET_CONTAINER_SLIST_DISPOSITION_DYNAMIC) GNUNET_free (i->elem->elem); GNUNET_free (i->elem); + i->list->length--; i->elem = next; } + /** * Insert an element into a list at a specific position * @param before where to insert the new element @@ -219,15 +314,23 @@ GNUNET_CONTAINER_slist_erase (struct GNUNET_CONTAINER_SList_Iterator *i) */ void GNUNET_CONTAINER_slist_insert (struct GNUNET_CONTAINER_SList_Iterator *before, - int disp, const void *buf, size_t len) + enum GNUNET_CONTAINER_SListDisposition disp, + const void *buf, size_t len) { struct GNUNET_CONTAINER_SList_Elem *e; e = create_elem (disp, buf, len); e->next = before->elem; - before->last->next = e; + if (before->last != NULL) + before->last->next = e; + else + before->list->head = e; + if (e->next == NULL) + before->list->tail = e; + before->list->length++; } + /** * Advance an iterator to the next element * @param i iterator @@ -239,11 +342,13 @@ GNUNET_CONTAINER_slist_next (struct GNUNET_CONTAINER_SList_Iterator *i) i->last = i->elem; i->elem = i->elem->next; - return i->elem != NULL; + return (i->elem != NULL) ? GNUNET_YES : GNUNET_NO; } + /** * Check if an iterator points beyond the end of a list + * * @param i iterator * @return GNUNET_YES if the end has been reached, GNUNET_NO if the iterator * points to a valid element @@ -251,9 +356,10 @@ GNUNET_CONTAINER_slist_next (struct GNUNET_CONTAINER_SList_Iterator *i) int GNUNET_CONTAINER_slist_end (struct GNUNET_CONTAINER_SList_Iterator *i) { - return i->elem == NULL; + return (i->elem == NULL) ? GNUNET_YES : GNUNET_NO; } + /** * Retrieve the element at a specific position in a list * @param i iterator @@ -268,3 +374,14 @@ GNUNET_CONTAINER_slist_get (const struct GNUNET_CONTAINER_SList_Iterator *i, *len = i->elem->len; return i->elem->elem; } + +/** + * Release an iterator + * @param i iterator + */ +void +GNUNET_CONTAINER_slist_iter_destroy (struct GNUNET_CONTAINER_SList_Iterator *i) +{ +} + +/* end of container_slist.c */