diff options
Diffstat (limited to 'libbase/include/core')
| -rw-r--r-- | libbase/include/core/adt/ilist_node_options.h | 244 |
1 files changed, 244 insertions, 0 deletions
diff --git a/libbase/include/core/adt/ilist_node_options.h b/libbase/include/core/adt/ilist_node_options.h new file mode 100644 index 0000000..d26a6b8 --- /dev/null +++ b/libbase/include/core/adt/ilist_node_options.h @@ -0,0 +1,244 @@ +/* + RCC-Project + + Copyright (C) 2026 Richard Qin + + This file is part of RCC-Project. + + RCC-Project is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your option) any + later version. + + RCC-Project is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + RCC-Project; see the file COPYING. If not see + <http://www.gnu.org/licenses/>. +*/ + +//===- core/adt/ilist_node_options.h - ilist_node Options -------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LIBBASE_ADT_ILIST_NODE_OPTIONS_H +#define LIBBASE_ADT_ILIST_NODE_OPTIONS_H + +#include <type_traits> + +namespace libbase +{ + +template <bool EnableSentinelTracking, class ParentTy> class ilist_node_base; +template <bool EnableSentinelTracking, class ParentTy> class ilist_base; + +/// Option to choose whether to track sentinels. +/// +/// This option affects the ABI for the nodes. When not specified explicitly, +/// sentinel tracking is disabled by default. Specify explicitly to +/// enable \a ilist_node::isSentinel(). +template <bool EnableSentinelTracking> struct ilist_sentinel_tracking +{ +}; + +/// Option to specify a tag for the node type. +/// +/// This option allows a single value type to be inserted in multiple lists +/// simultaneously. See \a ilist_node for usage examples. +template <class Tag> struct ilist_tag +{ +}; + +/// Option to add extra bits to the ilist_iterator. +/// +/// Some use-cases (debug-info) need to know whether a position is intended +/// to be half-open or fully open, i.e. whether to include any immediately +/// adjacent debug-info in an operation. This option adds two bits to the +/// iterator class to store that information. +template <bool ExtraIteratorBits> struct ilist_iterator_bits +{ +}; + +/// Option to add a pointer to this list's owner in every node. +/// +/// This option causes the \a ilist_base_node for this list to contain a pointer +/// ParentTy *Parent, returned by \a ilist_base_node::getNodeBaseParent() and +/// set by \a ilist_base_node::setNodeBaseParent(ParentTy *Parent). The parent +/// value is not set automatically; the ilist owner should set itself as the +/// parent of the list sentinel, and the parent should be set on each node +/// inserted into the list. This value is also not used by +/// \a ilist_node_with_parent::getNodeParent(), but is used by \a +/// ilist_iterator::getNodeParent(), which allows the parent to be fetched from +/// any valid (non-null) iterator to this list, including the sentinel. +template <class ParentTy> struct ilist_parent +{ +}; + +namespace ilist_detail +{ + +/// Helper trait for recording whether an option is specified explicitly. +template <bool IsExplicit> struct explicitness +{ + static const bool is_explicit = IsExplicit; +}; +using is_explicit = explicitness<true>; +using is_implicit = explicitness<false>; + +/// Check whether an option is valid. +/// +/// The steps for adding and enabling a new ilist option include: +/// \li define the option, ilist_foo<Bar>, above; +/// \li add new parameters for Bar to \a ilist_detail::node_options; +/// \li add an extraction meta-function, ilist_detail::extract_foo; +/// \li call extract_foo from \a ilist_detail::compute_node_options and pass it +/// into \a ilist_detail::node_options; and +/// \li specialize \c is_valid_option<ilist_foo<Bar>> to inherit from \c +/// std::true_type to get static assertions passing in \a simple_ilist and \a +/// ilist_node. +template <class Option> struct is_valid_option : std::false_type +{ +}; + +/// Extract sentinel tracking option. +/// +/// Look through \p Options for the \a ilist_sentinel_tracking option, with the +/// default disabled. +template <class... Options> struct extract_sentinel_tracking; +template <bool EnableSentinelTracking, class... Options> +struct extract_sentinel_tracking< + ilist_sentinel_tracking<EnableSentinelTracking>, Options...> + : std::bool_constant<EnableSentinelTracking>, is_explicit +{ +}; +template <class Option1, class... Options> +struct extract_sentinel_tracking<Option1, Options...> + : extract_sentinel_tracking<Options...> +{ +}; +template <> struct extract_sentinel_tracking<> : std::false_type, is_implicit +{ +}; +template <bool EnableSentinelTracking> +struct is_valid_option<ilist_sentinel_tracking<EnableSentinelTracking>> + : std::true_type +{ +}; + +/// Extract custom tag option. +/// +/// Look through \p Options for the \a ilist_tag option, pulling out the +/// custom tag type, using void as a default. +template <class... Options> struct extract_tag; +template <class Tag, class... Options> +struct extract_tag<ilist_tag<Tag>, Options...> +{ + using type = Tag; +}; +template <class Option1, class... Options> +struct extract_tag<Option1, Options...> : extract_tag<Options...> +{ +}; +template <> struct extract_tag<> +{ + using type = void; +}; +template <class Tag> struct is_valid_option<ilist_tag<Tag>> : std::true_type +{ +}; + +/// Extract iterator bits option. +/// +/// Look through \p Options for the \a ilist_iterator_bits option. Defaults +/// to false. +template <class... Options> struct extract_iterator_bits; +template <bool IteratorBits, class... Options> +struct extract_iterator_bits<ilist_iterator_bits<IteratorBits>, Options...> + : std::bool_constant<IteratorBits> +{ +}; +template <class Option1, class... Options> +struct extract_iterator_bits<Option1, Options...> + : extract_iterator_bits<Options...> +{ +}; +template <> struct extract_iterator_bits<> : std::false_type, is_implicit +{ +}; +template <bool IteratorBits> +struct is_valid_option<ilist_iterator_bits<IteratorBits>> : std::true_type +{ +}; + +/// Extract node parent option. +/// +/// Look through \p Options for the \a ilist_parent option, pulling out the +/// custom parent type, using void as a default. +template <class... Options> struct extract_parent; +template <class ParentTy, class... Options> +struct extract_parent<ilist_parent<ParentTy>, Options...> +{ + using type = ParentTy; +}; +template <class Option1, class... Options> +struct extract_parent<Option1, Options...> : extract_parent<Options...> +{ +}; +template <> struct extract_parent<> +{ + using type = void; +}; +template <class ParentTy> +struct is_valid_option<ilist_parent<ParentTy>> : std::true_type +{ +}; + +/// Check whether options are valid. +/// +/// The conjunction of \a is_valid_option on each individual option. +template <class... Options> +struct check_options : std::conjunction<is_valid_option<Options>...> +{ +}; + +/// Traits for options for \a ilist_node. +/// +/// This is usually computed via \a compute_node_options. +template <class T, bool EnableSentinelTracking, bool IsSentinelTrackingExplicit, + class TagT, bool HasIteratorBits, class ParentTy> +struct node_options +{ + using value_type = T; + using pointer = T *; + using reference = T &; + using const_pointer = const T *; + using const_reference = const T &; + + static const bool enable_sentinel_tracking = EnableSentinelTracking; + static const bool is_sentinel_tracking_explicit = IsSentinelTrackingExplicit; + static const bool has_iterator_bits = HasIteratorBits; + using tag = TagT; + using parent_ty = ParentTy; + using node_base_type = ilist_node_base<enable_sentinel_tracking, parent_ty>; + using list_base_type = ilist_base<enable_sentinel_tracking, parent_ty>; +}; + +template <class T, class... Options> struct compute_node_options +{ + using type = node_options<T, extract_sentinel_tracking<Options...>::value, + extract_sentinel_tracking<Options...>::is_explicit, + typename extract_tag<Options...>::type, + extract_iterator_bits<Options...>::value, + typename extract_parent<Options...>::type>; +}; + +} // end namespace ilist_detail +} // end namespace libbase + +#endif // LIBBASE_ADT_ILIST_NODE_OPTIONS_H |
