// This may look like C code, but it is really -*- C++ -*-
// 
// <copyright> 
//  
//  Copyright (c) 1996
//  Institute for Information Processing and Computer Supported New Media (IICM), 
//  Graz University of Technology, Austria. 
//  
// </copyright> 
// 
// 
// <file> 
// 
// Name:        bimap.h
// 
// Purpose:     
// 
// Created:     14 Jun 96   Joerg Faschingbauer
// 
// Modified:    
// 
// Description: 
// 
// $Id: bimap_t.h,v 1.4 1997/02/12 20:09:31 jfasch Exp $
// 
// $Log: bimap_t.h,v $
// Revision 1.4  1997/02/12 20:09:31  jfasch
// moved to utils
//
// Revision 1.3  1996/08/20 14:21:19  jfasch
// added "int count() const"
//
// Revision 1.2  1996/07/22 08:12:34  jfasch
// *** empty log message ***
//
// Revision 1.1  1996/07/08 13:16:36  jfasch
// Initial revision
//
// 
// </file> 
#ifndef hg_utils_bimap_t_h
#define hg_utils_bimap_t_h

#include "map_t.h"

#define BiMapsdeclare(Name,Left,Right)\
\
Mapsdeclare(name2(Name,LeftRight),Left,Right) ;\
Mapsdeclare(name2(Name,RightLeft),Right,Left) ;\
\
class Name {\
public:\
   int count() const ;\
   bool insert (const Left&, const Right&) ;\
   bool findLeft (const Left&, Right&) const ;\
   bool findRight (const Right&, Left&) const ;\
   bool findLeft (const Left&) const ;\
   bool findRight (const Right&) const ;\
   bool removeLeft (const Left&, Right&) ;\
   bool removeRight (const Right&, Left&) ;\
   bool removeLeft (const Left&) ;\
   bool removeRight (const Right&) ;\
\
private:\
   name2(Name,LeftRight) lr_ ;\
   name2(Name,RightLeft) rl_ ;\
} ;\
\
inline int Name :: count() const {\
   return lr_.count() ;\
}\
inline bool Name :: findLeft (const Left& l) const {\
   Right r ;\
   return findLeft (l, r) ;\
}\
inline bool Name :: findRight (const Right& r) const {\
   Left l ;\
   return findRight (r, l) ;\
}\
inline bool Name :: removeLeft (const Left& l) {\
   Right r ;\
   return removeLeft (l, r) ;\
}\
inline bool Name :: removeRight (const Right& r) {\
   Left l ;\
   return removeRight (r, l) ;\
}


#define BiMapsimplement(Name,Left,Right)\
\
Mapsimplement(name2(Name,LeftRight),Left,Right) ;\
Mapsimplement(name2(Name,RightLeft),Right,Left) ;\
\
bool Name :: insert (const Left& l, const Right& r) {\
   if (! lr_.insert (l, r))\
      return false ;\
   else if (! rl_.insert (r, l)) {\
      lr_.remove (l) ;\
      return false ;\
   }\
   else \
      return true ;\
}\
\
bool Name :: findLeft (const Left& l, Right& r) const {\
   int pos ;\
   if (! lr_.position (l, pos))\
      return false ;\
   else {\
      r = lr_[pos].to() ;\
      return true ;\
   }\
}\
\
bool Name :: findRight (const Right& r, Left& l) const {\
   int pos ;\
   if (! rl_.position (r, pos))\
      return false ;\
   else {\
      l = rl_[pos].to() ;\
      return true ;\
   }\
}\
\
bool Name :: removeLeft (const Left& l, Right& r) {\
   int posl ;\
   if (! lr_.position (l, posl))\
      return false ;\
   else {\
      int posr ;\
      if (! rl_.position (lr_[posl].to(), posr))\
         return false ;\
      else {\
         r = lr_[posl].to() ; \
         lr_.removePos (posl) ;\
         rl_.removePos (posr) ;\
         return true ;\
      }\
   }\
}\
\
bool Name :: removeRight (const Right& r, Left& l) {\
   int posr ;\
   if (! rl_.position (r, posr))\
      return false ;\
   else {\
      int posl ;\
      if (! lr_.position (rl_[posr].to(), posl))\
         return false ;\
      else {\
         l = rl_[posr].to() ;\
         rl_.removePos (posr) ;\
         lr_.removePos (posl) ;\
         return true ;\
      }\
   }\
}


#endif
