2019-09-17 13:22:17 +02:00
|
|
|
/*
|
|
|
|
|
* Copyright Michael Schellenberger Costa
|
|
|
|
|
*
|
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
|
|
|
* to deal in the Software without restriction, including without limitation
|
|
|
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
|
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
|
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
|
|
|
*
|
|
|
|
|
* The above copyright notice and this permission notice (including the next
|
|
|
|
|
* paragraph) shall be included in all copies or substantial portions of the
|
|
|
|
|
* Software.
|
|
|
|
|
*
|
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
|
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
|
|
|
* IN THE SOFTWARE.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#ifndef ACO_UTIL_H
|
|
|
|
|
#define ACO_UTIL_H
|
|
|
|
|
|
|
|
|
|
#include <cassert>
|
|
|
|
|
#include <iterator>
|
|
|
|
|
|
|
|
|
|
namespace aco {
|
|
|
|
|
|
|
|
|
|
/*! \brief Definition of a span object
|
|
|
|
|
*
|
|
|
|
|
* \details A "span" is an "array view" type for holding a view of contiguous
|
|
|
|
|
* data. The "span" object does not own the data itself.
|
|
|
|
|
*/
|
|
|
|
|
template <typename T>
|
|
|
|
|
class span {
|
|
|
|
|
public:
|
|
|
|
|
using value_type = T;
|
|
|
|
|
using pointer = value_type*;
|
|
|
|
|
using const_pointer = const value_type*;
|
|
|
|
|
using reference = value_type&;
|
|
|
|
|
using const_reference = const value_type&;
|
|
|
|
|
using iterator = pointer;
|
|
|
|
|
using const_iterator = const_pointer;
|
|
|
|
|
using reverse_iterator = std::reverse_iterator<iterator>;
|
|
|
|
|
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
2020-01-08 12:46:47 +01:00
|
|
|
using size_type = uint16_t;
|
|
|
|
|
using difference_type = ptrdiff_t;
|
2019-09-17 13:22:17 +02:00
|
|
|
|
|
|
|
|
/*! \brief Compiler generated default constructor
|
|
|
|
|
*/
|
|
|
|
|
constexpr span() = default;
|
|
|
|
|
|
|
|
|
|
/*! \brief Constructor taking a pointer and the length of the span
|
|
|
|
|
* \param[in] data Pointer to the underlying data array
|
|
|
|
|
* \param[in] length The size of the span
|
|
|
|
|
*/
|
2020-01-08 12:46:47 +01:00
|
|
|
constexpr span(uint16_t offset, const size_type length)
|
|
|
|
|
: offset{ offset } , length{ length } {}
|
2019-09-17 13:22:17 +02:00
|
|
|
|
|
|
|
|
/*! \brief Returns an iterator to the begin of the span
|
|
|
|
|
* \return data
|
|
|
|
|
*/
|
|
|
|
|
constexpr iterator begin() noexcept {
|
2020-01-08 12:46:47 +01:00
|
|
|
return (pointer)((char*)this + offset);
|
2019-09-17 13:22:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*! \brief Returns a const_iterator to the begin of the span
|
|
|
|
|
* \return data
|
|
|
|
|
*/
|
|
|
|
|
constexpr const_iterator begin() const noexcept {
|
2020-01-08 12:46:47 +01:00
|
|
|
return (const_pointer)((const char *)this + offset);
|
2019-09-17 13:22:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*! \brief Returns an iterator to the end of the span
|
|
|
|
|
* \return data + length
|
|
|
|
|
*/
|
|
|
|
|
constexpr iterator end() noexcept {
|
2020-01-08 12:46:47 +01:00
|
|
|
return std::next(begin(), length);
|
2019-09-17 13:22:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*! \brief Returns a const_iterator to the end of the span
|
|
|
|
|
* \return data + length
|
|
|
|
|
*/
|
|
|
|
|
constexpr const_iterator end() const noexcept {
|
2020-01-08 12:46:47 +01:00
|
|
|
return std::next(begin(), length);
|
2019-09-17 13:22:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*! \brief Returns a const_iterator to the begin of the span
|
|
|
|
|
* \return data
|
|
|
|
|
*/
|
|
|
|
|
constexpr const_iterator cbegin() const noexcept {
|
2020-01-08 12:46:47 +01:00
|
|
|
return begin();
|
2019-09-17 13:22:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*! \brief Returns a const_iterator to the end of the span
|
|
|
|
|
* \return data + length
|
|
|
|
|
*/
|
|
|
|
|
constexpr const_iterator cend() const noexcept {
|
2020-01-08 12:46:47 +01:00
|
|
|
return std::next(begin(), length);
|
2019-09-17 13:22:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*! \brief Returns a reverse_iterator to the end of the span
|
|
|
|
|
* \return reverse_iterator(end())
|
|
|
|
|
*/
|
|
|
|
|
constexpr reverse_iterator rbegin() noexcept {
|
|
|
|
|
return reverse_iterator(end());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*! \brief Returns a const_reverse_iterator to the end of the span
|
|
|
|
|
* \return reverse_iterator(end())
|
|
|
|
|
*/
|
|
|
|
|
constexpr const_reverse_iterator rbegin() const noexcept {
|
|
|
|
|
return const_reverse_iterator(end());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*! \brief Returns a reverse_iterator to the begin of the span
|
|
|
|
|
* \return reverse_iterator(begin())
|
|
|
|
|
*/
|
|
|
|
|
constexpr reverse_iterator rend() noexcept {
|
|
|
|
|
return reverse_iterator(begin());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*! \brief Returns a const_reverse_iterator to the begin of the span
|
|
|
|
|
* \return reverse_iterator(begin())
|
|
|
|
|
*/
|
|
|
|
|
constexpr const_reverse_iterator rend() const noexcept {
|
|
|
|
|
return const_reverse_iterator(begin());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*! \brief Returns a const_reverse_iterator to the end of the span
|
|
|
|
|
* \return rbegin()
|
|
|
|
|
*/
|
|
|
|
|
constexpr const_reverse_iterator crbegin() const noexcept {
|
|
|
|
|
return const_reverse_iterator(cend());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*! \brief Returns a const_reverse_iterator to the begin of the span
|
|
|
|
|
* \return rend()
|
|
|
|
|
*/
|
|
|
|
|
constexpr const_reverse_iterator crend() const noexcept {
|
|
|
|
|
return const_reverse_iterator(cbegin());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*! \brief Unchecked access operator
|
|
|
|
|
* \param[in] index Index of the element we want to access
|
|
|
|
|
* \return *(std::next(data, index))
|
|
|
|
|
*/
|
|
|
|
|
constexpr reference operator[](const size_type index) noexcept {
|
|
|
|
|
assert(length > index);
|
2020-01-08 12:46:47 +01:00
|
|
|
return *(std::next(begin(), index));
|
2019-09-17 13:22:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*! \brief Unchecked const access operator
|
|
|
|
|
* \param[in] index Index of the element we want to access
|
|
|
|
|
* \return *(std::next(data, index))
|
|
|
|
|
*/
|
|
|
|
|
constexpr const_reference operator[](const size_type index) const noexcept {
|
|
|
|
|
assert(length > index);
|
2020-01-08 12:46:47 +01:00
|
|
|
return *(std::next(begin(), index));
|
2019-09-17 13:22:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*! \brief Returns a reference to the last element of the span
|
|
|
|
|
* \return *(std::next(data, length - 1))
|
|
|
|
|
*/
|
|
|
|
|
constexpr reference back() noexcept {
|
|
|
|
|
assert(length > 0);
|
2020-01-08 12:46:47 +01:00
|
|
|
return *(std::next(begin(), length - 1));
|
2019-09-17 13:22:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*! \brief Returns a const_reference to the last element of the span
|
|
|
|
|
* \return *(std::next(data, length - 1))
|
|
|
|
|
*/
|
|
|
|
|
constexpr const_reference back() const noexcept {
|
|
|
|
|
assert(length > 0);
|
2020-01-08 12:46:47 +01:00
|
|
|
return *(std::next(begin(), length - 1));
|
2019-09-17 13:22:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*! \brief Returns a reference to the first element of the span
|
|
|
|
|
* \return *begin()
|
|
|
|
|
*/
|
|
|
|
|
constexpr reference front() noexcept {
|
|
|
|
|
assert(length > 0);
|
|
|
|
|
return *begin();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*! \brief Returns a const_reference to the first element of the span
|
|
|
|
|
* \return *cbegin()
|
|
|
|
|
*/
|
|
|
|
|
constexpr const_reference front() const noexcept {
|
|
|
|
|
assert(length > 0);
|
|
|
|
|
return *cbegin();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*! \brief Returns true if the span is empty
|
|
|
|
|
* \return length == 0
|
|
|
|
|
*/
|
|
|
|
|
constexpr bool empty() const noexcept {
|
|
|
|
|
return length == 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*! \brief Returns the size of the span
|
|
|
|
|
* \return length == 0
|
|
|
|
|
*/
|
|
|
|
|
constexpr size_type size() const noexcept {
|
|
|
|
|
return length;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*! \brief Decreases the size of the span by 1
|
|
|
|
|
*/
|
|
|
|
|
constexpr void pop_back() noexcept {
|
|
|
|
|
assert(length > 0);
|
|
|
|
|
--length;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*! \brief Clears the span
|
|
|
|
|
*/
|
|
|
|
|
constexpr void clear() noexcept {
|
2020-01-08 12:46:47 +01:00
|
|
|
offset = 0;
|
2019-09-17 13:22:17 +02:00
|
|
|
length = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
2020-01-08 12:46:47 +01:00
|
|
|
uint16_t offset{ 0 }; //!> Byte offset from span to data
|
2019-09-17 13:22:17 +02:00
|
|
|
size_type length{ 0 }; //!> Size of the span
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
} // namespace aco
|
|
|
|
|
|
2020-01-08 12:46:47 +01:00
|
|
|
#endif // ACO_UTIL_H
|