BLT/include/blt/std/queue.h

242 lines
6.1 KiB
C
Raw Permalink Normal View History

2022-12-26 00:31:00 -05:00
/*
* Created by Brett on 26/12/22.
* Licensed under GNU General Public License V3.0
* See LICENSE file for license detail
*/
2023-01-05 12:34:14 -05:00
#ifndef BLT_QUEUE_H
#define BLT_QUEUE_H
2022-12-26 00:31:00 -05:00
#include <blt/std/memory_util.h>
2022-12-26 23:36:34 -05:00
/**
2023-03-04 22:38:25 -05:00
*
2022-12-26 23:36:34 -05:00
*/
2023-12-16 15:53:02 -05:00
namespace blt
{
2022-12-26 00:31:00 -05:00
2023-01-05 12:34:14 -05:00
/**
* Standard array backed first in first out queue
* @tparam T type stored in the queue
*/
2022-12-26 00:31:00 -05:00
template<typename T>
2023-12-16 15:53:02 -05:00
class flat_stack
{
2022-12-26 01:10:37 -05:00
private:
2023-01-05 12:10:38 -05:00
int m_size = 16;
int m_insertIndex = 0;
T* m_data = new T[m_size];
2022-12-26 01:10:37 -05:00
/**
* Expands the internal array to the new size, copying over the data and shifting its minimal position to index 0
* and deletes the old array from memory.
* @param newSize new size of the internal array
*/
2023-12-16 15:53:02 -05:00
void expand()
{
int new_size = blt::mem::next_byte_allocation(m_size);
2023-03-04 22:38:25 -05:00
auto tempData = new T[new_size];
2023-01-05 12:10:38 -05:00
for (int i = 0; i < m_insertIndex; i++)
tempData[i] = m_data[i];
delete[] m_data;
m_data = tempData;
2023-03-04 22:38:25 -05:00
m_size = new_size;
2022-12-26 01:10:37 -05:00
}
2023-01-05 12:10:38 -05:00
public:
2023-12-16 15:53:02 -05:00
void push(const T& t)
{
if (m_insertIndex >= m_size)
{
2023-03-04 22:38:25 -05:00
expand();
2022-12-26 01:10:37 -05:00
}
2023-01-05 12:10:38 -05:00
m_data[m_insertIndex++] = t;
2022-12-26 01:10:37 -05:00
}
2023-01-05 12:10:38 -05:00
/**
* Warning does not contain runtime error checking!
* @return the element at the "front" of the queue.
*/
2023-12-16 15:53:02 -05:00
[[nodiscard]] const T& top() const
{
2023-01-05 12:10:38 -05:00
return m_data[m_insertIndex - 1];
2022-12-26 01:10:37 -05:00
}
2023-01-05 12:10:38 -05:00
2023-12-16 15:53:02 -05:00
void pop()
{
if (empty())
return;
2023-01-05 12:10:38 -05:00
m_insertIndex--;
}
2023-12-16 15:53:02 -05:00
[[nodiscard]] inline bool empty() const
{
2023-01-05 12:10:38 -05:00
return m_insertIndex <= 0;
2022-12-26 01:10:37 -05:00
}
2023-12-16 15:53:02 -05:00
[[nodiscard]] inline int size() const
{
2023-01-05 12:10:38 -05:00
return m_insertIndex;
2023-01-05 11:49:45 -05:00
}
2023-01-05 12:10:38 -05:00
2023-12-16 15:53:02 -05:00
~flat_stack()
{
2023-01-05 12:10:38 -05:00
delete[](m_data);
2022-12-26 01:10:37 -05:00
}
2022-12-26 00:31:00 -05:00
};
2023-01-05 12:34:14 -05:00
/**
* Standard array backed first in last out queue (stack)
* @tparam T type stored in the queue
*/
template<typename T>
2023-12-16 15:53:02 -05:00
class flat_queue
{
2023-01-05 12:34:14 -05:00
private:
int m_size = 16;
int m_headIndex = 0;
int m_insertIndex = 0;
2023-03-04 22:38:25 -05:00
T* m_data;
2023-12-16 15:53:02 -05:00
2023-01-05 12:34:14 -05:00
/**
2023-03-04 22:38:25 -05:00
* Expands the internal array to allow for more storage of elements
2023-01-05 12:34:14 -05:00
*/
2023-12-16 15:53:02 -05:00
void expand()
{
int new_size = blt::mem::next_byte_allocation(m_size);
2023-03-04 22:38:25 -05:00
int removed_size = m_size - m_headIndex;
auto tempData = new T[new_size];
// only copy data from where we've removed onward
for (int i = 0; i < removed_size; i++)
tempData[i] = m_data[i + m_headIndex]; // but don't copy data we've pop'd
2023-01-05 12:34:14 -05:00
delete[] m_data;
m_headIndex = 0;
2023-03-04 22:38:25 -05:00
m_insertIndex = removed_size - 1;
2023-01-05 12:34:14 -05:00
m_data = tempData;
2023-03-04 22:38:25 -05:00
m_size = new_size;
2023-01-05 12:34:14 -05:00
}
public:
2023-12-16 15:53:02 -05:00
flat_queue(): m_data(new T[m_size])
{
2023-03-04 22:38:25 -05:00
}
2023-12-16 15:53:02 -05:00
inline void push(const T& t)
{
if (m_insertIndex + 1 >= m_size)
{
2023-03-04 22:38:25 -05:00
expand();
2023-01-05 12:34:14 -05:00
}
m_data[m_insertIndex++] = t;
}
/**
* Warning does not contain runtime error checking!
* @return the element at the "front" of the queue.
*/
2023-12-16 15:53:02 -05:00
[[nodiscard]] const T& front() const
{
2023-01-05 12:34:14 -05:00
return m_data[m_headIndex];
}
2023-12-16 15:53:02 -05:00
[[nodiscard]] T& front()
{
return m_data[m_headIndex];
}
inline void pop()
{
if (empty())
2023-01-05 12:34:14 -05:00
return;
2023-01-05 12:40:08 -05:00
m_headIndex++;
2023-01-05 12:34:14 -05:00
}
2023-12-16 15:53:02 -05:00
[[nodiscard]] inline bool empty() const
{
2023-01-05 12:34:14 -05:00
return m_headIndex >= m_size;
}
2023-12-16 15:53:02 -05:00
[[nodiscard]] inline int size() const
{
2023-01-05 12:34:14 -05:00
return m_insertIndex - m_headIndex;
}
2023-12-16 15:53:02 -05:00
inline T* begin()
{
2023-01-26 00:59:36 -05:00
return m_data[m_headIndex];
}
2023-12-16 15:53:02 -05:00
inline T* end()
{
2023-01-26 00:59:36 -05:00
return m_data[m_insertIndex];
}
2023-12-16 15:53:02 -05:00
~flat_queue()
{
2023-01-05 12:34:14 -05:00
delete[](m_data);
}
};
2023-12-16 15:53:02 -05:00
template<typename T>
class linked_stack
{
private:
struct node
{
T t;
node* next;
node(const T& t, node* node): t(t), next(node)
{}
node(T&& t, node* node): t(std::move(t)), next(node)
{}
};
node* head = nullptr;
public:
inline void push(const T& t)
{
head = new node(t, head);
}
inline void push(T&& t)
{
head = new node(std::move(t), head);
}
inline T& top()
{
return head->t;
}
inline const T& top() const
{
return head->t;
}
inline void pop()
{
auto* h = head;
head = head->next;
delete h;
}
~linked_stack()
{
auto* h = head;
while (h != nullptr)
{
auto* hc = h;
h = h->next;
delete hc;
}
}
};
2022-12-26 00:31:00 -05:00
}
2023-01-05 12:34:14 -05:00
#endif //BLT_QUEUE_H