// set standard header -*-c++-*- 
// Copyright 2009-2020 IAR Systems AB.
#ifndef _DLIB5_SET_
#define _DLIB5_SET_

#ifndef _SYSTEM_BUILD
#pragma system_include
#endif

#include <dlib5/xtree>
_DLIB5_BEGIN

// TEMPLATE CLASS _Tset_traits
template<class _Kty,    // key/value type
         class _Pr,      // comparator predicate type
         class _Alloc,   // actual allocator type (should be value allocator)
         bool _Mfl>      // true if multiple equivalent keys are permitted
class _Tset_traits
{       // traits required to make _Tree behave like a set
public:
  typedef _Kty key_type;
  typedef _Kty value_type;
  typedef _Pr key_compare;
  typedef typename _Alloc::template rebind<value_type>::other
  allocator_type;
  typedef _POINTER_X(value_type, allocator_type) _ITptr;
  typedef _REFERENCE_X(value_type, allocator_type) _IReft;

  typedef typename _TypeUtil::_ParameterType<_Kty>::_Type _KeyParamTy;
  typedef typename _TypeUtil::_ParameterType<_Kty>::_Type _ValParamTy;

  enum
  {       // make multi parameter visible as an enumeration constant
    _Multi = _Mfl
  };

  _Tset_traits()
    : comp()
  {}      // construct with default comparator

  _Tset_traits(_Pr _Parg)
    : comp(_Parg)
  {}      // construct with specified comparator

  typedef key_compare value_compare;

  static _KeyParamTy _Kfn(_ValParamTy _Val)
  {       // extract key from element value
    return (_Val); 
  }

  _Pr comp;       // the comparator predicate for keys
};

// TEMPLATE CLASS set
template<class _Kty,
         class _Pr = less<_Kty>,
         class _Alloc = allocator<_Kty> >
class __memory_of(_Kty) set
  : public _Tree<_Tset_traits<_Kty, _Pr, _Alloc, false> >
{       // ordered red-black tree of key values, unique keys
public:
  typedef set<_Kty, _Pr, _Alloc> _Myt;
  typedef _Tree<_Tset_traits<_Kty, _Pr, _Alloc, false> > _Mybase;
  typedef _Kty key_type;
  typedef _Pr key_compare;
  typedef typename _Mybase::value_compare value_compare;
  typedef typename _Mybase::allocator_type allocator_type;
  typedef typename _Mybase::size_type size_type;
  typedef typename _Mybase::difference_type difference_type;
  typedef typename _Mybase::pointer pointer;
  typedef typename _Mybase::const_pointer const_pointer;
  typedef typename _Mybase::reference reference;
  typedef typename _Mybase::const_reference const_reference;
  typedef typename _Mybase::iterator iterator;
  typedef typename _Mybase::const_iterator const_iterator;
  typedef typename _Mybase::reverse_iterator reverse_iterator;
  typedef typename _Mybase::const_reverse_iterator
  const_reverse_iterator;
  typedef typename _Mybase::value_type value_type;

  typedef typename _Mybase::_ValParamTy _ValParamTy;
#pragma important_typedef
  typedef typename _Mybase::_Nodeptr _Nodeptr;

  set()
    : _Mybase(key_compare(), allocator_type())
  {}      // construct empty set from defaults

  explicit set(const key_compare& _Pred)
    : _Mybase(_Pred, allocator_type())
  {}      // construct empty set from comparator

  set(const key_compare& _Pred, const allocator_type& _Al)
    : _Mybase(_Pred, _Al)
  {}      // construct empty set from comparator and allocator

  template<class _Iter>
  set(_Iter _First,
      _ALLOW_ONLY_ITERATORS(_Iter, _Iter) _Last)
    : _Mybase(key_compare(), allocator_type())
  {       // construct set from [_First, _Last), defaults
    this->insert(_First, _Last);
  }

  template<class _Iter>
  set(_Iter _First, 
      _ALLOW_ONLY_ITERATORS(_Iter, _Iter) _Last, 
      const key_compare& _Pred)
    : _Mybase(_Pred, allocator_type())
  {       // construct set from [_First, _Last), comparator
    this->insert(_First, _Last);
  }

  template<class _Iter>
  set(_Iter _First, 
      _ALLOW_ONLY_ITERATORS(_Iter, _Iter) _Last, 
      const key_compare& _Pred,
      const allocator_type& _Al)
    : _Mybase(_Pred, _Al)
  {       // construct set from [_First, _Last), defaults, and allocator
    this->insert(_First, _Last);
  }
};

// TEMPLATE CLASS multiset
template<class _Kty,
         class _Pr = less<_Kty>,
         class _Alloc = allocator<_Kty> >
class __memory_of(_Kty) multiset
  : public _Tree<_Tset_traits<_Kty, _Pr, _Alloc, true> >
{       // ordered red-black tree of key values, non-unique keys
public:
  typedef multiset<_Kty, _Pr, _Alloc> _Myt;
  typedef _Tree<_Tset_traits<_Kty, _Pr, _Alloc, true> > _Mybase;
  typedef _Kty key_type;
  typedef _Pr key_compare;
  typedef typename _Mybase::value_compare value_compare;
  typedef typename _Mybase::allocator_type allocator_type;
  typedef typename _Mybase::size_type size_type;
  typedef typename _Mybase::difference_type difference_type;
  typedef typename _Mybase::pointer pointer;
  typedef typename _Mybase::const_pointer const_pointer;
  typedef typename _Mybase::reference reference;
  typedef typename _Mybase::const_reference const_reference;
  typedef typename _Mybase::iterator iterator;
  typedef typename _Mybase::const_iterator const_iterator;
  typedef typename _Mybase::reverse_iterator reverse_iterator;
  typedef typename _Mybase::const_reverse_iterator
  const_reverse_iterator;
  typedef typename _Mybase::value_type value_type;

  typedef typename _Mybase::_ValParamTy _ValParamTy;
#pragma important_typedef
  typedef typename _Mybase::_Nodeptr _Nodeptr;

  multiset()
    : _Mybase(key_compare(), allocator_type())
  {}      // construct empty set from defaults

  explicit multiset(const key_compare& _Pred)
    : _Mybase(_Pred, allocator_type())
  {}      // construct empty set from comparator

  multiset(const key_compare& _Pred, const allocator_type& _Al)
    : _Mybase(_Pred, _Al)
  {}      // construct empty set from comparator and allocator

  template<class _Iter>
  multiset(_Iter _First, _Iter _Last)
    : _Mybase(key_compare(), allocator_type())
  {       // construct set from [_First, _Last)
    _Mybase::insert(_First, _Last);
  }

  template<class _Iter>
  multiset(_Iter _First, _Iter _Last, const key_compare& _Pred)
    : _Mybase(_Pred, allocator_type())
  {       // construct set from [_First, _Last), comparator
    _Mybase::insert(_First, _Last);
  }

  template<class _Iter>
  multiset(_Iter _First, _Iter _Last, const key_compare& _Pred,
           const allocator_type& _Al)
    : _Mybase(_Pred, _Al)
  {       // construct set from [_First, _Last), comparator, and allocator
    _Mybase::insert(_First, _Last);
  }

  iterator insert(_ValParamTy _Val)
  {       // insert a key value
    return (_Mybase::insert(_Val).first); 
  }

  iterator insert(iterator _Where, _ValParamTy _Val)
  {       // insert a key value, with hint
    return (_Mybase::insert(_Where, _Val)); 
  }

  template<class _Iter>
  _ALLOW_ONLY_ITERATORS(_Iter, void)
  insert(_Iter _First, _Iter _Last)
  {
    _Mybase::insert(_First, _Last);
  }
};
_DLIB5_END
#endif /* _SET_ */

/*
 * Copyright (c) 1992-2009 by P.J. Plauger.  ALL RIGHTS RESERVED.
 * Consult your license regarding permissions and restrictions.
V5.04:0576 */
