2014-06-01 17:55:23 +00:00
|
|
|
/*
|
|
|
|
* This file is part of the DXX-Rebirth project <http://www.dxx-rebirth.com/>.
|
|
|
|
* 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"
|
2013-12-21 05:12:38 +00:00
|
|
|
#include "compiler-array.h"
|
2013-12-11 23:59:36 +00:00
|
|
|
|
|
|
|
template <typename T = unsigned>
|
|
|
|
class base_count_array_t
|
|
|
|
{
|
|
|
|
protected:
|
|
|
|
typedef T size_type;
|
|
|
|
typedef base_count_array_t<size_type> base_type;
|
|
|
|
void clear() { m_count = 0; }
|
|
|
|
size_type m_count;
|
|
|
|
public:
|
|
|
|
size_type count() const { return m_count; }
|
2013-12-20 00:07:07 +00:00
|
|
|
bool empty() const { return !m_count; }
|
2013-12-22 16:04:18 +00:00
|
|
|
base_count_array_t() : m_count(0) {}
|
2013-12-11 23:59:36 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
template <typename T, std::size_t S>
|
|
|
|
class count_array_t : public base_count_array_t<>
|
|
|
|
{
|
|
|
|
// typedef base_type::size_type size_type;
|
|
|
|
public:
|
|
|
|
typedef array<T, S> array_type;
|
|
|
|
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;
|
2013-12-22 16:04:18 +00:00
|
|
|
static typename array_type::size_type 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);
|
|
|
|
}
|
|
|
|
array<unsigned char, sizeof(T[S])> m_bytes;
|
|
|
|
array_type& arrayref() { return reinterpret_cast<array_type&>(m_bytes); }
|
|
|
|
const array_type& arrayref() const { return reinterpret_cast<const array_type&>(m_bytes); }
|
|
|
|
};
|