summaryrefslogtreecommitdiff
path: root/src/sp_list.c
blob: 8879d894878f9645893125bbc5bacce9102a505c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include "sp_list.h"
#include <stdio.h>
#include <stdlib.h>
#include "php_snuffleupagus.h"

void sp_list_free(sp_list_node *node) {
  while (node) {
    sp_list_node *tmp = node->next;
    pefree(node, 1);
    node = tmp;
  }
}

// Thanks to https://en.wikipedia.org/wiki/Insertion_sort :>
sp_list_node *sp_list_sort(sp_list_node *pList,
                           int (*cmp_func)(sp_list_node *, sp_list_node *)) {
  sp_list_node *head = NULL;

  if (pList == NULL || pList->next == NULL) {
    return pList;
  }
  while (pList != NULL) {
    sp_list_node *current = pList;
    pList = pList->next;
    if (head == NULL || 0 > cmp_func(current, head)) {
      current->next = head;
      head = current;
    } else {
      sp_list_node *p = head;
      while (p != NULL) {
        if (p->next == NULL || 0 > cmp_func(current, p->next)) {
          current->next = p->next;
          p->next = current;
          break;
        }
        p = p->next;
      }
    }
  }
  return head;
}

sp_list_node *sp_list_insert(sp_list_node *list, void *data) {
  sp_list_node *new = pecalloc(sizeof(*new), 1, 1);
  sp_list_node *origin = list;
  new->data = data;
  new->next = NULL;

  if (list == NULL) {
    origin = new;
  } else {
    while (list->next) {
      list = list->next;
    }
    list->next = new;
  }
  return origin;
}

sp_list_node *sp_list_prepend(sp_list_node *list, void *data) {
  sp_list_node *new = pecalloc(sizeof(*new), 1, 1);
  new->next = list;
  new->data = data;
  return new;
}