⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 configfile.cpp

📁 This is a pgm can be used for astronomy
💻 CPP
字号:
/*--------------------------------------------------------------------------*\
 * ConfigFile class
 *
 * Input file consists of lines of text of the form
 *   name = value
 * where 'name' is the look up key and 'value' is the resultant value
 *
 * '\' is the escape character and allows values to contain embedded '"' and
 *   '#' characters.
 * To put '"' in a value use '\"'.  To put '\' in a value use '\\'.
 *
 * '\' is also the line continuation char.  If '\' is the last character on
 *   a line, the following line will be appended to that line before the
 *   line is processed.
 *
 * Anything in double quotes is copied literally, except '\', as described
 *   above.
 *
 * Outside of double quotes:
 *   '#' starts a comment; the rest of the line is ignored
 *   White space is ignored
 *
 *--------------------------------------------------------------------------
 *
 * Created by Mark Huss <mark@mhuss.com>
 *
 * Developed and built using the mingw32 gcc compiler 2.95.2
 *
 * THIS SOFTWARE IS NOT COPYRIGHTED
 *
 * This source code is offered for use in the public domain. You may
 * use, modify or distribute it freely.
 *
 * This code is distributed in the hope that it will be useful but
 * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
 * DISCLAMED. This includes but is not limited to warranties of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
\*--------------------------------------------------------------------------*/

#include "ConfigFile.h"

using namespace std;

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//----------------------------------------------------------------------------
// CFList methods
//----------------------------------------------------------------------------

// C++ version of strdup()
//
char* CFList::strDup( const char* s ) {
  char* p = 0;
  if (s) if (*s) {
    p = new char[strlen(s)+1];
    if (p)
      strcpy( p, s );
  }
  return p;
}

// add a name/value pair to the list
//
void CFList::add(const char* name, const char* value) {
  if (name) if (*name) if (value) if (*value) {
    CFList* p = this;
    while ( 0 != p->m_next)
      p=p->m_next;

    p->m_next = new CFList( name, value );
  }
}

// update the value of a name/value pair in the list
// if name is not found, does an add()
//
void CFList::update(const char* name, const char* value) {
  if (name) if (*name) {
    CFList* p = this;
    bool found=false;

    while (0 != p && !found) {
      if ( !strcmp(p->m_name, name) ) {
        found = true;
        delete [] p->m_value;
        p->m_value = strDup(value);
      }
      p = p->m_next;
    }
    if ( !found )
      add( name, value );
  }
}

// get the string value that corresponds the the spec'd name
// returns null string if not found
// ALWAYS RETURNS A VALID POINTER
//
const char* CFList::value(const char* name) const {
  const CFList* p = this;
  const char* pVal = "";
  if (name) if (*name) {
    while (0 != p) {
      if ( !strcmp(p->m_name, name) ) {
        if ( p->m_value )
          pVal = p->m_value;
        break;
      }
      p = p->m_next;
    }
  }
  return pVal;
}

// get the boolean value that corresponds the the spec'd name
// returns false if not found
//
bool CFList::boolValue(const char* name) const {
  const char* p = value( name );
  return ( 't' == *p || 'T' == *p || ('1' == *p && 0 == *(p+1)) );
}

// get the int value that corresponds the the spec'd name
// returns 0 if not found
//
int CFList::intValue(const char* name) const {
  const char* p = value( name );
  return (*p) ? atoi( p ) : 0;
}

// get the double value that corresponds the the spec'd name
// returns 0.0 if not found
//
double CFList::dblValue(const char* name) const {
  const char* p = value( name );
  return (*p) ? atof( p ) : 0.;
}

// output all keys and values
//
void CFList::dump( FILE* fp ) const {
  const CFList* p = this;
  while ( 0 != p ) {
    fprintf( fp, "%s = %s\n", p->m_name, p->m_value );
    p=p->m_next;
  }
}

//----------------------------------------------------------------------------
// ConfigFile methods
//----------------------------------------------------------------------------

bool ConfigFile::debug = false;

//----------------------------------------------------------------------------
// compact input buffer (one line of the input file)
// eat white space, deal with quoted strings & escaped characters
//
bool ConfigFile::compactBuffer(char* buffer) {
  char* from = buffer;
  while ( (*from) > 0 && (*from) <= ' ' ) {
    from++;
  }
  // skip 'whole line' comments and blank lines
  if ( COMMENT_CHAR == (*from) || 0 == (*from) )
    return false;

  char* to = buffer;
  bool inQuotes = false;

  while ( *from ) {
    char c = *from++;
    if ( ESC_CHAR == c ) {           // deal with escaped chars
      if ( *from )
        *to++ = *from++;
    }
    else if ( c < ' ' )             // skip \n, etc.
      continue;
    else if ( QUOTE_CHAR == c ) {   // toggle quote flag
      inQuotes = !inQuotes;
      *to++ = c;
    }
    else {
      if ( inQuotes )               // if in quotes, copy everything
        *to++ = c;
      else {                        // outside of quotes,
        if ( c <= ' ' )               // if white space, skip it
          ;
        else if ( COMMENT_CHAR == c ) // if comment, ignore rest of line
          break;
        else                        // none of the above, just copy it
          *to++ = c;
      }
    }
  }
  *to = 0;

  if( debug )
    fprintf( stderr, "    compacted line: '%s'\n", buffer);

  return true;
}

//----------------------------------------------------------------------------
// load names & values from the input file
//
int ConfigFile::readAndParseFile( const char* fname ) {
  if( debug ) {
    fprintf( stderr, "> readAndParseFile( %s )\n", fname );
  }

  m_status = NO_ENTRIES;

  m_filename = fname;

  // check for filename
  //
  if ( !fname ) {
    m_status = INVALID_FILE_NAME;
    return m_status;
  }

  // open & read file
  //
  FILE* fp = fopen( m_filename, "r" );
  if ( !fp ) {
    m_status = FILE_NOT_FOUND;
    return m_status;
  }

  char buffer[BUFSIZE];

  while ( true ) {
    memset( buffer, 0, BUFSIZE );

    if ( 0 == fgets( buffer, BUFSIZE, fp ) )
      break;

    // check for and handle line continuation chars
    int len = strlen( buffer );
    while ( true ) {
      char* pEol = &buffer[len-1];
      if ( ESC_CHAR == *pEol ) {
        if ( 0 == fgets( buffer, BUFSIZE, fp ) ) {
          *pEol = 0;
          break;
        }
      }
      else
        break;
    }
    // lose EOL
    if ( buffer[len] <= ' ' )
      buffer[len] = 0;

    if( debug )
      fprintf( stderr, "    original line: '%s'\n", buffer );

    // compact input buffer
    // eat white space, deal with quoted strings & escaped characters
    //
    if (false ==compactBuffer(buffer))
      continue;  // false means empty buffer

    // parse name/value pair and add to Hashtable
    //
    char* line = buffer;

    // minimum valid length is 3 ( 'a=b' )
    if ( strlen(line) >= 3 ) {

      // look for separator
      char* sepIndex = strchr( line, NV_SEP_CHAR );
      if (0 != sepIndex) {
        // separator char found, split into name/value
        int nameLen = sepIndex-line;
        char name[BUFSIZE];
        char value[BUFSIZE];
        memcpy( name, line, nameLen );
        name[nameLen] = 0;
        strcpy( value, sepIndex+1 );

        // remove quote chars from quoted values
        int vlen = strlen(value);
        if ( vlen > 2 &&   // minimum valid length is 3 ( '"c"' )
            QUOTE_CHAR == value[0] &&     // starts with '"'
            QUOTE_CHAR == value[vlen-1] ) // ends with '"'
        {
          strncpy(value, value+1, vlen-2 );  // cut off both ends
          value[vlen-2] = 0;
        }

        if( debug ) {
          fprintf(stderr, "    name='%s', value='%s'\n", name, value);
        }

        // add name/value pair

        m_items.add( name, value );
      }
      // ignore lines with no separators for now
    }
  }
  m_items.update( "ConfigFile", fname );
  m_status = OK;

  return m_status;
}

#if defined(UNIT_TEST)
//----------------------------------------------------------------------------
// unit test bed
//
int main( int argc, char** argv ) {

  ConfigFile cf;
  //cf.debug = true;
  int rc = 0;

  if ( argc > 1 ) {
    cf.filename( argv[1] );
    cf.dump( stdout );
  }
  else {
    fprintf( stderr, "usage: %s <config file>\n", argv[0] );
    rc = 1;
  }

  return rc;

} // end function main()

//----------------------------------------------------------------------------

#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -