CASM  1.1.0
A Clusters Approach to Statistical Mechanics
InputParser_impl.hh
Go to the documentation of this file.
1 #ifndef CASM_InputParser_impl
2 #define CASM_InputParser_impl
3 
4 #include "casm/casm_io/Help.hh"
5 #include "casm/casm_io/Log.hh"
8 #include "casm/misc/TypeInfo.hh"
9 
10 namespace CASM {
11 
13 template <typename T>
14 template <typename... Args>
15 InputParser<T>::InputParser(jsonParser const &_input, Args &&... args)
16  : KwargsParser(_input, "", true) {
17  parse(*this, std::forward<Args>(args)...);
18 }
19 
22 template <typename T>
23 template <typename... Args>
24 InputParser<T>::InputParser(jsonParser const &_input, fs::path _path,
25  bool _required, Args &&... args)
26  : KwargsParser(_input, _path, _required) {
27  if (this->exists()) {
28  parse(*this, std::forward<Args>(args)...);
29  }
30 }
31 
33 template <typename T>
34 template <typename CustomParse>
35 InputParser<T>::InputParser(CustomParse f_parse, jsonParser const &_input)
36  : KwargsParser(_input, "", true) {
37  f_parse(*this);
38 }
39 
42 template <typename T>
43 template <typename CustomParse>
44 InputParser<T>::InputParser(CustomParse f_parse, jsonParser const &_input,
45  fs::path _path, bool _required)
46  : KwargsParser(_input, _path, _required) {
47  if (this->exists()) {
48  f_parse(*this);
49  }
50 }
51 
52 template <typename T>
53 template <typename RequiredType, typename... Args>
54 std::unique_ptr<RequiredType> InputParser<T>::require(fs::path option,
55  Args &&... args) {
56  auto it = self.find_at(option);
57  std::unique_ptr<RequiredType> res;
58  if (it == self.end()) {
59  std::stringstream msg;
60  msg << "Error: missing required option '" << option.string() << "'.";
61  this->insert_error(option, msg.str());
62  return res;
63  }
64 
65  try {
66  return it->template make<RequiredType>(std::forward<Args>(args)...);
67  } catch (std::exception &e) {
68  std::stringstream msg;
69  msg << "Error: could not construct type '"
70  << CASM::type_name<RequiredType>() << "' from option '"
71  << option.string() << "'.";
72  this->insert_error(option, msg.str());
73  return res;
74  }
75 }
76 
77 template <typename T>
78 template <typename RequiredType, typename... Args>
79 void InputParser<T>::require(RequiredType &value, fs::path option,
80  Args &&... args) {
81  auto it = self.find_at(option);
82  std::unique_ptr<RequiredType> res;
83  if (it == self.end()) {
84  std::stringstream msg;
85  msg << "Error: missing required option '" << option.string() << "'.";
86  this->insert_error(option, msg.str());
87  return;
88  }
89 
90  try {
91  it->template get<RequiredType>(value, std::forward<Args>(args)...);
92  return;
93  } catch (std::exception &e) {
94  std::stringstream msg;
95  msg << "Error: could not construct type '"
96  << CASM::type_name<RequiredType>() << "' from option '"
97  << option.string() << "'.";
98  this->insert_error(option, msg.str());
99  return;
100  }
101 }
102 
103 template <typename T>
104 template <typename RequiredType, typename... Args>
105 std::unique_ptr<RequiredType> InputParser<T>::optional(fs::path option,
106  Args &&... args) {
107  jsonParser const *ptr;
108  if (option.empty()) {
109  ptr = &self;
110  } else {
111  auto it = self.find_at(option);
112  if (it == self.end()) {
113  return std::unique_ptr<RequiredType>();
114  } else {
115  ptr = &(*it);
116  }
117  }
118 
119  try {
120  return ptr->make<RequiredType>(std::forward<Args>(args)...);
121  } catch (std::exception &e) {
122  std::stringstream msg;
123  msg << "Error: could not construct type '"
124  << CASM::type_name<RequiredType>() << "' from option '"
125  << option.string() << "'.";
126  this->insert_error(option, msg.str());
127  return std::unique_ptr<RequiredType>();
128  }
129 }
130 
131 template <typename T>
132 template <typename RequiredType, typename... Args>
133 void InputParser<T>::optional(RequiredType &value, fs::path option,
134  Args &&... args) {
135  jsonParser const *ptr;
136  if (option.empty()) {
137  ptr = &self;
138  } else {
139  auto it = self.find_at(option);
140  if (it == self.end()) {
141  return;
142  } else {
143  ptr = &(*it);
144  }
145  }
146 
147  try {
148  ptr->get<RequiredType>(value, std::forward<Args>(args)...);
149  return;
150  } catch (std::exception &e) {
151  std::stringstream msg;
152  msg << "Error: could not construct type '"
153  << CASM::type_name<RequiredType>() << "' from option '"
154  << option.string() << "'.";
155  this->insert_error(option, msg.str());
156  return;
157  }
158 }
159 
160 template <typename T>
161 template <typename RequiredType, typename... Args>
162 RequiredType InputParser<T>::optional_else(fs::path option,
163  const RequiredType &_default,
164  Args &&... args) {
165  jsonParser const *ptr;
166  if (option.empty()) {
167  ptr = &self;
168  } else {
169  auto it = self.find_at(option);
170  if (it == self.end()) {
171  return _default;
172  } else {
173  ptr = &(*it);
174  }
175  }
176 
177  try {
178  return ptr->get<RequiredType>(std::forward<Args>(args)...);
179  } catch (std::exception &e) {
180  std::stringstream msg;
181  msg << "Error: could not construct type '"
182  << CASM::type_name<RequiredType>() << "' from option '"
183  << option.string() << "'.";
184  this->insert_error(option, msg.str());
185  return _default;
186  }
187 }
188 
189 template <typename T>
190 template <typename RequiredType, typename... Args>
191 void InputParser<T>::optional_else(RequiredType &value, fs::path option,
192  const RequiredType &_default,
193  Args &&... args) {
194  jsonParser const *ptr;
195  if (option.empty()) {
196  ptr = &self;
197  } else {
198  auto it = self.find_at(option);
199  if (it == self.end()) {
200  value = _default;
201  return;
202  } else {
203  ptr = &(*it);
204  }
205  }
206 
207  try {
208  ptr->get<RequiredType>(value, std::forward<Args>(args)...);
209  return;
210  } catch (std::exception &e) {
211  std::stringstream msg;
212  msg << "Error: could not construct type '"
213  << CASM::type_name<RequiredType>() << "' from option '"
214  << option.string() << "'.";
215  this->insert_error(option, msg.str());
216  return;
217  }
218 }
219 
220 template <typename T>
221 template <typename RequiredType, typename... Args>
222 std::shared_ptr<InputParser<RequiredType>> InputParser<T>::subparse(
223  fs::path option, Args &&... args) {
224  auto subparser = std::make_shared<InputParser<RequiredType>>(
225  this->input, this->relpath(option), true, std::forward<Args>(args)...);
226  subparser->type_name = CASM::type_name<RequiredType>();
227  insert(subparser->path, subparser);
228  return subparser;
229 }
230 
231 template <typename T>
232 template <typename RequiredType, typename... Args>
233 std::shared_ptr<InputParser<RequiredType>> InputParser<T>::subparse_if(
234  fs::path option, Args &&... args) {
235  auto subparser = std::make_shared<InputParser<RequiredType>>(
236  this->input, this->relpath(option), false, std::forward<Args>(args)...);
237  subparser->type_name = CASM::type_name<RequiredType>();
238  insert(subparser->path, subparser);
239  return subparser;
240 }
241 
242 template <typename T>
243 template <typename RequiredType, typename... Args>
244 std::shared_ptr<InputParser<RequiredType>> InputParser<T>::subparse_else(
245  fs::path option, const RequiredType &_default, Args &&... args) {
246  auto subparser =
247  subparse_if<RequiredType>(option, std::forward<Args>(args)...);
248  if (!subparser->exists()) {
249  subparser->value = notstd::make_unique<RequiredType>(_default);
250  }
251  return subparser;
252 }
253 
254 template <typename T>
255 template <typename RequiredType, typename... Args>
256 std::shared_ptr<InputParser<RequiredType>> InputParser<T>::parse_as(
257  Args &&... args) {
258  auto subparser = std::make_shared<InputParser<RequiredType>>(
259  this->input, this->path, true, std::forward<Args>(args)...);
260  subparser->type_name = CASM::type_name<RequiredType>();
261  insert(subparser->path, subparser);
262  return subparser;
263 }
264 
265 template <typename ErrorType>
267  ErrorType error) {
268  if (!parser.valid()) {
269  jsonParser report = make_report(parser);
270  log << std::endl;
271  print_errors(parser, log, "Error Summary");
272  log << std::endl;
273  log.indent() << report << std::endl << std::endl;
274  throw error;
275  }
276  if (parser.all_warnings().size()) {
277  jsonParser report = make_report(parser);
278  log << std::endl;
279  print_warnings(parser, log, "Warning Summary");
280  log << std::endl;
281  log.indent() << report << std::endl << std::endl;
282  }
283 }
284 
285 template <typename T>
286 void parse(InputParser<T> &parser) {
287  if (parser.exists()) {
288  try {
289  parser.value = parser.self.template make<T>();
290  } catch (std::exception &e) {
291  parser.error.insert(std::string("Error: could not construct type '") +
292  CASM::type_name<T>() + "'.");
293  }
294  }
295 }
296 } // namespace CASM
297 
298 #endif
std::unique_ptr< RequiredType > optional(fs::path option, Args &&... args)
InputParser(jsonParser const &_input, Args &&... args)
Construct parser and use parse(*this)
std::shared_ptr< InputParser< RequiredType > > subparse_else(fs::path option, const RequiredType &_default, Args &&... args)
RequiredType optional_else(fs::path option, const RequiredType &_default, Args &&... args)
std::unique_ptr< RequiredType > require(fs::path option, Args &&... args)
std::shared_ptr< InputParser< RequiredType > > subparse(fs::path option, Args &&... args)
std::shared_ptr< InputParser< RequiredType > > parse_as(Args &&... args)
std::unique_ptr< T > value
Definition: InputParser.hh:234
std::shared_ptr< InputParser< RequiredType > > subparse_if(fs::path option, Args &&... args)
Definition: Log.hh:48
Log & indent()
Definition: Log.hh:289
jsonParser::iterator find_at(const fs::path &path)
Return iterator to sub-object or element, or 'end' if not found.
Definition: jsonParser.cc:556
std::unique_ptr< T > make(Args &&... args) const
Get data from json.
Definition: jsonParser.hh:806
T get(Args &&... args) const
Get data from json, using one of several alternatives.
Definition: jsonParser.hh:716
int error_index insert_error(std::string what)
Main CASM namespace.
Definition: APICommand.hh:8
Log & log()
Definition: Log.hh:424
void print_errors(KwargsParser const &parser, Log &log, std::string header="Errors")
Formatted print error messages, including all subparsers.
Definition: InputParser.cc:168
void print_warnings(KwargsParser const &parser, Log &log, std::string header="Warnings")
Formatted print warning messages, including all subparsers.
Definition: InputParser.cc:150
void report_and_throw_if_invalid(KwargsParser const &parser, Log &log, ErrorType error)
jsonParser make_report(KwargsParser const &parser)
Return parser.input with error and warning messages added in place.
Definition: InputParser.cc:214
void parse(InputParser< ConfigEnumOptions > &parser, std::string method_name, PrimClex const &primclex, DataFormatterDictionary< Configuration > const &dict)
bool valid() const
Return true if this and and all subparsers are valid.
Definition: InputParser.cc:56
std::map< fs::path, std::set< std::string > > all_warnings() const
Return warning messages from this and all subparsers.
Definition: InputParser.cc:61
jsonParser const & self
Definition: InputParser.hh:81
bool exists() const
Definition: InputParser.cc:44
std::set< std::string > error
Definition: Validator.hh:11