in code/include/swoc/MemSpan.h [1590:1713]
return offset <= _size ? self_type{detail::ptr_add(this->data(), offset), std::min(n, _size - offset)} : self_type{};
}
inline constexpr auto
MemSpan<void>::subspan(size_t offset, size_t n) const -> self_type {
return offset <= _size ? self_type{detail::ptr_add(this->data(), offset), std::min(n, _size - offset)} : self_type{};
}
template <typename T> constexpr auto MemSpan<T>::restrict(size_t n) -> self_type & {
_count = std::min(_count, n);
return *this;
}
template <typename T>
auto
MemSpan<void const>::align() const -> self_type {
return this->align(alignof(T), sizeof(T));
}
template <typename T>
auto
MemSpan<void>::align() const -> self_type {
return this->align(alignof(T), sizeof(T));
}
inline auto
MemSpan<void const>::align(size_t alignment) const -> self_type {
auto p = uintptr_t(_ptr);
auto padding = p & (alignment - 1);
size_t size = 0;
if (_size > padding) { // if there's not enough to pad, result is zero size.
size = _size - padding;
}
return {reinterpret_cast<void *>(p + padding), size};
}
inline auto
MemSpan<void>::align(size_t alignment) const -> self_type {
auto &&[ptr, size] = super_type::align(alignment);
return {ptr, size};
}
inline auto
MemSpan<void const>::align(size_t alignment, size_t obj_size) const -> self_type {
auto p = uintptr_t(_ptr);
auto padding = p & (alignment - 1);
size_t size = 0;
if (_size > padding) { // if there's not enough to pad, result is zero size.
size = ((_size - padding) / obj_size) * obj_size;
}
return {reinterpret_cast<void *>(p + padding), size};
}
inline auto
MemSpan<void>::align(size_t alignment, size_t obj_size) const -> self_type {
auto &&[ptr, n] = super_type::align(alignment, obj_size);
return {ptr, n};
}
template <typename U>
MemSpan<U>
MemSpan<void const>::rebind() const {
static_assert(std::is_const_v<U>, "Cannot rebind MemSpan<const void> to non-const type.");
return {static_cast<U *>(_ptr), detail::is_span_compatible<value_type, U>::count(_size)};
}
template <typename U>
MemSpan<U>
MemSpan<void>::rebind() const {
return {static_cast<U *>(_ptr), detail::is_span_compatible<value_type, U>::count(_size)};
}
// Specialize so that @c void -> @c void rebinding compiles and works as expected.
template <>
inline auto
MemSpan<void const>::rebind() const -> self_type {
return *this;
}
template <>
inline auto
MemSpan<void>::rebind() const -> self_type {
return *this;
}
template <>
inline auto
MemSpan<void>::rebind() const -> MemSpan<void const> {
return {_ptr, _size};
}
template <typename U>
U *
MemSpan<void>::as_ptr() const {
if (_size != sizeof(U)) {
throw std::invalid_argument("MemSpan::as size is not compatible with target type.");
}
return static_cast<U *>(_ptr);
}
template <typename U>
U const *
MemSpan<void const>::as_ptr() const {
if (_size != sizeof(U)) {
throw std::invalid_argument("MemSpan::as size is not compatible with target type.");
}
return static_cast<U const *>(_ptr);
}
/// Deduction guides
template <typename T, size_t N> MemSpan(std::array<T, N> &) -> MemSpan<T>;
template <typename T, size_t N> MemSpan(std::array<T, N> const &) -> MemSpan<T const>;
template <size_t N> MemSpan(char (&)[N]) -> MemSpan<char>;
template <size_t N> MemSpan(char const (&)[N]) -> MemSpan<char const>;
template <typename T> MemSpan(std::vector<T> &) -> MemSpan<T>;
template <typename T> MemSpan(std::vector<T> const &) -> MemSpan<T const>;
MemSpan(std::string_view const &) -> MemSpan<char const>;
MemSpan(std::string &) -> MemSpan<char>;
MemSpan(std::string const &) -> MemSpan<char const>;
namespace detail {
struct malloc_liberator {
void
operator()(void *ptr) {