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,2001, 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 */
00047 #include "GenericValues.h"
00048 #include "Parse.h"           // needed for 'gotoFirstNonSpace'
00049 #include <stdio.h>           // needed for 'sprintf'
00050 #include <stdlib.h>          // needed for 'free'
00051 #include <string.h>          // needed for 'strdup'
00052 #include <ctype.h>           // needed for 'isdigit'
00053 #include <fstream.h>         // needed for 'ifstream'
00054 
00055 /******************************************************************************/
00056 /********************   CLASS GENERICVALUET   *********************************/
00057 /******************************************************************************/
00058 
00068 GenericValueT::GenericValueT( const char *str, void *vAddr, GenericValueKind t )
00069 {
00070   m_strName  = strdup( str ); // strdup needed to allocate right amount of memory
00071   m_vAddress = vAddr;
00072   m_type     = t;
00073 }
00074 
00077 GenericValueT::~GenericValueT( )
00078 {
00079   if( m_strName )
00080     free( ( char * ) m_strName );
00081 }
00082 
00086 const char* GenericValueT::getName ( )
00087 {
00088   return ( m_strName );
00089 }
00090 
00098 bool GenericValueT::setValue( const char *strValue )
00099 {
00100   bool bReturn = true, b = false;
00101 
00102   // determine the generic type associated with this GenericValueT
00103   // object and apply the correct conversion of the string argument
00104   switch( m_type )
00105   {
00106     case GENERIC_VALUE_DOUBLE:
00107       *( double * ) m_vAddress = atof( strValue ? strValue : 0 );
00108       break;
00109     case GENERIC_VALUE_STRING:
00110       strcpy( ( char * ) m_vAddress, strValue );
00111       break;
00112     case GENERIC_VALUE_BOOLEAN:
00113       b = false;
00114       if( !strValue )
00115         ;
00116       else if( isdigit( strValue[ 0 ] ) )
00117         b = atoi( strValue ? strValue : 0 );
00118       else if( strcasecmp( strValue, "on"  ) == 0 ||
00119                strcasecmp( strValue, "true") == 0 ||
00120                strcasecmp( strValue, "yes" ) == 0 )
00121         b = true;
00122 
00123       *( bool * ) m_vAddress = ( b == true ) ? true : false;
00124       break;
00125     case GENERIC_VALUE_INTEGER:
00126       *( int * ) m_vAddress = atoi( strValue ? strValue : 0 );
00127       break;
00128     default:
00129       bReturn = false;
00130   }
00131 
00132   return ( bReturn );
00133 }
00134 
00144 char* GenericValueT::getValue( char *strValue )
00145 {
00146   // determine the generic type associated with this GenericValueT
00147   // object and apply the correct conversion into a string
00148   switch( m_type )
00149   {
00150     case GENERIC_VALUE_DOUBLE:
00151       sprintf( strValue, "%2f", *( double * ) m_vAddress );
00152       break;
00153     case GENERIC_VALUE_STRING:
00154       sprintf( strValue, "%s", *( char ** ) m_vAddress );
00155       break;
00156     case GENERIC_VALUE_BOOLEAN:
00157       sprintf( strValue, "%d", *( int * ) m_vAddress );
00158       break;
00159     case GENERIC_VALUE_INTEGER:
00160       sprintf( strValue, "%d", *( int * ) m_vAddress );
00161       break;
00162     default:
00163       *strValue = '\0';
00164   }
00165 
00166   return ( strValue );
00167 }
00168 
00177 void GenericValueT::show( ostream& out, const char *strSeparator )
00178 {
00179   // write the name associated with the variable in this GenericValueT
00180   // object followed by the separator to the specified output stream
00181   out << m_strName << strSeparator;
00182 
00183   // determine the generic type associated with this GenericValueT
00184   // object and write the correct value to the specified output stream
00185   switch( m_type )
00186   {
00187     case GENERIC_VALUE_DOUBLE:
00188       out << *( double * ) m_vAddress;
00189       break;
00190     case GENERIC_VALUE_STRING:
00191       out << ( char * ) m_vAddress;
00192       break;
00193     case GENERIC_VALUE_BOOLEAN:
00194       out << ( ( *( bool * ) m_vAddress == true ) ? "true" : "false");
00195       break;
00196     case GENERIC_VALUE_INTEGER:
00197       out << *( int * ) m_vAddress;
00198       break;
00199     default:
00200       break;
00201   }
00202 
00203   out << endl;
00204 }
00205 
00206 
00207 /******************************************************************************/
00208 /********************   CLASS GENERICVALUES   *********************************/
00209 /******************************************************************************/
00210 
00217 GenericValues::GenericValues( char *strName, int iMaxValues )
00218 {
00219   m_iValuesTotal = 0;   // total number of values in collection is set to zero
00220 
00221   if( strName )       // set the name of the collection
00222     m_strClassName = strdup( strName );
00223 
00224   m_iMaxGenericValues = iMaxValues;
00225 
00226   // a GenericValues object is a collection of GenericValueT objects
00227   m_values = new GenericValueT*[ iMaxValues ];
00228 }
00229 
00232 GenericValues::~GenericValues( void )
00233 {
00234   for( int i = 0 ; i < getValuesTotal( ) ; i++ )
00235     delete m_values[ i ];
00236   delete m_values;
00237 
00238   if( m_strClassName )
00239     free( m_strClassName );
00240 }
00241 
00245 char* GenericValues::getClassName( )
00246 {
00247   return ( m_strClassName );
00248 }
00249 
00252 int GenericValues::getValuesTotal( )
00253 {
00254   return ( m_iValuesTotal );
00255 }
00256 
00266 bool GenericValues::addSetting( const char *strName, void *vAddress,
00267                                                      GenericValueKind type )
00268 {
00269   if( getValuePtr( strName ) )               // setting already installed
00270   {
00271     cerr << "Setting '" << strName << "' already installed." << endl;
00272     return false;
00273   }
00274   if( m_iValuesTotal == m_iMaxGenericValues )    // buffer is full
00275   {
00276     cerr << "GenericValues::addSetting buffer for " << m_strClassName <<
00277             " is full (cannot add '" << strName << "')" << endl;
00278     return false;
00279   }
00280 
00281   m_values[ m_iValuesTotal++ ] = new GenericValueT( strName, vAddress, type );
00282 
00283   return ( true );
00284 }
00285 
00294 GenericValueT* GenericValues::getValuePtr( const char *strName )
00295 {
00296   GenericValueT *ptr = 0;
00297 
00298   // search through the collection for a GenericValueT object of which the name
00299   // associated with the variable matches the argument passed to the method
00300   for( int i = 0 ; i < getValuesTotal( ) ; i++ )
00301   {
00302     if( strcmp( m_values[ i ]->getName( ), strName ) == 0 )
00303     {
00304       ptr = m_values[ i ];
00305       break;
00306     }
00307   }
00308 
00309   return ( ptr );
00310 }
00311 
00325 char* GenericValues::getValue( const char *strName, char *strValue )
00326 {
00327   GenericValueT *parptr;
00328 
00329   parptr = getValuePtr( strName );
00330 
00331   if( parptr )
00332     strValue = parptr->getValue( strValue );   // this method returns a string
00333   else
00334     strValue[ 0 ] = '\0';
00335 
00336   return ( strValue );
00337 }
00338 
00348 bool GenericValues::setValue( const char *strName, const char *strValue )
00349 {
00350   bool bReturn = false;
00351   GenericValueT *parptr;
00352 
00353   parptr = getValuePtr( strName );
00354 
00355   if( parptr )
00356     bReturn = parptr->setValue( strValue ); // string is converted to right type
00357 
00358   return ( bReturn );
00359 }
00360 
00372 bool GenericValues::readValues( const char *strFile, const char *strSeparator )
00373 {
00374   ifstream in( strFile );
00375 
00376   if( !in )
00377   {
00378     cerr << "(GenericValues::readValues) Could not open file '" <<
00379     strFile << "'" << endl;
00380     return ( false );
00381   }
00382 
00383   bool  bReturn = true;
00384   char  strLine[ 256 ], strName[ 100 ], strValue[ 100 ];
00385   char* c;
00386   int   iLineNr = 0;
00387 
00388   // read each line in the configuration file and store the values
00389   while( in.getline( strLine, sizeof( strLine ) ) )
00390   {
00391     iLineNr++;
00392 
00393     // skip comment lines and empty lines; " #" is for server.conf version 7.xx
00394     if( !( strLine[ 0 ] == '\n' ||
00395            strLine[ 0 ] == '#'  ||
00396            strLine[ 0 ] == '\0' ||
00397            ( strlen( strLine ) > 1 &&
00398              strLine[ 0 ] == ' ' &&
00399              strLine[ 1 ] == '#' ) ) )
00400     {
00401       // convert all characters belonging to the separator to spaces
00402       if( strSeparator && ( c = strstr( strLine, strSeparator ) ) != NULL )
00403         for( size_t i = 0; i < strlen( strSeparator ); i++ )
00404           *( c + i ) = ' ';
00405 
00406       // read the name and value on this line and store the value
00407       if( !( sscanf( strLine, "%s%s", strName, strValue ) == 2 &&
00408              setValue( strName, strValue ) ) )
00409       {
00410         bReturn = false;
00411         cerr << "(GenericValues::readValues) '" << strFile << "' linenr "
00412              << iLineNr << ",  error in '" << strLine << "'" << endl;
00413       }
00414     }
00415   }
00416 
00417   return ( bReturn );
00418 }
00419 
00433 bool GenericValues::saveValues( const char *strFile, const char *strSeparator,
00434                                 bool bAppend )
00435 {
00436   ofstream outf( strFile, ( bAppend == false ? ( ios::out )
00437                                              : ( ios::out | ios::app ) ) );
00438 
00439   if( !outf )
00440   {
00441     cerr << "Could not open file '" << strFile << "'" << endl;
00442     return ( false );
00443   }
00444 
00445   // values are written to file using 'show' (note that
00446   // output stream to write to is a file in this case)
00447   show( outf, strSeparator );
00448 
00449   return ( true );
00450 }
00451 
00460 void GenericValues::show( ostream& out, const char *strSeparator )
00461 {
00462   for( int i = 0; i < getValuesTotal( ); i++ )
00463     m_values[ i ]->show( out, strSeparator );
00464 }
00465 
00466 /********************** TESTING PURPOSES **************************************/
00467 /*
00468 
00469 int main( void )
00470 {
00471   GenericValues g;
00472 
00473   int    i = 10;
00474   char*  c = "hallo";
00475   bool   b = true;
00476   double d = 10.14;
00477 
00478   cout << g.addSetting( "var1", &i, GENERIC_VALUE_INTEGER ) << endl;
00479   cout << g.addSetting( "var2", &c, GENERIC_VALUE_STRING  ) << endl;
00480   cout << g.addSetting( "var3", &d, GENERIC_VALUE_DOUBLE  ) << endl;
00481   cout << g.addSetting( "var4", &b, GENERIC_VALUE_BOOLEAN ) << endl;
00482   g.show( cout );
00483 
00484   g.setValue( "var1", "11"      );
00485   g.setValue( "var2", "hoi"     );
00486   g.setValue( "var3", "20.2342" );
00487   g.setValue( "var4", "false"   );
00488   g.show( cout );
00489 
00490   g.setIntegerValue( "var1", 22      );
00491   g.setStringValue ( "var2", "hoi2"  );
00492   g.setDoubleValue ( "var3", 30.2342 );
00493   g.setBooleanValue( "var4", true    );
00494   g.show( cout );
00495 
00496   g.readValues( "server.conf", ":" );
00497   g.show( cout );
00498 
00499   return ( 0 );
00500 }
00501 */

Generated on Thu Mar 7 00:37:42 2002 for UvA Trilearn 2001 by doxygen1.2.12 written by Dimitri van Heesch, © 1997-2001