/*******************************************************************************
+
+  LEDA 3.5
+
+  graph_map.h
+
+  This file is part of the LEDA research version (LEDA-R) that can be 
+  used free of charge in academic research and teaching. Any commercial
+  use of this software requires a license which is distributed by the
+  LEDA Software GmbH, Postfach 151101, 66041 Saarbruecken, FRG
+  (fax +49 681 31104).
+
+  Copyright (c) 1991-1997  by  Max-Planck-Institut fuer Informatik
+  Im Stadtwald, 66123 Saarbruecken, Germany     
+  All rights reserved.
+ 
*******************************************************************************/
#ifndef LEDA_GRAPH_MAP_H
#define LEDA_GRAPH_MAP_H

#if !defined(LEDA_ROOT_INCL_ID)
#define LEDA_ROOT_INCL_ID 350055
#include <LEDA/REDEFINE_NAMES.h>
#endif


#include <LEDA/basic.h>

/*
#define LEDA_GRAPH_DATA
*/


//------------------------------------------------------------------------------
// graph_map:  base type for node/edge/face arrays and node/edge/face maps
//------------------------------------------------------------------------------


class graph_map {

friend class graph;

virtual void init_entry(GenPtr&)  const {}
virtual void clear_entry(GenPtr&) const {}
virtual void copy_entry(GenPtr&)  const {}
virtual void read_entry(istream&, GenPtr&) {}
virtual void write_entry(ostream&, GenPtr&) const {}

int           kind;  // node/edge/face
GenPtr*       table;
int           table_size;
graph*        g;
int           g_index;
list_item     g_loc;
GenPtr        def_entry; 

int  next_power(int) const;
void resize_table(int sz);


protected:

void init_table(GenPtr*, GenPtr*);
void init_table() { init_table(table,table+table_size); }
void clear_table();

void init_def_entry() { init_entry(def_entry); }
void clear_def_entry() { clear_entry(def_entry); }

public:

virtual int cmp_entry(GenPtr,GenPtr) const  { return 0; }

virtual int elem_type_id() const { return UNKNOWN_TYPE_ID; }


int     size() const { return table_size; }
GenPtr& access(int i)     { return table[i]; }
GenPtr  read(int i) const { return table[i]; }

void re_init_entry(node);
void re_init_entry(edge);
void re_init_entry(face);


#if defined(LEDA_GRAPH_DATA)

GenPtr& array_access(node v) const { return v->data[g_index]; }
GenPtr& array_access(edge e) const { return e->data[g_index]; }
GenPtr& array_access(face f) const { return f->data[g_index]; }

const GenPtr& array_read(node v) const { return array_access(v); }
const GenPtr& array_read(edge e) const { return array_access(e); }
const GenPtr& array_read(face f) const { return array_access(f); }

GenPtr& map_access(node v) const { return v->data[g_index]; }
GenPtr& map_access(edge e) const { return e->data[g_index]; }
GenPtr& map_access(face f) const { return f->data[g_index]; }

const GenPtr& map_read(node v) const { return map_access(v); }
const GenPtr& map_read(edge e) const { return map_access(e); }
const GenPtr& map_read(face f) const { return map_access(f); }


#else

GenPtr& array_access(node v) const
{ if (g_index > -1) 
    return v->data[g_index];
  else {
#if ! defined(LEDA_CHECKING_OFF)
   if ((index(v) >= table_size) || graph_of(v) != g) 
     error_handler(999,"node_array: illegal node");
#endif
   return table[index(v)];
  }
}


GenPtr& array_access(edge e) const
{ if (g_index > -1) 
    return e->data[g_index];
  else {
#if ! defined(LEDA_CHECKING_OFF)
   if ((index(e) >= table_size) || graph_of(e) != g) 
     error_handler(999,"edge_array: illegal edge");
#endif
   return table[index(e)];
  }
}


GenPtr& array_access(face f) const
{ if (g_index > -1) 
    return f->data[g_index];
  else {
#if ! defined(LEDA_CHECKING_OFF)
   if ((index(f) >= table_size) || graph_of(f) != g) 
     error_handler(999,"face_array: illegal face");
#endif
   return table[index(f)];
  }
}


const GenPtr& array_read(node v) const { return array_access(v); }
const GenPtr& array_read(edge e) const { return array_access(e); }
const GenPtr& array_read(face f) const { return array_access(f); }


GenPtr& map_access(node v)
{ 
#if ! defined(LEDA_CHECKING_OFF)
if (graph_of(v) != g) error_handler(999,"node_map: illegal node");
#endif
  if (g_index > -1) 
    return v->data[g_index]; 
  else
   { int i = index(v);
     if (i >= table_size) resize_table(next_power(i+1));
     return table[i]; 
    }
}

GenPtr& map_access(edge e)
{
#if ! defined(LEDA_CHECKING_OFF)
if (graph_of(e) != g) error_handler(999,"edge_map: illegal edge");
#endif
  if (g_index > -1) 
    return e->data[g_index]; 
  else
   { int i = index(e);
     if (i >= table_size) resize_table(next_power(i+1));
     return table[i]; 
    }
}

GenPtr& map_access(face f)
{
#if ! defined(LEDA_CHECKING_OFF)
if (graph_of(f) != g) error_handler(999,"face_map: illegal face");
#endif
  if (g_index > -1) 
    return f->data[g_index]; 
  else
   { int i = index(f);
     if (i >= table_size) resize_table(next_power(i+1));
     return table[i]; 
    }
}





const GenPtr& map_read(node v) const
{ 
#if ! defined(LEDA_CHECKING_OFF)
if (graph_of(v) != g) error_handler(999,"node_map: illegal node");
#endif
  if (g_index > -1) 
    return v->data[g_index]; 
  else
   { int i = index(v);
     if (i < table_size)
        return table[i];
     else
        return def_entry;
    }
}


const GenPtr& map_read(edge e) const
{
#if ! defined(LEDA_CHECKING_OFF)
if (graph_of(e) != g) error_handler(999,"edge_map: illegal edge");
#endif
  if (g_index > -1) 
    return e->data[g_index]; 
  else
   { int i = index(e);
     if (i < table_size)
        return table[i];
     else
        return def_entry;
    }
}


const GenPtr& map_read(face f) const
{
#if ! defined(LEDA_CHECKING_OFF)
if (graph_of(f) != g) error_handler(999,"face_map: illegal face");
#endif
  if (g_index > -1) 
    return f->data[g_index]; 
  else
   { int i = index(f);
     if (i < table_size)
        return table[i];
     else
        return def_entry;
    }
}

#endif


void init(const graph* G, int sz, int k);

graph_map(const graph* G, int sz, int k);

graph_map(const graph* G,int k);

graph_map(const graph_map&);

graph_map& operator=(const graph_map&);

virtual ~graph_map();

};



#if LEDA_ROOT_INCL_ID == 350055
#undef LEDA_ROOT_INCL_ID
#include <LEDA/UNDEFINE_NAMES.h>
#endif


#endif
