summaryrefslogtreecommitdiff
path: root/Build/source/texk/xdvik/dl_list.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/xdvik/dl_list.c')
-rw-r--r--Build/source/texk/xdvik/dl_list.c164
1 files changed, 164 insertions, 0 deletions
diff --git a/Build/source/texk/xdvik/dl_list.c b/Build/source/texk/xdvik/dl_list.c
new file mode 100644
index 00000000000..76eeabc1297
--- /dev/null
+++ b/Build/source/texk/xdvik/dl_list.c
@@ -0,0 +1,164 @@
+#include "dl_list.h"
+
+size_t dl_list_len(struct dl_list *list)
+{
+ size_t len = 0;
+ struct dl_list *ptr;
+ for (ptr = list; ptr != NULL; ptr = ptr->next, len++) { ; }
+ return len;
+}
+
+/*
+ Insert item to the list and return the result.
+*/
+struct dl_list *
+dl_list_insert(struct dl_list *list, void *item)
+{
+ struct dl_list *new_elem = xmalloc(sizeof *new_elem);
+ new_elem->item = item;
+ new_elem->next = NULL;
+ new_elem->prev = NULL;
+
+ if (list == NULL) {
+ list = new_elem;
+ }
+ else {
+ /* append after current position */
+ struct dl_list *ptr = list;
+
+ new_elem->next = ptr->next;
+ new_elem->prev = ptr;
+
+ if (ptr->next != NULL)
+ ptr->next->prev = new_elem;
+
+ ptr->next = new_elem;
+ }
+ return new_elem;
+}
+
+/*
+ Return head of the list.
+*/
+struct dl_list *
+dl_list_head(struct dl_list *list)
+{
+ for (; list != NULL && list->prev != NULL; list = list->prev) { ; }
+ return list;
+}
+
+/*
+ Put a new item at the front of the list (current front is passed in first argument)
+ and return its position.
+*/
+struct dl_list *
+dl_list_push_front(struct dl_list *list, void *item)
+{
+ struct dl_list *new_elem = xmalloc(sizeof *new_elem);
+ new_elem->item = item;
+ new_elem->next = NULL;
+ new_elem->prev = NULL;
+
+ if (list != NULL) { /* prepend to current position */
+ new_elem->next = list;
+ list->prev = new_elem;
+ }
+ return new_elem;
+}
+
+/*
+ Truncate list so that current pointer is the last element.
+*/
+struct dl_list *
+dl_list_truncate(struct dl_list *list)
+{
+ struct dl_list *ptr = list->next;
+ struct dl_list *save;
+
+ list->next = NULL;
+
+ while (ptr != NULL) {
+ save = ptr->next;
+ free(ptr);
+ ptr = save;
+ }
+ return list;
+}
+
+/*
+ Truncate list at the head (i.e. remove the first element from it - head must be passed to this list),
+ and return the result.
+*/
+struct dl_list *
+dl_list_truncate_head(struct dl_list *list)
+{
+ struct dl_list *ptr = list->next;
+ if (list->next != NULL)
+ list->next->prev = NULL;
+ free(list);
+ return ptr;
+}
+
+/*
+ If the item pointed to by *list isn't the head of the list, remove it,
+ set *list to the previous item, and return True. Else return False.
+*/
+Boolean
+dl_list_remove_item(struct dl_list **list)
+{
+ struct dl_list *ptr = *list; /* item to remove */
+ if (ptr->prev == NULL)
+ return False;
+ ptr->prev->next = ptr->next;
+ if (ptr->next != NULL)
+ ptr->next->prev = ptr->prev;
+ /* update list */
+ *list = (*list)->prev;
+ /* remove item */
+ free(ptr);
+
+ return True;
+}
+
+void
+dl_list_apply(struct dl_list *list, void (*func)(const void *item))
+{
+ struct dl_list *ptr;
+ for (ptr = list; ptr != NULL; ptr = ptr->next) {
+ func(ptr->item);
+ }
+}
+
+/*
+ Remove all items matching compare_func() from list. Must be called
+ with a pointer to the head of the list, which is also returned.
+ Returns the number of removed items in `count'.
+*/
+struct dl_list *
+dl_list_remove(struct dl_list *list, const void *item,
+ int *count,
+ void **removed_item,
+ Boolean (*compare_func)(const void *item1, const void *item2))
+{
+ struct dl_list *ptr = list;
+ while (ptr != NULL) {
+ struct dl_list *next = ptr->next;
+ if (compare_func(ptr->item, item)) { /* match */
+ *removed_item = ptr->item;
+ (*count)++;
+ if (ptr->prev != NULL) {
+ ptr->prev->next = ptr->next;
+ }
+ else { /* removed first element */
+ list = list->next;
+ }
+
+ if (ptr->next != NULL)
+ ptr->next->prev = ptr->prev;
+ free(ptr);
+ ptr = NULL;
+ }
+ ptr = next;
+ }
+ return list;
+}