#ifndef cathlibcpp_listbase_H
#define cathlibcpp_listbase_H

// File:       listbase.h
// Author:     (c) Miles Sabin, 1997
// Purpose:    private header for list<T> non-template hoist base class


#ifndef included_stddef_H
#define included_stddef_H
#include <stddef.h>              // for ptrdiff_t, size_t
#endif

#ifndef cathlibcpp_bool_H
#include "bool.h"
#endif

#ifndef cathlibcpp_config_H
#include "config.h"
#endif

#ifndef cathlibcpp_newcasts_H
#include "newcasts.h"
#endif

#ifndef cathlibcpp_utility_H
#include "utility.h"
#endif


class HoistBinaryPredicateProtocol;
class HoistConstructorDestructorProtocol;
class HoistUnaryPredicateProtocol;


struct list_base_node
{
  list_base_node(list_base_node* prev, list_base_node* next)
    : prev_(prev),
      next_(next)
    {}

  list_base_node* prev_;
  list_base_node* next_;
};


class list_base
{
  friend bool operator==(list_base const& lhs, list_base const& rhs);
  friend bool operator< (list_base const& lhs, list_base const& rhs);

  public:

#   define size_type              size_t
#   define difference_type        ptrdiff_t

    // constructors
    list_base(HoistConstructorDestructorProtocol const& hoist_ctdt);
    list_base(HoistConstructorDestructorProtocol const& hoist_ctdt, size_type n, void const* value);
    list_base(HoistConstructorDestructorProtocol const& hoist_ctdt, list_base_node const* first, list_base_node const* last);
    list_base(HoistConstructorDestructorProtocol const& hoist_ctdt, void const* first, void const* last);
    list_base(list_base const& rhs);
    ~list_base();

    // accessors
    list_base_node const* begin() const
      { return control_node_->next_; }
    list_base_node const* end() const
      { return control_node_; }

    void const* front() const
      { return control_node_->next_+1; }
    void const* back() const
      { return control_node_->prev_+1; }

    bool empty() const
      { return size_ == 0; }
    size_type size() const
      { return size_; }
    size_type max_size() const;

    // mutators
    list_base& operator=(list_base const& rhs);

    void assign(list_base_node const* first, list_base_node const* last);
    void assign(void const* first, void const* last);
    void assign(size_type n, void const* t);

    list_base_node* begin()
      { return control_node_->next_; }
    list_base_node* end()
      { return control_node_; }

    void* front()
      { return control_node_->next_+1; }
    void* back()
      { return control_node_->prev_+1; }

    void push_front(void const* x);
    void push_back(void const* x);

    void pop_front();
    void pop_back();

    list_base_node* insert(list_base_node* position, void const* x);
    void insert(list_base_node* position, size_type n, void const* x);
    void insert(list_base_node* position, list_base_node const* first, list_base_node const* last);
    void insert(list_base_node* position, void const* first, void const* last);

    void erase(list_base_node* position);
    void erase(list_base_node* first, list_base_node* last);

    void swap(list_base& x);

    void clear();

    void splice(list_base_node* position, list_base& x);
    void splice(list_base_node* position, list_base& x, list_base_node* i);
    void splice(list_base_node* position, list_base& x, list_base_node* first, list_base_node* last);

    void remove_if(HoistUnaryPredicateProtocol const& hoist_pred);
    void unique(HoistBinaryPredicateProtocol const& hoist_pred);
    void merge(list_base& x, HoistBinaryPredicateProtocol const& hoist_comp);
    void sort(HoistBinaryPredicateProtocol const& hoist_comp);

    void reverse();

    void resize(size_type sz, void const* c);

    bool is_equal(HoistBinaryPredicateProtocol const& hoist_comparator, list_base const& rhs) const;
    bool is_less_than(HoistBinaryPredicateProtocol const& hoist_comparator, list_base const& rhs) const;

  private:

    void init();

    void transfer(list_base_node* position, list_base_node* first, list_base_node* last);

    list_base_node* control_node_;
    int size_;
    HoistConstructorDestructorProtocol const& hoist_ctdt_;

#   undef size_type
#   undef difference_type
};

#endif
