Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

GenericValues.C

Go to the documentation of this file.
00001 /*
00002 Copyright (c) 2000-2002, Jelle Kok, University of Amsterdam
00003 All rights reserved.
00004 
00005 Redistribution and use in source and binary forms, with or without 
00006 modification, are permitted provided that the following conditions are met:
00007 
00008 1. Redistributions of source code must retain the above copyright notice, this 
00009 list of conditions and the following disclaimer. 
00010 
00011 2. Redistributions in binary form must reproduce the above copyright notice, 
00012 this list of conditions and the following disclaimer in the documentation 
00013 and/or other materials provided with the distribution. 
00014 
00015 3. Neither the name of the University of Amsterdam nor the names of its 
00016 contributors may be used to endorse or promote products derived from this 
00017 software without specific prior written permission. 
00018 
00019 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
00020 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
00021 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
00022 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 
00023 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
00024 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
00025 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
00026 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 
00027 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
00028 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029 */
00054 #include "GenericValues.h"
00055 #include "Parse.h"           // needed for 'gotoFirstNonSpace'
00056 #include <stdio.h>           // needed for 'sprintf'
00057 #include <stdlib.h>          // needed for 'free'
00058 #include <string.h>          // needed for 'strdup'
00059 #include <ctype.h>           // needed for 'isdigit'
00060 #include <fstream.h>         // needed for 'ifstream'
00061 
00062 /******************************************************************************/
00063 /********************   CLASS GENERICVALUET   *********************************/
00064 /******************************************************************************/
00065 
00075 GenericValueT::GenericValueT( const char *str, void *vAddr, GenericValueKind t )
00076 {
00077   m_strName  = strdup( str ); // strdup needed to allocate right amount of memory
00078   m_vAddress = vAddr;
00079   m_type     = t;
00080 }
00081 
00084 GenericValueT::~GenericValueT( )
00085 {
00086   if( m_strName )
00087     free( ( char * ) m_strName );
00088 }
00089 
00093 const char* GenericValueT::getName ( )
00094 {
00095   return ( m_strName );
00096 }
00097 
00105 bool GenericValueT::setValue( const char *strValue )
00106 {
00107   bool bReturn = true, b = false;
00108 
00109   // determine the generic type associated with this GenericValueT
00110   // object and apply the correct conversion of the string argument
00111   switch( m_type )
00112   {
00113     case GENERIC_VALUE_DOUBLE:
00114       *( double * ) m_vAddress = atof( strValue ? strValue : 0 );
00115       break;
00116     case GENERIC_VALUE_STRING:
00117       strcpy( ( char * ) m_vAddress, strValue );
00118       break;
00119     case GENERIC_VALUE_BOOLEAN:
00120       b = false;
00121       if( !strValue )
00122         ;
00123       else if( isdigit( strValue[ 0 ] ) )
00124         b = atoi( strValue ? strValue : 0 );
00125       else if( strcasecmp( strValue, "on"  ) == 0 ||
00126                strcasecmp( strValue, "true") == 0 ||
00127                strcasecmp( strValue, "yes" ) == 0 )
00128         b = true;
00129 
00130       *( bool * ) m_vAddress = ( b == true ) ? true : false;
00131       break;
00132     case GENERIC_VALUE_INTEGER:
00133       *( int * ) m_vAddress = atoi( strValue ? strValue : 0 );
00134       break;
00135     default:
00136       bReturn = false;
00137   }
00138 
00139   return ( bReturn );
00140 }
00141 
00151 char* GenericValueT::getValue( char *strValue )
00152 {
00153   // determine the generic type associated with this GenericValueT
00154   // object and apply the correct conversion into a string
00155   switch( m_type )
00156   {
00157     case GENERIC_VALUE_DOUBLE:
00158       sprintf( strValue, "%2f", *( double * ) m_vAddress );
00159       break;
00160     case GENERIC_VALUE_STRING:
00161       sprintf( strValue, "%s", *( char ** ) m_vAddress );
00162       break;
00163     case GENERIC_VALUE_BOOLEAN:
00164       sprintf( strValue, "%d", *( int * ) m_vAddress );
00165       break;
00166     case GENERIC_VALUE_INTEGER:
00167       sprintf( strValue, "%d", *( int * ) m_vAddress );
00168       break;
00169     default:
00170       *strValue = '\0';
00171   }
00172 
00173   return ( strValue );
00174 }
00175 
00184 void GenericValueT::show( ostream& out, const char *strSeparator )
00185 {
00186   // write the name associated with the variable in this GenericValueT
00187   // object followed by the separator to the specified output stream
00188   out << m_strName << strSeparator;
00189 
00190   // determine the generic type associated with this GenericValueT
00191   // object and write the correct value to the specified output stream
00192   switch( m_type )
00193   {
00194     case GENERIC_VALUE_DOUBLE:
00195       out << *( double * ) m_vAddress;
00196       break;
00197     case GENERIC_VALUE_STRING:
00198       out << ( char * ) m_vAddress;
00199       break;
00200     case GENERIC_VALUE_BOOLEAN:
00201       out << ( ( *( bool * ) m_vAddress == true ) ? "true" : "false");
00202       break;
00203     case GENERIC_VALUE_INTEGER:
00204       out << *( int * ) m_vAddress;
00205       break;
00206     default:
00207       break;
00208   }
00209 
00210   out << endl;
00211 }
00212 
00213 
00214 /******************************************************************************/
00215 /********************   CLASS GENERICVALUES   *********************************/
00216 /******************************************************************************/
00217 
00224 GenericValues::GenericValues( char *strName, int iMaxValues )
00225 {
00226   m_iValuesTotal = 0;   // total number of values in collection is set to zero
00227 
00228   if( strName )       // set the name of the collection
00229     m_strClassName = strdup( strName );
00230 
00231   m_iMaxGenericValues = iMaxValues;
00232 
00233   // a GenericValues object is a collection of GenericValueT objects
00234   m_values = new GenericValueT*[ iMaxValues ];
00235 }
00236 
00239 GenericValues::~GenericValues( void )
00240 {
00241   for( int i = 0 ; i < getValuesTotal( ) ; i++ )
00242     delete m_values[ i ];
00243   delete m_values;
00244 
00245   if( m_strClassName )
00246     free( m_strClassName );
00247 }
00248 
00252 char* GenericValues::getClassName( )
00253 {
00254   return ( m_strClassName );
00255 }
00256 
00259 int GenericValues::getValuesTotal( )
00260 {
00261   return ( m_iValuesTotal );
00262 }
00263 
00273 bool GenericValues::addSetting( const char *strName, void *vAddress,
00274                                                      GenericValueKind type )
00275 {
00276   if( getValuePtr( strName ) )               // setting already installed
00277   {
00278     cerr << "Setting '" << strName << "' already installed." << endl;
00279     return false;
00280   }
00281   if( m_iValuesTotal == m_iMaxGenericValues )    // buffer is full
00282   {
00283     cerr << "GenericValues::addSetting buffer for " << m_strClassName <<
00284             " is full (cannot add '" << strName << "')" << endl;
00285     return false;
00286   }
00287 
00288   m_values[ m_iValuesTotal++ ] = new GenericValueT( strName, vAddress, type );
00289 
00290   return ( true );
00291 }
00292 
00301 GenericValueT* GenericValues::getValuePtr( const char *strName )
00302 {
00303   GenericValueT *ptr = 0;
00304 
00305   // search through the collection for a GenericValueT object of which the name
00306   // associated with the variable matches the argument passed to the method
00307   for( int i = 0 ; i < getValuesTotal( ) ; i++ )
00308   {
00309     if( strcmp( m_values[ i ]->getName( ), strName ) == 0 )
00310     {
00311       ptr = m_values[ i ];
00312       break;
00313     }
00314   }
00315 
00316   return ( ptr );
00317 }
00318 
00332 char* GenericValues::getValue( const char *strName, char *strValue )
00333 {
00334   GenericValueT *parptr;
00335 
00336   parptr = getValuePtr( strName );
00337 
00338   if( parptr )
00339     strValue = parptr->getValue( strValue );   // this method returns a string
00340   else
00341     strValue[ 0 ] = '\0';
00342 
00343   return ( strValue );
00344 }
00345 
00355 bool GenericValues::setValue( const char *strName, const char *strValue )
00356 {
00357   bool bReturn = false;
00358   GenericValueT *parptr;
00359 
00360   parptr = getValuePtr( strName );
00361 
00362   if( parptr )
00363     bReturn = parptr->setValue( strValue ); // string is converted to right type
00364 
00365   return ( bReturn );
00366 }
00367 
00379 bool GenericValues::readValues( const char *strFile, const char *strSeparator )
00380 {
00381   ifstream in( strFile );
00382 
00383   if( !in )
00384   {
00385     cerr << "(GenericValues::readValues) Could not open file '" <<
00386     strFile << "'" << endl;
00387     return ( false );
00388   }
00389 
00390   bool  bReturn = true;
00391   char  strLine[ 256 ], strName[ 100 ], strValue[ 100 ];
00392   char* c;
00393   int   iLineNr = 0;
00394 
00395   // read each line in the configuration file and store the values
00396   while( in.getline( strLine, sizeof( strLine ) ) )
00397   {
00398     iLineNr++;
00399 
00400     // skip comment lines and empty lines; " #" is for server.conf version 7.xx
00401     if( !( strLine[ 0 ] == '\n' ||
00402            strLine[ 0 ] == '#'  ||
00403            strLine[ 0 ] == '\0' ||
00404            ( strlen( strLine ) > 1 &&
00405              strLine[ 0 ] == ' ' &&
00406              strLine[ 1 ] == '#' ) ) )
00407     {
00408       // convert all characters belonging to the separator to spaces
00409       if( strSeparator && ( c = strstr( strLine, strSeparator ) ) != NULL )
00410         for( size_t i = 0; i < strlen( strSeparator ); i++ )
00411           *( c + i ) = ' ';
00412 
00413       // read the name and value on this line and store the value
00414       if( !( sscanf( strLine, "%s%s", strName, strValue ) == 2 &&
00415              setValue( strName, strValue ) ) )
00416       {
00417         bReturn = false;
00418         cerr << "(GenericValues::readValues) '" << strFile << "' linenr "
00419              << iLineNr << ",  error in '" << strLine << "'" << endl;
00420       }
00421     }
00422   }
00423 
00424   return ( bReturn );
00425 }
00426 
00440 bool GenericValues::saveValues( const char *strFile, const char *strSeparator,
00441                                 bool bAppend )
00442 {
00443   ofstream outf( strFile, ( bAppend == false ? ( ios::out )
00444                                              : ( ios::out | ios::app ) ) );
00445 
00446   if( !outf )
00447   {
00448     cerr << "Could not open file '" << strFile << "'" << endl;
00449     return ( false );
00450   }
00451 
00452   // values are written to file using 'show' (note that
00453   // output stream to write to is a file in this case)
00454   show( outf, strSeparator );
00455 
00456   return ( true );
00457 }
00458 
00467 void GenericValues::show( ostream& out, const char *strSeparator )
00468 {
00469   for( int i = 0; i < getValuesTotal( ); i++ )
00470     m_values[ i ]->show( out, strSeparator );
00471 }
00472 
00473 /********************** TESTING PURPOSES **************************************/
00474 /*
00475 
00476 int main( void )
00477 {
00478   GenericValues g;
00479 
00480   int    i = 10;
00481   char*  c = "hallo";
00482   bool   b = true;
00483   double d = 10.14;
00484 
00485   cout << g.addSetting( "var1", &i, GENERIC_VALUE_INTEGER ) << endl;
00486   cout << g.addSetting( "var2", &c, GENERIC_VALUE_STRING  ) << endl;
00487   cout << g.addSetting( "var3", &d, GENERIC_VALUE_DOUBLE  ) << endl;
00488   cout << g.addSetting( "var4", &b, GENERIC_VALUE_BOOLEAN ) << endl;
00489   g.show( cout );
00490 
00491   g.setValue( "var1", "11"      );
00492   g.setValue( "var2", "hoi"     );
00493   g.setValue( "var3", "20.2342" );
00494   g.setValue( "var4", "false"   );
00495   g.show( cout );
00496 
00497   g.setIntegerValue( "var1", 22      );
00498   g.setStringValue ( "var2", "hoi2"  );
00499   g.setDoubleValue ( "var3", 30.2342 );
00500   g.setBooleanValue( "var4", true    );
00501   g.show( cout );
00502 
00503   g.readValues( "server.conf", ":" );
00504   g.show( cout );
00505 
00506   return ( 0 );
00507 }
00508 */

Generated on Tue Jul 2 10:18:51 2002 for UvA Trilearn 2002 by doxygen1.2.12 written by Dimitri van Heesch, © 1997-2001