Teuchos - Trilinos Tools Package  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Teuchos_YamlParser.cpp
1 // @HEADER
2 //
3 // ***********************************************************************
4 //
5 // Teuchos: Common Tools Package
6 // Copyright (2004) Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact
39 // Dan Ibanez (daibane@sandia.gov)
40 //
41 // ***********************************************************************
42 //
43 // @HEADER
44 
45 #include <iostream>
46 #include <iomanip>
47 #include <ios>
48 #include <sstream>
49 #include <cctype>
50 #include <fstream>
51 
55 #include "Teuchos_TwoDArray.hpp"
56 
57 #include "Teuchos_Reader.hpp"
58 
59 #ifdef HAVE_TEUCHOSPARAMETERLIST_YAMLCPP
60 #include "yaml-cpp/yaml.h"
61 #endif // HAVE_TEUCHOSPARAMETERLIST_YAMLCPP
62 #include "Teuchos_YAML.hpp"
63 
64 
65 namespace Teuchos {
66 
67 #ifdef HAVE_TEUCHOSPARAMETERLIST_YAMLCPP
68 
69 /* see https://github.com/jbeder/yaml-cpp/issues/261
70  there are times when we want to insist that a parameter
71  value be interpreted as a string despite it being parseable
72  as a number.
73  the standard way to do this in YAML is to put the number in quotes,
74  i.e. '1e-3' instead of 1e-3.
75  however, the usual YAML::Node::as<T> system doesn't respect quoting
76  when trying to cast to numbers.
77  so, this is our own version of as<T>, called quoted_as<T>, using
78  the Tag workaround suggested in the issue linked above. */
79 
80 template <typename T>
81 struct QuotedAs {
82  static T eval(::YAML::Node const& node) {
83  // this "!" tag apparently denotes that the value was quoted
84  if (node.Tag() == "!") {
85  throw std::runtime_error("quoted_as from quoted string to number");
86  }
87  return node.as<T>();
88  }
89 };
90 
91 template <>
92 struct QuotedAs<std::string> {
93  // only a cast to string will succeed if quoted
94  static std::string eval(::YAML::Node const& node) { return node.as<std::string>(); }
95 };
96 
97 template <typename T>
98 static T quoted_as(::YAML::Node const& node) { return QuotedAs<T>::eval(node); }
99 
100 template<typename T>
101 Teuchos::Array<T> getYamlArray(const ::YAML::Node& node)
102 {
103  Teuchos::Array<T> arr;
104  for(::YAML::const_iterator it = node.begin(); it != node.end(); it++)
105  {
106  arr.push_back(quoted_as<T>(*it));
107  }
108  return arr;
109 }
110 
111 bool checkYamlTwoDArrayIsRagged(const ::YAML::Node& node)
112 {
113  bool ragged = false;
114  for (::YAML::const_iterator it = node.begin(); it != node.end(); ++it)
115  {
116  if (it->size() != node.begin()->size())
117  {
118  ragged=true;
119  }
120  }
121  return ragged;
122 }
123 
124 template<typename T> Teuchos::TwoDArray<T> getYamlTwoDArray(const ::YAML::Node& node)
125 {
127  typename Teuchos::TwoDArray<T>::size_type i, j;
128  arr.resizeRows(node.size());
129  arr.resizeCols(node.begin()->size());
130  i = 0;
131  for (::YAML::const_iterator rit = node.begin(); rit != node.end(); ++rit)
132  {
133  j = 0;
134  for (::YAML::const_iterator cit = rit->begin(); cit != rit->end(); ++cit)
135  {
136  arr(i, j) = quoted_as<T>(*cit);
137  ++j;
138  }
139  ++i;
140  }
141  return arr;
142 }
143 
144 int getYamlArrayDim(const ::YAML::Node& node)
145 {
146  int ndim = 0;
147  if (node.Type() == ::YAML::NodeType::Sequence)
148  {
149  ++ndim;
150  if (node.begin()->Type() == ::YAML::NodeType::Sequence)
151  {
152  ++ndim;
153  if (node.begin()->begin()->Type() == ::YAML::NodeType::Sequence)
154  {
155  ++ndim;
156  }
157  }
158  }
159  return ndim;
160 }
161 
162 template <typename tarray_t, typename T>
163 tarray_t getYaml2DRaggedArray(::YAML::Node node, int ndim, std::string key)
164 {
165  tarray_t base_arr;
166  if (ndim == 2) {
167  Teuchos::Array<T> sub_arr;
168  for (::YAML::const_iterator it1 = node.begin(); it1 != node.end(); ++it1) {
169  for (::YAML::const_iterator it2 = it1->begin(); it2 != it1->end(); ++it2) {
170  sub_arr.push_back(quoted_as<T>(*it2));
171  } base_arr.push_back(sub_arr);
172  sub_arr.clear();
173  }
174  }
175  else
176  {
177  throw YamlSequenceError(std::string("MDArray \"" + key + "\" must have dim 2."));
178  }
179  return base_arr;
180 }
181 
182 // This handles the requested use case of a list of 2D arrays; further nesting would require a getYaml4DArray() function,
183 // which could be straightforwardly implemented along the lines of the below function.
184 
185 template <typename tarray_t, typename T>
186 tarray_t getYaml3DArray(::YAML::Node node, int ndim, std::string key)
187 {
188  tarray_t base_arr;
189  if (ndim == 3) {
191  Teuchos::Array<T> sub_sub_arr;
192  for (::YAML::const_iterator it1 = node.begin(); it1 != node.end(); ++it1) {
193  for (::YAML::const_iterator it2 = it1->begin(); it2 != it1->end(); ++it2) {
194  for (::YAML::const_iterator it3 = it2->begin(); it3 != it2->end(); ++it3) {
195  sub_sub_arr.push_back(quoted_as<T>(*it3));
196  } sub_arr.push_back(sub_sub_arr);
197  sub_sub_arr.clear();
198  } base_arr.push_back(sub_arr);
199  sub_arr.clear();
200  }
201  }
202  else
203  {
204  throw YamlSequenceError(std::string("MDArray \"" + key + "\" must have dim 3."));
205  }
206  return base_arr;
207 }
208 
209 template <typename T>
210 void safe_set_entry(ParameterList& list, std::string const& name_in, T const& entry_in) {
211  TEUCHOS_TEST_FOR_EXCEPTION(list.isParameter(name_in), ParserFail,
212  "Parameter \"" << name_in << "\" already exists in list \"" << list.name() << "\"\n");
213  list.set(name_in, entry_in);
214 }
215 #endif // HAVE_TEUCHOSPARAMETERLIST_YAMLCPP
216 
217 std::string remove_trailing_whitespace(std::string const& in) {
218  std::size_t new_end = 0;
219  for (std::size_t ri = 0; ri < in.size(); ++ri) {
220  std::size_t i = in.size() - 1 - ri;
221  if (in[i] != ' ' && in[i] != '\t') {
222  new_end = i + 1;
223  break;
224  }
225  }
226  return in.substr(0, new_end);
227 }
228 
229 std::string remove_trailing_whitespace_and_newlines(std::string const& in) {
230  std::size_t new_end = 0;
231  for (std::size_t ri = 0; ri < in.size(); ++ri) {
232  std::size_t i = in.size() - 1 - ri;
233  if (in[i] != ' ' && in[i] != '\t' && in[i] != '\n' && in[i] != '\r') {
234  new_end = i + 1;
235  break;
236  }
237  }
238  return in.substr(0, new_end);
239 }
240 
241 template <typename T>
242 bool is_parseable_as(std::string const& text) {
243  std::istringstream ss(text);
244  T val;
245  ss >> std::noskipws >> val;
246  return ss.eof() && !ss.fail();
247 }
248 
249 template <>
250 bool is_parseable_as<int>(std::string const& text) {
251  std::istringstream ss(text);
252  using LL = long long;
253  LL val;
254  ss >> std::noskipws >> val;
255  return ss.eof() && !ss.fail() &&
256  (val >= LL(std::numeric_limits<int>::min())) &&
257  (val <= LL(std::numeric_limits<int>::max()));
258 }
259 
260 template <typename T>
261 T parse_as(std::string const& text) {
262  std::istringstream ss(text);
263  T value;
264  ss >> value;
265  return value;
266 }
267 
268 // http://en.cppreference.com/w/cpp/string/byte/tolower
269 static char my_tolower(char ch)
270 {
271  return std::tolower(static_cast<unsigned char>(ch));
272 }
273 
274 // http://en.cppreference.com/w/cpp/string/byte/isdigit
275 static bool my_isdigit(char ch)
276 {
277  return std::isdigit(static_cast<unsigned char>(ch));
278 }
279 
280 template <>
281 bool is_parseable_as<bool>(std::string const& text) {
282  std::string lower;
283  for (std::size_t i = 0; i < text.size(); ++i) {
284  lower.push_back(my_tolower(text[i]));
285  }
286  return lower == "true" || lower == "yes" ||
287  lower == "false" || lower == "no";
288 }
289 
290 template <>
291 bool parse_as<bool>(std::string const& text) {
292  std::string lower;
293  for (std::size_t i = 0; i < text.size(); ++i) {
294  lower.push_back(my_tolower(text[i]));
295  }
296  return !(lower == "false" || lower == "no");
297 }
298 
299 struct PLPair {
300  std::string key;
301  ParameterEntry value;
302 };
303 
304 struct Scalar {
305  enum Source {
306  RAW,
307  DQUOTED,
308  SQUOTED,
309  BLOCK
310  };
311  /* order matters, a higher type should be convertible to a lower type */
312  enum Type {
313  STRING = 0,
314  DOUBLE = 1,
315  LONG_LONG = 2,
316  INT = 3,
317  BOOL = 4
318  };
319  int source;
320  int tag_type;
321  std::string text;
322  int infer_type() const {
323  if (tag_type != -1) {
324  return tag_type;
325  }
326  if (source != RAW) {
327  return STRING;
328  }
329  if (is_parseable_as<bool>(text)) {
330  return BOOL;
331  }
332  if (is_parseable_as<int>(text)) {
333  return INT;
334  }
335  if (is_parseable_as<long long>(text)) {
336  return LONG_LONG;
337  }
338  if (is_parseable_as<double>(text)) {
339  return DOUBLE;
340  }
341  return STRING;
342  }
343 };
344 
345 bool operator==(Scalar const&, Scalar const&) { return false; }
346 std::ostream& operator<<(std::ostream& os, Scalar const&) { return os; }
347 
348 void safe_set_entry(ParameterList& list, std::string const& name_in, ParameterEntry const& entry_in) {
349  TEUCHOS_TEST_FOR_EXCEPTION(list.isParameter(name_in), ParserFail,
350  "Parameter \"" << name_in << "\" already exists in list \"" << list.name() << "\"\n");
351  list.setEntry(name_in, entry_in);
352 }
353 
354 namespace YAMLParameterList {
355 
356 class Reader : public Teuchos::Reader {
357  public:
358  Reader():Teuchos::Reader(Teuchos::YAML::ask_reader_tables()) {}
359  virtual ~Reader() {}
360  protected:
361  enum {
362  TRIM_NORMAL,
363  TRIM_DASH
364  };
365  virtual void at_shift(any& result_any, int token, std::string& text) {
366  using std::swap;
367  switch (token) {
368  case Teuchos::YAML::TOK_NEWLINE: {
369  std::string& result = make_any_ref<std::string>(result_any);
370  swap(result, text);
371  break;
372  }
373  case Teuchos::YAML::TOK_SPACE:
374  case Teuchos::YAML::TOK_OTHER: {
375  result_any = text.at(0);
376  break;
377  }
378  }
379  }
380  virtual void at_reduce(any& result_any, int prod, std::vector<any>& rhs) {
381  using std::swap;
382  switch (prod) {
383  case Teuchos::YAML::PROD_DOC:
384  case Teuchos::YAML::PROD_DOC2: {
385  std::size_t offset = prod == Teuchos::YAML::PROD_DOC2 ? 1 : 0;
386  TEUCHOS_ASSERT(rhs.at(offset).has_value());
387  swap(result_any, rhs.at(offset));
388  TEUCHOS_ASSERT(result_any.type() == typeid(ParameterList));
389  break;
390  }
391  case Teuchos::YAML::PROD_TOP_BMAP: {
392  TEUCHOS_ASSERT(rhs.at(0).has_value());
393  TEUCHOS_ASSERT(rhs.at(0).type() == typeid(PLPair));
394  PLPair& pair = any_ref_cast<PLPair>(rhs.at(0));
395  any& pair_rhs_any = pair.value.getAny(/* set isUsed = */ false);
396  result_any = pair_rhs_any;
397  break;
398  }
399  case Teuchos::YAML::PROD_TOP_FIRST: {
400  if (rhs.at(0).type() == typeid(ParameterList)) {
401  swap(result_any, rhs.at(0));
402  }
403  break;
404  }
405  case Teuchos::YAML::PROD_TOP_NEXT: {
406  if (rhs.at(1).type() == typeid(ParameterList)) {
407  TEUCHOS_TEST_FOR_EXCEPTION(rhs.at(0).has_value(), ParserFail,
408  "Can't specify multiple top-level ParameterLists in one YAML file!\n");
409  swap(result_any, rhs.at(1));
410  } else {
411  swap(result_any, rhs.at(0));
412  }
413  break;
414  }
415  case Teuchos::YAML::PROD_BMAP_FIRST:
416  case Teuchos::YAML::PROD_FMAP_FIRST: {
417  TEUCHOS_ASSERT(rhs.at(0).type() == typeid(PLPair));
418  map_first_item(result_any, rhs.at(0));
419  TEUCHOS_ASSERT(result_any.type() == typeid(ParameterList));
420  break;
421  }
422  case Teuchos::YAML::PROD_BMAP_NEXT: {
423  map_next_item(result_any, rhs.at(0), rhs.at(1));
424  break;
425  }
426  case Teuchos::YAML::PROD_FMAP_NEXT: {
427  map_next_item(result_any, rhs.at(0), rhs.at(3));
428  break;
429  }
430  case Teuchos::YAML::PROD_BMAP_SCALAR:
431  case Teuchos::YAML::PROD_FMAP_SCALAR:
432  case Teuchos::YAML::PROD_FMAP_FMAP:
433  case Teuchos::YAML::PROD_FMAP_FSEQ: {
434  int scalar_type = interpret_tag(rhs.at(3));
435  map_item(result_any, rhs.at(0), rhs.at(4), scalar_type);
436  break;
437  }
438  case Teuchos::YAML::PROD_BMAP_BSCALAR: {
439  map_item(result_any, rhs.at(0), rhs.at(3), Scalar::STRING);
440  break;
441  }
442  case Teuchos::YAML::PROD_BMAP_BVALUE: {
443  map_item(result_any, rhs.at(0), rhs.at(4));
444  break;
445  }
446  case Teuchos::YAML::PROD_BVALUE_EMPTY: {
447  result_any = ParameterList();
448  break;
449  }
450  case Teuchos::YAML::PROD_BVALUE_BMAP:
451  case Teuchos::YAML::PROD_BVALUE_BSEQ: {
452  swap(result_any, rhs.at(1));
453  break;
454  }
455  case Teuchos::YAML::PROD_BMAP_FMAP: {
456  map_item(result_any, rhs.at(0), rhs.at(4));
457  break;
458  }
459  case Teuchos::YAML::PROD_BMAP_FSEQ: {
460  TEUCHOS_ASSERT(rhs.at(4).type() == typeid(Array<Scalar>) ||
461  rhs.at(4).type() == typeid(Array<Array<Scalar>>));
462  int scalar_type = interpret_tag(rhs.at(3));
463  map_item(result_any, rhs.at(0), rhs.at(4), scalar_type);
464  break;
465  }
466  case Teuchos::YAML::PROD_BSEQ_FIRST: {
467  seq_first_item(result_any, rhs.at(0));
468  break;
469  }
470  case Teuchos::YAML::PROD_BSEQ_NEXT: {
471  seq_next_item(result_any, rhs.at(0), rhs.at(1));
472  break;
473  }
474  case Teuchos::YAML::PROD_BSEQ_SCALAR: {
475  swap(result_any, rhs.at(3));
476  Scalar& scalar = any_ref_cast<Scalar>(result_any);
477  scalar.tag_type = interpret_tag(rhs.at(2));
478  break;
479  }
480  case Teuchos::YAML::PROD_BSEQ_BSCALAR: {
481  swap(result_any, rhs.at(2));
482  break;
483  }
484  case Teuchos::YAML::PROD_BSEQ_BMAP:
485  case Teuchos::YAML::PROD_BSEQ_BMAP_TRAIL:
486  case Teuchos::YAML::PROD_BSEQ_FMAP: {
487  throw ParserFail("Can't interpret a map inside a sequence as a Teuchos Parameter");
488  }
489  case Teuchos::YAML::PROD_BSEQ_BSEQ: {
490  swap(result_any, rhs.at(3));
491  break;
492  }
493  case Teuchos::YAML::PROD_BSEQ_BSEQ_TRAIL: {
494  swap(result_any, rhs.at(4));
495  break;
496  }
497  case Teuchos::YAML::PROD_BSEQ_FSEQ: {
498  swap(result_any, rhs.at(3));
499  break;
500  }
501  case Teuchos::YAML::PROD_FMAP: {
502  swap(result_any, rhs.at(2));
503  break;
504  }
505  case Teuchos::YAML::PROD_FMAP_EMPTY: {
506  result_any = ParameterList();
507  break;
508  }
509  case Teuchos::YAML::PROD_FSEQ: {
510  swap(result_any, rhs.at(2));
511  TEUCHOS_ASSERT(result_any.type() == typeid(Array<Scalar>) ||
512  result_any.type() == typeid(Array<Array<Scalar>>));
513  break;
514  }
515  case Teuchos::YAML::PROD_FSEQ_EMPTY: {
516  result_any = Array<Scalar>();
517  break;
518  }
519  case Teuchos::YAML::PROD_FSEQ_FIRST: {
520  seq_first_item(result_any, rhs.at(0));
521  break;
522  }
523  case Teuchos::YAML::PROD_FSEQ_NEXT: {
524  seq_next_item(result_any, rhs.at(0), rhs.at(3));
525  break;
526  }
527  case Teuchos::YAML::PROD_FSEQ_SCALAR: {
528  swap(result_any, rhs.at(1));
529  Scalar& scalar = any_ref_cast<Scalar>(result_any);
530  scalar.tag_type = interpret_tag(rhs.at(0));
531  break;
532  }
533  case Teuchos::YAML::PROD_FSEQ_FSEQ:
534  case Teuchos::YAML::PROD_FSEQ_FMAP: {
535  swap(result_any, rhs.at(1));
536  break;
537  }
538  case Teuchos::YAML::PROD_SCALAR_QUOTED:
539  case Teuchos::YAML::PROD_MAP_SCALAR_QUOTED: {
540  swap(result_any, rhs.at(0));
541  break;
542  }
543  case Teuchos::YAML::PROD_SCALAR_RAW:
544  case Teuchos::YAML::PROD_MAP_SCALAR_RAW: {
545  Scalar& scalar = make_any_ref<Scalar>(result_any);
546  TEUCHOS_ASSERT(rhs.at(0).has_value());
547  scalar.text = any_ref_cast<std::string>(rhs.at(0));
548  scalar.text += any_ref_cast<std::string>(rhs.at(1));
549  if (prod == Teuchos::YAML::PROD_MAP_SCALAR_RAW) {
550  scalar.text += any_ref_cast<std::string>(rhs.at(2));
551  }
552  scalar.text = remove_trailing_whitespace(scalar.text);
553  scalar.source = Scalar::RAW;
554  scalar.tag_type = -1;
555  break;
556  }
557  case Teuchos::YAML::PROD_SCALAR_HEAD_OTHER:
558  case Teuchos::YAML::PROD_SCALAR_HEAD_DOT:
559  case Teuchos::YAML::PROD_SCALAR_HEAD_DASH:
560  case Teuchos::YAML::PROD_SCALAR_HEAD_DOT_DOT: {
561  std::size_t offset;
562  if (prod == Teuchos::YAML::PROD_SCALAR_HEAD_OTHER) offset = 0;
563  else if (prod == Teuchos::YAML::PROD_SCALAR_HEAD_DOT_DOT) offset = 2;
564  else offset = 1;
565  char second = any_cast<char>(rhs.at(offset));
566  std::string& result = make_any_ref<std::string>(result_any);
567  if (prod == Teuchos::YAML::PROD_SCALAR_HEAD_DOT) result += '.';
568  else if (prod == Teuchos::YAML::PROD_SCALAR_HEAD_DASH) result += '-';
569  else if (prod == Teuchos::YAML::PROD_SCALAR_HEAD_DOT_DOT) result += "..";
570  result += second;
571  break;
572  }
573  case Teuchos::YAML::PROD_SCALAR_DQUOTED:
574  case Teuchos::YAML::PROD_SCALAR_SQUOTED: {
575  std::string& first = any_ref_cast<std::string>(rhs.at(1));
576  std::string& rest = any_ref_cast<std::string>(rhs.at(2));
577  Scalar& scalar = make_any_ref<Scalar>(result_any);
578  scalar.text += first;
579  scalar.text += rest;
580  if (prod == Teuchos::YAML::PROD_SCALAR_DQUOTED) {
581  scalar.source = Scalar::DQUOTED;
582  } else if (prod == Teuchos::YAML::PROD_SCALAR_SQUOTED) {
583  scalar.source = Scalar::SQUOTED;
584  }
585  scalar.tag_type = -1;
586  break;
587  }
588  case Teuchos::YAML::PROD_MAP_SCALAR_ESCAPED_EMPTY: {
589  result_any = std::string();
590  break;
591  }
592  case Teuchos::YAML::PROD_MAP_SCALAR_ESCAPED_NEXT: {
593  swap(result_any, rhs.at(0));
594  std::string& str = any_ref_cast<std::string>(result_any);
595  str += ',';
596  str += any_ref_cast<std::string>(rhs.at(2));
597  break;
598  }
599  case Teuchos::YAML::PROD_TAG: {
600  swap(result_any, rhs.at(2));
601  break;
602  }
603  case Teuchos::YAML::PROD_BSCALAR: {
604  std::size_t parent_indent_level =
605  this->symbol_indentation_stack.at(
606  this->symbol_indentation_stack.size() - 5);
607  std::string& header = any_ref_cast<std::string>(rhs.at(0));
608  std::string& leading_empties_or_comments =
609  any_ref_cast<std::string>(rhs.at(2));
610  std::string& rest = any_ref_cast<std::string>(rhs.at(4));
611  std::string& content = make_any_ref<std::string>(result_any);
612  std::string comment;
613  handle_block_scalar(
614  parent_indent_level,
615  header, leading_empties_or_comments, rest,
616  content, comment);
617  break;
618  }
619  case Teuchos::YAML::PROD_BSCALAR_FIRST: {
620  swap(result_any, rhs.at(0));
621  break;
622  }
623  // all these cases reduce to concatenating two strings
624  case Teuchos::YAML::PROD_BSCALAR_NEXT:
625  case Teuchos::YAML::PROD_BSCALAR_LINE:
626  case Teuchos::YAML::PROD_DESCAPE_NEXT:
627  case Teuchos::YAML::PROD_SESCAPE_NEXT: {
628  swap(result_any, rhs.at(0));
629  std::string& str = any_ref_cast<std::string>(result_any);
630  str += any_ref_cast<std::string>(rhs.at(1));
631  break;
632  }
633  case Teuchos::YAML::PROD_BSCALAR_INDENT: {
634  swap(result_any, rhs.at(1));
635  break;
636  }
637  case Teuchos::YAML::PROD_BSCALAR_HEADER_LITERAL:
638  case Teuchos::YAML::PROD_BSCALAR_HEADER_FOLDED: {
639  std::string& result = make_any_ref<std::string>(result_any);
640  if (prod == Teuchos::YAML::PROD_BSCALAR_HEADER_LITERAL) {
641  result += "|";
642  } else {
643  result += ">";
644  }
645  std::string& rest = any_ref_cast<std::string>(rhs.at(1));
646  result += rest;
647  break;
648  }
649  case Teuchos::YAML::PROD_DESCAPE: {
650  std::string& str = make_any_ref<std::string>(result_any);
651  std::string& rest = any_ref_cast<std::string>(rhs.at(2));
652  str += any_cast<char>(rhs.at(1));
653  str += rest;
654  break;
655  }
656  case Teuchos::YAML::PROD_SESCAPE: {
657  std::string& str = make_any_ref<std::string>(result_any);
658  std::string& rest = any_ref_cast<std::string>(rhs.at(2));
659  str += '\'';
660  str += rest;
661  break;
662  }
663  case Teuchos::YAML::PROD_OTHER_FIRST:
664  case Teuchos::YAML::PROD_SPACE_PLUS_FIRST: {
665  std::string& str = make_any_ref<std::string>(result_any);
666  str.push_back(any_cast<char>(rhs.at(0)));
667  break;
668  }
669  case Teuchos::YAML::PROD_SCALAR_TAIL_SPACE:
670  case Teuchos::YAML::PROD_SCALAR_TAIL_OTHER:
671  case Teuchos::YAML::PROD_DESCAPED_DQUOTED:
672  case Teuchos::YAML::PROD_DQUOTED_COMMON:
673  case Teuchos::YAML::PROD_SQUOTED_COMMON:
674  case Teuchos::YAML::PROD_ANY_COMMON:
675  case Teuchos::YAML::PROD_COMMON_SPACE:
676  case Teuchos::YAML::PROD_COMMON_OTHER:
677  case Teuchos::YAML::PROD_BSCALAR_HEAD_OTHER: {
678  swap(result_any, rhs.at(0));
679  break;
680  }
681  // all these cases reduce to appending a character
682  case Teuchos::YAML::PROD_DQUOTED_NEXT:
683  case Teuchos::YAML::PROD_SQUOTED_NEXT:
684  case Teuchos::YAML::PROD_ANY_NEXT:
685  case Teuchos::YAML::PROD_SCALAR_TAIL_NEXT:
686  case Teuchos::YAML::PROD_SPACE_STAR_NEXT:
687  case Teuchos::YAML::PROD_SPACE_PLUS_NEXT:
688  case Teuchos::YAML::PROD_BSCALAR_HEAD_NEXT: {
689  TEUCHOS_TEST_FOR_EXCEPTION(!rhs.at(0).has_value(), ParserFail,
690  "leading characters in " << prod << ": any was empty\n");
691  swap(result_any, rhs.at(0));
692  std::string& str = any_ref_cast<std::string>(result_any);
693  str += any_cast<char>(rhs.at(1));
694  break;
695  }
696  case Teuchos::YAML::PROD_DQUOTED_EMPTY:
697  case Teuchos::YAML::PROD_SQUOTED_EMPTY:
698  case Teuchos::YAML::PROD_ANY_EMPTY:
699  case Teuchos::YAML::PROD_DESCAPE_EMPTY:
700  case Teuchos::YAML::PROD_SESCAPE_EMPTY:
701  case Teuchos::YAML::PROD_SCALAR_TAIL_EMPTY:
702  case Teuchos::YAML::PROD_SPACE_STAR_EMPTY:
703  case Teuchos::YAML::PROD_BSCALAR_HEAD_EMPTY: {
704  result_any = std::string();
705  break;
706  }
707  case Teuchos::YAML::PROD_DESCAPED_DQUOT:
708  case Teuchos::YAML::PROD_SQUOTED_DQUOT:
709  case Teuchos::YAML::PROD_ANY_DQUOT: {
710  result_any = '"';
711  break;
712  }
713  case Teuchos::YAML::PROD_DESCAPED_SLASH:
714  case Teuchos::YAML::PROD_SQUOTED_SLASH:
715  case Teuchos::YAML::PROD_ANY_SLASH: {
716  result_any = '\\';
717  break;
718  }
719  case Teuchos::YAML::PROD_SCALAR_TAIL_SQUOT:
720  case Teuchos::YAML::PROD_DQUOTED_SQUOT:
721  case Teuchos::YAML::PROD_ANY_SQUOT: {
722  result_any = '\'';
723  break;
724  }
725  case Teuchos::YAML::PROD_COMMON_COLON: {
726  result_any = ':';
727  break;
728  }
729  case Teuchos::YAML::PROD_SCALAR_TAIL_DOT:
730  case Teuchos::YAML::PROD_COMMON_DOT: {
731  result_any = '.';
732  break;
733  }
734  case Teuchos::YAML::PROD_SCALAR_TAIL_DASH:
735  case Teuchos::YAML::PROD_COMMON_DASH:
736  case Teuchos::YAML::PROD_BSCALAR_HEAD_DASH: {
737  result_any = '-';
738  break;
739  }
740  case Teuchos::YAML::PROD_COMMON_PIPE: {
741  result_any = '|';
742  break;
743  }
744  case Teuchos::YAML::PROD_COMMON_LSQUARE: {
745  result_any = '[';
746  break;
747  }
748  case Teuchos::YAML::PROD_COMMON_RSQUARE: {
749  result_any = ']';
750  break;
751  }
752  case Teuchos::YAML::PROD_COMMON_LCURLY: {
753  result_any = '{';
754  break;
755  }
756  case Teuchos::YAML::PROD_COMMON_RCURLY: {
757  result_any = '}';
758  break;
759  }
760  case Teuchos::YAML::PROD_COMMON_RANGLE: {
761  result_any = '>';
762  break;
763  }
764  case Teuchos::YAML::PROD_COMMON_COMMA: {
765  result_any = ',';
766  break;
767  }
768  case Teuchos::YAML::PROD_COMMON_PERCENT: {
769  result_any = '%';
770  break;
771  }
772  case Teuchos::YAML::PROD_COMMON_EXCL: {
773  result_any = '!';
774  break;
775  }
776  }
777  }
778  void map_first_item(any& result_any, any& first_item) {
779  ParameterList& list = make_any_ref<ParameterList>(result_any);
780  TEUCHOS_ASSERT(first_item.has_value());
781  PLPair& pair = any_ref_cast<PLPair>(first_item);
782  safe_set_entry(list, pair.key, pair.value);
783  }
784  void map_next_item(any& result_any, any& items, any& next_item) {
785  using std::swap;
786  swap(result_any, items);
787  ParameterList& list = any_ref_cast<ParameterList>(result_any);
788  PLPair& pair = any_ref_cast<PLPair>(next_item);
789  safe_set_entry(list, pair.key, pair.value);
790  }
791  void map_item(any& result_any, any& key_any, any& value_any, int scalar_type = -1) {
792  using std::swap;
793  PLPair& result = make_any_ref<PLPair>(result_any);
794  {
795  std::string& key = any_ref_cast<Scalar>(key_any).text;
796  swap(result.key, key);
797  }
798  resolve_map_value(value_any, scalar_type);
799  if (value_any.type() == typeid(bool)) {
800  bool value = any_cast<bool>(value_any);
801  result.value = ParameterEntry(value);
802  } else if (value_any.type() == typeid(int)) {
803  int value = any_cast<int>(value_any);
804  result.value = ParameterEntry(value);
805  } else if (value_any.type() == typeid(long long)) {
806  long long value = any_cast<long long>(value_any);
807  result.value = ParameterEntry(value);
808  } else if (value_any.type() == typeid(double)) {
809  double value = any_cast<double>(value_any);
810  result.value = ParameterEntry(value);
811  } else if (value_any.type() == typeid(std::string)) {
812  std::string& value = any_ref_cast<std::string >(value_any);
813  result.value = ParameterEntry(value);
814  } else if (value_any.type() == typeid(Array<int>)) {
815  Array<int>& value = any_ref_cast<Array<int> >(value_any);
816  result.value = ParameterEntry(value);
817  } else if (value_any.type() == typeid(Array<long long>)) {
818  Array<long long>& value = any_ref_cast<Array<long long> >(value_any);
819  result.value = ParameterEntry(value);
820  } else if (value_any.type() == typeid(Array<double>)) {
821  Array<double>& value = any_ref_cast<Array<double> >(value_any);
822  result.value = ParameterEntry(value);
823  } else if (value_any.type() == typeid(Array<std::string>)) {
824  Array<std::string>& value = any_ref_cast<Array<std::string> >(value_any);
825  result.value = ParameterEntry(value);
826  } else if (value_any.type() == typeid(TwoDArray<int>)) {
827  TwoDArray<int>& value = any_ref_cast<TwoDArray<int> >(value_any);
828  result.value = ParameterEntry(value);
829  } else if (value_any.type() == typeid(TwoDArray<long long>)) {
830  TwoDArray<long long>& value = any_ref_cast<TwoDArray<long long> >(value_any);
831  result.value = ParameterEntry(value);
832  } else if (value_any.type() == typeid(TwoDArray<double>)) {
833  TwoDArray<double>& value = any_ref_cast<TwoDArray<double> >(value_any);
834  result.value = ParameterEntry(value);
835  } else if (value_any.type() == typeid(TwoDArray<std::string>)) {
836  TwoDArray<std::string>& value = any_ref_cast<TwoDArray<std::string> >(value_any);
837  result.value = ParameterEntry(value);
838  } else if (value_any.type() == typeid(ParameterList)) {
839  ParameterList& value = any_ref_cast<ParameterList>(value_any);
840  ParameterList& result_pl = result.value.setList();
841  swap(result_pl, value);
842  result_pl.setName(result.key);
843  } else {
844  std::string msg = "unexpected YAML map value type ";
845  msg += value_any.type().name();
846  msg += " for key \"";
847  msg += result.key;
848  msg += "\"\n";
849  throw ParserFail(msg);
850  }
851  }
852  void resolve_map_value(any& value_any, int scalar_type = -1) const {
853  if (value_any.type() == typeid(Scalar)) {
854  Scalar& scalar_value = any_ref_cast<Scalar>(value_any);
855  if (scalar_type == -1) {
856  scalar_type = scalar_value.infer_type();
857  }
858  if (scalar_type == Scalar::BOOL) {
859  value_any = parse_as<bool>(scalar_value.text);
860  } else if (scalar_type == Scalar::INT) {
861  value_any = parse_as<int>(scalar_value.text);
862  } else if (scalar_type == Scalar::LONG_LONG) {
863  value_any = parse_as<long long>(scalar_value.text);
864  } else if (scalar_type == Scalar::DOUBLE) {
865  value_any = parse_as<double>(scalar_value.text);
866  } else {
867  value_any = scalar_value.text;
868  }
869  } else if (value_any.type() == typeid(Array<Scalar>)) {
870  Array<Scalar>& scalars = any_ref_cast<Array<Scalar> >(value_any);
871  if (scalar_type == -1) {
872  if (scalars.size() == 0) {
873  throw ParserFail("implicitly typed arrays can't be empty\n"
874  "(need to determine their element type)\n");
875  }
876  /* Teuchos::Array uses std::vector but doesn't account for std::vector<bool>,
877  so it can't store bools */
878  scalar_type = Scalar::INT;
879  for (Teuchos_Ordinal i = 0; i < scalars.size(); ++i) {
880  scalar_type = std::min(scalar_type, scalars[i].infer_type());
881  }
882  }
883  if (scalar_type == Scalar::INT) {
884  Array<int> result(scalars.size());
885  for (Teuchos_Ordinal i = 0; i < scalars.size(); ++i) {
886  result[i] = parse_as<int>(scalars[i].text);
887  }
888  value_any = result;
889  } else if (scalar_type == Scalar::LONG_LONG) {
890  Array<long long> result(scalars.size());
891  for (Teuchos_Ordinal i = 0; i < scalars.size(); ++i) {
892  result[i] = parse_as<long long>(scalars[i].text);
893  }
894  value_any = result;
895  } else if (scalar_type == Scalar::DOUBLE) {
896  Array<double> result(scalars.size());
897  for (Teuchos_Ordinal i = 0; i < scalars.size(); ++i) {
898  result[i] = parse_as<double>(scalars[i].text);
899  }
900  value_any = result;
901  } else if (scalar_type == Scalar::STRING) {
902  Array<std::string> result(scalars.size());
903  for (Teuchos_Ordinal i = 0; i < scalars.size(); ++i) {
904  result[i] = scalars[i].text;
905  }
906  value_any = result;
907  }
908  } else if (value_any.type() == typeid(Array<Array<Scalar>>)) {
909  Array<Array<Scalar>>& scalars = any_ref_cast<Array<Array<Scalar>> >(value_any);
910  if (scalar_type == -1) {
911  if (scalars.size() == 0) {
912  throw ParserFail("implicitly typed 2D arrays can't be empty\n"
913  "(need to determine their element type)\n");
914  }
915  /* Teuchos::Array uses std::vector but doesn't account for std::vector<bool>,
916  so it can't store bools */
917  scalar_type = Scalar::INT;
918  for (Teuchos_Ordinal i = 0; i < scalars.size(); ++i) {
919  if (scalars[0].size() == 0) {
920  throw ParserFail("implicitly typed 2D arrays can't have empty rows\n"
921  "(need to determine their element type)\n");
922  }
923  if (scalars[i].size() != scalars[0].size()) {
924  throw ParserFail("2D array: sub-arrays are different sizes");
925  }
926  for (Teuchos_Ordinal j = 0; j < scalars[i].size(); ++j) {
927  int item_type = scalars[i][j].infer_type();
928  scalar_type = std::min(scalar_type, item_type);
929  }
930  }
931  }
932  if (scalar_type == Scalar::INT) {
933  TwoDArray<int> result(scalars.size(), scalars[0].size());
934  for (Teuchos_Ordinal i = 0; i < scalars.size(); ++i) {
935  for (Teuchos_Ordinal j = 0; j < scalars[0].size(); ++j) {
936  result(i, j) = parse_as<int>(scalars[i][j].text);
937  }
938  }
939  value_any = result;
940  } else if (scalar_type == Scalar::LONG_LONG) {
941  TwoDArray<long long> result(scalars.size(), scalars[0].size());
942  for (Teuchos_Ordinal i = 0; i < scalars.size(); ++i) {
943  for (Teuchos_Ordinal j = 0; j < scalars[0].size(); ++j) {
944  result(i, j) = parse_as<long long>(scalars[i][j].text);
945  }
946  }
947  value_any = result;
948  } else if (scalar_type == Scalar::DOUBLE) {
949  TwoDArray<double> result(scalars.size(), scalars[0].size());
950  for (Teuchos_Ordinal i = 0; i < scalars.size(); ++i) {
951  for (Teuchos_Ordinal j = 0; j < scalars[0].size(); ++j) {
952  result(i, j) = parse_as<double>(scalars[i][j].text);
953  }
954  }
955  value_any = result;
956  } else if (scalar_type == Scalar::STRING) {
957  TwoDArray<std::string> result(scalars.size(), scalars[0].size());
958  for (Teuchos_Ordinal i = 0; i < scalars.size(); ++i) {
959  for (Teuchos_Ordinal j = 0; j < scalars[0].size(); ++j) {
960  result(i, j) = scalars[i][j].text;
961  }
962  }
963  value_any = result;
964  }
965  }
966  }
967  int interpret_tag(any& tag_any) {
968  if (tag_any.type() != typeid(std::string)) return -1;
969  std::string& text = any_ref_cast<std::string>(tag_any);
970  if (text.find("bool") != std::string::npos) return Scalar::BOOL;
971  else if (text.find("int") != std::string::npos) return Scalar::INT;
972  else if (text.find("double") != std::string::npos) return Scalar::DOUBLE;
973  else if (text.find("string") != std::string::npos) return Scalar::STRING;
974  else {
975  std::string msg = "Unable to parse type tag \"";
976  msg += text;
977  msg += "\"\n";
978  throw ParserFail(msg);
979  }
980  }
981  void seq_first_item(any& result_any, any& first_any) {
982  using std::swap;
983  if (first_any.type() == typeid(Scalar)) {
984  Array<Scalar>& a = make_any_ref<Array<Scalar> >(result_any);
985  Scalar& v = any_ref_cast<Scalar>(first_any);
986  a.push_back(Scalar());
987  swap(a.back(), v);
988  } else if (first_any.type() == typeid(Array<Scalar>)) {
989  Array<Array<Scalar>>& a = make_any_ref<Array<Array<Scalar>> >(result_any);
990  Array<Scalar>& v = any_ref_cast<Array<Scalar> >(first_any);
991  a.push_back(Array<Scalar>());
992  swap(a.back(), v);
993  } else {
994  throw Teuchos::ParserFail(
995  "bug in YAMLParameterList::Reader: unexpected type for first sequence item");
996  }
997  }
998  void seq_next_item(any& result_any, any& items, any& next_item) {
999  using std::swap;
1000  swap(result_any, items);
1001  if (result_any.type() == typeid(Array<Scalar>)) {
1002  Array<Scalar>& a = any_ref_cast<Array<Scalar> >(result_any);
1003  Scalar& val = any_ref_cast<Scalar>(next_item);
1004  a.push_back(Scalar());
1005  swap(a.back(), val);
1006  } else if (result_any.type() == typeid(Array<Array<Scalar>>)) {
1007  Array<Array<Scalar>>& a = any_ref_cast<Array<Array<Scalar>> >(result_any);
1008  Array<Scalar>& v = any_ref_cast<Array<Scalar> >(next_item);
1009  a.push_back(Array<Scalar>());
1010  swap(a.back(), v);
1011  } else {
1012  throw Teuchos::ParserFail(
1013  "bug in YAMLParameterList::Reader: unexpected type for next sequence item");
1014  }
1015  }
1016  /* block scalars are a super complicated mess, this function handles that mess */
1017  void handle_block_scalar(
1018  std::size_t parent_indent_level,
1019  std::string const& header,
1020  std::string const& leading_empties_or_comments,
1021  std::string const& rest,
1022  std::string& content,
1023  std::string& comment) {
1024  /* read the header, resulting in: block style, chomping indicator, and indentation indicator */
1025  char style;
1026  char chomping_indicator;
1027  std::size_t indentation_indicator = 0;
1028  style = header[0];
1029  std::stringstream ss(header.substr(1,std::string::npos));
1030  if (header.size() > 1 && my_isdigit(header[1])) {
1031  ss >> indentation_indicator;
1032  // indentation indicator is given as a relative number, but we need it in absolute terms
1033  indentation_indicator += parent_indent_level;
1034  }
1035  if (!(ss >> chomping_indicator)) chomping_indicator = '\0';
1036  /* get information about newlines, indentation level, and comment from
1037  the leading_empties_or_comments string */
1038  std::size_t first_newline = leading_empties_or_comments.find_first_of("\r\n");
1039  std::string newline;
1040  if (first_newline > 0 && leading_empties_or_comments[first_newline - 1] == '\r') {
1041  newline = "\r\n";
1042  } else {
1043  newline = "\n";
1044  }
1045  std::size_t keep_beg = first_newline + 1 - newline.size();
1046  if (leading_empties_or_comments[0] == '#') {
1047  comment = leading_empties_or_comments.substr(1, keep_beg);
1048  }
1049  // according to the YAML spec, a tab is content, not indentation
1050  std::size_t content_beg = leading_empties_or_comments.find_first_not_of("\r\n ");
1051  if (content_beg == std::string::npos) content_beg = leading_empties_or_comments.size();
1052  std::size_t newline_before_content = leading_empties_or_comments.rfind("\n", content_beg);
1053  std::size_t num_indent_spaces = (content_beg - newline_before_content) - 1;
1054  /* indentation indicator overrides the derived level of indentation, in case the
1055  user wants to keep some of that indentation as content */
1056  if (indentation_indicator > 0) {
1057  TEUCHOS_TEST_FOR_EXCEPTION(num_indent_spaces < indentation_indicator,
1059  "Indentation indicator " << indentation_indicator << " > leading spaces " << num_indent_spaces);
1060  num_indent_spaces = indentation_indicator;
1061  }
1062  /* prepend the content from the leading_empties_or_comments to the rest */
1063  content = leading_empties_or_comments.substr(keep_beg, std::string::npos);
1064  content += rest;
1065  /* per Trilinos issue #2090, there can be trailing comments after the block
1066  scalar which are less indented than it, but they will be included in the
1067  final NEWLINE token.
1068  this code removes all contiguous trailing lines which are less indented
1069  than the content.
1070  */
1071  while (true) {
1072  auto last_newline = content.find_last_of("\n", content.size() - 2);
1073  if (last_newline == std::string::npos) break;
1074  std::size_t num_spaces = 0;
1075  for (auto ispace = last_newline + 1;
1076  ispace < content.size() && content[ispace] == ' ';
1077  ++ispace) {
1078  ++num_spaces;
1079  }
1080  if (num_spaces >= num_indent_spaces) break;
1081  content.erase(content.begin() + last_newline + 1, content.end());
1082  }
1083  /* remove both indentation and newlines as dictated by header information */
1084  std::size_t unindent_pos = 0;
1085  while (true) {
1086  std::size_t next_newline = content.find_first_of("\n", unindent_pos);
1087  if (next_newline == std::string::npos) break;
1088  std::size_t start_cut = next_newline + 1;
1089  /* folding block scalars remove newlines */
1090  if (style == '>') start_cut -= newline.size();
1091  std::size_t end_cut = next_newline + 1;
1092  /* the actual amount of indentation in the content varies, start by
1093  marking it all for removal */
1094  while (end_cut < content.size() && content[end_cut] == ' ') {
1095  ++end_cut;
1096  }
1097  /* but don't remove more than the actual indent number */
1098  end_cut = std::min(next_newline + 1 + num_indent_spaces, end_cut);
1099  /* cut this (newline?)+indentation out of the content */
1100  content = content.substr(0, start_cut) +
1101  content.substr(end_cut, std::string::npos);
1102  unindent_pos = start_cut;
1103  }
1104  if (chomping_indicator != '+') {
1105  content = remove_trailing_whitespace_and_newlines(content);
1106  if (chomping_indicator != '-') content += newline;
1107  }
1108  if (style == '|') {
1109  // if not already, remove the leading newline
1110  content = content.substr(newline.size(), std::string::npos);
1111  }
1112  }
1113 };
1114 
1115 } // end namespace YAMLParameterList
1116 
1117 /* Helper functions */
1118 
1119 void updateParametersFromYamlFile(const std::string& yamlFileName,
1120  const Teuchos::Ptr<Teuchos::ParameterList>& paramList)
1121 {
1122  //load the YAML file in as a new param list
1123  Teuchos::RCP<Teuchos::ParameterList> updated = YAMLParameterList::parseYamlFile(yamlFileName);
1124  if (paramList->name() == "ANONYMOUS") {
1125  paramList->setName(updated->name());
1126  }
1127  //now update the original list (overwriting values with same key)
1128  paramList->setParameters(*updated);
1129 }
1130 
1131 void updateParametersFromYamlCString(const char* const data,
1132  const Teuchos::Ptr<Teuchos::ParameterList>& paramList,
1133  bool overwrite)
1134 {
1135  Teuchos::RCP<Teuchos::ParameterList> updated = YAMLParameterList::parseYamlText(data, "CString");
1136  if(overwrite)
1137  {
1138  if (paramList->name() == "ANONYMOUS") {
1139  paramList->setName(updated->name());
1140  }
1141  paramList->setParameters(*updated);
1142  }
1143  else
1144  {
1145  paramList->setParametersNotAlreadySet(*updated);
1146  }
1147 }
1148 
1149 void updateParametersFromYamlString(const std::string& yamlData,
1150  const Teuchos::Ptr<Teuchos::ParameterList>& paramList,
1151  bool overwrite,
1152  const std::string& name)
1153 {
1154  Teuchos::RCP<Teuchos::ParameterList> updated = YAMLParameterList::parseYamlText(yamlData, name);
1155  if(overwrite)
1156  {
1157  if (paramList->name() == "ANONYMOUS") {
1158  paramList->setName(updated->name());
1159  }
1160  paramList->setParameters(*updated);
1161  }
1162  else
1163  {
1164  paramList->setParametersNotAlreadySet(*updated);
1165  }
1166 }
1167 
1168 Teuchos::RCP<Teuchos::ParameterList> getParametersFromYamlFile(const std::string& yamlFileName)
1169 {
1170  return YAMLParameterList::parseYamlFile(yamlFileName);
1171 }
1172 
1173 Teuchos::RCP<Teuchos::ParameterList> getParametersFromYamlString(const std::string& yamlStr)
1174 {
1175  std::stringstream ss(yamlStr);
1176  return YAMLParameterList::parseYamlStream(ss);
1177 }
1178 
1179 void writeParameterListToYamlOStream(
1180  const ParameterList &paramList,
1181  std::ostream &yamlOut
1182  )
1183 {
1184  YAMLParameterList::writeYamlStream(yamlOut, paramList);
1185 }
1186 
1187 void writeParameterListToYamlFile(
1188  const ParameterList &paramList,
1189  const std::string &yamlFileName
1190  )
1191 {
1192  YAMLParameterList::writeYamlFile(yamlFileName, paramList);
1193 }
1194 
1195 std::string convertXmlToYaml(const std::string& xmlFileName)
1196 {
1197  //load the parameter list from xml
1198  Teuchos::RCP<Teuchos::ParameterList> toConvert = Teuchos::getParametersFromXmlFile(xmlFileName);
1199  //replace the file extension ".xml" with ".yaml", or append it if there was no extension
1200  std::string yamlFileName;
1201  if(xmlFileName.find(".xml") == std::string::npos)
1202  {
1203  yamlFileName = xmlFileName + ".yaml";
1204  }
1205  else
1206  {
1207  yamlFileName = xmlFileName.substr(0, xmlFileName.length() - 4) + ".yaml";
1208  }
1209  YAMLParameterList::writeYamlFile(yamlFileName, *toConvert);
1210  return yamlFileName;
1211 }
1212 
1213 void convertXmlToYaml(const std::string& xmlFileName, const std::string& yamlFileName)
1214 {
1215  Teuchos::RCP<Teuchos::ParameterList> toConvert = Teuchos::getParametersFromXmlFile(xmlFileName);
1216  YAMLParameterList::writeYamlFile(yamlFileName, *toConvert);
1217 }
1218 
1219 void convertXmlToYaml(std::istream& xmlStream, std::ostream& yamlStream)
1220 {
1221  //read xmlStream into a string until EOF
1222  std::istreambuf_iterator<char> begin(xmlStream);
1223  std::istreambuf_iterator<char> end;
1224  std::string xmlString(begin, end);
1225  Teuchos::RCP<Teuchos::ParameterList> toConvert = Teuchos::getParametersFromXmlString(xmlString);
1226  YAMLParameterList::writeYamlStream(yamlStream, *toConvert);
1227 }
1228 
1229 namespace YAMLParameterList
1230 {
1231 
1232 Teuchos::RCP<Teuchos::ParameterList> parseYamlText(const std::string& text, const std::string& name)
1233 {
1234 #ifdef HAVE_TEUCHOSPARAMETERLIST_YAMLCPP
1235  auto yaml_input = ::YAML::LoadAll(text); // std::vector<::YAML::Node>
1236  return readParams(yaml_input);
1237 #else
1238  any result;
1239  Teuchos::YAMLParameterList::Reader reader;
1240  reader.read_string(result, text, name);
1241  ParameterList& pl = any_ref_cast<ParameterList>(result);
1242  return Teuchos::rcp(new ParameterList(pl));
1243 #endif // HAVE_TEUCHOSPARAMETERLIST_YAMLCPP
1244 }
1245 
1246 Teuchos::RCP<Teuchos::ParameterList> parseYamlFile(const std::string& yamlFile)
1247 {
1248 #ifdef HAVE_TEUCHOSPARAMETERLIST_YAMLCPP
1249  auto yaml_input = ::YAML::LoadAllFromFile(yamlFile);
1250  return readParams(yaml_input);
1251 #else
1252  any result;
1253  Teuchos::YAMLParameterList::Reader reader;
1254  reader.read_file(result, yamlFile);
1255  ParameterList& pl = any_ref_cast<ParameterList>(result);
1256  return Teuchos::rcp(new ParameterList(pl));
1257 #endif // HAVE_TEUCHOSPARAMETERLIST_YAMLCPP
1258 }
1259 
1260 Teuchos::RCP<Teuchos::ParameterList> parseYamlStream(std::istream& yaml)
1261 {
1262 #ifdef HAVE_TEUCHOSPARAMETERLIST_YAMLCPP
1263  auto yaml_input = ::YAML::LoadAll(yaml);
1264  return readParams(yaml_input);
1265 #else
1266  any result;
1267  Teuchos::YAMLParameterList::Reader reader;
1268  reader.read_stream(result, yaml, "parseYamlStream");
1269  ParameterList& pl = any_ref_cast<ParameterList>(result);
1270  return Teuchos::rcp(new ParameterList(pl));
1271 #endif // HAVE_TEUCHOSPARAMETERLIST_YAMLCPP
1272 }
1273 
1274 // The following three functions (readParams, processMapNode, and processKeyValueNode)
1275 // were previously removed from Trilinos in PR 1779 (Teuchos: use Parser, not yaml-cpp, to read YAML PL).
1276 
1277 #ifdef HAVE_TEUCHOSPARAMETERLIST_YAMLCPP
1278 
1279 Teuchos::RCP<Teuchos::ParameterList> readParams(std::vector<::YAML::Node>& lists)
1280 {
1281  Teuchos::RCP<Teuchos::ParameterList> pl = rcp(new Teuchos::ParameterList); //pl is the root ParameterList to be returned
1282  // If there is exactly one element in "lists", assume it is the anonymous top-level parameter list
1283  // If there are more than one, place them all in the anonymous top-level list
1284  for(size_t i = 0; i < lists.size(); i++)
1285  {
1286  processMapNode(lists[i], *pl, true);
1287  }
1288  return pl;
1289 }
1290 
1291 void processMapNode(const ::YAML::Node& node, Teuchos::ParameterList& parent, bool topLevel)
1292 {
1293  if (node.Type() != ::YAML::NodeType::Map)
1294  {
1295  throw YamlStructureError("All top-level elements of the YAML file must be maps.");
1296  }
1297  if (topLevel)
1298  {
1299  parent.setName(node.begin()->first.as<std::string>());
1300  processMapNode(node.begin()->second, parent);
1301  }
1302  else
1303  {
1304  for (::YAML::const_iterator i = node.begin(); i != node.end(); i++)
1305  {
1306  // make sure the key type is a string
1307  if(i->first.Type() != ::YAML::NodeType::Scalar)
1308  {
1309  throw YamlKeyError("Keys must be YAML scalars (int, double, or string)");
1310  }
1311  // if this conversion fails and throws for any reason (shouldn't), let the caller handle it
1312  const std::string key = quoted_as<std::string>(i->first);
1313  processKeyValueNode(key, i->second, parent, topLevel);
1314  }
1315  }
1316 }
1317 
1318 void processKeyValueNode(const std::string& key, const ::YAML::Node& node, Teuchos::ParameterList& parent, bool topLevel)
1319 {
1320  // node (value) type can be a map (for nested param lists),
1321  // a scalar (int, double, string), or a sequence of doubles (vector<double>)
1322  if(node.Type() == ::YAML::NodeType::Scalar)
1323  {
1324  try
1325  {
1326  safe_set_entry<int>(parent, key, quoted_as<int>(node));
1327  }
1328  catch(...)
1329  {
1330  try
1331  {
1332  safe_set_entry<long long>(parent, key, quoted_as<long long>(node));
1333  }
1334  catch(...)
1335  {
1336  try
1337  {
1338  safe_set_entry<double>(parent, key, quoted_as<double>(node));
1339  }
1340  catch(...)
1341  {
1342  try
1343  {
1344  bool raw_bool = quoted_as<bool>(node);
1345 
1346  /* yaml-cpp parses ON/OFF as a bool, but the in-house parser does not.
1347  To preserve backwards compatibility, make sure the string passes
1348  the in-house parser's is_parseable_as<bool> function (which protects
1349  against the ON/OFF case).
1350  Otherwise, a failure is observed in YAML_ConvertFromXML unit test.*/
1351 
1352  std::string raw_string = quoted_as<std::string>(node);
1353  if (is_parseable_as<bool>(raw_string))
1354  {
1355  safe_set_entry<bool>(parent, key, raw_bool);
1356  }
1357  else
1358  {
1359  safe_set_entry<std::string>(parent, key, raw_string);
1360  }
1361  }
1362  catch(...)
1363  {
1364  safe_set_entry<std::string>(parent, key, quoted_as<std::string>(node));
1365  }
1366  }
1367  }
1368  }
1369  }
1370  else if(node.Type() == ::YAML::NodeType::Map)
1371  {
1372  if(topLevel)
1373  {
1374  processMapNode(node, parent);
1375  }
1376  else
1377  {
1378  Teuchos::ParameterList& sublist = parent.sublist(key);
1379  processMapNode(node, sublist);
1380  }
1381  }
1382  else if(node.Type() == ::YAML::NodeType::Sequence)
1383  {
1384  int ndim = getYamlArrayDim(node);
1385  if (ndim == 1)
1386  {
1387  ::YAML::Node const& first_value = *(node.begin());
1388  try
1389  {
1390  quoted_as<int>(first_value);
1391  safe_set_entry<Teuchos::Array<int>>(parent, key, getYamlArray<int>(node));
1392  }
1393  catch(...)
1394  {
1395  try
1396  {
1397  quoted_as<double>(first_value);
1398  safe_set_entry<Teuchos::Array<double>>(parent, key, getYamlArray<double>(node));
1399  }
1400  catch(...)
1401  {
1402  try
1403  {
1404  quoted_as<std::string>(first_value);
1405  safe_set_entry<Teuchos::Array<std::string>>(parent, key, getYamlArray<std::string>(node));
1406  }
1407  catch(...)
1408  {
1409  throw YamlSequenceError(std::string("Array \"") + key + "\" must contain int, double, bool or string");
1410  }
1411  }
1412  }
1413  }
1414  else if (ndim == 2)
1415  {
1416  bool is_ragged = checkYamlTwoDArrayIsRagged(node);
1417  ::YAML::Node const& first_value = *(node.begin()->begin());
1418  try
1419  {
1420  quoted_as<int>(first_value);
1421  using arr_t = Teuchos::Array<Teuchos::Array<int>>;
1422  if (is_ragged) {
1423  safe_set_entry<arr_t>(parent, key, getYaml2DRaggedArray<arr_t, int>(node, ndim, key));
1424  } else {
1425  safe_set_entry<Teuchos::TwoDArray<int>>(parent, key, getYamlTwoDArray<int>(node));
1426  }
1427  }
1428  catch(...)
1429  {
1430  try
1431  {
1432  quoted_as<double>(first_value);
1434  if (is_ragged) {
1435  safe_set_entry<arr_t>(parent, key, getYaml2DRaggedArray<arr_t, double>(node, ndim, key));
1436  } else {
1437  safe_set_entry<Teuchos::TwoDArray<double>>(parent, key, getYamlTwoDArray<double>(node));
1438  }
1439  }
1440  catch(...)
1441  {
1442  try
1443  {
1444  quoted_as<std::string>(first_value);
1446  if (is_ragged) {
1447  safe_set_entry<arr_t>(parent, key, getYaml2DRaggedArray<arr_t, std::string>(node, ndim, key));
1448  } else {
1449  safe_set_entry<Teuchos::TwoDArray<std::string>>(parent, key, getYamlTwoDArray<std::string>(node));
1450  }
1451  }
1452  catch(...)
1453  {
1454  throw YamlSequenceError(std::string("TwoDArray \"") + key + "\" must contain int, double, bool or string");
1455  }
1456  }
1457  }
1458  }
1459  else if (ndim == 3)
1460  {
1461  ::YAML::Node const& first_value = *(node.begin()->begin()->begin());
1462  try
1463  {
1464  quoted_as<int>(first_value);
1466  safe_set_entry<arr_t>(parent, key, getYaml3DArray<arr_t, int>(node, ndim, key));
1467  }
1468  catch(...)
1469  {
1470  try
1471  {
1472  quoted_as<double>(first_value);
1474  safe_set_entry<arr_t>(parent, key, getYaml3DArray<arr_t, double>(node, ndim, key));
1475 
1476  }
1477  catch(...)
1478  {
1479  try
1480  {
1481  quoted_as<std::string>(first_value);
1483  safe_set_entry<arr_t>(parent, key, getYaml3DArray<arr_t, std::string>(node, ndim, key));
1484 
1485  }
1486  catch(...)
1487  {
1488  throw YamlSequenceError(std::string("3DArray \"") + key + "\" must contain int, double, bool or string");
1489  }
1490  }
1491  }
1492  }
1493  }
1494  else if(node.Type() == ::YAML::NodeType::Null)
1495  {
1496  // treat NULL as empty sublist (not an error)
1497  parent.sublist(key);
1498  }
1499  else
1500  {
1501  // Undefined
1502  throw YamlUndefinedNodeError("Value type in a key-value pair must be one of: int, double, string, array, sublist.");
1503  }
1504 }
1505 
1506 #endif // HAVE_TEUCHOSPARAMETERLIST_YAMLCPP
1507 
1508 void writeYamlStream(std::ostream& yaml, const Teuchos::ParameterList& pl)
1509 {
1510  // warn the user if floats/doubles with integer values will be printed incorrectly
1511  std::ios_base::fmtflags flags = yaml.flags();
1512  // make temporary stringstream to test flags
1513  std::ostringstream testStream;
1514  testStream.flags(flags);
1515  double testVal = 1;
1516  testStream << testVal;
1517  bool popFlags = false;
1518  if(testStream.str() == "1")
1519  {
1520  // must add showpoint to flags while writing yaml
1521  // this will always disambiguate (double) n and n, even if stream precision is 0
1522  // prints as "n.0000" where the number of trailing zeros is the stream precision
1523  // note: in YAML, "5." is a double but not an int
1524  std::cout << "Warning: yaml stream format flags would confuse double with integer value with int.\n";
1525  std::cout << "Setting std::ios::showpoint on the stream to fix this (will restore flags when done)\n";
1526  std::ios_base::fmtflags flagsCopy = flags;
1527  flagsCopy |= std::ios::showpoint;
1528  popFlags = true;
1529  }
1530  yaml << "%YAML 1.1\n---\n";
1531  yaml << pl.name() << ':';
1532  if(pl.numParams() == 0)
1533  {
1534  yaml << " { }\n";
1535  }
1536  else
1537  {
1538  writeParameterList(pl, yaml, 2);
1539  }
1540  yaml << "...\n";
1541  // restore flags
1542  if(popFlags)
1543  {
1544  yaml.flags(flags);
1545  }
1546 }
1547 
1548 void writeYamlFile(const std::string& yamlFile, const Teuchos::ParameterList& pl)
1549 {
1550  std::ofstream yaml(yamlFile.c_str());
1551  /* set default floating-point style:
1552  1. 17 decimal places to ensure the value remains the same
1553  2. scientific: this prevents floating-point values that happen
1554  to be integers from being printed as integers, because YAML
1555  will then read that value back typed as an integer.
1556  */
1557  yaml << std::scientific << std::setprecision(17);
1558  writeYamlStream(yaml, pl);
1559 }
1560 
1561 void writeParameterList(const Teuchos::ParameterList& pl, std::ostream& yaml, int indentLevel)
1562 {
1563  if(pl.begin() == pl.end())
1564  {
1565  yaml << "{ }\n";
1566  }
1567  else
1568  {
1569  yaml << '\n';
1570  for(PLIter it = pl.begin(); it != pl.end(); it++)
1571  {
1572  writeParameter(pl.name(it), pl.entry(it), yaml, indentLevel);
1573  }
1574  }
1575 }
1576 
1577 template <typename T>
1578 struct YamlWrite {
1579  static void write(T const& x, std::ostream& stream) {
1580  stream << x;
1581  }
1582 };
1583 
1584 template <>
1585 struct YamlWrite<double> {
1586  static void write(double const& x, std::ostream& stream) {
1587  generalWriteDouble(x, stream);
1588  }
1589 };
1590 
1591 template <>
1592 struct YamlWrite<std::string> {
1593  static void write(std::string const& x, std::ostream& stream) {
1594  generalWriteString(x, stream);
1595  }
1596 };
1597 
1598 template <typename T>
1599 void writeYamlTwoDArray(Teuchos::TwoDArray<T> const& arr, std::ostream& stream)
1600 {
1601  typename Teuchos::TwoDArray<T>::size_type i, j;
1602  stream << '[';
1603  for (i = 0; i < arr.getNumRows(); ++i)
1604  {
1605  if (i) stream << ", ";
1606  stream << '[';
1607  for (j = 0; j < arr.getNumCols(); ++j)
1608  {
1609  if (j) stream << ", ";
1610  YamlWrite<T>::write(arr(i, j), stream);
1611  }
1612  stream << ']';
1613  }
1614  stream << ']';
1615 }
1616 
1617 void writeParameter(const std::string& paramName, const Teuchos::ParameterEntry& entry, std::ostream& yaml, int indentLevel)
1618 {
1619  for(int i = 0; i < indentLevel; i++)
1620  {
1621  yaml << ' ';
1622  }
1623  generalWriteString(paramName, yaml);
1624  yaml << ": ";
1625  if(entry.isList())
1626  {
1627  writeParameterList(Teuchos::getValue<Teuchos::ParameterList>(entry), yaml, indentLevel + 2);
1628  return;
1629  }
1630  else if(entry.isArray())
1631  {
1632  yaml << '[';
1633  if(entry.isType<Teuchos::Array<int> >())
1634  {
1635  Teuchos::Array<int>& arr = Teuchos::getValue<Teuchos::Array<int> >(entry);
1636  for(int i = 0; i < arr.size(); i++)
1637  {
1638  yaml << arr[i];
1639  if(i != arr.size() - 1)
1640  yaml << ", ";
1641  }
1642  }
1643  if(entry.isType<Teuchos::Array<long long> >())
1644  {
1645  Teuchos::Array<long long>& arr = Teuchos::getValue<Teuchos::Array<long long> >(entry);
1646  for(int i = 0; i < arr.size(); i++)
1647  {
1648  yaml << arr[i];
1649  if(i != arr.size() - 1)
1650  yaml << ", ";
1651  }
1652  }
1653  else if(entry.isType<Teuchos::Array<double> >())
1654  {
1655  Teuchos::Array<double>& arr = Teuchos::getValue<Teuchos::Array<double> >(entry);
1656  for(int i = 0; i < arr.size(); i++)
1657  {
1658  generalWriteDouble(arr[i], yaml);
1659  if(i != arr.size() - 1)
1660  yaml << ", ";
1661  }
1662  }
1663  else if(entry.isType<Teuchos::Array<std::string> >())
1664  {
1665  Teuchos::Array<std::string>& arr = Teuchos::getValue<Teuchos::Array<std::string> >(entry);
1666  for(int i = 0; i < arr.size(); i++)
1667  {
1668  generalWriteString(arr[i], yaml);
1669  if(i != arr.size() - 1)
1670  yaml << ", ";
1671  }
1672  }
1673  yaml << ']';
1674  }
1675  else if(entry.isTwoDArray())
1676  {
1677  if(entry.isType<Teuchos::TwoDArray<int> >())
1678  {
1679  writeYamlTwoDArray<int>(
1680  Teuchos::getValue<Teuchos::TwoDArray<int> >(entry), yaml);
1681  }
1683  {
1684  writeYamlTwoDArray<long long>(
1685  Teuchos::getValue<Teuchos::TwoDArray<long long> >(entry), yaml);
1686  }
1687  else if(entry.isType<Teuchos::TwoDArray<double> >())
1688  {
1689  writeYamlTwoDArray<double>(
1690  Teuchos::getValue<Teuchos::TwoDArray<double> >(entry), yaml);
1691  }
1692  else if(entry.isType<Teuchos::TwoDArray<std::string> >())
1693  {
1694  writeYamlTwoDArray<std::string>(
1695  Teuchos::getValue<Teuchos::TwoDArray<std::string> >(entry), yaml);
1696  }
1697  }
1698  else if(entry.isType<int>())
1699  {
1700  yaml << Teuchos::getValue<int>(entry);
1701  }
1702  else if(entry.isType<long long>())
1703  {
1704  yaml << Teuchos::getValue<long long>(entry);
1705  }
1706  else if(entry.isType<double>())
1707  {
1708  generalWriteDouble(Teuchos::getValue<double>(entry), yaml);
1709  }
1710  else if(entry.isType<std::string>())
1711  {
1712  std::string& str = Teuchos::getValue<std::string>(entry);
1713  if(strchr(str.c_str(), '\n'))
1714  {
1715  yaml << "|";
1716  // if the content has leading spaces, automatic indentation
1717  // detection would fail, in which case we must emit
1718  // an indentation indicator
1719  std::size_t first_non_newline_pos = str.find_first_not_of("\r\n");
1720  if (first_non_newline_pos != std::string::npos &&
1721  str[first_non_newline_pos] == ' ') {
1722  yaml << "2";
1723  }
1724  if (str[str.size() - 1] != '\n') yaml << "-";
1725  yaml << "\n";
1726  //for each line, apply indent then print the line verbatim
1727  size_t index = 0;
1728  while(true)
1729  {
1730  size_t next = str.find('\n', index);
1731  for(int i = 0; i < indentLevel + 2; i++)
1732  {
1733  yaml << ' ';
1734  }
1735  if(next == std::string::npos)
1736  {
1737  yaml << str.substr(index, std::string::npos);
1738  break;
1739  }
1740  else
1741  {
1742  yaml << str.substr(index, next - index) << '\n';
1743  }
1744  index = next + 1;
1745  }
1746  }
1747  else
1748  {
1749  generalWriteString(str, yaml);
1750  }
1751  }
1752  else if(entry.isType<bool>())
1753  {
1754  yaml << (Teuchos::getValue<bool>(entry) ? "true" : "false");
1755  }
1756  yaml << '\n';
1757 }
1758 
1759 void generalWriteString(const std::string& str, std::ostream& yaml)
1760 {
1761  // default to single quoting
1762  if(stringNeedsQuotes(str))
1763  {
1764  yaml << '\'';
1765  for (std::size_t i = 0; i < str.size(); ++i) {
1766  if (str[i] == '\'') yaml << "''";
1767  else yaml << str[i];
1768  }
1769  yaml << '\'';
1770  }
1771  else
1772  {
1773  yaml << str;
1774  }
1775 }
1776 
1777 void generalWriteDouble(double d, std::ostream& yaml)
1778 {
1779  yaml << d;
1780 }
1781 
1782 static bool containsSpecialCharacters(std::string const& s) {
1783  char const* const control_chars = ":'{}[],&*#?|<>=!%@\\";
1784  return s.find_first_of(control_chars) != std::string::npos;
1785 }
1786 
1787 bool stringNeedsQuotes(const std::string& s)
1788 {
1789  return s.empty() ||
1790  containsSpecialCharacters(s) ||
1791  is_parseable_as<bool>(s) ||
1792  is_parseable_as<int>(s) ||
1793  is_parseable_as<long long>(s) ||
1794  is_parseable_as<double>(s);
1795 }
1796 
1797 } //namespace YAMLParameterList
1798 
1799 } //namespace Teuchos
A thin wrapper around the Teuchos Array class that allows for 2 dimensional arrays.
const std::string & name() const
The name of this ParameterList.
Reader(ReaderTablesPtr tables_in)
Constructor: accepts an RCP to ReaderTables.
ConstIterator end() const
An iterator pointing beyond the last entry.
Functions to convert between ParameterList and YAML.
This object is held as the &quot;value&quot; in the Teuchos::ParameterList std::map.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Macro for throwing an exception with breakpointing to ease debugging.
bool isArray() const
Test if the type of data being contained is a Teuchos::Array.
Tries to create LALR(1) parser tables for a given grammar.
bool isType() const
Test the type of the data being contained.
Ordinal numParams() const
Get the number of stored parameters.
A TeuchosParser Language for a subset of YAML.
Simple helper functions that make it easy to read and write XML to and from a parameterlist.
A thin wrapper around the Array class which causes it to be interpreted as a 2D Array.
The main class for users to read text using TeuchosParser.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Deprecated.
size_type getNumCols() const
returns the number of columns in the TwoDArray.
void resizeCols(size_type numberOfCols)
Changes the number of rows in the matrix.
void resizeRows(size_type numberOfRows)
Changes the number of rows in the matrix.
ConstIterator begin() const
An iterator pointing to the first entry.
bool isList() const
Return whether or not the value itself is a list.
A list of parameters of arbitrary type.
ParameterList & setParameters(const ParameterList &source)
const ParameterEntry & entry(ConstIterator i) const
Access to ParameterEntry (i.e., returns i-&gt;second)
size_type getNumRows() const
returns the number of rows in the TwoDArray.
void push_back(const value_type &x)
ParameterList & setParametersNotAlreadySet(const ParameterList &source)
bool isTwoDArray() const
Test if the type of data being contained is a Teuchos::TwoDArray.
size_type size() const
ParameterList & sublist(const std::string &name, bool mustAlreadyExist=false, const std::string &docString="")
Creates an empty sublist and returns a reference to the sublist name. If the list already exists...
ParameterList & setName(const std::string &name)
Set the name of *this list.
#define TEUCHOS_ASSERT(assertion_test)
This macro is throws when an assert fails.
Simple helper functions that make it easy to read and write Yaml to and from a parameterlist.
Simple wrapper class for raw pointers to single objects where no persisting relationship exists...
Replacement for std::vector that is compatible with the Teuchos Memory Management classes...
Declares Teuchos::Reader.