// Copyright Microsoft and CHERIoT Contributors.
// SPDX-License-Identifier: MIT

/**
 * @file A (circular) doubly linked list, abstracted over cons cell
 * representations.
 */

#pragma once

#include <concepts>
#include <ds/pointer.h>

namespace ds::linked_list
{

	namespace cell
	{
		/**
		 * The primitive, required, abstract interface to our cons cells.
		 *
		 * All methods are "namespaced" with `cell_` to support the case where
		 * the encoded forms are also representing other state (for example,
		 * bit-packed flags in pointer address bits).
		 */
		template<typename T>
		concept HasCellOperations = requires(T &t)
		{
			/** Proxies for list linkages */
			{
				t.cell_next()
				} -> ds::pointer::proxy::Proxies<T>;
			{
				t.cell_prev()
				} -> ds::pointer::proxy::Proxies<T>;
		};

		/**
		 * Reset a cell to a singleton ring.  Not all cons cells are required to
		 * be able to do this, though if you're sticking to rings and not
		 * (ab)using the machinery here in interesting ways, this should be easy
		 * to specify.
		 *
		 * This is a method, and not a constructor, to handle cases where the
		 * cell is also packing other state into its representation.
		 */
		template<typename T>
		concept HasReset = requires(T &t)
		{
			{
				t.cell_reset()
				} -> std::same_as<void>;
		};

		template<typename T>
		concept HasCellOperationsReset = HasCellOperations<T> && HasReset<T>;

		/**
		 * Additional, optional overrides available within implementation of
		 * cons cells.  It may be useful to static_assert() these in
		 * implementations to make sure we are not falling back to the defaults
		 * in terms of the above primops.
		 *
		 * @{
		 */
		template<typename T>
		concept HasIsSingleton = requires(T &t)
		{
			{
				t.cell_is_singleton()
				} -> std::same_as<bool>;
		};

		template<typename T>
		concept HasIsSingletonCheck = requires(T &t)
		{
			{
				t.cell_is_singleton_check()
				} -> std::same_as<bool>;
		};

		template<typename T>
		concept HasIsDoubleton = requires(T &t)
		{
			{
				t.cell_is_doubleton()
				} -> std::same_as<bool>;
		};

		/** @} */

	} // namespace cell

	/**
	 * Self-loops indicate either the sentinels of an empty list or,
	 * less often, singletons without their sentinels; it's up to
	 * the caller to know which is being tested for, here.
	 *
	 * The default implementation decodes and compares one link;
	 * implementations may have more efficient mechanisms.
	 *
	 * @{
	 */
	template<cell::HasCellOperations T>
	requires(!cell::HasIsSingleton<T>) __always_inline bool is_singleton(T *e)
	{
		return e == e->cell_prev();
	}

	template<cell::HasCellOperations T>
	requires(cell::HasIsSingleton<T>) __always_inline bool is_singleton(T *e)
	{
		return e->cell_is_singleton();
	}
	/** @} */

	/**
	 * Like is_singleton(), but checks both edges.  Useful only for
	 * testing invariants.
	 *
	 * The default implementation decodes and compares both links.
	 */
	template<cell::HasCellOperations T>
	requires(!cell::HasIsSingletonCheck<T>) __always_inline
	  bool is_singleton_check(T *e)
	{
		return (e == e->cell_next()) && (e == e->cell_prev());
	}

	template<cell::HasCellOperations T>
	requires(cell::HasIsSingletonCheck<T>) __always_inline
	  bool is_singleton_check(T *e)
	{
		return e->is_singleton_check();
	}
	/** @} */

	/**
	 * Doubletons are either singleton collections (with both the sentinel
	 * and the single element satisfying this test) or, less often, a pair
	 * of elements without a sentinel.  The caller is expected to know
	 * what's meant by this test.
	 *
	 * The default implementation decodes and compares both links.
	 * @{
	 */
	template<cell::HasCellOperations T>
	requires(!cell::HasIsDoubleton<T>) __always_inline bool is_doubleton(T *e)
	{
		return e->cell_prev() == e->cell_next();
	}

	template<cell::HasCellOperations T>
	requires(cell::HasIsDoubleton<T>) __always_inline bool is_doubleton(T *e)
	{
		return e->cell_is_doubleton();
	}
	/** @} */

	/**
	 * Verify linkage invariants.  Again, useful only for testing.
	 *
	 * The default implementation decodes all four relevant links.
	 */
	template<cell::HasCellOperations T>
	__always_inline bool is_well_formed(T *e)
	{
		return (e == e->cell_prev()->cell_next()) &&
		       (e == e->cell_next()->cell_prev());
	}

	/**
	 * Insert a ring of `elem`-ents (typically, a singleton ring) before the
	 * `curr`-ent element (or sentinel) in the ring.  In general, you will
	 * probably want to make sure that at most one of `elem` or `curr`
	 * points to a ring with a sentinel node.
	 *
	 * If `curr` is the sentinel, this is appending to the list, in the
	 * sense that the element(s) occupy (or span) the next-most and
	 * prev-least position from the sentinel.
	 *
	 * By symmetry, if `elem` is, instead, the sentinel, then `curr` is
	 * prepended to the list in the same sense.
	 */
	template<cell::HasCellOperations Cell>
	__always_inline void insert_before(Cell *curr, Cell *elem)
	{
		curr->cell_prev()->cell_next() = elem->cell_next();
		elem->cell_next()->cell_prev() = curr->cell_prev();
		curr->cell_prev()              = elem;
		elem->cell_next()              = curr;
	}

	/**
	 * Emplacement before.  This fuses initialization and insertion, so that
	 *
	 *    emplace_before(c, e);
	 *
	 * is semantically equivalent to
	 *
	 *    e->cell_reset(); insert_before(c, e);
	 *
	 * but spelled in a way that the compiler can understand a bit better, with
	 * less effort spent in provenance and/or alias analysis.
	 */
	template<cell::HasCellOperations Cell, typename P>
	requires std::same_as<P, Cell *> || ds::pointer::proxy::Proxies<P, Cell>
	  __always_inline void emplace_before(P curr, Cell *elem)
	{
		auto prev         = curr->cell_prev();
		elem->cell_next() = curr;
		elem->cell_prev() = prev;
		prev->cell_next() = elem;
		prev              = elem;
	}

	/**
	 * Emplacement after.  This fuses initialization and insertion, so that
	 *
	 *    emplace_after(c, e);
	 *
	 * is semantically equivalent to
	 *
	 *    e->cell_reset(); insert_before(e, c);
	 *
	 * but spelled in a way that the compiler can understand a bit better, with
	 * less effort spent in provenance and/or alias analysis.
	 */
	template<cell::HasCellOperations Cell, typename P>
	requires std::same_as<P, Cell *> || ds::pointer::proxy::Proxies<P, Cell>
	  __always_inline void emplace_after(P curr, Cell *elem)
	{
		auto next         = curr->cell_next();
		elem->cell_prev() = curr;
		elem->cell_next() = next;
		next->cell_prev() = elem;
		next              = elem;
	}

	/**
	 * Remove from the list without turning the removed span into a
	 * well-formed ring.  This is useful only if that invariant will be
	 * restored later (prior to insertion, at the very least).
	 *
	 * The removed element or span instead retains links into the ring
	 * whence it was removed, but is no longer well-formed, since that ring
	 * no longer references the removed element or span.
	 *
	 * This can be used to remove...
	 *
	 *   - a single element (`el == er`)
	 *
	 *   - the sentinel (`el == er`), leaving the rest of the ring, if any,
	 *     as a sentinel-free ring
	 *
	 *   - a span of elements from `el` to `er` via the `next` links; the
	 *     removed span is damaged and must be corrected, while the residual
	 *     ring remains well-formed.
	 *
	 * In all cases, `el`'s previous element is returned as a handle to the
	 * residual ring.
	 */
	template<cell::HasCellOperations Cell>
	__always_inline Cell *unsafe_remove(Cell *el, Cell *er)
	{
		auto p         = el->cell_prev();
		auto n         = er->cell_next();
		n->cell_prev() = p;
		p->cell_next() = n;
		return p;
	}

	template<cell::HasCellOperations Cell>
	__always_inline Cell *unsafe_remove(Cell *e)
	{
		return unsafe_remove(e, e);
	}

	/**
	 * Remove a particular element `rem` from the ring, already knowing its
	 * adjacent, previous link `prev`.  `prev` remains connected to the ring
	 * but `rem` will no longer be well-formed.  Returns a proxy to prev's
	 * next field.
	 */
	template<cell::HasCellOperations Cell>
	__always_inline auto unsafe_remove_link(Cell *prev, Cell *rem)
	{
		auto next         = rem->cell_next();
		auto prevnext     = prev->cell_next();
		prevnext          = next;
		next->cell_prev() = prev;
		return prevnext;
	}

	/**
	 * Remove from the ring, cleaving the ring into two well-formed rings.
	 *
	 * This can be used to remove...
	 *
	 *   - a single element (`el == er`)
	 *
	 *   - the sentinel (`el == er`), leaving the rest of the ring, if any,
	 *     as a sentinel-free collection
	 *
	 *   - a span of elements from `el` to `er` via `next` links; the
	 *     removed span is made into a ring and the residual ring is left
	 *     well-formed.
	 *
	 * In all cases, `el`'s previous element is returned as a handle to the
	 * residual ring.  (The caller must already have a reference to the span
	 * being removed).  This is especially useful when `remove`-ing elements
	 * during a `search`, below: overwriting the callback's Cell pointer
	 * (passed by *reference*) will continue the iteration, calling back at
	 * the removed node's successor.
	 *
	 * Removing a singleton from its ring from itself causes no change, as
	 * any would-be residual ring is empty.  This corner case requires some
	 * care on occasion.
	 */
	template<cell::HasCellOperations Cell>
	__always_inline Cell *remove(Cell *el, Cell *er)
	{
		Cell *p         = unsafe_remove(el, er);
		el->cell_prev() = er;
		er->cell_next() = el;
		return p;
	}

	template<cell::HasCellOperations Cell>
	__always_inline Cell *remove(Cell *e)
	{
		return remove(e, e);
	}

	/**
	 * Search through a span of a ring, inclusively from `from` through
	 * exclusively to `to`, applying `f` to each cons cell in turn.  If `f`
	 * returns `true`, the search stops early and returns `true`; otherwise,
	 * search returns `false`.  To (side-effectfully) visit every node in the
	 * span, have `f` always return false.
	 */
	template<cell::HasCellOperations Cell, typename F>
	__always_inline bool search(Cell *from, Cell *to, F f)
	{
		Cell *elem;
		for (elem = from; elem != to; elem = elem->cell_next())
		{
			if (f(elem))
			{
				return true;
			}
		}
		return false;
	}

	/**
	 * Search through all elements of a ring *except* `elem`.  If `elem` is the
	 * sentinel of a ring, then this is, as one expects, a `search` over all
	 * non-sentinel memebers of the ring.
	 */
	template<cell::HasCellOperations Cell, typename F>
	__always_inline bool search(Cell *elem, F f)
	{
		return search(static_cast<Cell *>(elem->cell_next()), elem, f);
	}

	/**
	 * Convenience wrapper for a sentinel cons cell, encapsulating some common
	 * patterns.
	 */
	template<cell::HasCellOperationsReset CellTemplateArg>
	struct Sentinel
	{
		using Cell = CellTemplateArg;

		/**
		 * The sentinel node itself.  Viewing the ring as a list, this
		 * effectively serves as pointers to the head (next) and to the tail
		 * (prev) of the list.  Unlike more traditional nullptr-terminated
		 * lists, though, here, the sentinel participates in the ring.
		 *
		 * This is marked `cheri_no_subobject_bounds` because some of our cons
		 * cell implementations use pointer proxies that rely on the bounds
		 * provided by `this` (which, in turn, is likely to be
		 * `cheri_no_subobject_bounds`)
		 */
		Cell sentinel __attribute__((__cheri_no_subobject_bounds__)) = {};

		__always_inline void reset()
		{
			sentinel.cell_reset();
		}

		__always_inline bool is_empty()
		{
			return linked_list::is_singleton(&sentinel);
		}

		__always_inline void append(Cell *elem)
		{
			linked_list::insert_before(&sentinel, elem);
		}

		__always_inline void append_emplace(Cell *elem)
		{
			linked_list::emplace_before(&sentinel, elem);
		}

		__always_inline void prepend(Cell *elem)
		{
			linked_list::insert_before(elem, &sentinel);
		}

		__always_inline Cell *first()
		{
			return sentinel.cell_next();
		}

		__always_inline Cell *last()
		{
			return sentinel.cell_prev();
		}

		__always_inline Cell *unsafe_take_first()
		{
			Cell *f = sentinel.cell_next();
			linked_list::unsafe_remove_link(&sentinel, f);
			return f;
		}

		__always_inline Cell *take_all()
		{
			auto p = linked_list::unsafe_remove(&sentinel);
			sentinel.cell_reset();
			return p;
		}

		template<typename F>
		__always_inline bool search(F f)
		{
			return linked_list::search(&sentinel, f);
		}
	};

	namespace cell
	{

		/** Cons cell using two pointers */
		class Pointer
		{
			Pointer *prev, *next;

			public:
			Pointer()
			{
				this->cell_reset();
			}

			__always_inline void cell_reset()
			{
				prev = next = this;
			}

			__always_inline auto cell_next()
			{
				return ds::pointer::proxy::Pointer(next);
			}

			__always_inline auto cell_prev()
			{
				return ds::pointer::proxy::Pointer(prev);
			}
		};
		static_assert(HasCellOperationsReset<Pointer>);

		/**
		 * Encode a linked list cons cell as a pair of addresses (but present an
		 * interface in terms of pointers).  CHERI bounds on the returned
		 * pointers are inherited from the pointer to `this` cons cell.
		 */
		class PtrAddr
		{
			ptraddr_t prev, next;

			public:
			PtrAddr()
			{
				this->cell_reset();
			}
			/* Primops */

			__always_inline void cell_reset()
			{
				prev = next = CHERI::Capability{this}.address();
			}

			__always_inline auto cell_next()
			{
				return ds::pointer::proxy::PtrAddr(this, next);
			}

			__always_inline auto cell_prev()
			{
				return ds::pointer::proxy::PtrAddr(this, prev);
			}

			/*
			 * Specialized implementations that may be slightly fewer
			 * instructions than the generic approaches in terms of the primops.
			 */

			__always_inline bool cell_is_singleton()
			{
				return prev == CHERI::Capability{this}.address();
			}

			__always_inline bool cell_is_doubleton()
			{
				return prev == next;
			}
		};
		static_assert(HasCellOperationsReset<PtrAddr>);
		static_assert(HasIsSingleton<PtrAddr>);
		static_assert(HasIsDoubleton<PtrAddr>);

		/**
		 * Encode a linked list cons cell as a pair of addresses (but present an
		 * interface in terms of pointers).  CHERI bounds on the returned
		 * pointers are inherited from the pointer to `this` cons cell.
		 */
		template<ptrdiff_t Offset>
		class OffsetPtrAddr
		{
			ptraddr_t prev, next;

			public:
			OffsetPtrAddr()
			{
				this->cell_reset();
			}

			/* Primops */

			__always_inline void cell_reset()
			{
				prev = next = CHERI::Capability{this}.address() - Offset;
			}

			__always_inline auto cell_next()
			{
				return ds::pointer::proxy::OffsetPtrAddr<Offset, OffsetPtrAddr>(
				  this, next);
			}

			__always_inline auto cell_prev()
			{
				return ds::pointer::proxy::OffsetPtrAddr<Offset, OffsetPtrAddr>(
				  this, prev);
			}

			/*
			 * Specialized implementations that may be slightly fewer
			 * instructions than the generic approaches in terms of the primops.
			 */

			__always_inline bool cell_is_singleton()
			{
				return prev == CHERI::Capability{this}.address() - Offset;
			}

			__always_inline bool cell_is_doubleton()
			{
				return prev == next;
			}
		};
		static_assert(HasCellOperationsReset<OffsetPtrAddr<0>>);
		static_assert(HasIsSingleton<OffsetPtrAddr<0>>);
		static_assert(HasIsDoubleton<OffsetPtrAddr<0>>);

	} // namespace cell

} // namespace ds::linked_list
