/*
    C++ Mesh Generation Library
    Copyright (c) 2000echet <eric at bechet dot ca>

    This file is part of the C++ Mesh Generation Library.

    See the NOTICE & LICENSE files for conditions.
*/
// Projet de mailleur generique
// Fichier "value_field.h"
// Structures de representation de champs physiques
// Compilateur : Microsoft VisualC6 / GNU

//-------------------------------------------------------------------
#ifndef VALUEFIELDH
#define VALUEFIELDH
//--------------------------------------------------------------------


#include "mesh_const.h"

#ifdef USE_HASH_TABLE
#include <hash_map>
#endif
#include <map>


using namespace std;


///
class generic_type
{
///
  bool is_set;
public:
///
  generic_type ( void ) :is_set ( false ) {};
///
  generic_type ( bool s ) :is_set ( s ) {};
///
  const bool get ( void ) const
  {
    return is_set;
  };
///
  void set ( void )
  {
    is_set=true;
  };
///
  void unset ( void )
  {
    is_set=false;
  };
};

///
class scalar_type : public generic_type
{
///
  float value;
public:
///
  scalar_type ( void ) :generic_type(),value ( 0.0 ) {}
///
  scalar_type ( float v,bool s=false ) :generic_type ( s ),value ( v ) {}
///
  const bool get ( float &v ) const
  {
    v=value;
    return generic_type::get();
  }
///
  void set ( float v )
  {
    value=v;
    generic_type::set();
  }
///
  void unset ( float v )
  {
    value=v;
    generic_type::unset();
  }
///
  void unset ( void )
  {
    generic_type::unset();
    value=0.0;
  }
};

///
class vector_type : public generic_type
{
///
  float value[3];
public:
///
  vector_type ( void ) :generic_type()
  {
    for ( int i ( 0 ); i<3; ++i )
    {
      value[i]=0.0;
    }
  }
///
  vector_type ( const float v[],bool s=false ) :generic_type ( s )
  {
    for ( int i ( 0 ); i<3; ++i )
    {
      value[i]=v[i];
    }
  }
///
  const bool get ( float v[] ) const
  {
    for ( int i ( 0 ); i<3; ++i )
    {
      v[i]=value[i];
    }

    return generic_type::get();
  }
///
  void set ( const float v[] )
  {
    for ( int i ( 0 ); i<3; ++i )
    {
      value[i]=v[i];
    }

    generic_type::set();
  }
///
  void unset ( const float v[] )
  {
    for ( int i ( 0 ); i<3; ++i )
    {
      value[i]=v[i];
    }

    generic_type::unset();
  }
///
  void unset ( void )
  {
    generic_type::unset();

    for ( int i ( 0 ); i<3; ++i )
    {
      value[i]=0.0;
    }
  }
};

///
class tensor_type : public generic_type
{
///
  float value[3][3];
public:
///
  tensor_type ( void ) :generic_type()
  {
    for ( int i ( 0 ); i<3; ++i ) for ( int j ( 0 ); j<3; ++j )
      {
        value[i][j]=0.0;
      }
  }
///
  tensor_type ( const float v[3][3],bool s=false ) :generic_type ( s )
  {
    for ( int i ( 0 ); i<3; ++i ) for ( int j ( 0 ); j<3; ++j )
      {
        value[i][j]=v[i][j];
      }
  }
///
  const bool get ( float v[3][3] ) const
  {
    for ( int i ( 0 ); i<3; ++i ) for ( int j ( 0 ); j<3; ++j )
      {
        v[i][j]=value[i][j];
      }

    return generic_type::get();
  }
///
  void set ( const float v[3][3] )
  {
    for ( int i ( 0 ); i<3; ++i ) for ( int j ( 0 ); j<3; ++j )
      {
        value[i][j]=v[i][j];
      }

    generic_type::set();
  }
///
  void unset ( const float v[3][3] )
  {
    for ( int i ( 0 ); i<3; ++i ) for ( int j ( 0 ); j<3; ++j )
      {
        value[i][j]=v[i][j];
      }

    generic_type::unset();
  }
///
  void unset ( void )
  {
    generic_type::unset();

    for ( int i ( 0 ); i<3; ++i ) for ( int j ( 0 ); j<3; ++j )
      {
        value[i][j]=0.0;
      }
  }
};



/** template used to store any kind of value based on a key K
K might be of any type (including and especially integral types)
however there might be some trouble to define a hash function
please see "base_entities.h" for some hint*/
template<class T,class K> class ValueField
{
public:

#ifndef USE_HASH_TABLE
///
  typedef map<K,T> container_type;
#endif
#ifdef USE_HASH_TABLE
///
  typedef hash_map<K,T> container_type;
#endif
///
  typedef container_type::iterator iterator_type;
///
  typedef container_type::const_iterator const_iterator_type;

private:
///
  container_type container;
///
  int type;
///
  T defaultvalue;
public:

///
  ValueField() : type ( 0 )
  {
  }

///
  ValueField ( const ValueField<T,K> &other )
  {
    container=other.container;
    type=other.type;
    defaultvalue=other.defaultvalue;
  }

///
  const_iterator_type begin ( void ) const
  {
    return container.begin();
  }

///
  const_iterator_type end ( void ) const
  {
    return container.end();
  }

///
  iterator_type begin ( void )
  {
    return container.begin();
  }

///
  iterator_type end ( void )
  {
    return container.end();
  }

///
  virtual ~ValueField()
  {
  }

///
  void operator= ( const ValueField<T,K> &other )
  {
    container=other.container;
    type=other.type;
    defaultvalue=other.defaultvalue;
  }


/// retourne false et default_value si non trouve
  virtual bool GetValue ( T &value, K key ) const
  {
    const_iterator_type it ( container.find ( key ) );

    if ( it==container.end() )
    {
      value=defaultvalue;
      return false;
    }
    else
    {
      value= ( ( *it ).second );
      return true;
    }
  }

/// comme getvalue, mais pas de booleen
  const T& operator[] ( K key ) const
  {
    const_iterator_type it ( container.find ( key ) );

    if ( it==container.end() )
    {
      return ( defaultvalue );
    }
    else
    {
      return ( ( *it ).second );
    }
  }

///  attention, insere si key non trouve !
  T& Value ( K key )
  {
    iterator_type it ( container.find ( key ) );

    if ( it!=container.end() )
    {
      return ( ( *it ).second );
    }
    else
    {
      pair<iterator_type,bool> result ( container.insert ( container_type::value_type ( key,defaultvalue ) ) );
      return ( *result.first ).second;
    }
  }


///
  const T& GetDefaultValue()
  {
    return defaultvalue;
  }

///
  int GetType()
  {
    return type;
  }

///
  void SetDefaultValue ( T value )
  {
    defaultvalue = value;
  }

///
  void SetType ( int t )
  {
    type=t;
  }

///
  bool SetValue ( T& value,K key )
  {
    pair<iterator_type,bool> result ( container.insert ( container_type::value_type ( key,value ) ) );

    if ( !result.second )
    {
      ( *result.first ).second=value;
    }

    return result.second;
  }

///
  bool DeleteValue ( T& value,K key )
  {
    iterator_type it ( container.find ( key ) );

    if ( it==container.end() )
    {
      return ( false );
    }
    else
    {
      value= ( *it ).second;
      container.erase ( it );
      return ( true );
    }
  }

///
  bool DeleteValue ( K key )
  {
    iterator_type it ( container.find ( key ) );

    if ( it==container.end() )
    {
      return ( false );
    }
    else
    {
      container.erase ( it );
      return ( true );
    }
  }

///
  void Clear ( void )
  {
    container.clear();
  }

};





#endif

 
