cgma
CGMFileOptions.cpp
Go to the documentation of this file.
00001 
00006 #include "CGMFileOptions.hpp"
00007 
00008 #include <ctype.h>
00009 #include <stdlib.h>
00010 #include <string.h>
00011 
00012 const char DEFAULT_SEPARATOR = ';';
00013 
00014 static inline bool strempty( const char* s ) { return !*s; }
00015 
00016 CGMFileOptions::CGMFileOptions( const char* str )
00017   : mData(0)
00018 {
00019     // if option string is null, just return
00020   if (!str)
00021     return;
00022   
00023     // check if alternate separator is specified
00024   char separator[2] = { DEFAULT_SEPARATOR, '\0' };
00025   if (*str == DEFAULT_SEPARATOR) {
00026     ++str;
00027     if (strempty(str))
00028       return;
00029     separator[0] = *str;
00030     ++str;
00031   }
00032   
00033     // don't bother allocating copy of input string if
00034     // input string is empty.
00035   if (!strempty(str))
00036   {
00037        // tokenize at separator character
00038     mData = strdup( str );
00039     for (char* i = strtok( mData, separator ); i; i = strtok( 0, separator )) 
00040       if (!strempty(i)) // skip empty strings
00041         mOptions.push_back( i );
00042   }
00043 }
00044 
00045 CGMFileOptions::CGMFileOptions( const CGMFileOptions& copy ) :
00046   mData(0), mOptions( copy.mOptions.size() )
00047 {
00048   if (!copy.mOptions.empty()) {
00049     const char* last = copy.mOptions.back();
00050     const char* endptr = last + strlen(last) + 1;
00051     size_t len = endptr - copy.mData;
00052     mData = (char*)malloc( len );
00053     memcpy( mData, copy.mData, len );
00054     for (size_t i = 0; i < mOptions.size(); ++i)
00055       mOptions[i] = mData + (copy.mOptions[i] - copy.mData);
00056   }
00057 }
00058 
00059 CGMFileOptions& CGMFileOptions::operator=( const CGMFileOptions& copy )
00060 {
00061   free( mData );
00062   mData = 0;
00063   mOptions.resize( copy.mOptions.size() );
00064 
00065   if (!copy.mOptions.empty()) {
00066     const char* last = copy.mOptions.back();
00067     const char* endptr = last + strlen(last) + 1;
00068     size_t len = endptr - copy.mData;
00069     mData = (char*)malloc( len );
00070     memcpy( mData, copy.mData, len );
00071     for (size_t i = 0; i < mOptions.size(); ++i)
00072       mOptions[i] = mData + (copy.mOptions[i] - copy.mData);
00073   }
00074     
00075   return *this;
00076 }
00077 
00078 CGMFileOptions::~CGMFileOptions()
00079 {
00080   free( mData );
00081 }
00082 
00083 CGMFOErrorCode CGMFileOptions::get_null_option( const char* name ) const
00084 {
00085   const char* s;
00086   CGMFOErrorCode rval = get_option( name, s );
00087   if (FO_SUCCESS != rval)
00088     return rval;
00089   return strempty(s) ? FO_SUCCESS : FO_TYPE_OUT_OF_RANGE;
00090 }
00091 
00092 CGMFOErrorCode CGMFileOptions::get_int_option( const char* name, int& value ) const
00093 {
00094   const char* s;
00095   CGMFOErrorCode rval = get_option( name, s );
00096   if (FO_SUCCESS != rval)
00097     return rval;
00098   
00099     // empty string
00100   if (strempty(s))
00101     return FO_TYPE_OUT_OF_RANGE;
00102   
00103     // parse value
00104   char* endptr;
00105   long int pval = strtol( s, &endptr, 0 );
00106   if (!strempty(endptr)) // syntax error
00107     return FO_TYPE_OUT_OF_RANGE;
00108   
00109     // check for overflow (parsing long int, returning int)
00110   value = pval;
00111   if (pval != (long int)value)
00112     return FO_TYPE_OUT_OF_RANGE;
00113   
00114   return FO_SUCCESS;
00115 }
00116 
00117 CGMFOErrorCode CGMFileOptions::get_ints_option( const char* name, 
00118                                           std::vector<int>& values) const
00119 {
00120   const char* s;
00121   CGMFOErrorCode rval = get_option( name, s );
00122   if (FO_SUCCESS != rval)
00123     return rval;
00124   
00125     // empty string
00126   if (strempty(s))
00127     return FO_TYPE_OUT_OF_RANGE;
00128   
00129     // parse values
00130   while (!strempty(s)) {
00131     char* endptr;
00132     long int sval = strtol( s, &endptr, 0 );
00133 
00134 #define EATSPACE(a) while ((!strncmp(a, " ", 1) ||  \
00135                 !strncmp(a, ",", 1)) && !strempty(a)) a++;
00136     //EATSPACE(endptr);
00137 
00138     while ((!strncmp(endptr, " ", 1) ||
00139         !strncmp(endptr, ",", 1)) && !strempty(endptr)) {
00140       endptr++;
00141     }
00142 
00143     long int eval = sval;
00144     if (!strcmp(endptr, "-")) {
00145       endptr++;
00146       s = endptr;
00147       eval = strtol(s, &endptr, 0);
00148       EATSPACE(endptr);
00149     }
00150   
00151       // check for overflow (parsing long int, returning int)
00152     int value = sval;
00153     if (sval != (long int)value)
00154       return FO_TYPE_OUT_OF_RANGE;
00155     value = eval;
00156     if (eval != (long int)value)
00157       return FO_TYPE_OUT_OF_RANGE;
00158   
00159     for (int i = sval; i <= eval; i++)
00160       values.push_back(i);
00161 
00162     s = endptr;
00163   }
00164   
00165   return FO_SUCCESS;
00166 }
00167 
00168 CGMFOErrorCode CGMFileOptions::get_real_option ( const char* name, double& value ) const
00169 {
00170   const char* s;
00171   CGMFOErrorCode rval = get_option( name, s );
00172   if (FO_SUCCESS != rval)
00173     return rval;
00174   
00175     // empty string
00176   if (strempty(s))
00177     return FO_TYPE_OUT_OF_RANGE;
00178   
00179     // parse value
00180   char* endptr;
00181   value = strtod( s, &endptr );
00182   if (!strempty(endptr)) // syntax error
00183     return FO_TYPE_OUT_OF_RANGE;
00184   
00185   return FO_SUCCESS;
00186 }
00187 
00188 CGMFOErrorCode CGMFileOptions::get_str_option( const char* name, std::string& value ) const
00189 {
00190   const char* s;
00191   CGMFOErrorCode rval = get_option( name, s );
00192   if (FO_SUCCESS != rval)
00193     return rval;
00194   if (strempty(s))
00195     return FO_TYPE_OUT_OF_RANGE;
00196   value = s;
00197   return FO_SUCCESS;
00198 }
00199 
00200 CGMFOErrorCode CGMFileOptions::get_option( const char* name, std::string& value ) const
00201 {
00202   const char* s;
00203   CGMFOErrorCode rval = get_option( name, s );
00204   if (FO_SUCCESS != rval)
00205     return rval;
00206   
00207   value = s;
00208   return FO_SUCCESS;
00209 }  
00210 
00211 CGMFOErrorCode CGMFileOptions::get_option( const char* name, const char*& value ) const
00212 {
00213   std::vector<const char*>::const_iterator i;
00214   for (i = mOptions.begin(); i != mOptions.end(); ++i) {
00215     const char* opt = *i;
00216     if (compare( name, opt )) {
00217       value = opt + strlen(name);
00218         // if compare returned true, next char after option
00219         // name must be either the null char or an equals symbol.
00220       if (*value == '=') 
00221         ++value;
00222         
00223       return FO_SUCCESS;
00224     }
00225   }
00226   
00227   return FO_ENTITY_NOT_FOUND;
00228 }
00229 
00230 CGMFOErrorCode CGMFileOptions::match_option( const char* name, 
00231                                        const char* value ) const
00232 {
00233   int idx;
00234   const char* array[] = { value, NULL };
00235   return match_option( name, array, idx );
00236 }
00237 
00238 CGMFOErrorCode CGMFileOptions::match_option( const char* name, 
00239                                        const char* const* values, 
00240                                        int& index ) const
00241 {
00242   const char* optval;
00243   CGMFOErrorCode rval = get_option( name, optval );
00244   if (FO_SUCCESS != rval)
00245     return rval;
00246   
00247   for (index = 0; values[index]; ++index)
00248     if (compare( optval, values[index] ))
00249       return FO_SUCCESS;
00250   
00251   index = -1;
00252   return FO_FAILURE;
00253 }
00254 
00255 
00256 bool CGMFileOptions::compare( const char* name, const char* option )
00257 {
00258   while (!strempty(name) && toupper(*name) == toupper(*option)) {
00259     ++name;
00260     ++option;
00261   }
00262    // match if name matched option for length of name,
00263    // and option either matched entirely or matches up to
00264    // and equals sign.
00265   return strempty(name) && (strempty(option) || *option == '=');
00266 }
00267 
00268 void CGMFileOptions::get_options( std::vector<std::string>& list ) const
00269 {
00270   list.clear();
00271   list.resize( mOptions.size() );
00272   std::copy( mOptions.begin(), mOptions.end(), list.begin() );
00273 }
00274 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines