/* common.h */

#ifndef COMMON__H
#define COMMON__H

/* COMMENT THIS LINE OUT TO TURN TRACING OFF */
#define DC_TRACING_ON

#include <LEDA/basic.h>
#include "types.h"

/* TRACING
   - trace levels are used to switch error/warning messages on or off.

   - there is a global trace level, and all descendant classes of common have a
   local trace level.
   
   - the macros dc_trace( trace_level ) { cerr << ...; ... } and 
   if_trc( condition, trace_level ) { ... } should be used to output error 
   messages.
   
   - exits or returns on errors must be outside the traces {}s.
   */
/* trace levels */
enum trace_level { TRACE_NONE = 0,
		   TRACE_ERROR = 1, /* only error messages */
		   TRACE_WARNING = 2, /* warnings too */
		   TRACE_FEW = 3, /* creations / deletions */
		   TRACE_SOME = 4, /* hierarchy changes / rehashes */
		   TRACE_MANY = 5, /* updates */
		   TRACE_ALL = 6 /* value_changes */ };

#ifdef DC_TRACING_ON

/* labels have local versions of set/get_trace_level */
static trace_level GLOBAL_TRACE = TRACE_FEW; /* initial trace level for all 
						instances and temporaries */
static trace_level TRACE_MAX = TRACE_SOME; /* traces above max are skipped no
					      matter what */
inline trace_level get_trace_level( void ) { return GLOBAL_TRACE; }
inline void set_trace_level( trace_level t_lvl ) { GLOBAL_TRACE = t_lvl; }
inline void set_trace_max( trace_level t_lvl ) { TRACE_MAX = t_lvl; }
inline trace_level get_trace_max( void ) { return TRACE_MAX; }

#define if_trc( cond, lvl ) if( ( ( lvl ) <= get_trace_level() ) && ( ( lvl ) <= get_trace_max() ) && ( cond ) )
#define dc_trace( lvl ) if( ( ( lvl ) <= get_trace_level() ) && ( ( lvl ) <= get_trace_max() ) )
#else 
#define if_trc( cond, lvl ) if( false )
#define dc_trace( lvl ) if( false )
inline trace_level get_trace_level( void ) { return -1; }
inline void set_trace_level( trace_level ) { ; }
inline trace_level get_trace_max( void ) { return -1; }
inline void set_trace_max( trace_level ) { ; }
#endif /* ifdef TRACING_ON */

typedef const string &cstring;

/* - dc_common is an abstract base class for dc_label.  it includes inline 
   member functions that allow generic pointer type checking for all derived 
   classes as well as tracing functions defined above */
class dc_common {
#ifdef DC_TRACING_ON
private:
  int trace_level;
#endif

protected:
  /* - valid has a different meaning for different classes.  for matrices and
     vectors it is false if a dimension is 0. it is not well used for other
     classes */
  bool valid;

public:
  dc_common( void ) { trace_level = GLOBAL_TRACE; }

  virtual const dc_type type( void ) const = 0;
  virtual const dc_type sub_type( void ) const { return type(); }
  virtual string type_string( void ) const = 0;

  bool is_type( dc_type t ) const { return ( t == type() ); }
  bool is_valid( void ) const { return valid; }

  virtual ostream &display( ostream &stream = cout ) = 0;

#ifdef DC_TRACING_ON
  void set_trace_level( int t_lvl ) { trace_level = t_lvl; }
  int get_trace_level( void ) const { return trace_level; }
#else
  void set_trace_level( int t_lvl ) const { ; }
  int get_trace_level( void ) const { ; }
#endif
};

#endif
