aboutsummaryrefslogtreecommitdiff
path: root/libbase
diff options
context:
space:
mode:
Diffstat (limited to 'libbase')
-rw-r--r--libbase/include/core/adt/ilist_node_options.h244
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