See

<project-file type=“source”/>

<content> #include “parameters.h” #include <string.h> #include <iostream> #include <fstream> #include <stdlib.h> #include <stdio.h>

Argument::Argument(const char *name, const char *help, Requirement required) {

Name = new char[strlen(name)+1];
strcpy(Name, name);
Help = new char[strlen(help)+1];
strcpy(Help, help);
Error = NULL;
Set = false;
Required = required;

}

Argument::~Argument() {

if (Name != NULL) delete Name;
if (Help != NULL) delete Help;
if (Error != NULL) delete Error;

}

void Argument::setError(const char *error) {

if (Error != NULL) delete Error;
Error = new char[strlen(error)+1];
strcpy(Error, error);

}

const char *Argument::parsable(const char *s) const {

  if (s == NULL) return NULL;
char key[strlen(Name)+4];
sprintf(key, "--%s=", Name);
if (strstr(s, key) != s) return NULL;
return &s[strlen(key)];

}

IntArgument::IntArgument(const char *name, const char *help, Requirement required, int defaultvalue) : Argument(name, help, required) {

Value = defaultvalue;

}

bool IntArgument::parse(const char *s) {

if (sscanf(s, "%d", &Value) == 1)
	return true;
setError("not a number");
return false;

}

void IntArgument::formatHelp(std::ostream &stream) const {

stream << "--" << Name << "=number\t";
if (Required == NOT_REQUIRED) stream << "optional, ";
stream << Help << std::endl;

}

BoolArgument::BoolArgument(const char *name, const char *help, Requirement required, bool defaultvalue) : Argument(name, help, required) {

Value = defaultvalue;

}

bool BoolArgument::parse(const char *s) {

if (strcmp(s, "yes") == 0)
	Value = true;
else if (strcmp(s, "no") == 0)
	Value = false;
else {
	setError("value must be either yes or no");
	return false;
}
return true;

}

void BoolArgument::formatHelp(std::ostream &stream) const {

stream << "--" << Name << "=yes/no\t";
if (Required == NOT_REQUIRED) stream << "optional, ";
stream << Help << std::endl;

}

FloatArgument::FloatArgument(const char *name, const char *help, Requirement required, float defaultvalue) : Argument(name, help, required) {

Value = defaultvalue;

}

bool FloatArgument::parse(const char *s) {

if (sscanf(s, "%f", &Value) == 1)
	return true;
setError("not a number");
return false;

}

void FloatArgument::formatHelp(std::ostream &stream) const {

stream << "--" << Name << "=number\t";
if (Required == NOT_REQUIRED) stream << "optional, ";
stream << Help << std::endl;

}

LongArgument::LongArgument(const char *name, const char *help, Requirement required, long defaultvalue) : Argument(name, help, required) {

Value = defaultvalue;

}

bool LongArgument::parse(const char *s) {

if (sscanf(s, "%ld", &Value) == 1)
	return true;
setError("not a number");
return false;

}

void LongArgument::formatHelp(std::ostream &stream) const {

stream << "--" << Name << "=number\t";
if (Required == NOT_REQUIRED) stream << "optional, ";
stream << Help << std::endl;

}

StringArgument::StringArgument(const char *name, const char *help, Requirement required, const char *defaultvalue) : Argument(name, help, required) {

if (defaultvalue == NULL)
    Value = NULL;
else {
	Value = new char[strlen(defaultvalue) + 1];
	strcpy(Value, defaultvalue);
}

}

StringArgument::~StringArgument() {

if (Value != NULL) delete Value;

}

bool StringArgument::parse(const char *s) {

if (Value != NULL) delete Value;
Value = new char[strlen(s) + 1];
strcpy(Value, s);
return true;

}

void StringArgument::formatHelp(std::ostream &stream) const {

stream << "--" << Name << "=string\t";
if (Required == NOT_REQUIRED) stream << "optional, ";
stream << Help << std::endl;

}

DistributionArgument::DistributionArgument(const char *name, const char *help, Requirement required, SimDistribution *defaultvalue) : Argument(name, help, required) {

Value = defaultvalue;
EnableExp = true;
EnableGamma = true;
EnableNormal = true;
EnableDiscrete = true;
EnableNULL = true;

}

DistributionArgument::~DistributionArgument() {

if (Value != NULL) delete Value;

}

bool DistributionArgument::parse(const char *s) {

if (Value != NULL) {
	delete Value;
	Value = NULL;
}
if (strstr(s, "exp,") == s) {
	if (!EnableExp) {
		setError("exponential distribution is not supported");
		return false;
	}
	const char *arg = &s[strlen("exp,")];
	float mean;
	if (sscanf(arg, "%f", &mean) != 1) {
		setError("the mean of the exponential distribution is not given");
		return false;
	}
	Value = new SimExpDistribution(1 / mean);
}
else if (strstr(s, "gamma,") == s) {
	if (!EnableGamma) {
		setError("gamma distribution is not supported");
		return false;
	}
	const char *arg = &s[strlen("gamma,")];
	float mean, var;
	if (sscanf(arg, "%f,%f", &mean, &var) != 2) {
		setError("both the mean and the variance of the gamma distribution must be given");
		return false;
	}
	float theta = var / mean;
	float shape = mean / theta;
	Value = new SimGammaDistribution(shape, theta);
}
else if (strstr(s, "normal,") == s) {
	if (!EnableNormal) {
		setError("normal distribution is not supported");
		return false;
	}
	const char *arg = &s[strlen("normal,")];
	float mean, std;
	if (sscanf(arg, "%f,%f", &mean, &std) != 2) {
		setError("both the mean and the standard deviation of the normal distribution must be given");
		return false;
	}
	Value = new SimNormalDistribution(mean, std);
}
else if (strstr(s, "NULL") == s) {
	if (!EnableNULL) {
		setError("NULL is not supported");
		return false;
	}
}
else {
          SimDiscreteDistribution *dist = new SimDiscreteDistribution();
          float point, value;
          while (*s != 0) {
              if (sscanf(s, "%f,%f", &point, &value) == 2) {
                  while (*s != 0 && *s != '/') s++;
                  if (*s != 0) s++;
                  dist->set(point, value);
              }
              else break;
          }
          if (*s != 0 && dist->points() > 0) {
              delete dist;
              setError("the format of the discrete distribution is wrong");
              return false;
          }
          if (*s != 0) {
              delete dist;
              setError("unrecognized distribution format");
              return false;
          }
          Value = dist;
}	
return true;

}

void DistributionArgument::formatHelp(std::ostream &stream) const {

stream << "--" << Name << "=<distribution>\t";
if (Required == NOT_REQUIRED) stream << "optional, ";
stream << Help << std::endl;
stream << "\tallowed <distribution> includes:";
if (EnableExp) stream << " exponential";
if (EnableGamma) stream << " gamma";
if (EnableNormal) stream << " normal";
if (EnableDiscrete) stream << " discrete";
stream << std::endl;

}

void DistributionArgument::formatDistributionHelp(std::ostream &stream) {

stream << "<distribution> can be one of the following:" << std::endl;
stream << "\texp,mean\texponential distribution, where mean is a number" << std::endl;
stream << "\tgamma,mean,variance\tgamma distribution, where mean and variance are numbers" << std::endl;
stream << "\tnormal,mean,std\tnormal distribution, where mean and std are numbers" << std::endl;
      stream << "\tvalue1,frequency1/value1,frequency2/...\tdiscrete distribution, where each number is the frequency for value1, value2,..." << std::endl;

}

Parameters::Parameters() { }

Parameters::~Parameters() { }

void Parameters::usage(const char *program) const {

  std::cerr<<"Usage: "<<program<<" parameters"<<std::endl;
  std::cerr<<"Parameters can be:"<<std::endl;
  bool hasdist = false;
  for (std::map<std::string, Argument*>::const_iterator i = Arguments.begin();
  	 i != Arguments.end(); i++)
  {
  	if (!hasdist && dynamic_cast<DistributionArgument*>(i->second) != NULL)
  		hasdist = true;
	i->second->formatHelp(std::cerr);
  }
  if (hasdist) {
  	std::cerr<<std::endl;
  	DistributionArgument::formatDistributionHelp(std::cerr);	
}

}

bool Parameters::parseFile(const char *file) {

  std::ifstream f(file);
  if (f.bad()) {
      std::cerr<<"Cannot read parameter file "<<file<<std::endl;
      return false;
  }
  std::string line;
  while (!f.eof()) {
      getline(f, line);
      int l = line.length();
      // skip empty lines
      if (l == 0) continue;
      char s[l + 3];
      // prepend '--' to each line
      s[0] = s[1] = '-';
      int nonspace = -1, k = 2;
      for (int i = 0; i < l; i++) {
          // trim the white space
          while (i < l && line[i] == ' ' || line[i] == '\t' || line[i] == '\r') i++;
          if (i == l) break;
          // if the spaces are between two wods, keep them
          if (nonspace >= 0 && (isalnum(line[nonspace]) || line[nonspace] == '_')
              && (isalnum(line[i]) || line[i] == '_')) {
              for (int j = nonspace + 1; j < i; j++) s[k++] = line[j];
          }
          s[k++] = line[i];
          nonspace = i;
      }
      // skip empty lines
      if (k == 0) continue;
      // skip comments, i.e., lines starting with #
      if (s[2] == '#') continue;
      s[k] = 0;
      if (!parseArgument(s)) return false;
  }
  return true;

}

bool Parameters::parseArgument(const char *arg) {

  bool result;
  if (arg[0] != '-') return parseFile(arg);
  std::map<std::string, Argument*>::iterator i;
  for (i = Arguments.begin(); i != Arguments.end(); i++) {
      const char *arguments = i->second->parsable(arg);
      if (arguments != NULL) {
          result = i->second->parse(arguments);
          if (result) {
              i->second->setParsed(true);
              return true;
          }
          break;
      }
  }
  if (i == Arguments.end())
      std::cerr << "unrecognized argument " << arg << std::endl;
  else
      std::cerr << i->second->error() << std::endl;
  return false;

}

bool Parameters::parse(int args, const char *argv[]) {

  for (int i = 1; i < args; i++)
      if (!parseArgument(argv[i])) return false;
  std::map<std::string, Argument*>::iterator j;
  for (j = Arguments.begin(); j != Arguments.end(); j++)
  	if (j->second->required() && !j->second->set()) {
          std::cerr << "Error: argument " << j->second->name() << " is required" << std::endl;
          return false;
      }
  return true;

}

void Parameters::addArgument(Argument &arg) {

std::string name(arg.name());
Arguments[name] = &arg;

}

const Argument *Parameters::value(const char *name) const {

std::string n(name);
  std::map<std::string, Argument*>::const_iterator i =	Arguments.find(n);
  if (i == Arguments.end()) return NULL;
  return i->second;

}

const IntArgument *Parameters::intValue(const char *name) const {

  return dynamic_cast<const IntArgument*>(value(name));

}

const LongArgument *Parameters::longValue(const char *name) const {

  return dynamic_cast<const LongArgument*>(value(name));

}

const FloatArgument *Parameters::floatValue(const char *name) const {

  return dynamic_cast<const FloatArgument*>(value(name));

}

const BoolArgument *Parameters::boolValue(const char *name) const {

  return dynamic_cast<const BoolArgument*>(value(name));

}

const StringArgument *Parameters::stringValue(const char *name) const {

  return dynamic_cast<const StringArgument*>(value(name));

}

const DistributionArgument *Parameters::distributionValue(const char *name) const {

  return dynamic_cast<const DistributionArgument*>(value(name));

}

bool Parameters::set(const char *name) const {

const Argument *arg = value(name);
return arg != NULL && arg->set();

} </content> <use name=“parameters.h”/>