summaryrefslogtreecommitdiff
path: root/src/user/include/cxx/structs/dllist.h
blob: 91b0369145ab8da4a098da0601a09ed56096a59d (plain) (blame)
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
66
67
68
69
70
71
72
73
74
75
#ifndef STRUCTS_DLLIST_H
#define STRUCTS_DLLIST_H

#include <stdint.h>

template<class data>
class dllist {
public:
  class node {
  public:
    node *next;
    node *prev;
    data d;
    node(node *next, node *prev, data d)
      : next(next), prev(prev), d(d) {}
  };
  node *first;
  node *last;

  dllist() : first(0), last(0) {}

  void add_front(data d) {
    node *const n = new node(first, 0, d);
    if (first)
      first->prev = n;
    first = n;
    if (!last)
      last = n;
  }

  void add_back(data d) {
    node *const n = new node(0, last, d);
    if (last)
      last->next = n;
    last = n;
    if (!first)
      first = n;
  }

  //return previous, or zero if this is the first
  node *remove_in_place(node *n) {
    if (n == first)
      first = n->next;
    if (n == last)
      last = n->prev;
    if (n->next)
      n->next->prev = n->prev;
    if (n->prev)
      n->prev->next = n->next;
    delete n;
    return n->prev;
  }

  bool try_remove_by_ref(data d) {
    for (node *n = first; n; n = n->next)
      if (&n->d == &d) {
        remove_in_place(n);
        return true;
      }
    return false;
  }

  //returns -1 if it isn't found
  uint32_t index_of(data d) {
    uint32_t i = 0;
    for (const node *n = first; n; n = n->next)
      if (d == n->d)
        return i;
      else
        ++i;
    return -1;
  }
};

#endif