From 2f3f1a621f7f934182a56d169859fc668d055ab1 Mon Sep 17 00:00:00 2001 From: Dan Ibanez Date: Mon, 6 Mar 2017 13:49:45 -0700 Subject: [PATCH] Teuchos: YAML parse support for TwoDArray This enhancement supports gahansen/Albany#74. Albany uses TwoDArray type ParameterLists, and getting these supported in the YAML parser would streamline our migration from XML to YAML. There should be no compatibility issue, as I don't think the current parser can handle nested Sequences. A unit test is included. --- .../parameterlist/src/Teuchos_YamlParser.cpp | 86 ++++++++++++++++--- .../parameterlist/test/yaml/TwoDArray.yaml | 5 ++ .../test/yaml/YamlParameterList.cpp | 17 ++++ 3 files changed, 95 insertions(+), 13 deletions(-) create mode 100644 packages/teuchos/parameterlist/test/yaml/TwoDArray.yaml diff --git a/packages/teuchos/parameterlist/src/Teuchos_YamlParser.cpp b/packages/teuchos/parameterlist/src/Teuchos_YamlParser.cpp index 28916f58ed54..770784d68a1b 100644 --- a/packages/teuchos/parameterlist/src/Teuchos_YamlParser.cpp +++ b/packages/teuchos/parameterlist/src/Teuchos_YamlParser.cpp @@ -49,6 +49,7 @@ #include "Teuchos_YamlParser_decl.hpp" #include "Teuchos_XMLParameterListCoreHelpers.hpp" +#include "Teuchos_TwoDArray.hpp" namespace Teuchos { @@ -63,6 +64,36 @@ template Teuchos::Array getYamlArray(const YAML::Node& node) return arr; } +void checkYamlTwoDArray(const YAML::Node& node, const std::string& key) +{ + for (YAML::const_iterator it = node.begin(); it != node.end(); ++it) + { + if (it->size() != node.begin()->size()) + { + throw YamlSequenceError(std::string("TwoDArray \"") + key + "\" has irregular sizes"); + } + } +} + +template Teuchos::TwoDArray getYamlTwoDArray(const YAML::Node& node) +{ + Teuchos::TwoDArray arr; + typename Teuchos::TwoDArray::size_type i, j; + arr.resizeRows(node.size()); + arr.resizeCols(node.begin()->size()); + i = 0; + for (YAML::const_iterator rit = node.begin(); rit != node.end(); ++rit) + { + j = 0; + for (YAML::const_iterator cit = rit->begin(); cit != rit->end(); ++cit) + { + arr(i, j) = cit->as(); + ++j; + } + ++i; + } + return arr; +} /* Helper functions */ @@ -327,29 +358,58 @@ void processKeyValueNode(const std::string& key, const YAML::Node& node, Teuchos } else if(node.Type() == YAML::NodeType::Sequence) { - //typeString is used to provide a useful error message if types inconsistent - try - { - node.begin()->as(); - parent.set(key, getYamlArray(node)); - } - catch(...) - { + if (node.begin()->Type() == YAML::NodeType::Sequence) { + checkYamlTwoDArray(node, key); + try + { + node.begin()->begin()->as(); + parent.set(key, getYamlTwoDArray(node)); + } + catch(...) + { + try + { + node.begin()->begin()->as(); + parent.set(key, getYamlTwoDArray(node)); + } + catch(...) + { + try + { + node.begin()->begin()->as(); + parent.set(key, getYamlTwoDArray(node)); + } + catch(...) + { + throw YamlSequenceError(std::string("TwoDArray \"") + key + "\" must contain int, double, bool or string"); + } + } + } + } else { + //typeString is used to provide a useful error message if types inconsistent try { - node.begin()->as(); - parent.set(key, getYamlArray(node)); + node.begin()->as(); + parent.set(key, getYamlArray(node)); } catch(...) { try { - node.begin()->as(); - parent.set(key, getYamlArray(node)); + node.begin()->as(); + parent.set(key, getYamlArray(node)); } catch(...) { - throw YamlSequenceError(std::string("Array \"") + key + "\" must contain int, double, bool or string"); + try + { + node.begin()->as(); + parent.set(key, getYamlArray(node)); + } + catch(...) + { + throw YamlSequenceError(std::string("Array \"") + key + "\" must contain int, double, bool or string"); + } } } } diff --git a/packages/teuchos/parameterlist/test/yaml/TwoDArray.yaml b/packages/teuchos/parameterlist/test/yaml/TwoDArray.yaml new file mode 100644 index 000000000000..5700d7e385ed --- /dev/null +++ b/packages/teuchos/parameterlist/test/yaml/TwoDArray.yaml @@ -0,0 +1,5 @@ +%YAML 1.1 +--- +Albany: + str2d: [[R, G, B], ['1', '2', '3']] +... diff --git a/packages/teuchos/parameterlist/test/yaml/YamlParameterList.cpp b/packages/teuchos/parameterlist/test/yaml/YamlParameterList.cpp index 702ae6b67cab..929debadf301 100644 --- a/packages/teuchos/parameterlist/test/yaml/YamlParameterList.cpp +++ b/packages/teuchos/parameterlist/test/yaml/YamlParameterList.cpp @@ -53,6 +53,7 @@ #include #include #include +#include @@ -129,5 +130,21 @@ namespace TeuchosTests } }); } + TEUCHOS_UNIT_TEST(YAML, ReadTwoDArray) + { + std::string correctStrings[2][3] = {{"R", "G", "B"}, {"1", "2", "3"}}; + TEST_NOTHROW({ + RCP plist = Teuchos::getParametersFromYamlFile("TwoDArray.yaml"); + const Teuchos::TwoDArray& str2d = plist->get >("str2d"); + for (int i = 0; i < 2; ++i) { + for (int j = 0; j < 3; ++j) { + if (str2d[i][j] != correctStrings[i][j]) { + throw std::runtime_error(std::string("str2d[") + std::to_string(i) + "][" + + std::to_string(j) + "] is incorrect."); + } + } + } + }); + } } //namespace TeuchosTests