Ocular Engine
PriorityList.hpp
1 
17 #pragma once
18 #ifndef __H__OCULAR_UTILS_PRIORITY_LIST__H__
19 #define __H__OCULAR_UTILS_PRIORITY_LIST__H__
20 
21 #include "Exceptions/Exception.hpp"
22 #include "Priority.hpp"
23 
24 #include <utility>
25 #include <cstdint>
26 
27 //------------------------------------------------------------------------------------------
28 
33 namespace Ocular
34 {
39  namespace Utils
40  {
44  template<typename T, std::size_t MAX_ELEMENTS>
46  {
47  public:
48 
52  PriorityList()
53  {
54  m_TrueSize = 0;
55  }
56 
60  ~PriorityList()
61  {
62 
63  }
64 
73  bool push(T const element, uint32_t priority)
74  {
75  bool retVal = false;
76 
77  if(m_TrueSize < MAX_ELEMENTS)
78  {
79  retVal = add(element, priority);
80  }
81 
82  return retVal;
83  }
84 
90  bool pop()
91  {
92  bool retVal = false;
93 
94  if(m_TrueSize > 0)
95  {
96  removeIndex(0);
97  retVal = true;
98  }
99 
100  return retVal;
101  }
102 
112  bool add(T const element, uint32_t priority)
113  {
114  bool result = false;
115 
116  if(m_TrueSize < MAX_ELEMENTS)
117  {
118  insertElement(element, static_cast<uint32_t>(priority));
119  m_TrueSize++;
120  result = true;
121  }
122 
123  return result;
124  }
125 
129  void removeElement(T const element)
130  {
131  if(m_TrueSize > 0)
132  {
133  std::size_t index = locateIndex(element);
134 
135  if(index != MAX_ELEMENTS)
136  {
137  deleteElement(index);
138  m_TrueSize--;
139  }
140  }
141  }
142 
147  void removeIndex(uint32_t index)
148  {
149  if(index >= m_TrueSize)
150  {
151  THROW_EXCEPTION("Index Out of Bounds");
152  }
153 
154  deleteElement(index);
155  m_TrueSize--;
156  }
157 
162  T const get(std::size_t index) const
163  {
164  if(index >= m_TrueSize)
165  {
166  THROW_EXCEPTION("Index Out of Bounds");
167  }
168 
169  return m_Array[index].first;
170  }
171 
175  std::size_t size() const
176  {
177  return m_TrueSize;
178  }
179 
183  std::size_t maxSize() const
184  {
185  return MAX_ELEMENTS;
186  }
187 
191  bool empty() const
192  {
193  return (m_TrueSize == 0);
194  }
195 
200  bool contains(T const element) const
201  {
202  std::size_t index = locateIndex(element);
203  return (index != MAX_ELEMENTS);
204  }
205 
209  void clear()
210  {
211  while(size() > 0)
212  {
213  removeIndex(0);
214  }
215  }
216 
217  protected:
218 
222  void insertElement(T const element, uint32_t const priority)
223  {
224  std::size_t index = findIndex(priority);
225 
226  shiftRight(index);
227  m_Array[index] = std::pair<T, uint32_t>(element, priority);
228  }
229 
233  void deleteElement(std::size_t const index)
234  {
235  //m_Array[index].first = 0;
236  shiftLeft(index);
237  }
238 
243  void shiftLeft(std::size_t const index)
244  {
245  // Effectively does the following (shiftLeft(3)):
246  //
247  // [0][1][2][3][4][5][6][7][8][9]
248  // Before: [*][*][*][ ][*][*][*][*][ ][ ]
249  // After: [*][*][*][*][*][*][*][ ][ ][ ]
250 
251  for(std::size_t i = index; i < m_TrueSize - 1; i++)
252  {
253  m_Array[i] = m_Array[i + 1];
254  }
255 
256  //m_Array[m_TrueSize - 1].first = 0;
257  }
258 
263  void shiftRight(std::size_t const index)
264  {
265  // Effectively does the following (shiftRight(3)):
266  //
267  // Before: [0][1][2][3][4][5][6][ ][ ][ ]
268  // After: [0][1][2][ ][3][4][5][6][ ][ ]
269 
270  if(m_TrueSize != MAX_ELEMENTS)
271  {
272  for(std::size_t i = m_TrueSize; i > index; i--)
273  {
274  m_Array[i] = m_Array[i - 1];
275  }
276 
277  //m_Array[index].first = 0;
278  }
279  }
280 
285  std::size_t locateIndex(T const element) const
286  {
287  std::size_t index = MAX_ELEMENTS;
288 
289  for(std::size_t i = 0; i < m_TrueSize; i++)
290  {
291  if(m_Array[i].first == element)
292  {
293  index = i;
294  break;
295  }
296  }
297 
298  return index;
299  }
300 
304  std::size_t findIndex(uint32_t const priority) const
305  {
306  // If the array is empty, return index 0
307  if(m_TrueSize == 0)
308  {
309  return 0;
310  }
311 
312  // Quick check to see if we should insert at the front
313  // or at the back of the list.
314  if(priority < m_Array[0].second)
315  {
316  return 0;
317  }
318  else if(priority > m_Array[m_TrueSize - 1].second)
319  {
320  return m_TrueSize;
321  }
322 
323  return binaryFind(priority);
324  }
325 
330  std::size_t binaryFind(uint32_t const priority) const
331  {
332  uint32_t upper = static_cast<uint32_t>(m_TrueSize);
333  uint32_t index = static_cast<uint32_t>(m_TrueSize / 2);
334  uint32_t increment = static_cast<uint32_t>(index / 2);
335 
336  // While this could be done in a while(true){}, we
337  // place an upper bound on the potential number of
338  // iterations to avoid any (unlikely) infinite loops.
339 
340  for( ; upper > 0; upper--, increment /= 2)
341  {
342  if (increment == 0)
343  {
344  increment = 1;
345  }
346 
347  if(m_Array[index].second == priority)
348  {
349  break;
350  }
351  else if (m_Array[index].second > priority)
352  {
353  // If we are at the front of the list we can not go any further
354  if(index == 0)
355  {
356  break;
357  }
358 
359  index -= increment;
360  }
361  else
362  {
363  // If we are at the end of the list we can not go any further
364  if((index == m_TrueSize) || (index == MAX_ELEMENTS - 1))
365  {
366  break;
367  }
368 
369  index += increment;
370  }
371  }
372 
373  return index;
374  }
375 
376  private:
377 
378  std::size_t m_TrueSize;
379  //std::array<std::pair<T, uint32_t>, MAX_ELEMENTS> m_Array;
380  std::pair<T, std::size_t> m_Array[MAX_ELEMENTS] = {};
381  };
382  }
386 }
391 //------------------------------------------------------------------------------------------
392 
393 #endif
void insertElement(T const element, uint32_t const priority)
Definition: PriorityList.hpp:222
bool empty() const
Definition: PriorityList.hpp:191
std::size_t findIndex(uint32_t const priority) const
Definition: PriorityList.hpp:304
Note: Once this library is made dynamic, this will no longer be needed.
Definition: Common.hpp:70
std::size_t size() const
Definition: PriorityList.hpp:175
void deleteElement(std::size_t const index)
Definition: PriorityList.hpp:233
bool add(T const element, uint32_t priority)
Definition: PriorityList.hpp:112
bool pop()
Definition: PriorityList.hpp:90
void removeElement(T const element)
Definition: PriorityList.hpp:129
void clear()
Definition: PriorityList.hpp:209
std::size_t locateIndex(T const element) const
Definition: PriorityList.hpp:285
bool contains(T const element) const
Definition: PriorityList.hpp:200
void shiftLeft(std::size_t const index)
Definition: PriorityList.hpp:243
bool push(T const element, uint32_t priority)
Definition: PriorityList.hpp:73
void removeIndex(uint32_t index)
Definition: PriorityList.hpp:147
Definition: PriorityList.hpp:45
std::size_t maxSize() const
Definition: PriorityList.hpp:183
void shiftRight(std::size_t const index)
Definition: PriorityList.hpp:263
std::size_t binaryFind(uint32_t const priority) const
Definition: PriorityList.hpp:330