PetaVision  Alpha
ConfigParser.cpp
1 /*
2  * ConfigParser.cpp
3  *
4  * Created on: Nov 23, 2016
5  * Author: Pete Schultz
6  */
7 
8 #include "ConfigParser.hpp"
9 #include "utils/PVLog.hpp"
10 #include <cctype>
11 #include <exception>
12 #include <fstream>
13 #include <sstream>
14 #include <stdexcept>
15 #include <string>
16 
17 namespace PV {
18 
19 ConfigParser::ConfigParser(std::istream &configStream, bool allowUnrecognizedArguments) {
20  initialize(configStream, allowUnrecognizedArguments);
21  if (!configStream.eof() && configStream.fail()) {
22  Fatal() << "Reading configuration stream failed.\n";
23  }
24 }
25 
26 void ConfigParser::initialize(std::istream &configStream, bool allowUnrecognizedArguments) {
27  mAllowUnrecognizedArguments = allowUnrecognizedArguments;
28  std::string line;
29  unsigned int lineNumber = 0;
30  while (std::getline(configStream, line)) {
31  lineNumber++;
32  auto start = line.begin();
33  // seek to first non-whitespace character
34  while (start != line.end() && std::isspace((int)(*start))) {
35  ++start;
36  }
37  if (start >= line.end()) { // Skip if line is all whitespace
38  continue;
39  }
40  if (*start == '#') { // Skip if line is a comment
41  continue;
42  }
43  auto colonPosition = line.find(':', (std::size_t)(start - line.begin()));
44  FatalIf(
45  colonPosition == std::string::npos,
46  "configuration line \"%s\" does not have the format \"argument:value\".\n");
47 
48  std::string argument{start, line.begin() + colonPosition};
49  argument = stripLeadingTrailingWhitespace(argument);
50  std::string value{line.begin() + colonPosition + 1, line.end()};
51  value = stripLeadingTrailingWhitespace(value);
52  try {
53  bool status = mConfig.setArgumentUsingString(argument, value);
54  if (!status) {
55  handleUnrecognized(argument, value, lineNumber);
56  }
57  } catch (...) {
58  Fatal() << "Unable to parse config file line number " << lineNumber << ", " << argument
59  << ":" << value << "\n";
60  }
61  }
62  bool restartFlag = mConfig.getBooleanArgument("Restart");
63  std::string checkpointReadDirectory = mConfig.getStringArgument("CheckpointReadDirectory");
64  bool checkpointReadConflict = restartFlag && !checkpointReadDirectory.empty();
65  FatalIf(
66  checkpointReadConflict,
67  "ConfigParser: cannot set both the restart flag and the checkpoint read directory.\n");
68 }
69 
71  std::string const &argument,
72  std::string const &value,
73  int lineNumber) {
74  if (!mAllowUnrecognizedArguments) {
75  Fatal() << "allowUnrecognizedArguments is false but line number " << lineNumber << " ("
76  << argument << ":" << value << ") is not a recognized argument.\n";
77  }
78 }
79 
80 std::string ConfigParser::stripLeadingTrailingWhitespace(std::string const &inString) {
81  auto start = inString.begin();
82  auto stop = inString.end();
83  while (start < stop && std::isspace((int)(*start))) {
84  ++start;
85  }
86  while (stop > start && std::isspace((int)(*(stop - 1)))) {
87  --stop;
88  }
89  std::string outString{start, stop};
90  return outString;
91 }
92 
93 std::string ConfigParser::createString(
94  bool requireReturnFlag,
95  std::string const &outputPath,
96  std::string const &paramsFile,
97  std::string const &logFile,
98  std::string const &gpuDevices,
99  unsigned int randomSeed,
100  std::string const &workingDir,
101  bool restartFlag,
102  std::string const &checkpointReadDir,
103  bool useDefaultNumThreads,
104  int numThreads,
105  int numRows,
106  int numColumns,
107  int batchWidth,
108  bool dryRunFlag) {
109  std::string configString;
110  FatalIf(
111  restartFlag && !checkpointReadDir.empty(),
112  "ConfigParser::createStream called with both Restart and CheckpointReadDirectory set.\n");
113  if (requireReturnFlag) {
114  configString.append("RequireReturn:true\n");
115  }
116  if (!outputPath.empty()) {
117  configString.append("OutputPath:").append(outputPath).append("\n");
118  }
119  if (!paramsFile.empty()) {
120  configString.append("ParamsFile:").append(paramsFile).append("\n");
121  }
122  if (!logFile.empty()) {
123  configString.append("LogFile:").append(logFile).append("\n");
124  }
125  if (!gpuDevices.empty()) {
126  configString.append("GPUDevices:").append(gpuDevices).append("\n");
127  }
128  if (randomSeed) {
129  configString.append("RandomSeed:").append(std::to_string(randomSeed)).append("\n");
130  }
131  if (!workingDir.empty()) {
132  configString.append("WorkingDirectory:").append(workingDir).append("\n");
133  }
134  if (restartFlag) {
135  configString.append("Restart:true\n");
136  }
137  if (!checkpointReadDir.empty()) {
138  configString.append("CheckpointReadDirectory:").append(checkpointReadDir).append("\n");
139  }
140  if (useDefaultNumThreads) {
141  configString.append("NumThreads:-\n");
142  }
143  else if (numThreads >= 0) {
144  configString.append("NumThreads:").append(std::to_string(numThreads)).append("\n");
145  }
146  if (numRows) {
147  configString.append("NumRows:").append(std::to_string(numRows)).append("\n");
148  }
149  if (numColumns) {
150  configString.append("NumColumns:").append(std::to_string(numColumns)).append("\n");
151  }
152  if (batchWidth) {
153  configString.append("BatchWidth:").append(std::to_string(batchWidth)).append("\n");
154  }
155  if (dryRunFlag) {
156  configString.append("DryRun:true\n");
157  }
158  return configString;
159 }
160 
161 } // namespace PV
ConfigParser(std::istream &configStream, bool allowUnrecognizedArguments)
void initialize(std::istream &inputStream, bool allowUnrecognizedArguments)
std::string stripLeadingTrailingWhitespace(std::string const &inString)
void handleUnrecognized(std::string const &argument, std::string const &value, int linenumber)