/* Intrusive double linked list for GDB, the GNU debugger.
   Copyright (C) 2021-2023 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
  {
    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)
  { 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)
  { 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)
    : m_elem (elem)
  {}

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

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

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

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

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

protected:
  static node_type *as_node (pointer elem)
  { 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++ ()
  {
    node_type *node = this->as_node (m_elem);
    m_elem = node->next;
    return *this;
  }

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

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

  self_type operator-- (int)
  {
    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++ ()
  {
    node_type *node = this->as_node (m_elem);
    m_elem = node->prev;
    return *this;
  }

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

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

  self_type operator-- (int)
  {
    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 () = default;

  ~intrusive_list ()
  {
    clear ();
  }

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

  intrusive_list &operator= (intrusive_list &&other)
  {
    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)
  {
    std::swap (m_front, other.m_front);
    std::swap (m_back, other.m_back);
  }

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

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

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

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

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

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

  void push_front (reference elem)
  {
    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)
  {
    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.  */
  void insert (const_iterator pos, reference elem)
  {
    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;
  }

  /* Move elements from LIST at the end of the current list.  */
  void splice (intrusive_list &&other)
  {
    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 ()
  {
    gdb_assert (!this->empty ());
    erase_element (*m_front);
  }

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

private:
  /* Push ELEM in the list, knowing the list is empty.  */
  void push_empty (reference elem)
  {
    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;
  }

  /* Push ELEM at the front of the list, knowing the list is not empty.  */
  void push_front_non_empty (reference elem)
  {
    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;
  }

  /* Push ELEM at the back of the list, knowing the list is not empty.  */
  void push_back_non_empty (reference elem)
  {
    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;
  }

  void erase_element (reference elem)
  {
    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)
  {
    iterator ret = i;
    ++ret;

    erase_element (*i);

    return ret;
  }

  /* Erase all the elements.  The elements are not destroyed.  */
  void clear ()
  {
    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)
  {
    while (!this->empty ())
      {
	pointer p = &front ();
	pop_front ();
	disposer (p);
      }
  }

  bool empty () const
  {
    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)
  {
    return AsNode::as_node (elem);
  }

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

#endif /* GDBSUPPORT_INTRUSIVE_LIST_H */
