/* Intrusive double linked list for GDB, the GNU debugger.
   Copyright (C) 2021-2025 Free Software Foundation, Inc.

   This file is part of GDB.

   This program 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.

   This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.  */

#ifndef GDBSUPPORT_INTRUSIVE_LIST_H
#define GDBSUPPORT_INTRUSIVE_LIST_H

#define INTRUSIVE_LIST_UNLINKED_VALUE ((T *) -1)

/* A list node.  The elements put in an intrusive_list either inherit
   from this, or have a field of this type.  */
template<typename T>
class intrusive_list_node
{
public:
  bool is_linked () const noexcept
  {
    return next != INTRUSIVE_LIST_UNLINKED_VALUE;
  }

private:
  T *next = INTRUSIVE_LIST_UNLINKED_VALUE;
  T *prev = INTRUSIVE_LIST_UNLINKED_VALUE;

  template<typename T2, typename AsNode>
  friend struct intrusive_list_iterator;

  template<typename T2, typename AsNode>
  friend struct intrusive_list_reverse_iterator;

  template<typename T2, typename AsNode>
  friend struct intrusive_list;
};

/* Follows a couple types used by intrusive_list as template parameter to find
   the intrusive_list_node for a given element.  One for lists where the
   elements inherit intrusive_list_node, and another for elements that keep the
   node as member field.  */

/* For element types that inherit from intrusive_list_node.  */

template<typename T>
struct intrusive_base_node
{
  static intrusive_list_node<T> *as_node (T *elem) noexcept
  { return elem; }
};

/* For element types that keep the node as member field.  */

template<typename T, intrusive_list_node<T> T::*MemberNode>
struct intrusive_member_node
{
  static intrusive_list_node<T> *as_node (T *elem) noexcept
  { return &(elem->*MemberNode); }
};

/* Common code for forward and reverse iterators.  */

template<typename T, typename AsNode, typename SelfType>
struct intrusive_list_base_iterator
{
  using self_type = SelfType;
  using iterator_category = std::bidirectional_iterator_tag;
  using value_type = T;
  using pointer = T *;
  using const_pointer = const T *;
  using reference = T &;
  using const_reference = const T &;
  using difference_type = ptrdiff_t;
  using size_type = size_t;
  using node_type = intrusive_list_node<T>;

  /* Create an iterator pointing to ELEM.  */
  explicit intrusive_list_base_iterator (pointer elem) noexcept
    : m_elem (elem)
  {}

  /* Create a past-the-end iterator.  */
  intrusive_list_base_iterator () noexcept
    : m_elem (nullptr)
  {}

  reference operator* () const noexcept
  { return *m_elem; }

  pointer operator-> () const noexcept
  { return m_elem; }

  bool operator== (const self_type &other) const noexcept
  { return m_elem == other.m_elem; }

  bool operator!= (const self_type &other) const noexcept
  { return m_elem != other.m_elem; }

protected:
  static node_type *as_node (pointer elem) noexcept
  { return AsNode::as_node (elem); }

  /* A past-end-the iterator points to the list's head.  */
  pointer m_elem;
};

/* Forward iterator for an intrusive_list.  */

template<typename T, typename AsNode = intrusive_base_node<T>>
struct intrusive_list_iterator
  : public intrusive_list_base_iterator
	     <T, AsNode, intrusive_list_iterator<T, AsNode>>
{
  using base = intrusive_list_base_iterator
		 <T, AsNode, intrusive_list_iterator<T, AsNode>>;
  using self_type = typename base::self_type;
  using node_type = typename base::node_type;

  /* Inherit constructor and M_NODE visibility from base.  */
  using base::base;
  using base::m_elem;

  self_type &operator++ () noexcept
  {
    node_type *node = this->as_node (m_elem);
    m_elem = node->next;
    return *this;
  }

  self_type operator++ (int) noexcept
  {
    self_type temp = *this;
    node_type *node = this->as_node (m_elem);
    m_elem = node->next;
    return temp;
  }

  self_type &operator-- () noexcept
  {
    node_type *node = this->as_node (m_elem);
    m_elem = node->prev;
    return *this;
  }

  self_type operator-- (int) noexcept
  {
    self_type temp = *this;
    node_type *node = this->as_node (m_elem);
    m_elem = node->prev;
    return temp;
  }
};

/* Reverse iterator for an intrusive_list.  */

template<typename T, typename AsNode = intrusive_base_node<T>>
struct intrusive_list_reverse_iterator
  : public intrusive_list_base_iterator
	     <T, AsNode, intrusive_list_reverse_iterator<T, AsNode>>
{
  using base = intrusive_list_base_iterator
		 <T, AsNode, intrusive_list_reverse_iterator<T, AsNode>>;
  using self_type = typename base::self_type;

  /* Inherit constructor and M_NODE visibility from base.  */
  using base::base;
  using base::m_elem;
  using node_type = typename base::node_type;

  self_type &operator++ () noexcept
  {
    node_type *node = this->as_node (m_elem);
    m_elem = node->prev;
    return *this;
  }

  self_type operator++ (int) noexcept
  {
    self_type temp = *this;
    node_type *node = this->as_node (m_elem);
    m_elem = node->prev;
    return temp;
  }

  self_type &operator-- () noexcept
  {
    node_type *node = this->as_node (m_elem);
    m_elem = node->next;
    return *this;
  }

  self_type operator-- (int) noexcept
  {
    self_type temp = *this;
    node_type *node = this->as_node (m_elem);
    m_elem = node->next;
    return temp;
  }
};

/* An intrusive double-linked list.

   T is the type of the elements to link.  The type T must either:

    - inherit from intrusive_list_node<T>
    - have an intrusive_list_node<T> member

   AsNode is a type with an as_node static method used to get a node from an
   element.  If elements inherit from intrusive_list_node<T>, use the default
   intrusive_base_node<T>.  If elements have an intrusive_list_node<T> member,
   use:

     intrusive_member_node<T, &T::member>

   where `member` is the name of the member.  */

template <typename T, typename AsNode = intrusive_base_node<T>>
class intrusive_list
{
public:
  using value_type = T;
  using pointer = T *;
  using const_pointer = const T *;
  using reference = T &;
  using const_reference = const T &;
  using difference_type = ptrdiff_t;
  using size_type = size_t;
  using iterator = intrusive_list_iterator<T, AsNode>;
  using reverse_iterator = intrusive_list_reverse_iterator<T, AsNode>;
  using const_iterator = const intrusive_list_iterator<T, AsNode>;
  using const_reverse_iterator
    = const intrusive_list_reverse_iterator<T, AsNode>;
  using node_type = intrusive_list_node<T>;

  intrusive_list () noexcept = default;

  ~intrusive_list ()
  {
    clear ();
  }

  intrusive_list (intrusive_list &&other) noexcept
    : m_front (other.m_front),
      m_back (other.m_back)
  {
    other.m_front = nullptr;
    other.m_back = nullptr;
  }

  intrusive_list &operator= (intrusive_list &&other) noexcept
  {
    m_front = other.m_front;
    m_back = other.m_back;
    other.m_front = nullptr;
    other.m_back = nullptr;

    return *this;
  }

  void swap (intrusive_list &other) noexcept
  {
    std::swap (m_front, other.m_front);
    std::swap (m_back, other.m_back);
  }

  iterator iterator_to (reference value) noexcept
  {
    return iterator (&value);
  }

  const_iterator iterator_to (const_reference value) noexcept
  {
    return const_iterator (&value);
  }

  reference front () noexcept
  {
    gdb_assert (!this->empty ());
    return *m_front;
  }

  const_reference front () const noexcept
  {
    gdb_assert (!this->empty ());
    return *m_front;
  }

  reference back () noexcept
  {
    gdb_assert (!this->empty ());
    return *m_back;
  }

  const_reference back () const noexcept
  {
    gdb_assert (!this->empty ());
    return *m_back;
  }

  void push_front (reference elem) noexcept
  {
    intrusive_list_node<T> *elem_node = as_node (&elem);

    gdb_assert (elem_node->next == INTRUSIVE_LIST_UNLINKED_VALUE);
    gdb_assert (elem_node->prev == INTRUSIVE_LIST_UNLINKED_VALUE);

    if (this->empty ())
      this->push_empty (elem);
    else
      this->push_front_non_empty (elem);
  }

  void push_back (reference elem) noexcept
  {
    intrusive_list_node<T> *elem_node = as_node (&elem);

    gdb_assert (elem_node->next == INTRUSIVE_LIST_UNLINKED_VALUE);
    gdb_assert (elem_node->prev == INTRUSIVE_LIST_UNLINKED_VALUE);

    if (this->empty ())
      this->push_empty (elem);
    else
      this->push_back_non_empty (elem);
  }

  /* Inserts ELEM before POS.

     Returns an iterator to the inserted element.  */
  iterator insert (const_iterator pos, reference elem) noexcept
  {
    if (this->empty ())
      return this->push_empty (elem);

    if (pos == this->begin ())
      return this->push_front_non_empty (elem);

    if (pos == this->end ())
      return this->push_back_non_empty (elem);

    intrusive_list_node<T> *elem_node = as_node (&elem);
    pointer pos_elem = &*pos;
    intrusive_list_node<T> *pos_node = as_node (pos_elem);
    pointer prev_elem = pos_node->prev;
    intrusive_list_node<T> *prev_node = as_node (prev_elem);

    gdb_assert (elem_node->next == INTRUSIVE_LIST_UNLINKED_VALUE);
    gdb_assert (elem_node->prev == INTRUSIVE_LIST_UNLINKED_VALUE);

    elem_node->prev = prev_elem;
    prev_node->next = &elem;
    elem_node->next = pos_elem;
    pos_node->prev = &elem;

    return this->iterator_to (elem);
  }

  /* Move elements from LIST at the end of the current list.  */
  void splice (intrusive_list &&other) noexcept
  {
    if (other.empty ())
      return;

    if (this->empty ())
      {
	*this = std::move (other);
	return;
      }

    /* [A ... B] + [C ... D] */
    pointer b_elem = m_back;
    node_type *b_node = as_node (b_elem);
    pointer c_elem = other.m_front;
    node_type *c_node = as_node (c_elem);
    pointer d_elem = other.m_back;

    b_node->next = c_elem;
    c_node->prev = b_elem;
    m_back = d_elem;

    other.m_front = nullptr;
    other.m_back = nullptr;
  }

  void pop_front () noexcept
  {
    gdb_assert (!this->empty ());
    unlink_element (*m_front);
  }

  void pop_back () noexcept
  {
    gdb_assert (!this->empty ());
    unlink_element (*m_back);
  }

private:
  /* Push ELEM in the list, knowing the list is empty.  */
  iterator push_empty (reference elem) noexcept
  {
    gdb_assert (this->empty ());

    intrusive_list_node<T> *elem_node = as_node (&elem);

    gdb_assert (elem_node->next == INTRUSIVE_LIST_UNLINKED_VALUE);
    gdb_assert (elem_node->prev == INTRUSIVE_LIST_UNLINKED_VALUE);

    m_front = &elem;
    m_back = &elem;
    elem_node->prev = nullptr;
    elem_node->next = nullptr;

    return this->iterator_to (elem);
  }

  /* Push ELEM at the front of the list, knowing the list is not empty.  */
  iterator push_front_non_empty (reference elem) noexcept
  {
    gdb_assert (!this->empty ());

    intrusive_list_node<T> *elem_node = as_node (&elem);
    intrusive_list_node<T> *front_node = as_node (m_front);

    gdb_assert (elem_node->next == INTRUSIVE_LIST_UNLINKED_VALUE);
    gdb_assert (elem_node->prev == INTRUSIVE_LIST_UNLINKED_VALUE);

    elem_node->next = m_front;
    front_node->prev = &elem;
    elem_node->prev = nullptr;
    m_front = &elem;

    return this->iterator_to (elem);
  }

  /* Push ELEM at the back of the list, knowing the list is not empty.  */
  iterator push_back_non_empty (reference elem) noexcept
  {
    gdb_assert (!this->empty ());

    intrusive_list_node<T> *elem_node = as_node (&elem);
    intrusive_list_node<T> *back_node = as_node (m_back);

    gdb_assert (elem_node->next == INTRUSIVE_LIST_UNLINKED_VALUE);
    gdb_assert (elem_node->prev == INTRUSIVE_LIST_UNLINKED_VALUE);

    elem_node->prev = m_back;
    back_node->next = &elem;
    elem_node->next = nullptr;
    m_back = &elem;

    return this->iterator_to (elem);
  }

protected:
  void unlink_element (reference elem) noexcept
  {
    intrusive_list_node<T> *elem_node = as_node (&elem);

    gdb_assert (elem_node->prev != INTRUSIVE_LIST_UNLINKED_VALUE);
    gdb_assert (elem_node->next != INTRUSIVE_LIST_UNLINKED_VALUE);

    if (m_front == &elem)
      {
	gdb_assert (elem_node->prev == nullptr);
	m_front = elem_node->next;
      }
    else
      {
	gdb_assert (elem_node->prev != nullptr);
	intrusive_list_node<T> *prev_node = as_node (elem_node->prev);
	prev_node->next = elem_node->next;
      }

    if (m_back == &elem)
      {
	gdb_assert (elem_node->next == nullptr);
	m_back = elem_node->prev;
      }
    else
      {
	gdb_assert (elem_node->next != nullptr);
	intrusive_list_node<T> *next_node = as_node (elem_node->next);
	next_node->prev = elem_node->prev;
      }

    elem_node->next = INTRUSIVE_LIST_UNLINKED_VALUE;
    elem_node->prev = INTRUSIVE_LIST_UNLINKED_VALUE;
  }

public:
  /* Remove the element pointed by I from the list.  The element
     pointed by I is not destroyed.  */
  iterator erase (const_iterator i) noexcept
  {
    iterator ret = i;
    ++ret;

    unlink_element (*i);

    return ret;
  }

  /* Erase all the elements.  The elements are not destroyed.  */
  void clear () noexcept
  {
    while (!this->empty ())
      pop_front ();
  }

  /* Erase all the elements.  Disposer::operator()(pointer) is called
     for each of the removed elements.  */
  template<typename Disposer>
  void clear_and_dispose (Disposer disposer) noexcept
  {
    while (!this->empty ())
      {
	pointer p = &front ();
	pop_front ();
	disposer (p);
      }
  }

  bool empty () const noexcept
  {
    return m_front == nullptr;
  }

  iterator begin () noexcept
  {
    return iterator (m_front);
  }

  const_iterator begin () const noexcept
  {
    return const_iterator (m_front);
  }

  const_iterator cbegin () const noexcept
  {
    return const_iterator (m_front);
  }

  iterator end () noexcept
  {
    return {};
  }

  const_iterator end () const noexcept
  {
    return {};
  }

  const_iterator cend () const noexcept
  {
    return {};
  }

  reverse_iterator rbegin () noexcept
  {
    return reverse_iterator (m_back);
  }

  const_reverse_iterator rbegin () const noexcept
  {
    return const_reverse_iterator (m_back);
  }

  const_reverse_iterator crbegin () const noexcept
  {
    return const_reverse_iterator (m_back);
  }

  reverse_iterator rend () noexcept
  {
    return {};
  }

  const_reverse_iterator rend () const noexcept
  {
    return {};
  }

  const_reverse_iterator crend () const noexcept
  {
    return {};
  }

private:
  static node_type *as_node (pointer elem) noexcept
  {
    return AsNode::as_node (elem);
  }

  pointer m_front = nullptr;
  pointer m_back = nullptr;
};

#endif /* GDBSUPPORT_INTRUSIVE_LIST_H */
