2020-07-25 16:00:26 +02:00
|
|
|
/*
|
2021-02-21 11:30:24 +01:00
|
|
|
* Copyright (c) 2020-2021, the SerenityOS developers.
|
2020-07-25 16:00:26 +02:00
|
|
|
*
|
2021-04-22 01:24:48 -07:00
|
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
2020-07-25 16:00:26 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
2021-12-19 18:20:11 +01:00
|
|
|
#include <AK/Array.h>
|
2020-07-25 16:00:26 +02:00
|
|
|
#include <AK/Assertions.h>
|
2020-09-06 21:14:08 +02:00
|
|
|
#include <AK/Iterator.h>
|
2020-09-09 13:44:51 +02:00
|
|
|
#include <AK/TypedTransfer.h>
|
2020-07-25 16:00:26 +02:00
|
|
|
#include <AK/Types.h>
|
|
|
|
|
|
|
|
namespace AK {
|
|
|
|
|
2020-07-27 13:51:12 +02:00
|
|
|
namespace Detail {
|
|
|
|
|
2020-07-25 16:00:26 +02:00
|
|
|
template<typename T>
|
|
|
|
class Span {
|
|
|
|
public:
|
2020-10-13 18:27:00 -04:00
|
|
|
ALWAYS_INLINE constexpr Span() = default;
|
2020-07-25 16:00:26 +02:00
|
|
|
|
2020-10-13 18:27:00 -04:00
|
|
|
ALWAYS_INLINE constexpr Span(T* values, size_t size)
|
2020-07-27 13:51:12 +02:00
|
|
|
: m_values(values)
|
|
|
|
, m_size(size)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2021-02-21 01:59:08 -08:00
|
|
|
template<size_t size>
|
|
|
|
ALWAYS_INLINE constexpr Span(T (&values)[size])
|
|
|
|
: m_values(values)
|
|
|
|
, m_size(size)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2021-12-19 18:20:11 +01:00
|
|
|
template<size_t size>
|
|
|
|
ALWAYS_INLINE constexpr Span(Array<T, size>& array)
|
|
|
|
: m_values(array.data())
|
|
|
|
, m_size(size)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
template<size_t size>
|
|
|
|
requires(IsConst<T>)
|
2022-10-17 00:06:11 +02:00
|
|
|
ALWAYS_INLINE constexpr Span(Array<T, size> const& array)
|
2021-12-19 18:20:11 +01:00
|
|
|
: m_values(array.data())
|
|
|
|
, m_size(size)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2020-07-27 13:51:12 +02:00
|
|
|
protected:
|
|
|
|
T* m_values { nullptr };
|
|
|
|
size_t m_size { 0 };
|
|
|
|
};
|
2020-07-25 16:00:26 +02:00
|
|
|
|
2020-07-27 13:51:12 +02:00
|
|
|
template<>
|
|
|
|
class Span<u8> {
|
|
|
|
public:
|
2020-10-13 18:27:00 -04:00
|
|
|
ALWAYS_INLINE constexpr Span() = default;
|
2020-07-27 13:51:12 +02:00
|
|
|
|
2020-10-13 18:27:00 -04:00
|
|
|
ALWAYS_INLINE constexpr Span(u8* values, size_t size)
|
2020-07-25 16:00:26 +02:00
|
|
|
: m_values(values)
|
|
|
|
, m_size(size)
|
|
|
|
{
|
|
|
|
}
|
2023-04-02 13:00:05 -04:00
|
|
|
|
2020-07-27 13:51:12 +02:00
|
|
|
ALWAYS_INLINE Span(void* values, size_t size)
|
|
|
|
: m_values(reinterpret_cast<u8*>(values))
|
|
|
|
, m_size(size)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2023-04-02 13:00:05 -04:00
|
|
|
template<size_t size>
|
|
|
|
ALWAYS_INLINE constexpr Span(u8 (&values)[size])
|
|
|
|
: m_values(values)
|
|
|
|
, m_size(size)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2020-07-27 13:51:12 +02:00
|
|
|
protected:
|
|
|
|
u8* m_values { nullptr };
|
|
|
|
size_t m_size { 0 };
|
|
|
|
};
|
|
|
|
|
|
|
|
template<>
|
2021-09-13 02:13:48 +04:30
|
|
|
class Span<u8 const> {
|
2020-07-27 13:51:12 +02:00
|
|
|
public:
|
2020-10-13 18:27:00 -04:00
|
|
|
ALWAYS_INLINE constexpr Span() = default;
|
2020-07-27 13:51:12 +02:00
|
|
|
|
2021-09-13 02:13:48 +04:30
|
|
|
ALWAYS_INLINE constexpr Span(u8 const* values, size_t size)
|
2020-07-27 13:51:12 +02:00
|
|
|
: m_values(values)
|
|
|
|
, m_size(size)
|
|
|
|
{
|
|
|
|
}
|
2023-04-02 13:00:05 -04:00
|
|
|
|
2021-09-13 02:13:48 +04:30
|
|
|
ALWAYS_INLINE Span(void const* values, size_t size)
|
|
|
|
: m_values(reinterpret_cast<u8 const*>(values))
|
2020-07-27 13:51:12 +02:00
|
|
|
, m_size(size)
|
|
|
|
{
|
|
|
|
}
|
2023-04-02 13:00:05 -04:00
|
|
|
|
2021-09-13 02:13:48 +04:30
|
|
|
ALWAYS_INLINE Span(char const* values, size_t size)
|
|
|
|
: m_values(reinterpret_cast<u8 const*>(values))
|
2020-07-27 13:51:12 +02:00
|
|
|
, m_size(size)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2023-04-02 13:00:05 -04:00
|
|
|
template<size_t size>
|
|
|
|
ALWAYS_INLINE constexpr Span(u8 const (&values)[size])
|
|
|
|
: m_values(values)
|
|
|
|
, m_size(size)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2020-07-27 13:51:12 +02:00
|
|
|
protected:
|
2021-09-13 02:13:48 +04:30
|
|
|
u8 const* m_values { nullptr };
|
2020-07-27 13:51:12 +02:00
|
|
|
size_t m_size { 0 };
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
class Span : public Detail::Span<T> {
|
|
|
|
public:
|
|
|
|
using Detail::Span<T>::Span;
|
|
|
|
|
2021-01-10 16:29:28 -07:00
|
|
|
constexpr Span() = default;
|
2020-07-27 14:16:04 +02:00
|
|
|
|
2021-09-13 02:13:48 +04:30
|
|
|
[[nodiscard]] ALWAYS_INLINE constexpr T const* data() const { return this->m_values; }
|
2021-07-01 13:38:58 -07:00
|
|
|
[[nodiscard]] ALWAYS_INLINE constexpr T* data() { return this->m_values; }
|
2020-07-25 16:00:26 +02:00
|
|
|
|
2021-09-13 02:13:48 +04:30
|
|
|
[[nodiscard]] ALWAYS_INLINE constexpr T const* offset_pointer(size_t offset) const { return this->m_values + offset; }
|
2021-07-01 13:38:58 -07:00
|
|
|
[[nodiscard]] ALWAYS_INLINE constexpr T* offset_pointer(size_t offset) { return this->m_values + offset; }
|
2020-12-19 15:07:09 +01:00
|
|
|
|
2021-09-13 02:13:48 +04:30
|
|
|
using ConstIterator = SimpleIterator<Span const, T const>;
|
2020-09-06 21:14:08 +02:00
|
|
|
using Iterator = SimpleIterator<Span, T>;
|
2020-07-25 16:00:26 +02:00
|
|
|
|
2020-09-06 21:14:08 +02:00
|
|
|
constexpr ConstIterator begin() const { return ConstIterator::begin(*this); }
|
|
|
|
constexpr Iterator begin() { return Iterator::begin(*this); }
|
|
|
|
|
|
|
|
constexpr ConstIterator end() const { return ConstIterator::end(*this); }
|
|
|
|
constexpr Iterator end() { return Iterator::end(*this); }
|
2020-07-25 16:00:26 +02:00
|
|
|
|
2021-07-01 13:38:58 -07:00
|
|
|
[[nodiscard]] ALWAYS_INLINE constexpr size_t size() const { return this->m_size; }
|
|
|
|
[[nodiscard]] ALWAYS_INLINE constexpr bool is_null() const { return this->m_values == nullptr; }
|
|
|
|
[[nodiscard]] ALWAYS_INLINE constexpr bool is_empty() const { return this->m_size == 0; }
|
2020-07-25 16:00:26 +02:00
|
|
|
|
2020-12-19 18:13:36 +01:00
|
|
|
[[nodiscard]] ALWAYS_INLINE constexpr Span slice(size_t start, size_t length) const
|
2020-07-25 16:00:26 +02:00
|
|
|
{
|
2021-02-23 20:42:32 +01:00
|
|
|
VERIFY(start + length <= size());
|
2020-08-18 18:02:04 +02:00
|
|
|
return { this->m_values + start, length };
|
2020-07-25 16:00:26 +02:00
|
|
|
}
|
2020-12-19 18:13:36 +01:00
|
|
|
[[nodiscard]] ALWAYS_INLINE constexpr Span slice(size_t start) const
|
2020-08-14 12:19:39 +02:00
|
|
|
{
|
2021-02-23 20:42:32 +01:00
|
|
|
VERIFY(start <= size());
|
2020-08-18 18:02:04 +02:00
|
|
|
return { this->m_values + start, size() - start };
|
|
|
|
}
|
2021-05-25 16:54:04 +04:30
|
|
|
[[nodiscard]] ALWAYS_INLINE constexpr Span slice_from_end(size_t count) const
|
|
|
|
{
|
|
|
|
VERIFY(count <= size());
|
|
|
|
return { this->m_values + size() - count, count };
|
|
|
|
}
|
2020-08-18 18:02:04 +02:00
|
|
|
|
2020-12-19 18:13:36 +01:00
|
|
|
[[nodiscard]] ALWAYS_INLINE constexpr Span trim(size_t length) const
|
2020-08-18 18:02:04 +02:00
|
|
|
{
|
|
|
|
return { this->m_values, min(size(), length) };
|
2020-08-14 12:19:39 +02:00
|
|
|
}
|
|
|
|
|
2023-04-25 07:36:08 +02:00
|
|
|
[[nodiscard]] Span align_to(size_t alignment) const
|
|
|
|
{
|
|
|
|
auto* start = reinterpret_cast<T*>(align_up_to((FlatPtr)data(), alignment));
|
|
|
|
auto* end = reinterpret_cast<T*>(align_down_to((FlatPtr)(data() + size()), alignment));
|
|
|
|
if (end < start)
|
|
|
|
return {};
|
|
|
|
size_t length = end - start;
|
|
|
|
return { start, length };
|
|
|
|
}
|
|
|
|
|
2021-07-01 13:38:58 -07:00
|
|
|
[[nodiscard]] ALWAYS_INLINE constexpr T* offset(size_t start) const
|
2020-07-27 15:19:29 +02:00
|
|
|
{
|
2021-02-23 20:42:32 +01:00
|
|
|
VERIFY(start < this->m_size);
|
2020-07-27 15:19:29 +02:00
|
|
|
return this->m_values + start;
|
|
|
|
}
|
|
|
|
|
2021-09-13 02:13:48 +04:30
|
|
|
ALWAYS_INLINE constexpr void overwrite(size_t offset, void const* data, size_t data_size)
|
2020-12-19 15:56:15 +01:00
|
|
|
{
|
|
|
|
// make sure we're not told to write past the end
|
2021-02-23 20:42:32 +01:00
|
|
|
VERIFY(offset + data_size <= size());
|
2021-09-12 16:02:04 +00:00
|
|
|
__builtin_memmove(this->data() + offset, data, data_size);
|
2020-12-19 15:56:15 +01:00
|
|
|
}
|
|
|
|
|
2021-04-10 18:29:06 +04:30
|
|
|
ALWAYS_INLINE constexpr size_t copy_to(Span<RemoveConst<T>> other) const
|
2020-08-12 11:44:20 +02:00
|
|
|
{
|
2021-02-23 20:42:32 +01:00
|
|
|
VERIFY(other.size() >= size());
|
2021-04-10 18:29:06 +04:30
|
|
|
return TypedTransfer<RemoveConst<T>>::copy(other.data(), data(), size());
|
2020-08-12 11:44:20 +02:00
|
|
|
}
|
|
|
|
|
2021-04-10 18:29:06 +04:30
|
|
|
ALWAYS_INLINE constexpr size_t copy_trimmed_to(Span<RemoveConst<T>> other) const
|
2020-08-12 11:44:20 +02:00
|
|
|
{
|
2021-09-13 02:13:48 +04:30
|
|
|
auto const count = min(size(), other.size());
|
2021-04-10 18:29:06 +04:30
|
|
|
return TypedTransfer<RemoveConst<T>>::copy(other.data(), data(), count);
|
2020-08-12 11:44:20 +02:00
|
|
|
}
|
|
|
|
|
2021-09-13 02:13:48 +04:30
|
|
|
ALWAYS_INLINE constexpr size_t fill(T const& value)
|
2020-08-14 12:16:17 +02:00
|
|
|
{
|
2020-09-15 12:18:31 +02:00
|
|
|
for (size_t idx = 0; idx < size(); ++idx)
|
2020-08-14 12:16:17 +02:00
|
|
|
data()[idx] = value;
|
2020-09-15 12:18:31 +02:00
|
|
|
|
|
|
|
return size();
|
2020-08-14 12:16:17 +02:00
|
|
|
}
|
|
|
|
|
2021-09-13 02:13:48 +04:30
|
|
|
[[nodiscard]] bool constexpr contains_slow(T const& value) const
|
2020-09-07 11:53:54 +02:00
|
|
|
{
|
|
|
|
for (size_t i = 0; i < size(); ++i) {
|
|
|
|
if (at(i) == value)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-02-05 19:02:54 +00:00
|
|
|
[[nodiscard]] bool constexpr starts_with(ReadonlySpan<T> other) const
|
2021-05-03 21:46:18 +03:00
|
|
|
{
|
|
|
|
if (size() < other.size())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return TypedTransfer<T>::compare(data(), other.data(), other.size());
|
|
|
|
}
|
|
|
|
|
2021-09-13 02:13:48 +04:30
|
|
|
[[nodiscard]] ALWAYS_INLINE constexpr T const& at(size_t index) const
|
2020-07-25 16:00:26 +02:00
|
|
|
{
|
2021-02-23 20:42:32 +01:00
|
|
|
VERIFY(index < this->m_size);
|
2020-07-27 13:51:12 +02:00
|
|
|
return this->m_values[index];
|
2020-07-25 16:00:26 +02:00
|
|
|
}
|
2021-07-01 13:38:58 -07:00
|
|
|
|
|
|
|
[[nodiscard]] ALWAYS_INLINE constexpr T& at(size_t index)
|
2020-07-25 16:00:26 +02:00
|
|
|
{
|
2021-02-23 20:42:32 +01:00
|
|
|
VERIFY(index < this->m_size);
|
2020-07-27 13:51:12 +02:00
|
|
|
return this->m_values[index];
|
2020-07-25 16:00:26 +02:00
|
|
|
}
|
|
|
|
|
2023-01-09 23:30:12 +00:00
|
|
|
[[nodiscard]] ALWAYS_INLINE constexpr T const& first() const
|
|
|
|
{
|
|
|
|
return this->at(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
[[nodiscard]] ALWAYS_INLINE constexpr T& first()
|
|
|
|
{
|
|
|
|
return this->at(0);
|
|
|
|
}
|
|
|
|
|
2022-04-02 02:23:33 +01:00
|
|
|
[[nodiscard]] ALWAYS_INLINE constexpr T const& last() const
|
|
|
|
{
|
|
|
|
return this->at(this->size() - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
[[nodiscard]] ALWAYS_INLINE constexpr T& last()
|
|
|
|
{
|
|
|
|
return this->at(this->size() - 1);
|
|
|
|
}
|
|
|
|
|
2021-09-13 02:13:48 +04:30
|
|
|
[[nodiscard]] ALWAYS_INLINE constexpr T const& operator[](size_t index) const
|
2020-07-25 16:00:26 +02:00
|
|
|
{
|
2021-02-21 11:30:24 +01:00
|
|
|
return at(index);
|
2020-07-25 16:00:26 +02:00
|
|
|
}
|
2021-07-01 13:38:58 -07:00
|
|
|
|
|
|
|
[[nodiscard]] ALWAYS_INLINE constexpr T& operator[](size_t index)
|
2020-07-25 16:00:26 +02:00
|
|
|
{
|
2021-02-21 11:30:24 +01:00
|
|
|
return at(index);
|
2020-07-25 16:00:26 +02:00
|
|
|
}
|
|
|
|
|
2021-09-13 02:16:10 +04:30
|
|
|
constexpr bool operator==(Span const& other) const
|
2020-09-09 13:44:51 +02:00
|
|
|
{
|
|
|
|
if (size() != other.size())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return TypedTransfer<T>::compare(data(), other.data(), size());
|
|
|
|
}
|
|
|
|
|
2023-02-05 19:02:54 +00:00
|
|
|
ALWAYS_INLINE constexpr operator ReadonlySpan<T>() const
|
2020-07-26 18:08:40 +02:00
|
|
|
{
|
|
|
|
return { data(), size() };
|
|
|
|
}
|
2020-07-25 16:00:26 +02:00
|
|
|
};
|
|
|
|
|
2022-02-22 21:28:36 +00:00
|
|
|
template<typename T>
|
|
|
|
struct Traits<Span<T>> : public GenericTraits<Span<T>> {
|
|
|
|
static unsigned hash(Span<T> const& span)
|
|
|
|
{
|
|
|
|
unsigned hash = 0;
|
|
|
|
for (auto const& value : span) {
|
|
|
|
auto value_hash = Traits<T>::hash(value);
|
|
|
|
hash = pair_int_hash(hash, value_hash);
|
|
|
|
}
|
|
|
|
return hash;
|
|
|
|
}
|
2022-11-03 10:30:12 +03:30
|
|
|
|
|
|
|
constexpr static bool is_trivial() { return true; }
|
2022-02-22 21:28:36 +00:00
|
|
|
};
|
|
|
|
|
2023-02-05 17:59:03 +00:00
|
|
|
template<typename T>
|
|
|
|
using ReadonlySpan = Span<T const>;
|
|
|
|
|
|
|
|
using ReadonlyBytes = ReadonlySpan<u8>;
|
2020-07-25 16:00:26 +02:00
|
|
|
using Bytes = Span<u8>;
|
2020-09-06 21:14:08 +02:00
|
|
|
|
2020-07-25 16:00:26 +02:00
|
|
|
}
|
|
|
|
|
2022-11-26 12:18:30 +01:00
|
|
|
#if USING_AK_GLOBALLY
|
2020-07-25 16:00:26 +02:00
|
|
|
using AK::Bytes;
|
|
|
|
using AK::ReadonlyBytes;
|
2023-02-05 17:59:03 +00:00
|
|
|
using AK::ReadonlySpan;
|
2020-07-25 16:00:26 +02:00
|
|
|
using AK::Span;
|
2022-11-26 12:18:30 +01:00
|
|
|
#endif
|