| /* |
| * 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; |