// This may look like C code, but it is really -*- C++ -*-
/* 
Copyright (C) 1988 Free Software Foundation
    written by Doug Lea (dl@rocky.oswego.edu)

This file is part of the GNU C++ Library.  This library is free
software; you can redistribute it and/or modify it under the terms of
the GNU Library General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your
option) any later version.  This library 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 Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*/


#ifndef _PtrPtrSplayMap_h
#ifdef __GNUG__
#pragma interface
#endif
#define _PtrPtrSplayMap_h 1

#include "PMap.h"

#ifndef _PtrPtrSplayNode
#define _PtrPtrSplayNode 1

struct PtrPtrSplayNode
{
  PtrPtrSplayNode*   lt;
  PtrPtrSplayNode*   rt;
  PtrPtrSplayNode*   par;
  Ptr                item;
  Ptr                cont;
                     PtrPtrSplayNode(Ptr  h, Ptr  c, 
                                     PtrPtrSplayNode* l=0, 
                                     PtrPtrSplayNode* r=0);
                  ~PtrPtrSplayNode();
};


inline PtrPtrSplayNode::PtrPtrSplayNode(Ptr  h, Ptr  c, 
                                        PtrPtrSplayNode* l, 
                                        PtrPtrSplayNode* r)
     :item(h), cont(c), lt(l), rt(r), par(0) {}

inline PtrPtrSplayNode::~PtrPtrSplayNode() {}

typedef PtrPtrSplayNode* PtrPtrSplayNodePtr;

#endif

class PtrPtrSplayMap : public PtrPtrMap
{
protected:
  PtrPtrSplayNode*   root;

  PtrPtrSplayNode*   leftmost();
  PtrPtrSplayNode*   rightmost();
  PtrPtrSplayNode*   pred(PtrPtrSplayNode* t);
  PtrPtrSplayNode*   succ(PtrPtrSplayNode* t);
  void               _kill(PtrPtrSplayNode* t);
  PtrPtrSplayNode*   _copy(PtrPtrSplayNode* t);

public:
               PtrPtrSplayMap(Ptr  dflt);
               PtrPtrSplayMap(PtrPtrSplayMap& a);
               ~PtrPtrSplayMap();

  Ptr&          operator [] (Ptr  key);

  void          del(Ptr  key);

  Pix           first();
  void          next(Pix& i);
  Ptr&          key(Pix i);
  Ptr&          contents(Pix i);

  Pix           seek(Ptr  key);
  int           contains(Ptr  key);

  void          clear(); 

  Pix           last();
  void          prev(Pix& i);

  int           OK();
};


inline PtrPtrSplayMap::~PtrPtrSplayMap()
{
  _kill(root);
}

inline PtrPtrSplayMap::PtrPtrSplayMap(Ptr  dflt) :PtrPtrMap(dflt)
{
  root = 0;
}

inline PtrPtrSplayMap::PtrPtrSplayMap(PtrPtrSplayMap& b) :PtrPtrMap(b.def)
{
  count = b.count;
  root = _copy(b.root);
}

inline Pix PtrPtrSplayMap::first()
{
  return Pix(leftmost());
}

inline Pix PtrPtrSplayMap::last()
{
  return Pix(rightmost());
}

inline void PtrPtrSplayMap::next(Pix& i)
{
  if (i != 0) i = Pix(succ((PtrPtrSplayNode*)i));
}

inline void PtrPtrSplayMap::prev(Pix& i)
{
  if (i != 0) i = Pix(pred((PtrPtrSplayNode*)i));
}

inline Ptr& PtrPtrSplayMap::key (Pix i)
{
  if (i == 0) error("null Pix");
  return ((PtrPtrSplayNode*)i)->item;
}

inline Ptr& PtrPtrSplayMap::contents (Pix i)
{
  if (i == 0) error("null Pix");
  return ((PtrPtrSplayNode*)i)->cont;
}

inline void PtrPtrSplayMap::clear()
{
  _kill(root);
  count = 0;
  root = 0;
}

inline int PtrPtrSplayMap::contains(Ptr  key)
{
  return seek(key) != 0;
}

#endif
