// =====================================================================
//  $Id: TEnvironmentVariableTable.cc,v 1.4 2004/03/07 10:30:34 goiwai Exp $
//  $Name: CLDAQ-1-14-03 $
//  $Log: TEnvironmentVariableTable.cc,v $
//  Revision 1.4  2004/03/07 10:30:34  goiwai
//  ROOTに組みこむためのおまじないマクロを埋めこみました。
//  全てにおいて完全に動作するわけではありません。
//
//  Revision 1.3  2003/10/06 16:38:26  goiwai
//  *** empty log message ***
//
//  Revision 1.2  2003/07/30 16:21:20  goiwai
//  ファイルにコミットログをつけることにしました.
//
// =====================================================================
#include "TEnvironmentVariableTable.hh"
#include "TRunCommandEnvironmentVariable.hh"

TEnvironmentVariableTable::TEnvironmentVariableTable()
  : theItemList(), theValueList(), theNumberOfEnvironments( 0 )
{
  ResetEnvironment();
}

TEnvironmentVariableTable::TEnvironmentVariableTable( const Tstring& rcfile )
  : theItemList(), theValueList(), theNumberOfEnvironments( 0 )
{
  ResetEnvironment();
  TRunCommandEnvironmentVariable rc( rcfile );
  TstringList readbuf;
  while ( rc.IsSuccess() ) {
    readbuf = rc.ReadLine();
    if ( rc.IsExecutable( readbuf ) ) {
      SetEnvironment( readbuf[ 0 ], readbuf[ 1 ] );
    }
  }
  rc.Close();
}

TEnvironmentVariableTable::TEnvironmentVariableTable( const TstringList& itemlist )
  : theItemList(), theValueList(), theNumberOfEnvironments( 0 )
{
  ResetEnvironment();
  for ( Tsize_t i = 0; i < itemlist.size(); i ++ ) {
    SetEnvironment( itemlist[ i ], "" );
  }
}

TEnvironmentVariableTable::TEnvironmentVariableTable( const TstringList& itemlist, const TstringList& valuelist )
  : theItemList(), theValueList(), theNumberOfEnvironments( 0 )
{
  ResetEnvironment();
  SetEnvironment( itemlist, valuelist );
}

TEnvironmentVariableTable::TEnvironmentVariableTable( const TEnvironmentVariableTable& right )
  : theItemList( right.theItemList ),
    theValueList( right.theValueList ),
    theNumberOfEnvironments( right.theNumberOfEnvironments )
{
  SetEnvironment( theItemList, theValueList );
}

TEnvironmentVariableTable::~TEnvironmentVariableTable()
{;}

const TEnvironmentVariableTable& TEnvironmentVariableTable::operator=( const TEnvironmentVariableTable& right )
{
  theItemList = right.theItemList;
  theValueList = right.theValueList;
  theNumberOfEnvironments = right.theNumberOfEnvironments;
  SetEnvironment( theItemList, theValueList );
  return *this;
}

Tbool TEnvironmentVariableTable::operator==( const TEnvironmentVariableTable& right ) const
{
  Tbool retval = Ttrue;
  retval &= ( theItemList == right.theItemList );
  retval &= ( theValueList == right.theValueList );
  return retval;
}

Tbool TEnvironmentVariableTable::operator!=( const TEnvironmentVariableTable& right ) const
{
  Tbool retval = Tfalse;
  retval |= ( theItemList != right.theItemList );
  retval |= ( theValueList != right.theValueList );
  return retval;
}

Tostream& operator<<( Tostream& tos, const TEnvironmentVariableTable& right )
{
  Tint nenv = right.theNumberOfEnvironments;
  for ( Tint i = 0; i < nenv; i ++ ) {
    tos << right.theItemList[ i ] << "=" << right.theValueList[ i ];
    if ( i != nenv - 1 )
      tos << Tendl;
  }
  tos << Tflush;
  return tos;
}

Tstring TEnvironmentVariableTable::GetEnvironmentValue( const Tstring& item ) const
{
  Tstring value = "";
  Tint pos = FindEnvironmentItem( item );
  if ( pos >= 0 ) {
    value = theValueList[ pos ];
  }
  return value;
}

Tstring TEnvironmentVariableTable::GetEnvironmentValue( Tint row ) const
{
  Tstring value = "";
  if ( ! theValueList.empty() && row < (Tint)theValueList.size() ) {
    value = theValueList[ row ];
  }
  return value;
}

Tstring TEnvironmentVariableTable::GetEnvironmentItem( Tint row ) const
{
  Tstring item = "";
  if ( ! theItemList.empty() && row < (Tint)theItemList.size() ) {
    item = theItemList[ row ];
  }
  return item;
}

Tint TEnvironmentVariableTable::FindEnvironmentItem( const Tstring& item ) const
{
  for ( Tint i = 0; i < (Tint)theItemList.size(); i ++ ) {
    if ( theItemList[ i ] == item ) {
      return i;
    }
  }
  return tNotFound;
}

Tint TEnvironmentVariableTable::FindEnvironmentValue( const Tstring& value ) const
{
  for ( Tint i = 0; i < (Tint)theValueList.size(); i ++ ) {
    if ( theValueList[ i ] == value ) {
      return i;
    }
  }
  return tNotFound;
}

Tbool TEnvironmentVariableTable::HasEnvironmentItem( const Tstring& item ) const
{
  if ( FindEnvironmentItem( item ) == tNotFound ) {
    return Tfalse;
  } else {
    return Ttrue;
  }
}

Tbool TEnvironmentVariableTable::HasEnvironmentValue( const Tstring& value ) const
{
  if ( FindEnvironmentValue( value ) == tNotFound ) {
    return Tfalse;
  } else {
    return Ttrue;
  }
}

Tvoid TEnvironmentVariableTable::UnsetEnvironment( const Tstring& item )
{
  Tint pos = FindEnvironmentItem( item );
  if ( pos != tNotFound ) {
    unsetenv( theItemList[ pos ].c_str() );
    theItemList.erase( theItemList.begin() + pos );
    theValueList.erase( theValueList.begin() + pos );
    theNumberOfEnvironments --;
  }
  return;
}

Tvoid TEnvironmentVariableTable::UnsetEnvironment( const TstringList& item )
{
  for ( Tsize_t i = 0; i < item.size(); i ++ ) {
    UnsetEnvironment( item[ i ] );
  }
  return;
}

Tvoid TEnvironmentVariableTable::SetEnvironment( const Tstring& item, const Tstring& value )
{
  Tint pos = FindEnvironmentItem( item );
  if ( pos == tNotFound ) {
    theItemList.push_back( item );
    theValueList.push_back( value );
    theNumberOfEnvironments ++;
  } else {
    theValueList[ pos ] = value;
  }
  if ( setenv( item.c_str(), value.c_str(), 1 ) < 0 ) {
    Tcerr << "TEnvironmentVariableTable::SetEnvironment: no space." << Tendl;
  }
  return;
}

Tvoid TEnvironmentVariableTable::SetEnvironment( const TstringList& item, const TstringList& value )
{
  if ( item.size() != value.size() ) {
    Tcerr << "TEnvironmentVariableTable::SetEnvironment: not match." << Tendl;
    return;
  }
  for ( Tsize_t i = 0; i < item.size(); i ++ ) {
    SetEnvironment( item[ i ], value[ i ] );
  }
  return;
}

Tvoid TEnvironmentVariableTable::SetEnvironment( const Tstring& rcfile )
{
  TRunCommandEnvironmentVariable rc( rcfile );
  TstringList readbuf;
  while ( rc.IsSuccess() ) {
    readbuf = rc.ReadLine();
    if ( rc.IsExecutable( readbuf ) ) {
      SetEnvironment( readbuf[ 0 ], readbuf[ 1 ] );
    }
  }
  rc.Close();
  return;
}

Tvoid TEnvironmentVariableTable::ClearEnvironment()
{
  for ( Tsize_t i = 0; i < theItemList.size(); i ++ ) {
    unsetenv( theItemList[ i ].c_str() );
  }
  theItemList.clear();
  theValueList.clear();
  theNumberOfEnvironments = 0;
  return;
}

Tvoid TEnvironmentVariableTable::ResetEnvironment()
{
  theItemList.clear();
  theValueList.clear();
  Tchar** env = environ;
  while ( *env != 0 ) {
    Tstring item = *env;
    Tsize_t eqpos = item.find( "=" );
    Tstring value = item.substr( eqpos + 1, item.size() - eqpos );
    item.erase( item.begin() + eqpos, item.end() );
    theItemList.push_back( item );
    theValueList.push_back( value );
    env ++;
  }
  if ( theItemList.size() != theValueList.size() ) {
    Tcerr << "TEnvironmentVariableTable::ResetEnvironment: invalid table." << Tendl;
  }
  theNumberOfEnvironments = (Tint)theItemList.size();
  return;
}

Tint TEnvironmentVariableTable::GetIntegerValue( const Tstring& item ) const
{
  // should check string.
  // isdigit()
  // isxdigit()
  return strtol( GetEnvironmentValue( item ).c_str(), 0, 0 );
}

Tdouble TEnvironmentVariableTable::GetDoubleValue( const Tstring& item ) const
{
  // should check string.
  // isdigit()
  // isxdigit()
  return strtod( GetEnvironmentValue( item ).c_str(), 0 );
}

#ifdef __CLDAQ_ROOT_DLL
    ClassImp(TEnvironmentVariableTable)
#endif
