2014-06-01 17:55:23 +00:00
|
|
|
/*
|
2018-09-02 00:57:29 +00:00
|
|
|
* This file is part of the DXX-Rebirth project <https://www.dxx-rebirth.com/>.
|
2014-06-01 17:55:23 +00:00
|
|
|
* It is copyright by its individual contributors, as recorded in the
|
|
|
|
* project's Git history. See COPYING.txt at the top level for license
|
|
|
|
* terms and a link to the Git history.
|
|
|
|
*/
|
2013-12-11 23:59:36 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
#include <cstddef>
|
2013-12-22 20:07:18 +00:00
|
|
|
#include <memory>
|
2013-12-11 23:59:36 +00:00
|
|
|
#include <stdexcept>
|
|
|
|
#include "dxxsconf.h"
|
2020-05-02 21:18:42 +00:00
|
|
|
#include <array>
|
2013-12-11 23:59:36 +00:00
|
|
|
|
|
|
|
template <typename T = unsigned>
|
|
|
|
class base_count_array_t
|
|
|
|
{
|
|
|
|
protected:
|
|
|
|
typedef T size_type;
|
|
|
|
void clear() { m_count = 0; }
|
2020-04-26 17:26:23 +00:00
|
|
|
size_type m_count = 0;
|
2013-12-11 23:59:36 +00:00
|
|
|
public:
|
2017-06-10 03:31:03 +00:00
|
|
|
size_type size() const { return m_count; }
|
2013-12-20 00:07:07 +00:00
|
|
|
bool empty() const { return !m_count; }
|
2013-12-11 23:59:36 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
template <typename T, std::size_t S>
|
|
|
|
class count_array_t : public base_count_array_t<>
|
|
|
|
{
|
|
|
|
public:
|
2020-05-02 21:18:42 +00:00
|
|
|
using array_type = std::array<T, S>;
|
2013-12-11 23:59:36 +00:00
|
|
|
typedef typename array_type::value_type value_type;
|
|
|
|
typedef typename array_type::iterator iterator;
|
|
|
|
typedef typename array_type::const_iterator const_iterator;
|
|
|
|
typedef typename array_type::const_reference const_reference;
|
2017-06-10 03:31:03 +00:00
|
|
|
static typename array_type::size_type max_size() { return S; }
|
2013-12-11 23:59:36 +00:00
|
|
|
~count_array_t() { clear(); }
|
|
|
|
count_array_t &operator=(const count_array_t &rhs)
|
|
|
|
{
|
|
|
|
if (this != &rhs)
|
|
|
|
{
|
|
|
|
iterator lb = begin();
|
|
|
|
iterator le = end();
|
|
|
|
const_iterator rb = rhs.begin();
|
|
|
|
const_iterator re = rhs.end();
|
|
|
|
for (; lb != le && rb != re; ++lb, ++rb)
|
|
|
|
*lb = *rb;
|
|
|
|
shrink(lb);
|
|
|
|
for (; rb != re; ++rb)
|
|
|
|
emplace_back(*rb);
|
|
|
|
}
|
|
|
|
return *this;
|
|
|
|
}
|
2013-12-20 00:07:07 +00:00
|
|
|
template <typename... Args>
|
|
|
|
void emplace_back(Args&&... args)
|
2013-12-11 23:59:36 +00:00
|
|
|
{
|
|
|
|
if (m_count >= S)
|
|
|
|
throw std::length_error("too many elements");
|
2013-12-22 20:07:18 +00:00
|
|
|
T *uninitialized = static_cast<T *>(&arrayref()[m_count]);
|
|
|
|
new(static_cast<void *>(uninitialized)) T(std::forward<Args>(args)...);
|
2013-12-11 23:59:36 +00:00
|
|
|
++ m_count;
|
|
|
|
}
|
|
|
|
void clear()
|
|
|
|
{
|
|
|
|
shrink(begin());
|
|
|
|
}
|
2013-12-22 16:04:18 +00:00
|
|
|
// for std::back_insert_iterator
|
|
|
|
void push_back(const T& t)
|
|
|
|
{
|
|
|
|
emplace_back(t);
|
|
|
|
}
|
2013-12-20 00:07:07 +00:00
|
|
|
void pop_back()
|
|
|
|
{
|
|
|
|
shrink(end() - 1);
|
|
|
|
}
|
2013-12-11 23:59:36 +00:00
|
|
|
iterator begin() { return arrayref().begin(); }
|
|
|
|
iterator end() { return arrayref().begin() + m_count; }
|
|
|
|
iterator find(const T &t) { return std::find(begin(), end(), t); }
|
|
|
|
const_iterator find(const T &t) const { return std::find(begin(), end(), t); }
|
|
|
|
const_reference operator[](size_type i) const
|
|
|
|
{
|
|
|
|
if (i >= m_count)
|
|
|
|
throw std::out_of_range("not enough elements");
|
|
|
|
return arrayref()[i];
|
|
|
|
}
|
2013-12-22 16:04:18 +00:00
|
|
|
const_reference back() const { return (*this)[m_count - 1]; }
|
2013-12-11 23:59:36 +00:00
|
|
|
bool contains(const T &t) const { return find(t) != end(); }
|
2013-12-11 23:59:36 +00:00
|
|
|
void erase(iterator i)
|
|
|
|
{
|
|
|
|
shrink(i);
|
|
|
|
}
|
2013-12-11 23:59:36 +00:00
|
|
|
void erase(const T &t)
|
|
|
|
{
|
|
|
|
shrink(std::remove(begin(), end(), t));
|
|
|
|
}
|
|
|
|
template <typename F>
|
|
|
|
void erase_if(F f)
|
|
|
|
{
|
|
|
|
shrink(std::remove_if(begin(), end(), f));
|
|
|
|
}
|
|
|
|
void replace(const T &o, const T &n)
|
|
|
|
{
|
|
|
|
std::replace(begin(), end(), o, n);
|
|
|
|
}
|
|
|
|
const_iterator begin() const { return arrayref().begin(); }
|
|
|
|
const_iterator end() const { return arrayref().begin() + m_count; }
|
|
|
|
private:
|
|
|
|
void destroy(iterator b, iterator e)
|
|
|
|
{
|
|
|
|
for (; b != e; ++b)
|
|
|
|
b->~T();
|
|
|
|
}
|
|
|
|
void shrink(iterator b)
|
|
|
|
{
|
|
|
|
destroy(b, end());
|
|
|
|
m_count = std::distance(begin(), b);
|
|
|
|
}
|
2017-06-07 02:44:54 +00:00
|
|
|
private:
|
|
|
|
union U {
|
|
|
|
array_type m_data;
|
|
|
|
U() {}
|
|
|
|
} u;
|
|
|
|
array_type &arrayref() { return u.m_data; }
|
|
|
|
const array_type &arrayref() const { return u.m_data; }
|
2013-12-11 23:59:36 +00:00
|
|
|
};
|