libcruft-util/array/parray.cpp
Danny Robson fdaa5e1392 assert: split CHECK_LIMIT into INCLUSIVE and INDEX
LIMIT hid an off-by-one bug when tests used end iterators. We rename the
assertion to uncover all uses of the flawed implementation, and split it
into an identical assertion, and one intended to protect against
iterator ends.
2020-09-24 08:03:41 +10:00

205 lines
5.0 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-2016 Danny Robson <danny@nerdcruft.net>
*/
#include "parray.hpp"
#include "../debug/assert.hpp"
#include <iterator>
#include <stdexcept>
using cruft::parray;
///////////////////////////////////////////////////////////////////////////////
template <typename DataT, typename SizeT>
parray<DataT,SizeT>::parray (SizeT _size, DataT *_data)
: m_size (_size)
, m_data (_data)
{ ; }
///////////////////////////////////////////////////////////////////////////////
template <typename DataT, typename SizeT>
DataT&
parray<DataT, SizeT>::operator[] (SizeT idx)
{
CHECK_INDEX (idx, m_size);
return data ()[idx];
}
//-----------------------------------------------------------------------------
template <typename DataT, typename SizeT>
const DataT&
parray<DataT, SizeT>::operator[] (SizeT idx) const
{
CHECK_INDEX (idx, m_size);
return data ()[idx];
}
///////////////////////////////////////////////////////////////////////////////
template <typename DataT, typename SizeT>
DataT&
parray<DataT, SizeT>::at (SizeT idx)
{
if (idx >= size ())
throw std::out_of_range ("invalid index for parray");
return (*this)[idx];
}
//-----------------------------------------------------------------------------
template <typename DataT, typename SizeT>
const DataT&
parray<DataT, SizeT>::at (SizeT idx) const
{
if (idx >= size ())
throw std::out_of_range ("invalid index for parray");
return (*this)[idx];
}
///////////////////////////////////////////////////////////////////////////////
template <typename DataT, typename SizeT>
DataT*
parray<DataT, SizeT>::begin (void)
{
return data ();
}
//-----------------------------------------------------------------------------
template <typename DataT, typename SizeT>
DataT*
parray<DataT, SizeT>::end (void)
{
return data () + size ();
}
///////////////////////////////////////////////////////////////////////////////
template <typename DataT, typename SizeT>
const DataT*
parray<DataT, SizeT>::cbegin (void) const
{
return data ();
}
//-----------------------------------------------------------------------------
template <typename DataT, typename SizeT>
const DataT*
parray<DataT, SizeT>::cend (void) const
{
return data () + size ();
}
///////////////////////////////////////////////////////////////////////////////
template <typename DataT, typename SizeT>
const DataT*
parray<DataT, SizeT>::data (void) const
{
return m_data;
}
//-----------------------------------------------------------------------------
template <typename DataT, typename SizeT>
DataT*
parray<DataT, SizeT>::data (void)
{
return m_data;
}
//-----------------------------------------------------------------------------
template <typename DataT, typename SizeT>
SizeT
parray<DataT, SizeT>::size (void) const
{
return m_size;
}
///////////////////////////////////////////////////////////////////////////////
template <typename SizeT>
std::ostream&
cruft::operator<< (std::ostream &os, parray<const char,SizeT> p)
{
std::copy_n (
p.cbegin (),
p.size (),
std::ostream_iterator<const char> (os)
);
return os;
}
//-----------------------------------------------------------------------------
template <typename SizeT>
std::ostream&
cruft::operator<< (std::ostream &os, parray<char,SizeT> p)
{
std::copy_n (
p.cbegin (),
p.size (),
std::ostream_iterator<char> (os)
);
return os;
}
///////////////////////////////////////////////////////////////////////////////
template <typename DataT, typename SizeT>
std::ostream&
cruft::operator<< (std::ostream &os, parray<DataT,SizeT> p)
{
auto size = p.size ();
uintptr_t ptr = reinterpret_cast<uintptr_t> (p.data ());
os << "[" << +size << ", " << std::hex << ptr << std::dec << "]";
return os;
}
///////////////////////////////////////////////////////////////////////////////
#define INSTANTIATE_D_S(D,S) \
template std::ostream& cruft::operator<< (std::ostream&, parray< D,S>); \
template std::ostream& cruft::operator<< (std::ostream&, parray<const D,S>); \
\
template class cruft::parray< D,S>; \
template class cruft::parray<const D,S>;
//-----------------------------------------------------------------------------
#define INSTANTIATE_D(D) \
INSTANTIATE_D_S(D, uint16_t) \
INSTANTIATE_D_S(D, uint32_t) \
INSTANTIATE_D_S(D, uint64_t)
//-----------------------------------------------------------------------------
INSTANTIATE_D (char)
INSTANTIATE_D (uint8_t)
INSTANTIATE_D (uint16_t)
INSTANTIATE_D (uint32_t)
INSTANTIATE_D (uint64_t)
INSTANTIATE_D (int8_t)
INSTANTIATE_D (int16_t)
INSTANTIATE_D (int32_t)
INSTANTIATE_D (int64_t)