diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 05:54:39 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 05:54:39 +0000 |
commit | 267c6f2ac71f92999e969232431ba04678e7437e (patch) | |
tree | 358c9467650e1d0a1d7227a21dac2e3d08b622b2 /include/o3tl/enumarray.hxx | |
parent | Initial commit. (diff) | |
download | libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.tar.xz libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.zip |
Adding upstream version 4:24.2.0.upstream/4%24.2.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'include/o3tl/enumarray.hxx')
-rw-r--r-- | include/o3tl/enumarray.hxx | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/include/o3tl/enumarray.hxx b/include/o3tl/enumarray.hxx new file mode 100644 index 0000000000..4fd5cab315 --- /dev/null +++ b/include/o3tl/enumarray.hxx @@ -0,0 +1,157 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_O3TL_ENUMARRAY_HXX +#define INCLUDED_O3TL_ENUMARRAY_HXX + +#include <iterator> +#include <type_traits> +#include <utility> +#include <array> +#include <cassert> + +namespace o3tl { + +template<typename EA> +class enumarray_iterator; +template<typename EA> +class enumarray_const_iterator; + +/// +/// This is a container convenience class for arrays indexed by enum values. +/// +/// This assumes that the 'enum class' definition +/// - starts at zero +/// - has no holes in its sequence of values +/// - defines a value called LAST which refers to the greatest constant. +/// +/// \param E the 'enum class' type. +/// \param V the value type to be stored in the array +template<typename E, typename V> +class enumarray final +{ +public: + typedef enumarray<E, V> self_type; + typedef enumarray_iterator<self_type> iterator; + typedef enumarray_const_iterator<self_type> const_iterator; + + typedef V value_type; + typedef E key_type; + typedef size_t size_type; + + static const size_type max_index = static_cast<size_type>(E::LAST); + + // If this ctor only had the args parameter pack, it would erroneously get picked as a better + // choice than the (implicit) copy ctor (taking a const lvalue reference) when a copy is made + // from a non-const lvalue enumarray; the easiest way to avoid that is the additional arg + // parameter; and to keep things simple that parameter is always passed by const lvalue + // reference for now even if there could be cases where passing it by rvalue reference might be + // beneficial or even necessary if V is a move-only type: + template<typename... T> constexpr enumarray(V const & arg, T && ...args): + detail_values{arg, std::forward<T>(args)...} + { + static_assert(sizeof... (T) == max_index); + } + + // coverity[uninit_ctor] - by design: + enumarray() {} + + const V& operator[](E index) const + { + assert(index>=static_cast<E>(0) && index<=E::LAST); + return detail_values[static_cast<size_type>(index)]; + } + + V& operator[](E index) + { + assert(index>=static_cast<E>(0) && index<=E::LAST); + return detail_values[static_cast<size_type>(index)]; + } + + void fill(V val) + { for (size_type i=0; i<=max_index; ++i) detail_values[i] = val; } + + static size_type size() { return max_index + 1; } + iterator begin() { return iterator(*this, 0); } + iterator end() { return iterator(*this, size()); } + const_iterator begin() const { return const_iterator(*this, 0); } + const_iterator end() const { return const_iterator(*this, size()); } + + V* data() { return detail_values.data(); } + +private: + std::array<V, max_index + 1> detail_values; +}; + + +template<typename EA> +class enumarray_iterator { + EA* m_buf; + size_t m_pos; +public: + typedef enumarray_iterator<EA> self_type; + typedef typename EA::value_type value_type; + typedef typename EA::key_type key_type; + typedef std::bidirectional_iterator_tag iterator_category; //should be random access, but that would require define subtraction operators on the enums + typedef + typename std::make_signed< + typename std::underlying_type<typename EA::key_type>::type>::type + difference_type; + typedef typename EA::value_type* pointer; + typedef typename EA::value_type& reference; + + enumarray_iterator(EA& b, size_t start_pos) + : m_buf(&b), m_pos(start_pos) {} + value_type& operator*() const { return (*m_buf)[static_cast<key_type>(m_pos)]; } + value_type* operator->() const { return &(operator*()); } + self_type& operator++() { ++m_pos; return *this; } + bool operator!=(self_type const & other) const { return m_buf != other.m_buf || m_pos != other.m_pos; } + bool operator==(self_type const & other) const { return m_buf == other.m_buf && m_pos == other.m_pos; } +}; + +template<typename EA> +class enumarray_const_iterator { + EA const * m_buf; + size_t m_pos; +public: + typedef enumarray_const_iterator<EA> self_type; + typedef typename EA::value_type const value_type; + typedef typename EA::key_type key_type; + typedef std::bidirectional_iterator_tag iterator_category; //should be random access, but that would require define subtraction operators on the enums + typedef + typename std::make_signed< + typename std::underlying_type<typename EA::key_type>::type>::type + difference_type; + typedef typename EA::value_type const * pointer; + typedef typename EA::value_type const & reference; + + enumarray_const_iterator(EA const & b, size_t start_pos) + : m_buf(&b), m_pos(start_pos) {} + value_type& operator*() const { return (*m_buf)[static_cast<key_type>(m_pos)]; } + value_type* operator->() const { return &(operator*()); } + self_type& operator++() { ++m_pos; return *this; } + bool operator!=(self_type const & other) const { return m_buf != other.m_buf || m_pos != other.m_pos; } + bool operator==(self_type const & other) const { return m_buf == other.m_buf && m_pos == other.m_pos; } +}; + +}; // namespace o3tl + +#endif /* INCLUDED_O3TL_ENUMARRAY_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |