AK: Add generic SimpleIterator class to replace VectorIterator.

This commit is contained in:
asynts 2020-09-06 21:14:08 +02:00 committed by Andreas Kling
parent 9648bf4ada
commit 1b3ecb01a5
8 changed files with 152 additions and 90 deletions

View file

@ -26,8 +26,9 @@
#pragma once
#include <AK/Iterator.h>
#include <AK/Span.h>
#include <AK/Vector.h>
#include <AK/kmalloc.h>
namespace AK {
@ -142,13 +143,14 @@ public:
::swap(m_size, other.m_size);
}
using Iterator = VectorIterator<FixedArray, T>;
Iterator begin() { return Iterator(*this, 0); }
Iterator end() { return Iterator(*this, size()); }
using ConstIterator = SimpleIterator<const FixedArray, const T>;
using Iterator = SimpleIterator<FixedArray, T>;
using ConstIterator = VectorIterator<const FixedArray, const T>;
ConstIterator begin() const { return ConstIterator(*this, 0); }
ConstIterator end() const { return ConstIterator(*this, size()); }
ConstIterator begin() const { return ConstIterator::begin(*this); }
Iterator begin() { return Iterator::begin(*this); }
ConstIterator end() const { return ConstIterator::end(*this); }
Iterator end() { return Iterator::end(*this); }
operator Bytes() { return bytes(); }
operator ReadonlyBytes() const { return bytes(); }

View file

@ -61,6 +61,12 @@ class CircularDuplexStream;
template<typename T>
class Span;
template<typename T>
class Array;
template<typename Container, typename ValueType>
class SimpleIterator;
using ReadonlyBytes = Span<const u8>;
using Bytes = Span<u8>;
@ -123,6 +129,7 @@ class Vector;
}
using AK::Array;
using AK::Atomic;
using AK::Badge;
using AK::Bitmap;

103
AK/Iterator.h Normal file
View file

@ -0,0 +1,103 @@
/*
* Copyright (c) 2020, the SerenityOS developers.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include <AK/Forward.h>
namespace AK {
template<typename Container, typename ValueType>
class SimpleIterator {
public:
friend Container;
constexpr bool is_end() const { return m_index == SimpleIterator::end(m_container).m_index; }
constexpr size_t index() const { return m_index; }
constexpr bool operator==(SimpleIterator other) const { return m_index == other.m_index; }
constexpr bool operator!=(SimpleIterator other) const { return m_index != other.m_index; }
constexpr bool operator<(SimpleIterator other) const { return m_index < other.m_index; }
constexpr bool operator>(SimpleIterator other) const { return m_index > other.m_index; }
constexpr bool operator<=(SimpleIterator other) const { return m_index <= other.m_index; }
constexpr bool operator>=(SimpleIterator other) const { return m_index >= other.m_index; }
constexpr SimpleIterator operator+(ptrdiff_t delta) const { return SimpleIterator { m_container, m_index + delta }; }
constexpr SimpleIterator operator-(ptrdiff_t delta) const { return SimpleIterator { m_container, m_index - delta }; }
constexpr ptrdiff_t operator-(SimpleIterator other) const { return static_cast<ptrdiff_t>(m_index) - other.m_index; }
constexpr SimpleIterator operator++()
{
++m_index;
return *this;
}
constexpr SimpleIterator operator++(int)
{
++m_index;
return SimpleIterator { m_container, m_index - 1 };
}
constexpr SimpleIterator operator--()
{
--m_index;
return *this;
}
constexpr SimpleIterator operator--(int)
{
--m_index;
return SimpleIterator { m_container, m_index + 1 };
}
constexpr const ValueType& operator*() const { return m_container[m_index]; }
constexpr ValueType& operator*() { return m_container[m_index]; }
constexpr const ValueType* operator->() const { return &m_container[m_index]; }
constexpr ValueType* operator->() { return &m_container[m_index]; }
private:
static constexpr SimpleIterator begin(Container& container) { return { container, 0 }; }
static constexpr SimpleIterator end(Container& container)
{
using RawContainerType = typename RemoveCV<Container>::Type;
if constexpr (IsSame<StringView, RawContainerType>::value || IsSame<String, RawContainerType>::value)
return { container, container.length() };
else
return { container, container.size() };
}
constexpr SimpleIterator(Container& container, size_t index)
: m_container(container)
, m_index(index)
{
}
Container& m_container;
size_t m_index;
};
}

View file

@ -51,13 +51,14 @@ public:
using Base::size;
using Iterator = VectorIterator<NonnullPtrVector, T>;
Iterator begin() { return Iterator(*this, 0); }
Iterator end() { return Iterator(*this, size()); }
using ConstIterator = SimpleIterator<const NonnullPtrVector, const T>;
using Iterator = SimpleIterator<NonnullPtrVector, T>;
using ConstIterator = VectorIterator<const NonnullPtrVector, const T>;
ConstIterator begin() const { return ConstIterator(*this, 0); }
ConstIterator end() const { return ConstIterator(*this, size()); }
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); }
PtrType& ptr_at(int index) { return Base::at(index); }
const PtrType& ptr_at(int index) const { return Base::at(index); }

View file

@ -28,6 +28,7 @@
#include <AK/Assertions.h>
#include <AK/Checked.h>
#include <AK/Iterator.h>
#include <AK/Types.h>
namespace AK {
@ -102,9 +103,6 @@ protected:
template<typename T>
class Span : public Detail::Span<T> {
public:
using Iterator = T*;
using ConstIterator = const T*;
using Detail::Span<T>::Span;
ALWAYS_INLINE Span(std::nullptr_t)
@ -120,23 +118,14 @@ public:
ALWAYS_INLINE const T* data() const { return this->m_values; }
ALWAYS_INLINE T* data() { return this->m_values; }
ALWAYS_INLINE ConstIterator begin() const
{
return this->m_values;
}
ALWAYS_INLINE ConstIterator end() const
{
return begin() + size();
}
using ConstIterator = SimpleIterator<const Span, const T>;
using Iterator = SimpleIterator<Span, T>;
ALWAYS_INLINE Iterator begin()
{
return this->m_values;
}
ALWAYS_INLINE Iterator end()
{
return begin() + size();
}
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); }
ALWAYS_INLINE size_t size() const { return this->m_size; }
@ -220,6 +209,7 @@ public:
using ReadonlyBytes = Span<const u8>;
using Bytes = Span<u8>;
}
using AK::Bytes;

View file

@ -58,8 +58,6 @@ namespace AK {
class String {
public:
using ConstIterator = const char*;
~String() { }
String() { }
@ -155,8 +153,10 @@ public:
return (*m_impl)[i];
}
ConstIterator begin() const { return characters(); }
ConstIterator end() const { return begin() + length(); }
using ConstIterator = SimpleIterator<const String, const char>;
constexpr ConstIterator begin() const { return ConstIterator::begin(*this); }
constexpr ConstIterator end() const { return ConstIterator::end(*this); }
bool starts_with(const StringView&, CaseSensitivity = CaseSensitivity::CaseSensitive) const;
bool ends_with(const StringView&, CaseSensitivity = CaseSensitivity::CaseSensitive) const;

View file

@ -37,8 +37,6 @@ namespace AK {
class StringView {
public:
using ConstIterator = const char*;
ALWAYS_INLINE constexpr StringView() { }
ALWAYS_INLINE constexpr StringView(const char* characters, size_t length)
: m_characters(characters)
@ -77,8 +75,10 @@ public:
const char& operator[](size_t index) const { return m_characters[index]; }
ConstIterator begin() const { return characters_without_null_termination(); }
ConstIterator end() const { return begin() + length(); }
using ConstIterator = SimpleIterator<const StringView, const char>;
constexpr ConstIterator begin() const { return ConstIterator::begin(*this); }
constexpr ConstIterator end() const { return ConstIterator::end(*this); }
unsigned hash() const;

View file

@ -28,6 +28,7 @@
#include <AK/Assertions.h>
#include <AK/Forward.h>
#include <AK/Iterator.h>
#include <AK/Optional.h>
#include <AK/Span.h>
#include <AK/StdLibExtras.h>
@ -47,49 +48,6 @@
namespace AK {
template<typename VectorType, typename ElementType>
class VectorIterator {
public:
bool operator!=(const VectorIterator& other) const { return m_index != other.m_index; }
bool operator==(const VectorIterator& other) const { return m_index == other.m_index; }
bool operator<(const VectorIterator& other) const { return m_index < other.m_index; }
bool operator>(const VectorIterator& other) const { return m_index > other.m_index; }
bool operator>=(const VectorIterator& other) const { return m_index >= other.m_index; }
ALWAYS_INLINE VectorIterator& operator++()
{
++m_index;
return *this;
}
VectorIterator& operator--()
{
--m_index;
return *this;
}
VectorIterator operator-(size_t value) { return { m_vector, m_index - value }; }
VectorIterator operator+(size_t value) { return { m_vector, m_index + value }; }
VectorIterator& operator=(const VectorIterator& other)
{
m_index = other.m_index;
return *this;
}
ALWAYS_INLINE ElementType& operator*() { return m_vector[m_index]; }
ALWAYS_INLINE ElementType* operator->() { return &m_vector[m_index]; }
size_t operator-(const VectorIterator& other) { return m_index - other.m_index; }
bool is_end() const { return m_index == m_vector.size(); }
size_t index() const { return m_index; }
private:
friend VectorType;
VectorIterator(VectorType& vector, size_t index)
: m_vector(vector)
, m_index(index)
{
}
VectorType& m_vector;
size_t m_index { 0 };
};
template<typename T>
class TypedTransfer {
public:
@ -582,13 +540,14 @@ public:
return resize(new_size, true);
}
using Iterator = VectorIterator<Vector, T>;
Iterator begin() { return Iterator(*this, 0); }
Iterator end() { return Iterator(*this, size()); }
using ConstIterator = SimpleIterator<const Vector, const T>;
using Iterator = SimpleIterator<Vector, T>;
using ConstIterator = VectorIterator<const Vector, const T>;
ConstIterator begin() const { return ConstIterator(*this, 0); }
ConstIterator end() const { return ConstIterator(*this, size()); }
ConstIterator begin() const { return ConstIterator::begin(*this); }
Iterator begin() { return Iterator::begin(*this); }
ConstIterator end() const { return ConstIterator::end(*this); }
Iterator end() { return Iterator::end(*this); }
template<typename Finder>
ConstIterator find(Finder finder) const
@ -605,7 +564,7 @@ public:
{
for (size_t i = 0; i < m_size; ++i) {
if (finder(at(i)))
return Iterator(*this, i);
return Iterator { *this, i };
}
return end();
}