/* This file is part of the OpenLB library
*
* Copyright (C) 2010 Jonas Latt, Jonas Fietz, Mathias Krause
* E-mail contact: info@openlb.net
* The most recent release of OpenLB can be downloaded at
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/** \file
* Input/Output in XML format -- non-generic code.
*/
#include "io/xmlReader.h"
#include
#include
#include
#include "communication/mpiManager.h"
namespace olb {
XMLreader XMLreader::_notFound;
XMLreader::XMLreader()
: clout(std::cout,"XMLreader")
{
_name = "XML node not found";
_warningsOn = true;
}
XMLreader::XMLreader( TiXmlNode* pParent)
: clout(std::cout,"XMLreader")
{
_warningsOn = true;
if (singleton::mpi().isMainProcessor()) {
mainProcessorIni(pParent);
} else {
slaveProcessorIni();
}
}
XMLreader::XMLreader(const std::string& fName)
: clout("XMLreader")
{
_warningsOn = true;
TiXmlDocument* doc = nullptr;
int loadOK = false;
#ifdef PARALLEL_MODE_MPI // parallel program execution
if (singleton::mpi().isMainProcessor()) {
#endif
doc = new TiXmlDocument(fName.c_str());
loadOK = doc->LoadFile();
if (!loadOK) {
clout << std::string("Problem processing input XML file ") << fName << std::endl;
}
#ifdef PARALLEL_MODE_MPI // parallel program execution
}
if (singleton::mpi().isMainProcessor()) {
#endif
mainProcessorIni(doc);
delete doc;
#ifdef PARALLEL_MODE_MPI // parallel program execution
} else {
slaveProcessorIni();
}
#endif
}
XMLreader::~XMLreader()
{
for (unsigned int iNode=0; iNode<_children.size(); ++iNode) {
delete _children[iNode];
}
}
void XMLreader::mainProcessorIni( TiXmlNode* pParent )
{
assert (pParent->Type()==TiXmlNode::TINYXML_DOCUMENT || pParent->Type()==TiXmlNode::TINYXML_ELEMENT );
if (pParent->Type() == TiXmlNode::TINYXML_DOCUMENT) {
// ignore the surrounding PARAM-block
pParent = pParent->FirstChildElement();
}
_name = pParent->ValueStr();
#ifdef PARALLEL_MODE_MPI // parallel program execution
singleton::mpi().bCast(&_name,1);
#endif
TiXmlAttribute* attr = pParent->ToElement()->FirstAttribute();
while (attr != nullptr) {
#ifdef PARALLEL_MODE_MPI // parallel program execution
int size = 0;
std::string* key = const_cast(&attr->NameTStr());
singleton::mpi().bCast(key, size);
std::string* value = const_cast(&attr->ValueStr());
singleton::mpi().bCast(value, size);
#endif
_attributes[attr->NameTStr()] = attr->ValueStr();
attr = attr->Next();
}
#ifdef PARALLEL_MODE_MPI // parallel program execution
std::string tmpstr = "";
int size = 0;
singleton::mpi().bCast(&tmpstr, size);
singleton::mpi().bCast(&tmpstr, size);
#endif
TiXmlNode * pChild;
int type = 0;
for ( pChild = pParent->FirstChild(); pChild != nullptr; pChild = pChild->NextSibling()) {
type = pChild->Type();
#ifdef PARALLEL_MODE_MPI // parallel program execution
singleton::mpi().bCast(&type, 1);
#endif
if ( type==TiXmlNode::TINYXML_ELEMENT ) {
_children.push_back( new XMLreader( pChild ) );
} else if ( type==TiXmlNode::TINYXML_TEXT ) {
_text = pChild->ToText()->ValueStr();
#ifdef PARALLEL_MODE_MPI // parallel program execution
singleton::mpi().bCast(&_text,1);
#endif
}
}
type = TiXmlNode::TINYXML_UNKNOWN;
#ifdef PARALLEL_MODE_MPI // parallel program execution
singleton::mpi().bCast(&type, 1);
#endif
}
void XMLreader::slaveProcessorIni()
{
#ifdef PARALLEL_MODE_MPI // parallel program execution
singleton::mpi().bCast(&_name,1);
std::string key = "";
std::string value = "";
int size = int();
do {
singleton::mpi().bCast(&key, size);
singleton::mpi().bCast(&value, size);
_attributes[key] = value;
} while (key != "");
#endif
int type=0;
do {
#ifdef PARALLEL_MODE_MPI // parallel program execution
singleton::mpi().bCast(&type, 1);
#endif
if ( type==TiXmlNode::TINYXML_ELEMENT ) {
_children.push_back( new XMLreader( nullptr ) );
} else if ( type==TiXmlNode::TINYXML_TEXT ) {
#ifdef PARALLEL_MODE_MPI // parallel program execution
singleton::mpi().bCast(&_text,1);
#endif
}
} while (type != TiXmlNode::TINYXML_UNKNOWN);
}
void XMLreader::print(int indent) const
{
std::string indentStr(indent, ' ');
clout << indentStr << "[" << _name << "]" << std::endl;
if (!_text.empty()) {
clout << indentStr << " " << _text << std::endl;
}
for (unsigned int iNode=0; iNode<_children.size(); ++iNode) {
_children[iNode]->print(indent+2);
}
}
XMLreader const& XMLreader::operator[] (std::string fName) const
{
for (unsigned int iNode=0; iNode<_children.size(); ++iNode) {
if (_children[iNode]->_name == fName) {
return *_children[iNode];
}
}
if ( _warningsOn ) {
clout << "Warning: cannot read value from node \"" << _name << "\"" << ", \"" << fName <<"\"" << std::endl;
}
return _notFound;
}
std::vector::const_iterator XMLreader::begin() const
{
return _children.begin();
}
std::vector::const_iterator XMLreader::end() const
{
return _children.end();
}
std::string XMLreader::getName() const
{
return _name;
}
void XMLreader::setWarningsOn(bool warnings) const
{
_warningsOn = warnings;
for (unsigned int iNode=0; iNode<_children.size(); ++iNode) {
_children[iNode]->setWarningsOn(warnings);
}
}
// template specialization for T=bool
template <>
bool XMLreader::read(bool& value, bool verboseOn, bool exitIfMissing) const
{
std::stringstream valueStr(_text);
std::string word;
valueStr >> word;
// Transform to lower-case, so that "true" and "false" are case-insensitive.
std::transform(word.begin(), word.end(), word.begin(), ::tolower);
if (!word.compare("true") || (word=="1")) {
value = true;
return true;
} else if (!word.compare("false") || (word=="0")) {
value=false;
return true;
} else {
if ( verboseOn ) {
std::stringstream ss;
ss << ( value ? "true" : "false" );
printWarning("bool", ss.str(), verboseOn, exitIfMissing);
}
}
return false;
}
// template specialization for T=int
template <>
bool XMLreader::read(int& value, bool verboseOn, bool exitIfMissing) const
{
std::stringstream valueStr(_text);
int tmp = int();
if (!(valueStr >> tmp)) {
std::stringstream ss;
ss << value;
printWarning("int", ss.str(), verboseOn, exitIfMissing);
return false;
}
value = tmp;
return true;
}
// template specialization for T=double
template <>
bool XMLreader::read(double& value, bool verboseOn, bool exitIfMissing) const
{
std::stringstream valueStr(_text);
double tmp = double();
if (!(valueStr >> tmp)) {
std::stringstream ss;
ss << value;
printWarning("double", ss.str(), verboseOn, exitIfMissing);
return false;
}
value = tmp;
return true;
}
template <>
bool XMLreader::read(std::string& entry, bool verboseOn, bool exitIfMissing) const
{
if (_name == "XML node not found") {
return false;
}
std::stringstream valueStr(_text);
std::string tmp = std::string();
if (!(valueStr >> tmp)) {
std::stringstream ss;
ss << entry;
printWarning("string", ss.str(), verboseOn, exitIfMissing);
return false;
}
entry = _text;
return true;
}
std::string XMLreader::getAttribute(const std::string& aName) const
{
std::map::const_iterator it = _attributes.find(aName);
if ( it == _attributes.end()) {
return "Attribute not found.";
}
return it->second;
//return attributes[aName];
}
/// print warning if verbose mode is on and exit, if exItMissing is true
void XMLreader::printWarning(std::string typeName, std::string value, bool verboseOn, bool exitIfMissing) const
{
if ( verboseOn ) {
clout << "Warning: Cannot read " << typeName << " value from XML element " << _name << "." << std::endl;
if ( ! value.empty() ) {
clout << " Setting default value = " << value << std::endl;
}
}
if ( exitIfMissing ) {
clout << "Error: This program cannot continue without \"" << _name << "\". Optimization aborted." << std::endl;
exit(1);
}
}
} // namespace olb