blob: 7b3d6a43e4936e9c7600e5b177565f37b5147e10 [file] [log] [blame]
/*
* Copyright (C) 2022 Apple Inc. 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 APPLE INC. ``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 APPLE INC. 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 <array>
namespace WTF {
// This is an std::array where the indices of the array are values of an enum (rather than a size_t).
// This assumes the values of the enum start at 0 and monotonically increase by 1
// (so the conversion function between size_t and the enum is just a simple static_cast).
// LastValue is the maximum value of the enum, which determines the size of the array.
template <typename Key, typename T, Key LastValue>
class EnumeratedArray {
WTF_MAKE_FAST_ALLOCATED;
public:
using value_type = T;
using size_type = Key;
using reference = value_type&;
using const_reference = const value_type&;
using pointer = value_type*;
using const_pointer = const value_type*;
private:
// We add 1 to the size because we expect that LastValue is the maximum value of the enum,
// rather than the count of items in the enum.
// We're assuming the values in the enum are zero-indexed.
using UnderlyingType = std::array<T, static_cast<std::size_t>(LastValue) + 1>;
public:
using iterator = typename UnderlyingType::iterator;
using const_iterator = typename UnderlyingType::const_iterator;
using reverse_iterator = std::reverse_iterator<iterator>;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
EnumeratedArray() = default;
EnumeratedArray(const EnumeratedArray& from)
: m_storage(from.m_storage)
{
}
EnumeratedArray(EnumeratedArray&& from)
: m_storage(WTFMove(from.m_storage))
{
}
EnumeratedArray(const UnderlyingType& from)
: m_storage(from)
{
}
EnumeratedArray(UnderlyingType&& from)
: m_storage(WTFMove(from))
{
}
EnumeratedArray& operator=(const EnumeratedArray& from)
{
m_storage = from.m_storage;
return *this;
}
EnumeratedArray& operator=(EnumeratedArray&& from)
{
m_storage = WTFMove(from.m_storage);
return *this;
}
constexpr reference at(size_type pos)
{
return m_storage.at(index(pos));
}
constexpr const_reference at(size_type pos) const
{
return m_storage.at(index(pos));
}
constexpr reference operator[](size_type pos)
{
return m_storage[index(pos)];
}
constexpr const_reference operator[](size_type pos) const
{
return m_storage[index(pos)];
}
constexpr reference front()
{
return m_storage.front();
}
constexpr const_reference front() const
{
return m_storage.front();
}
constexpr reference back()
{
return m_storage.back();
}
constexpr const_reference back() const
{
return m_storage.back();
}
constexpr T* data() noexcept
{
return m_storage.data();
}
constexpr const T* data() const noexcept
{
return m_storage.data();
}
constexpr iterator begin() noexcept
{
return m_storage.begin();
}
constexpr const_iterator begin() const noexcept
{
return m_storage.begin();
}
constexpr const_iterator cbegin() const noexcept
{
return m_storage.cbegin();
}
constexpr iterator end() noexcept
{
return m_storage.end();
}
constexpr const_iterator end() const noexcept
{
return m_storage.end();
}
constexpr const_iterator cend() const noexcept
{
return m_storage.cend();
}
constexpr reverse_iterator rbegin() noexcept
{
return m_storage.rbegin();
}
constexpr const_reverse_iterator rbegin() const noexcept
{
return m_storage.rbegin();
}
constexpr const_reverse_iterator crbegin() const noexcept
{
return m_storage.crbegin();
}
constexpr reverse_iterator rend() noexcept
{
return m_storage.rend();
}
constexpr const_reverse_iterator rend() const noexcept
{
return m_storage.rend();
}
constexpr const_reverse_iterator crend() const noexcept
{
return m_storage.crend();
}
constexpr bool empty() const noexcept
{
return m_storage.empty();
}
constexpr typename UnderlyingType::size_type size() const noexcept
{
return m_storage.size();
}
constexpr typename UnderlyingType::size_type max_size() const noexcept
{
return m_storage.max_size();
}
constexpr void fill(const T& value)
{
m_storage.fill(value);
}
constexpr void swap(EnumeratedArray& other) noexcept
{
return m_storage.swap(other.m_storage);
}
template <typename Key2, typename T2, Key2 LastValue2>
constexpr bool operator==(const EnumeratedArray<Key2, T2, LastValue2>& rhs) const
{
return m_storage == rhs.m_storage;
}
template <typename Key2, typename T2, Key2 LastValue2>
bool operator!=(const EnumeratedArray<Key2, T2, LastValue2>& rhs) const
{
return m_storage != rhs.m_storage;
}
template <typename Key2, typename T2, Key2 LastValue2>
bool operator<(const EnumeratedArray<Key2, T2, LastValue2>& rhs) const
{
return m_storage < rhs.m_storage;
}
template <typename Key2, typename T2, Key2 LastValue2>
bool operator<=(const EnumeratedArray<Key2, T2, LastValue2>& rhs) const
{
return m_storage <= rhs.m_storage;
}
template <typename Key2, typename T2, Key2 LastValue2>
bool operator>(const EnumeratedArray<Key2, T2, LastValue2>& rhs) const
{
return m_storage > rhs.m_storage;
}
template <typename Key2, typename T2, Key2 LastValue2>
bool operator>=(const EnumeratedArray<Key2, T2, LastValue2>& rhs) const
{
return m_storage >= rhs.m_storage;
}
private:
typename UnderlyingType::size_type index(size_type pos)
{
return static_cast<typename UnderlyingType::size_type>(pos);
}
UnderlyingType m_storage;
};
} // namespace WTF
using WTF::EnumeratedArray;