Teuchos - Trilinos Tools Package  Version of the Day
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 // Jonathan Hu (jhu@sandia.gov)
40 // Andrey Prokopenko (aprokop@sandia.gov)
41 // Ray Tuminaro (rstumin@sandia.gov)
42 //
43 // ***********************************************************************
44 //
45 // @HEADER
46 
47 #ifndef TEUCHOS_YAMLPARSER_DEF_H_
48 #define TEUCHOS_YAMLPARSER_DEF_H_
49 
50 #include <iostream>
51 #include <iomanip>
52 #include <ios>
53 #include <sstream>
54 
55 #include "Teuchos_YamlParser_decl.hpp"
58 #include "Teuchos_TwoDArray.hpp"
59 
60 namespace Teuchos
61 {
62 
63 /* see https://github.com/jbeder/yaml-cpp/issues/261
64  there are times when we want to insist that a parameter
65  value be interpreted as a string despite it being parseable
66  as a number.
67  the standard way to do this in YAML is to put the number in quotes,
68  i.e. '1e-3' instead of 1e-3.
69  however, the usual YAML::Node::as<T> system doesn't respect quoting
70  when trying to cast to numbers.
71  so, this is our own version of as<T>, called quoted_as<T>, using
72  the Tag workaround suggested in the issue linked above. */
73 
74 template <typename T>
75 struct QuotedAs {
76  static T eval(YAML::Node const& node) {
77  // this "!" tag apparently denotes that the value was quoted
78  if (node.Tag() == "!") {
79  throw std::runtime_error("quoted_as from quoted string to number");
80  }
81  return node.as<T>();
82  }
83 };
84 
85 template <>
86 struct QuotedAs<std::string> {
87  // only a cast to string will succeed if quoted
88  static std::string eval(YAML::Node const& node) { return node.as<std::string>(); }
89 };
90 
91 template <typename T>
92 static T quoted_as(YAML::Node const& node) { return QuotedAs<T>::eval(node); }
93 
94 template<typename T> Teuchos::Array<T> getYamlArray(const YAML::Node& node)
95 {
97  for(YAML::const_iterator it = node.begin(); it != node.end(); it++)
98  {
99  arr.push_back(quoted_as<T>(*it));
100  }
101  return arr;
102 }
103 
104 void checkYamlTwoDArray(const YAML::Node& node, const std::string& key)
105 {
106  for (YAML::const_iterator it = node.begin(); it != node.end(); ++it)
107  {
108  if (it->size() != node.begin()->size())
109  {
110  throw YamlSequenceError(std::string("TwoDArray \"") + key + "\" has irregular sizes");
111  }
112  }
113 }
114 
115 template<typename T> Teuchos::TwoDArray<T> getYamlTwoDArray(const YAML::Node& node)
116 {
118  typename Teuchos::TwoDArray<T>::size_type i, j;
119  arr.resizeRows(node.size());
120  arr.resizeCols(node.begin()->size());
121  i = 0;
122  for (YAML::const_iterator rit = node.begin(); rit != node.end(); ++rit)
123  {
124  j = 0;
125  for (YAML::const_iterator cit = rit->begin(); cit != rit->end(); ++cit)
126  {
127  arr(i, j) = quoted_as<T>(*cit);
128  ++j;
129  }
130  ++i;
131  }
132  return arr;
133 }
134 
135 /* Helper functions */
136 
137 void updateParametersFromYamlFile(const std::string& yamlFileName,
138  const Teuchos::Ptr<Teuchos::ParameterList>& paramList)
139 {
140  //load the YAML file in as a new param list
141  Teuchos::RCP<Teuchos::ParameterList> updated = YAMLParameterList::parseYamlFile(yamlFileName);
142  //now update the original list (overwriting values with same key)
143  paramList->setParameters(*updated);
144 }
145 
146 void updateParametersFromYamlCString(const char* const data,
147  const Teuchos::Ptr<Teuchos::ParameterList>& paramList,
148  bool overwrite)
149 {
150  Teuchos::RCP<Teuchos::ParameterList> updated = YAMLParameterList::parseYamlText(data);
151  if(overwrite)
152  {
153  paramList->setParameters(*updated);
154  }
155  else
156  {
157  paramList->setParametersNotAlreadySet(*updated);
158  }
159 }
160 
161 void updateParametersFromYamlString(const std::string& yamlData,
162  const Teuchos::Ptr<Teuchos::ParameterList>& paramList,
163  bool overwrite)
164 {
165  Teuchos::RCP<Teuchos::ParameterList> updated = YAMLParameterList::parseYamlText(yamlData);
166  if(overwrite)
167  {
168  paramList->setParameters(*updated);
169  }
170  else
171  {
172  paramList->setParametersNotAlreadySet(*updated);
173  }
174 }
175 
176 Teuchos::RCP<Teuchos::ParameterList> getParametersFromYamlFile(const std::string& yamlFileName)
177 {
178  return YAMLParameterList::parseYamlFile(yamlFileName);
179 }
180 
181 Teuchos::RCP<Teuchos::ParameterList> getParametersFromYamlString(const std::string& yamlStr)
182 {
183  std::stringstream ss(yamlStr);
184  return YAMLParameterList::parseYamlStream(ss);
185 }
186 
187 void writeParameterListToYamlOStream(
188  const ParameterList &paramList,
189  std::ostream &yamlOut
190  )
191 {
192  YAMLParameterList::writeYamlStream(yamlOut, paramList);
193 }
194 
195 void writeParameterListToYamlFile(
196  const ParameterList &paramList,
197  const std::string &yamlFileName
198  )
199 {
200  YAMLParameterList::writeYamlFile(yamlFileName, paramList);
201 }
202 
203 std::string convertXmlToYaml(const std::string& xmlFileName)
204 {
205  //load the parameter list from xml
206  Teuchos::RCP<Teuchos::ParameterList> toConvert = Teuchos::getParametersFromXmlFile(xmlFileName);
207  //replace the file extension ".xml" with ".yaml", or append it if there was no extension
208  std::string yamlFileName;
209  if(xmlFileName.find(".xml") == std::string::npos)
210  {
211  yamlFileName = xmlFileName + ".yaml";
212  }
213  else
214  {
215  yamlFileName = xmlFileName.substr(0, xmlFileName.length() - 4) + ".yaml";
216  }
217  YAMLParameterList::writeYamlFile(yamlFileName, *toConvert);
218  return yamlFileName;
219 }
220 
221 void convertXmlToYaml(const std::string& xmlFileName, const std::string& yamlFileName)
222 {
223  //load the parameter list from xml
224  Teuchos::RCP<Teuchos::ParameterList> toConvert = Teuchos::getParametersFromXmlFile(xmlFileName);
225  //replace the file extension ".xml" with ".yaml", or append it if there was no extension
226  YAMLParameterList::writeYamlFile(yamlFileName, *toConvert);
227 }
228 
229 void convertXmlToYaml(std::istream& xmlStream, std::ostream& yamlStream)
230 {
231  //read xmlStream into a string until EOF
232  std::string xmlString(std::istreambuf_iterator<char>(xmlStream), {});
233  //load the parameter list from xml
234  Teuchos::RCP<Teuchos::ParameterList> toConvert = Teuchos::getParametersFromXmlString(xmlString);
235  //replace the file extension ".xml" with ".yaml", or append it if there was no extension
236  YAMLParameterList::writeYamlStream(yamlStream, *toConvert);
237 }
238 
239 bool haveSameValuesUnordered(const Teuchos::ParameterList& lhs, const Teuchos::ParameterList& rhs, bool verbose)
240 {
242  Iter i = lhs.begin();
243  Iter j = rhs.begin();
244  if(lhs.name() != rhs.name())
245  {
246  if(verbose)
247  {
248  std::cout << "Parameter list names: \"" << lhs.name() << "\" and \"" << rhs.name() << "\".\n";
249  }
250  return false;
251  }
252  for(; i != lhs.end(); i++)
253  {
254  const std::string& key = lhs.name(i);
255  const Teuchos::ParameterEntry& val1 = lhs.entry(i);
256  //check that rhs also contains this key
257  if(!rhs.isParameter(key))
258  {
259  if(verbose)
260  {
261  std::cout << "One list is missing parameter: \"" << key << "\"\n";
262  }
263  return false;
264  }
265  const Teuchos::ParameterEntry& val2 = rhs.getEntry(key);
266  const Teuchos::any& any1 = val1.getAny(false);
267  const Teuchos::any& any2 = val2.getAny(false);
268  //check that types match
269  if(any1.type() != any2.type())
270  {
271  if(verbose)
272  {
273  std::cout << "Values for key \"" << key << "\" have different types: \"" <<
274  any1.typeName() << "\" vs \"" << any2.typeName() << "\"\n";
275  }
276  return false;
277  }
278  //check for parameter list special case (don't use operator==)
279  if(any1.type() == typeid(Teuchos::ParameterList))
280  {
281  if(!haveSameValuesUnordered(Teuchos::any_cast<Teuchos::ParameterList>(any1), Teuchos::any_cast<Teuchos::ParameterList>(any2), verbose))
282  {
283  //Don't need to print message here, the deepest list not matching will do that
284  return false;
285  }
286  }
287  else
288  {
289  //otherwise, use == to compare the values
290  if(!(val1 == val2))
291  {
292  if(verbose)
293  {
294  std::cout << "Values for key \"" << key << "\" are different.\n";
295  }
296  return false;
297  }
298  }
299  j++;
300  }
301  //lists must have same # of entries
302  if(j != rhs.end())
303  {
304  if(verbose)
305  {
306  std::cout << "Lists \"" << lhs.name() << "\" and \"" << rhs.name() << "\" have different number of parameters.\n";
307  }
308  return false;
309  }
310  return true;
311 }
312 
313 namespace YAMLParameterList
314 {
315 
316 Teuchos::RCP<Teuchos::ParameterList> parseYamlText(const std::string& text)
317 {
319  std::vector<YAML::Node> baseMap = YAML::LoadAll(text);
320  return readParams(baseMap);
321 }
322 
323 Teuchos::RCP<Teuchos::ParameterList> parseYamlText(const char* text)
324 {
326  std::vector<YAML::Node> baseMap = YAML::LoadAll(text);
327  return readParams(baseMap);
328 }
329 
330 Teuchos::RCP<Teuchos::ParameterList> parseYamlFile(const std::string& yamlFile)
331 {
332  std::vector<YAML::Node> baseMap = YAML::LoadAllFromFile(yamlFile);
333  return readParams(baseMap);
334 }
335 
336 Teuchos::RCP<Teuchos::ParameterList> parseYamlStream(std::istream& yaml)
337 {
338  std::vector<YAML::Node> baseMap = YAML::LoadAll(yaml);
339  return readParams(baseMap);
340 }
341 
342 Teuchos::RCP<Teuchos::ParameterList> readParams(std::vector<YAML::Node>& lists)
343 {
344  Teuchos::RCP<Teuchos::ParameterList> pl = rcp(new Teuchos::ParameterList); //pl is the root ParameterList to be returned
345  //If there is exactly one element in "lists", assume it is the anonymous top-level parameter list
346  //If there are more than one, place them all in the anonymous top-level list
347  for(size_t i = 0; i < lists.size(); i++)
348  {
349  processMapNode(lists[i], *pl, true);
350  }
351  return pl;
352 }
353 
354 void processMapNode(const YAML::Node& node, Teuchos::ParameterList& parent, bool topLevel)
355 {
356  if(node.Type() != YAML::NodeType::Map)
357  {
358  throw YamlStructureError("All top-level elements of the YAML file must be maps.");
359  }
360  if(topLevel)
361  {
362  parent.setName("ANONYMOUS");
363  processMapNode(node.begin()->second, parent);
364  }
365  else
366  {
367  for(YAML::const_iterator i = node.begin(); i != node.end(); i++)
368  {
369  //make sure the key type is a string
370  if(i->first.Type() != YAML::NodeType::Scalar)
371  {
372  throw YamlKeyError("Keys must be plain strings");
373  }
374  //if this conversion fails and throws for any reason (shouldn't), let the caller handle it
375  const std::string key = quoted_as<std::string>(i->first);
376  processKeyValueNode(key, i->second, parent, topLevel);
377  }
378  }
379 }
380 
381 void processKeyValueNode(const std::string& key, const YAML::Node& node, Teuchos::ParameterList& parent, bool topLevel)
382 {
383  //node (value) type can be a map (for nested param lists),
384  //a scalar (int, double, string), or a sequence of doubles (vector<double>)
385  if(node.Type() == YAML::NodeType::Scalar)
386  {
387  try
388  {
389  parent.set(key, quoted_as<int>(node));
390  }
391  catch(...)
392  {
393  try
394  {
395  parent.set(key, quoted_as<double>(node));
396  }
397  catch(...)
398  {
399  try
400  {
401  std::string rawString = quoted_as<std::string>(node);
402  if(rawString == "true")
403  {
404  parent.set<bool>(key, true);
405  }
406  else if(rawString == "false")
407  {
408  parent.set<bool>(key, false);
409  }
410  else
411  {
412  parent.set(key, rawString);
413  }
414  }
415  catch(...)
416  {
417  throw YamlScalarError("YAML scalars must be int, double, bool or string.");
418  }
419  }
420  }
421  }
422  else if(node.Type() == YAML::NodeType::Map)
423  {
424  if(topLevel)
425  {
426  processMapNode(node, parent);
427  }
428  else
429  {
430  Teuchos::ParameterList& sublist = parent.sublist(key);
431  processMapNode(node, sublist);
432  }
433  }
434  else if(node.Type() == YAML::NodeType::Sequence)
435  {
436  if (node.begin()->Type() == YAML::NodeType::Sequence) {
437  checkYamlTwoDArray(node, key);
438  YAML::Node const& first_value = *(node.begin()->begin());
439  try
440  {
441  quoted_as<int>(first_value);
442  parent.set(key, getYamlTwoDArray<int>(node));
443  }
444  catch(...)
445  {
446  try
447  {
448  quoted_as<double>(first_value);
449  parent.set(key, getYamlTwoDArray<double>(node));
450  }
451  catch(...)
452  {
453  try
454  {
455  quoted_as<std::string>(first_value);
456  parent.set(key, getYamlTwoDArray<std::string>(node));
457  }
458  catch(...)
459  {
460  throw YamlSequenceError(std::string("TwoDArray \"") + key + "\" must contain int, double, bool or string");
461  }
462  }
463  }
464  } else {
465  YAML::Node const& first_value = *(node.begin());
466  try
467  {
468  quoted_as<int>(first_value);
469  parent.set(key, getYamlArray<int>(node));
470  }
471  catch(...)
472  {
473  try
474  {
475  quoted_as<double>(first_value);
476  parent.set(key, getYamlArray<double>(node));
477  }
478  catch(...)
479  {
480  try
481  {
482  quoted_as<std::string>(first_value);
483  parent.set(key, getYamlArray<std::string>(node));
484  }
485  catch(...)
486  {
487  throw YamlSequenceError(std::string("Array \"") + key + "\" must contain int, double, bool or string");
488  }
489  }
490  }
491  }
492  }
493  else if(node.Type() == YAML::NodeType::Null)
494  {
495  //treat NULL as empty string (not an error)
496  parent.set(key, std::string());
497  }
498  else
499  {
500  //Undefined
501  throw YamlUndefinedNodeError("Value type in a key-value pair must be one of: int, double, string, array, sublist.");
502  }
503 }
504 
505 void writeYamlStream(std::ostream& yaml, const Teuchos::ParameterList& pl)
506 {
507  //warn the user if floats/doubles with integer values will be printed incorrectly
508  auto flags = yaml.flags();
509  //make temporary stringstream to test flags
510  std::ostringstream testStream;
511  testStream.flags(flags);
512  double testVal = 1;
513  testStream << testVal;
514  bool popFlags = false;
515  if(testStream.str() == "1")
516  {
517  //must add showpoint to flags while writing yaml
518  //this will always disambiguate (double) n and n, even if stream precision is 0
519  //prints as "n.0000" where the number of trailing zeros is the stream precision
520  //note: in YAML, "5." is a double but not an int
521  std::cout << "Warning: yaml stream format flags would confuse double with integer value with int.\n";
522  std::cout << "Setting std::ios::showpoint on the stream to fix this (will restore flags when done)\n";
523  auto flagsCopy = flags;
524  flagsCopy |= std::ios::showpoint;
525  popFlags = true;
526  }
527  yaml << "%YAML 1.1\n---\n";
528  yaml << "ANONYMOUS:"; //original top-level list name is not stored by ParameterList
529  if(pl.numParams() == 0)
530  {
531  yaml << " { }\n";
532  }
533  else
534  {
535  writeParameterList(pl, yaml, 2);
536  }
537  yaml << "...\n";
538  //restore flags
539  if(popFlags)
540  {
541  yaml.flags(flags);
542  }
543 }
544 
545 void writeYamlFile(const std::string& yamlFile, const Teuchos::ParameterList& pl)
546 {
547  std::ofstream yaml(yamlFile);
548  /* set default floating-point style:
549  1. 17 decimal places to ensure the value remains the same
550  2. scientific: this prevents floating-point values that happen
551  to be integers from being printed as integers, because YAML
552  will then read that value back typed as an integer.
553  */
554  yaml << std::scientific << std::setprecision(17);
555  writeYamlStream(yaml, pl);
556 }
557 
558 void writeParameterList(const Teuchos::ParameterList& pl, std::ostream& yaml, int indentLevel)
559 {
560  if(pl.begin() == pl.end())
561  {
562  yaml << "{ }\n";
563  }
564  else
565  {
566  yaml << '\n';
567  for(PLIter it = pl.begin(); it != pl.end(); it++)
568  {
569  writeParameter(pl.name(it), pl.entry(it), yaml, indentLevel);
570  }
571  }
572 }
573 
574 template <typename T>
575 struct YamlWrite {
576  static void write(T const& x, std::ostream& stream) {
577  stream << x;
578  }
579 };
580 
581 template <>
582 struct YamlWrite<double> {
583  static void write(double const& x, std::ostream& stream) {
584  generalWriteDouble(x, stream);
585  }
586 };
587 
588 template <>
589 struct YamlWrite<std::string> {
590  static void write(std::string const& x, std::ostream& stream) {
591  generalWriteString(x, stream);
592  }
593 };
594 
595 template <typename T>
596 void writeYamlTwoDArray(Teuchos::TwoDArray<T> const& arr, std::ostream& stream)
597 {
598  typename Teuchos::TwoDArray<T>::size_type i, j;
599  stream << '[';
600  for (i = 0; i < arr.getNumRows(); ++i)
601  {
602  if (i) stream << ", ";
603  stream << '[';
604  for (j = 0; j < arr.getNumCols(); ++j)
605  {
606  if (j) stream << ", ";
607  YamlWrite<T>::write(arr(i, j), stream);
608  }
609  stream << ']';
610  }
611  stream << ']';
612 }
613 
614 void writeParameter(const std::string& paramName, const Teuchos::ParameterEntry& entry, std::ostream& yaml, int indentLevel)
615 {
616  for(int i = 0; i < indentLevel; i++)
617  {
618  yaml << ' ';
619  }
620  generalWriteString(paramName, yaml);
621  yaml << ": ";
622  if(entry.isList())
623  {
624  writeParameterList(Teuchos::getValue<Teuchos::ParameterList>(entry), yaml, indentLevel + 2);
625  return;
626  }
627  else if(entry.isArray())
628  {
629  yaml << '[';
630  if(entry.isType<Teuchos::Array<int> >())
631  {
632  Teuchos::Array<int>& arr = Teuchos::getValue<Teuchos::Array<int> >(entry);
633  for(int i = 0; i < arr.size(); i++)
634  {
635  yaml << arr[i];
636  if(i != arr.size() - 1)
637  yaml << ", ";
638  }
639  }
640  else if(entry.isType<Teuchos::Array<double> >())
641  {
642  Teuchos::Array<double>& arr = Teuchos::getValue<Teuchos::Array<double> >(entry);
643  for(int i = 0; i < arr.size(); i++)
644  {
645  generalWriteDouble(arr[i], yaml);
646  if(i != arr.size() - 1)
647  yaml << ", ";
648  }
649  }
650  else if(entry.isType<Teuchos::Array<std::string> >())
651  {
652  Teuchos::Array<std::string>& arr = Teuchos::getValue<Teuchos::Array<std::string> >(entry);
653  for(int i = 0; i < arr.size(); i++)
654  {
655  generalWriteString(arr[i], yaml);
656  if(i != arr.size() - 1)
657  yaml << ", ";
658  }
659  }
660  yaml << ']';
661  }
662  else if(entry.isTwoDArray())
663  {
664  if(entry.isType<Teuchos::TwoDArray<int> >())
665  {
666  writeYamlTwoDArray<int>(
667  Teuchos::getValue<Teuchos::TwoDArray<int> >(entry), yaml);
668  }
669  else if(entry.isType<Teuchos::TwoDArray<double> >())
670  {
671  writeYamlTwoDArray<double>(
672  Teuchos::getValue<Teuchos::TwoDArray<double> >(entry), yaml);
673  }
674  else if(entry.isType<Teuchos::TwoDArray<std::string> >())
675  {
676  writeYamlTwoDArray<std::string>(
677  Teuchos::getValue<Teuchos::TwoDArray<std::string> >(entry), yaml);
678  }
679  }
680  else if(entry.isType<int>())
681  {
682  yaml << Teuchos::getValue<int>(entry);
683  }
684  else if(entry.isType<double>())
685  {
686  generalWriteDouble(Teuchos::getValue<double>(entry), yaml);
687  }
688  else if(entry.isType<std::string>())
689  {
690  std::string& str = Teuchos::getValue<std::string>(entry);
691  if(strchr(str.c_str(), '\n'))
692  {
693  //need explicit indentation so that indentation in the string is preserved
694  yaml << "|2-\n";
695  //for each line, apply indent then print the line verbatim
696  size_t index = 0;
697  while(true)
698  {
699  size_t next = str.find('\n', index);
700  for(int i = 0; i < indentLevel + 2; i++)
701  {
702  yaml << ' ';
703  }
704  if(next == std::string::npos)
705  {
706  yaml << str.substr(index, std::string::npos);
707  break;
708  }
709  else
710  {
711  yaml << str.substr(index, next - index) << '\n';
712  }
713  index = next + 1;
714  }
715  }
716  else
717  {
718  generalWriteString(str, yaml);
719  }
720  }
721  else if(entry.isType<bool>())
722  {
723  yaml << (Teuchos::getValue<bool>(entry) ? "true" : "false");
724  }
725  yaml << '\n';
726 }
727 
728 void generalWriteString(const std::string& str, std::ostream& yaml)
729 {
730  if(stringNeedsQuotes(str))
731  {
732  yaml << '\'' << str << '\'';
733  }
734  else
735  {
736  yaml << str;
737  }
738 }
739 
740 void generalWriteDouble(double d, std::ostream& yaml)
741 {
742  yaml << d;
743 }
744 
745 template <typename T>
746 static bool canBeParsedAs(std::string const& s) {
747  std::istringstream iss(s);
748  T val;
749  iss >> std::noskipws >> val;
750  return iss.eof() && !iss.fail();
751 }
752 
753 static bool containsSpecialCharacters(std::string const& s) {
754  char const* const control_chars = ":{}[],&*#?|-<>=!%@\\";
755  return s.find_first_of(control_chars) != std::string::npos;
756 }
757 
758 bool stringNeedsQuotes(const std::string& s)
759 {
760  return containsSpecialCharacters(s) ||
761  canBeParsedAs<int>(s) ||
762  canBeParsedAs<double>(s);
763 }
764 
765 } //namespace YAMLParameterList
766 
767 } //namespace Teuchos
768 
769 #endif
A thin wrapper around the Teuchos Array class that allows for 2 dimensional arrays.
C++ Standard Library compatable filtered iterator.
ConstIterator begin() const
An iterator pointing to the first entry.
ParameterList & set(std::string const &name, T const &value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
Set a parameter whose value has type T.
This object is held as the "value" in the Teuchos::ParameterList std::map.
const ParameterEntry & entry(ConstIterator i) const
Access to ParameterEntry (i.e., returns i->second)
Ordinal numParams() const
Get the number of stored parameters.
size_type getNumRows() const
returns the number of rows in the TwoDArray.
Modified boost::any class, which is a container for a templated value.
Definition: Teuchos_any.hpp:86
Simple helper functions that make it easy to read and write XML to and from a parameterlist.
ConstIterator end() const
An iterator pointing beyond the last entry.
A thin wrapper around the Array class which causes it to be interpreted as a 2D Array.
size_type getNumCols() const
returns the number of columns in the TwoDArray.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Deprecated.
size_type size() const
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.
bool isList() const
Return whether or not the value itself is a list.
A list of parameters of arbitrary type.
bool isTwoDArray() const
Test if the type of data being contained is a Teuchos::TwoDArray.
ParameterList & setParameters(const ParameterList &source)
bool isType() const
Test the type of the data being contained.
const std::type_info & type() const
Return the type of value being stored.
const std::string & name() const
The name of this ParameterList.
any & getAny(bool activeQry=true)
Direct access to the Teuchos::any data value underlying this object. The bool argument activeQry (def...
void push_back(const value_type &x)
The Teuchos namespace contains all of the classes, structs and enums used by Teuchos, as well as a number of utility routines.
ParameterList & setParametersNotAlreadySet(const ParameterList &source)
std::string typeName() const
Return the name of the type.
bool isParameter(const std::string &name) const
Whether the given parameter exists in this list.
bool isArray() const
Test if the type of data being contained is a Teuchos::Array.
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.
ParameterEntry & getEntry(const std::string &name)
Retrieves an entry with the name name.
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...