Skip to content
Snippets Groups Projects
parse.cc 3.67 KiB
Newer Older
Stephen Smith's avatar
Stephen Smith committed
/*  Copyright (C) 1999-2004 University of Oxford  */

/*  CCOPYRIGHT */
David Flitney's avatar
David Flitney committed

Stephen Smith's avatar
Stephen Smith committed
#include "options.h"
David Flitney's avatar
David Flitney committed
#include <fstream>
David Flitney's avatar
David Flitney committed

namespace Utilities {

David Flitney's avatar
David Flitney committed
  using namespace std;

David Flitney's avatar
David Flitney committed
  BaseOption * OptionParser::find_matching_option(const string& optstr)
  {
    for(Options::iterator o = options_.begin();
	o != options_.end();
	++o)
David Flitney's avatar
David Flitney committed
      if((*o)->matches(optstr))
	return *o;
  unsigned int OptionParser::parse_option(const string& optstr, const string& valstr,
					  char *argv[], int valpos, int argc)
    throw(X_OptionError)
David Flitney's avatar
David Flitney committed
  {
    BaseOption * theOption = 0;

    if((theOption = find_matching_option(optstr)) == 0)
David Flitney's avatar
David Flitney committed
      throw X_OptionError(optstr, "Option doesn't exist");
David Flitney's avatar
David Flitney committed
    if(theOption->unset() || (overWriteMode_==Allow)) 
David Flitney's avatar
David Flitney committed
	  if(valstr.length() > 0) {
	    if(theOption->set_value(valstr,argv,valpos,argc))
	      string errstr = "Couldn't set_value! valstr=\"" + valstr;
	      for (int nn=valpos+1; nn<=valpos + theOption->nrequired(); nn++) {
		if (nn<argc)  errstr += " " + string(argv[nn]);
	      }
	      throw X_OptionError(optstr, errstr + "\""); 
David Flitney's avatar
David Flitney committed
	    }
	  } else if(!theOption->optional()) {
	    throw X_OptionError(optstr, "Missing non-optional argument");
	if(theOption->optional()) 
	  theOption->use_default_value();
	else
	  theOption->set_value(string());
David Flitney's avatar
David Flitney committed
	return 1;
      } 
    else 
      {
David Flitney's avatar
David Flitney committed
	if( overWriteMode_!= Ignore)
	  throw X_OptionError(optstr, "Option already set");
	else
	  return 1;
    throw X_OptionError(optstr);
David Flitney's avatar
David Flitney committed
    return 0;
  }

David Flitney's avatar
David Flitney committed
  unsigned int OptionParser::parse_long_option(const string& str)
  {
    string optstr(str);
    string valstr;

    string::size_type pos = 0;
    if((pos = str.find("=", 0)) != string::npos) {
      optstr = str.substr(0, pos);
      valstr = str.substr(pos + 1, str.length() - pos + 1);
    }

    parse_option(optstr, valstr, 0,0,0);
David Flitney's avatar
David Flitney committed
  unsigned int OptionParser::parse_config_file(const string& filename)
  {
    ifstream cf(filename.c_str());

    if(cf.fail())
      throw X_OptionError(filename, "Couldn't open the file");
    
    OverwriteMode oldMode=overWriteMode_;
    overWriteMode_=Ignore;

    string optstr; char buffer[1024];
    while (cf >> optstr) {
      if(optstr[0] == '#')
	cf.getline(buffer, 1024);	     // Read and discard the rest of this line
      else if(optstr.substr(0,2) == "--")
	parse_long_option(optstr); // Parse a long option
      else {
	cf.getline(buffer, 1024);
	parse_option(optstr, string(buffer), 0, 0, 0);
      }
    }
    overWriteMode_=oldMode;
    return 1;
  }
 
David Flitney's avatar
David Flitney committed
  unsigned int OptionParser::parse_command_line(unsigned int argc, 
David Flitney's avatar
David Flitney committed
  {
    unsigned int optpos = 1 + skip;
    unsigned int valpos = 1 + skip;
David Flitney's avatar
David Flitney committed

    while(optpos < argc) {
David Flitney's avatar
David Flitney committed

David Flitney's avatar
David Flitney committed
      unsigned int increments = 0;
David Flitney's avatar
David Flitney committed
      
      string optstr(argv[optpos]), valstr;
David Flitney's avatar
David Flitney committed

      if(optstr[0] != '-')	// End of parsable options
David Flitney's avatar
David Flitney committed
	break;

David Flitney's avatar
David Flitney committed
      if(optstr[1] == '-') {	// Parse a long opt

	increments = parse_long_option(optstr);
	optpos += increments;

      } else {

	valpos = optpos + 1;

	for(unsigned int i = 1; i < optstr.length(); ++i)
David Flitney's avatar
David Flitney committed
	  {
David Flitney's avatar
David Flitney committed
	    string suboptstr = "-" + optstr.substr(i, 1);
	    
	    if (valpos<argc) valstr=string(argv[valpos]); else valstr=string();
	    increments = parse_option(suboptstr, valstr, argv, valpos, argc);
David Flitney's avatar
David Flitney committed
	    
	    valpos += increments - 1;
David Flitney's avatar
David Flitney committed
	  }
David Flitney's avatar
David Flitney committed
	
	optpos = valpos;
David Flitney's avatar
David Flitney committed
      }
David Flitney's avatar
David Flitney committed
    } 
    return optpos;		// User should process any remaining args
David Flitney's avatar
David Flitney committed
  }

David Flitney's avatar
David Flitney committed
  std::ostream& operator<<(std::ostream& os, const OptionParser p) 
  {
    for(OptionParser::Options::const_iterator o = p.options_.begin();
	o != p.options_.end(); ++o)
      os << *(*o) << std::endl;

    return os;
  }
David Flitney's avatar
David Flitney committed
}