157 lines
4.3 KiB
C++
157 lines
4.3 KiB
C++
/*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* Copyright 2010-2018 Danny Robson <danny@nerdcruft.net>
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "../debug/assert.hpp"
|
|
#include "../cast.hpp"
|
|
|
|
#include <algorithm>
|
|
#include <iterator>
|
|
#include <cstddef>
|
|
#include <iosfwd>
|
|
|
|
|
|
namespace cruft {
|
|
///////////////////////////////////////////////////////////////////////////
|
|
/// A pascal style array consisting of a size and a bare pointer.
|
|
template <
|
|
typename DataT,
|
|
typename SizeT = std::size_t
|
|
>
|
|
class parray {
|
|
public:
|
|
using value_type = DataT;
|
|
using size_type = SizeT;
|
|
using reference = DataT&;
|
|
using const_reference = DataT const&;
|
|
using iterator = DataT*;
|
|
using const_iterator = DataT const*;
|
|
using difference_type = std::ptrdiff_t;
|
|
|
|
parray (SizeT size, DataT *data);
|
|
|
|
template <SizeT SizeV>
|
|
explicit
|
|
parray (DataT (&data)[SizeV]):
|
|
parray (SizeV, data+0)
|
|
{ ; }
|
|
|
|
parray (parray const&) noexcept = default;
|
|
parray& operator= (parray const&) noexcept = default;
|
|
|
|
parray (parray &&) noexcept = default;
|
|
parray& operator= (parray &&) noexcept = default;
|
|
|
|
// Only allows shrinking currently.
|
|
void resize (SizeT count)
|
|
{
|
|
CHECK_LE (count, m_size);
|
|
|
|
for (auto cursor = count; cursor < m_size; ++cursor)
|
|
m_data[cursor].~DataT ();
|
|
m_size = count;
|
|
}
|
|
|
|
DataT& operator[] (SizeT idx);
|
|
const DataT& operator[] (SizeT idx) const;
|
|
|
|
DataT& at (SizeT idx);
|
|
const DataT& at (SizeT idx) const;
|
|
|
|
DataT* begin (void);
|
|
DataT* end (void);
|
|
|
|
DataT const* begin (void) const { return cbegin (); }
|
|
DataT const* end (void) const { return cend (); }
|
|
|
|
const DataT* cbegin (void) const;
|
|
const DataT* cend (void) const;
|
|
|
|
const DataT* data (void) const;
|
|
|
|
DataT* data (void);
|
|
|
|
SizeT size (void) const;
|
|
bool empty (void) const { return size () == 0; }
|
|
|
|
template <
|
|
typename T = DataT,
|
|
typename = std::enable_if_t<std::is_move_assignable_v<T>>
|
|
>
|
|
DataT*
|
|
erase (DataT *first, DataT *last)
|
|
{
|
|
DataT *newend = std::move (last, m_data + m_size, first);
|
|
for (auto cursor = newend; cursor != end (); ++cursor)
|
|
cursor->~DataT ();
|
|
m_size = cruft::cast::lossless<SizeT> (newend - m_data);
|
|
return newend;
|
|
}
|
|
|
|
template <
|
|
typename T = DataT,
|
|
typename = std::enable_if_t<std::is_move_assignable_v<T>>
|
|
>
|
|
DataT*
|
|
erase (DataT *item)
|
|
{
|
|
return erase (item, item + 1);
|
|
}
|
|
|
|
private:
|
|
SizeT m_size;
|
|
DataT *m_data;
|
|
};
|
|
|
|
|
|
template <typename ValueA, typename SizeA, typename ValueB, std::size_t SizeB>
|
|
bool
|
|
equal (parray<ValueA,SizeA> const &a, ValueB const (&b)[SizeB])
|
|
{
|
|
return std::equal (
|
|
std::begin (a), std::end (b),
|
|
std::begin (b), std::end (b)
|
|
);
|
|
}
|
|
|
|
|
|
template <typename ValueA, typename SizeA, typename ValueB, std::size_t SizeB>
|
|
bool
|
|
equal (ValueB const (&a)[SizeB], parray<ValueA,SizeA> const &b)
|
|
{
|
|
return std::equal (
|
|
std::begin (a), std::end (b),
|
|
std::begin (b), std::end (b)
|
|
);
|
|
}
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
template <typename DataT, std::size_t SizeV>
|
|
parray (DataT (&)[SizeV]) -> parray<DataT,std::size_t>;
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
template <typename SizeT>
|
|
std::ostream&
|
|
operator<< (std::ostream&, cruft::parray<const char, SizeT>);
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
template <typename SizeT>
|
|
std::ostream&
|
|
operator<< (std::ostream&, cruft::parray<char, SizeT>);
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
template <typename DataT, typename SizeT>
|
|
std::ostream&
|
|
operator<< (std::ostream&, cruft::parray<DataT, SizeT>);
|
|
}
|