libcruft-util/array/parray.hpp

157 lines
4.3 KiB
C++
Raw Normal View History

/*
* 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
2019-06-02 11:09:58 +10:00
#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;
2019-06-02 11:09:58 +10:00
// 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);
2019-06-02 11:10:23 +10:00
SizeT size (void) const;
2019-06-02 11:10:23 +10:00
bool empty (void) const { return size () == 0; }
2019-06-02 11:10:31 +10:00
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:
2019-06-02 11:10:23 +10:00
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>);
}