Babel
Epitech's C++ VoIP project
FreeList.hpp
Go to the documentation of this file.
1 //
2 // Created by cbihan on 20/08/2021.
3 //
4 
5 #pragma once
6 
7 #include <functional>
8 
9 namespace Babel
10 {
11 
15  template<class T>
16  class FreeList
17  {
18  public:
20  static constexpr int EndOfList = -1;
21 
23  FreeList();
24 
26  int insert(T element);
27 
29  void remove(int n);
30 
32  void clear();
33 
35  [[nodiscard]] size_t size() const;
36 
39  void reset();
40 
42  [[nodiscard]] std::vector<T> toVector() const;
43 
45  [[nodiscard]] int range() const;
46 
48  [[nodiscard]] int findIndex(T element) const;
49 
51  T &operator[](int n);
52 
54  const T &operator[](int n) const;
55 
59  void forEach(std::function<bool(T &, int)> pred);
60 
64  void forEach(std::function<bool(T &)> pred);
65 
69  void forEach(std::function<bool(const T &, int)> pred) const;
70 
74  void forEach(std::function<bool(const T &)> pred) const;
75 
76  private:
78  std::vector<std::pair<T, int>> _data{};
81  };
82 
83  template<class T>
85  : _firstFree(EndOfList)
86  {
87  }
88 
89  template<class T>
90  int FreeList<T>::insert(T element)
91  {
92  if (this->_firstFree != EndOfList) {
93  const int index = this->_firstFree;
94  this->_firstFree = this->_data[this->_firstFree].second;
95  this->_data[index].first = std::move(element);
96  return index;
97  } else {
98  this->_data.push_back({element, EndOfList});
99  return static_cast<int>(this->_data.size() - 1);
100  }
101  }
102 
103  template<class T>
105  {
106  // the this->_firstFree index should be the lowest available and so on to use the lowest possible index at each insertion
107  // it helps for the forEach function and if we want to shrink the vector
108  if (n < this->_firstFree || this->_firstFree == EndOfList) {
109  this->_data[n].second = this->_firstFree;
110  this->_firstFree = n;
111  } else {
112  int freeIndex = this->_firstFree;
113  int prevFreeIndex = freeIndex;
114  while (freeIndex < n && freeIndex != EndOfList) {
115  prevFreeIndex = freeIndex;
116  freeIndex = this->_data[freeIndex].second;
117  }
118  this->_data[n].second = freeIndex;
119  this->_data[prevFreeIndex].second = n;
120  }
121  }
122 
123  template<class T>
125  {
126  this->_data.clear();
127  this->_firstFree = EndOfList;
128  }
129 
130  template<class T>
131  int FreeList<T>::range() const
132  {
133  return static_cast<int>(this->_data.size());
134  }
135 
136  template<class T>
138  {
139  return this->_data[n].first;
140  }
141 
142  template<class T>
143  const T &FreeList<T>::operator[](int n) const
144  {
145  return this->_data[n].first;
146  }
147 
148  template<class T>
149  int FreeList<T>::findIndex(T element) const
150  {
151  int indexFound = -1;
152  this->forEach([&element, &indexFound](const auto &elementList, int elementIndex) {
153  if (element == elementList) {
154  indexFound = elementIndex;
155  return false;
156  }
157  return true;
158  });
159  return indexFound;
160  }
161 
162  template<class T>
163  void FreeList<T>::forEach(std::function<bool(T &, int)> pred)
164  {
165  int next_empty_index = this->_firstFree;
166 
167  for (int i = 0; i < static_cast<int>(this->_data.size()); i++) {
168  if (i == next_empty_index) {
169  next_empty_index = this->_data[i].second;
170  continue;
171  }
172  if (!pred(this->_data[i].first, i)) {
173  break;
174  }
175  }
176  }
177 
178  template<class T>
179  void FreeList<T>::forEach(std::function<bool(T &)> pred)
180  {
181  this->forEach([&pred](T &element, int) {
182  return pred(element);
183  });
184  }
185 
186  template<class T>
187  void FreeList<T>::forEach(std::function<bool(const T &, int)> pred) const
188  {
189  int next_empty_index = this->_firstFree;
190 
191  for (int i = 0; i < static_cast<int>(this->_data.size()); i++) {
192  if (i == next_empty_index) {
193  next_empty_index = this->_data[i].second;
194  continue;
195  }
196  if (!pred(this->_data[i].first, i)) {
197  break;
198  }
199  }
200  }
201 
202  template<class T>
203  void FreeList<T>::forEach(std::function<bool(const T &)> pred) const
204  {
205  this->forEach([&pred](const T &element, int) {
206  return pred(element);
207  });
208  }
209 
210  template<class T>
211  std::vector<T> FreeList<T>::toVector() const
212  {
213  std::vector<T> v;
214  this->forEach([&v](const T &element) {
215  v.push_back(element);
216  return true;
217  });
218  return v;
219  }
220 
221  template<class T>
223  {
224  if (this->_data.empty()) {
225  return;
226  }
227  int size = this->_data.size();
228  this->_firstFree = 0;
229  for (int i = 0; i < size; i++) {
230  this->_data[i].second = i == size - 1 ? EndOfList : i + 1;
231  }
232  }
233 
234  template<class T>
235  size_t FreeList<T>::size() const
236  {
237  size_t size = 0;
238  this->forEach([&size](const T &, int) {
239  size++;
240  return true;
241  });
242  return size;
243  }
244 }
Babel::FreeList::size
size_t size() const
The number of active elements in the list.
Definition: FreeList.hpp:235
Babel::FreeList::toVector
std::vector< T > toVector() const
Create a vector with all the values of the list.
Definition: FreeList.hpp:211
Babel::FreeList::clear
void clear()
Removes all elements from the free list and free the memory.
Definition: FreeList.hpp:124
Babel::FreeList::findIndex
int findIndex(T element) const
Gives the index of an element, if not found returns -1.
Definition: FreeList.hpp:149
Babel::FreeList
Provides an indexed free list with constant-time removals from anywhere in the list without invalidat...
Definition: FreeList.hpp:16
Babel::FreeList::_firstFree
int _firstFree
first free index
Definition: FreeList.hpp:80
Babel::FreeList::operator[]
T & operator[](int n)
Returns the nth element.
Definition: FreeList.hpp:137
Babel::FreeList::_data
std::vector< std::pair< T, int > > _data
The internal vector.
Definition: FreeList.hpp:78
Babel
Definition: IAudioManager.hpp:13
Babel::FreeList::reset
void reset()
Removes all elements from the list but doesn't free the memory.
Definition: FreeList.hpp:222
Babel::FreeList::EndOfList
static constexpr int EndOfList
When this value is encountered in traversing a singly list it means it's the end of the list.
Definition: FreeList.hpp:20
Babel::FreeList::remove
void remove(int n)
Removes the nth element from the free list.
Definition: FreeList.hpp:104
Babel::FreeList::FreeList
FreeList()
Creates a new free list.
Definition: FreeList.hpp:84
Babel::FreeList::range
int range() const
Returns the range of valid indices.
Definition: FreeList.hpp:131
Babel::FreeList::insert
int insert(T element)
Inserts an element to the free list and returns an index to it.
Definition: FreeList.hpp:90
Babel::FreeList::forEach
void forEach(std::function< bool(T &, int)> pred)
call pred with all the active elements
Definition: FreeList.hpp:163