SatCat5
list.h
Go to the documentation of this file.
1 // Copyright 2021-2025 The Aerospace Corporation.
3 // This file is a part of SatCat5, licensed under CERN-OHL-W v2 or later.
36 
37 #pragma once
38 
39 namespace satcat5 {
40  namespace util {
52  class ListCore {
53  public:
55  template <class T> static inline
56  void add(T*& list, T* item) {
58  }
59 
62  template <class T> static inline
63  void add_list(T*& list1, T*& list2) {
64  while (T* item = satcat5::util::ListCore::pop_front(list2)) {
65  satcat5::util::ListCore::add(list1, item);
66  }
67  }
68 
71  template <class T> static inline
72  void add_safe(T*& list, T* item) {
73  if (!satcat5::util::ListCore::contains(list, item))
74  satcat5::util::ListCore::add(list, item);
75  }
76 
78  template <class T> static inline
79  bool contains(const T* list, const T* item) {
80  const T* ptr = list;
81  while (ptr) {
82  if (ptr == item) return true;
83  ptr = ptr->m_next;
84  }
85  return false;
86  }
87 
91  template <class T> static inline
92  T** find_ptr(T** list, const T* item) {
93  T** ptr = list;
94  while (1) {
95  if (*ptr == item) return ptr; // Found a match?
96  if (*ptr == 0) return 0; // End of list?
97  ptr = &((*ptr)->m_next);
98  }
99  }
100 
103  template <class T> static inline
104  T* get_index(T* list, unsigned idx) {
105  T* ptr = list;
106  while (ptr && idx--) {
107  ptr = ptr->m_next;
108  }
109  return ptr;
110  }
111 
114  template <class T> static inline
115  bool has_loop(const T* list) {
116  if (!list) return false; // Empty list has no loops.
117  const T* slow = list;
118  const T* fast = list->m_next;
119  while (fast && fast->m_next) {
120  if (slow == fast || slow == fast->m_next) return true;
121  slow = slow->m_next;
122  fast = fast->m_next->m_next;
123  }
124  return false; // Reached end with no loops.
125  }
126 
128  template <class T> static inline
129  void insert_after(T* where, T* item) {
130  if (where && item) {
131  item->m_next = where->m_next;
132  where->m_next = item;
133  }
134  }
135 
137  template <class T> static inline
138  unsigned len(const T* list) {
139  unsigned count = 0;
140  const T* ptr = list;
141  while (ptr) {
142  ++count;
143  ptr = ptr->m_next;
144  }
145  return count;
146  }
147 
150  template <class T> static inline
151  T* next(const T* item) {
152  return item->m_next;
153  }
154 
156  template <class T> static inline
157  T* pop_front(T*& list) {
158  if (!list) return 0;
159  T* item = list;
160  list = item->m_next;
161  item->m_next = 0;
162  return item;
163  }
164 
166  template <class T> static inline
167  void push_front(T*& list, T* item) {
168  item->m_next = list;
169  list = item;
170  }
171 
173  template <class T> static inline
174  void push_back(T*& list, T* item) {
175  T** ptr = satcat5::util::ListCore::find_ptr<T>(&list, 0);
176  *ptr = item;
177  item->m_next = 0;
178  }
179 
181  template <class T> static inline
182  void remove(T*& list, T* item) {
183  T** ptr = satcat5::util::ListCore::find_ptr<T>(&list, item);
184  if (ptr) *ptr = item->m_next;
185  item->m_next = 0;
186  }
187 
189  template <class T> static inline
190  void reset(T*& list, T* item) {
191  list = item;
192  if (item) item->m_next = 0;
193  }
194 
199  template <class T> static inline
200  bool pre_test_reset(T*& list, T* item) {
201  bool adj = (list != item) || (item && list->m_next);
202  if (adj) reset(list, item);
203  return adj;
204  }
205  };
206 
210  template <class T> class List final {
211  public:
212  constexpr List()
213  : m_head(0) {}
214  constexpr explicit List(T* item)
215  : m_head(item) {}
216  ~List() {}
217 
218  T* head() const {return m_head;}
219 
221  inline void add(T* item)
223 
226  inline void add_list(satcat5::util::List<T>& other)
228 
231  inline void add_safe(T* item)
233 
235  inline bool contains(const T* item) const
237 
240  inline T* get_index(unsigned idx)
242 
245  inline bool has_loop() const
247 
249  inline void insert_after(T* where, T* item)
251 
253  inline bool is_empty() const
254  {return m_head == 0;}
255 
257  inline unsigned len() const
259 
261  inline T* next(const T* item) const
262  {return satcat5::util::ListCore::next(item);}
263 
265  inline T* pop_front()
267 
269  inline void push_front(T* item)
271 
273  inline void push_back(T* item)
275 
277  inline void remove(T* item)
279 
281  inline void reset(T* item = 0)
282  {return satcat5::util::ListCore::reset(m_head, item);}
283 
284  protected:
285  T* m_head;
286  };
287  }
288 };
Helper functions for manipulating singly-linked lists.
Definition: list.h:52
static bool contains(const T *list, const T *item)
Scan the list, looking for the item in question.
Definition: list.h:79
static void push_back(T *&list, T *item)
Add a new item at the tail of the list.
Definition: list.h:174
static void reset(T *&list, T *item)
Discard list contents and reset to empty or a single item.
Definition: list.h:190
static T * get_index(T *list, unsigned idx)
Fetch the Nth item from the linked list.
Definition: list.h:104
static void add_list(T *&list1, T *&list2)
Add each item from "list2" onto "list1", destroying "list2".
Definition: list.h:63
static void remove(T *&list, T *item)
Remove the designated item from the list.
Definition: list.h:182
static T ** find_ptr(T **list, const T *item)
Find the link pointing to the designated item.
Definition: list.h:92
static T * pop_front(T *&list)
Remove the item at the head of the list.
Definition: list.h:157
static void add(T *&list, T *item)
Add new item to front or back, whichever is simpler.
Definition: list.h:56
static bool has_loop(const T *list)
Check if the linked list loops back on itself, using the two-pointer "tortoise and hare" algorithm.
Definition: list.h:115
static bool pre_test_reset(T *&list, T *item)
Check if a list contains exactly the specified item.
Definition: list.h:200
static void add_safe(T *&list, T *item)
Check if list already contains item before adding.
Definition: list.h:72
static void insert_after(T *where, T *item)
Insert a new item just after the designated position.
Definition: list.h:129
static T * next(const T *item)
Fetch pointer to the next item.
Definition: list.h:151
static unsigned len(const T *list)
Traverse the linked list to count its length.
Definition: list.h:138
static void push_front(T *&list, T *item)
Add a new item at the head of the list.
Definition: list.h:167
Templated linked-list class.
Definition: list.h:210
unsigned len() const
Traverse the linked list to count its length.
Definition: list.h:257
void add_list(satcat5::util::List< T > &other)
Add each item from "list2" onto "list1", destroying "list2".
Definition: list.h:226
constexpr List()
Construct an empty list.
Definition: list.h:212
T * next(const T *item) const
Fetch pointer to the next item.
Definition: list.h:261
~List()
Destructor requires no action.
Definition: list.h:216
void push_back(T *item)
Add a new item at the tail of the list.
Definition: list.h:273
constexpr List(T *item)
Construct list with one item.
Definition: list.h:214
T * get_index(unsigned idx)
Fetch the Nth item from the linked list.
Definition: list.h:240
void add_safe(T *item)
Check if list already contains item before adding.
Definition: list.h:231
void reset(T *item=0)
Discard list contents and reset to empty or a single item.
Definition: list.h:281
bool contains(const T *item) const
Scan the list, looking for the item in question.
Definition: list.h:235
bool has_loop() const
Check if the linked list loops back on itself, using the two-pointer "tortoise and hare" algorithm.
Definition: list.h:245
void insert_after(T *where, T *item)
Insert a new item just after the designated position.
Definition: list.h:249
void add(T *item)
Add new item to front or back, whichever is simpler.
Definition: list.h:221
bool is_empty() const
Is this list empty?
Definition: list.h:253
T * pop_front()
Remove the item at the head of the list.
Definition: list.h:265
void remove(T *item)
Remove the designated item from the list.
Definition: list.h:277
T * m_head
Pointer to first item, zero if empty.
Definition: list.h:285
void push_front(T *item)
Add a new item at the head of the list.
Definition: list.h:269