Commit 00561533 authored by Praetorius, Simon's avatar Praetorius, Simon

new Initfile parser

parent 32af9a5a
......@@ -68,7 +68,7 @@ set(AMDIS_MINOR_VERSION @AMDIS_MINOR@)
if(AMDiS_NEED_UMFPACK)
#look for umfpack, we need the headers only
find_file(UMFPACK_H umfpack.h
HINTS /usr/include /usr/include/suitesparse
HINTS /usr/include /usr/include/suitesparse /usr/include/ufsparse
DOC "headerfile umfpack.h for UMFPACK")
if( UMFPACK_H )
#construct the include path
......@@ -125,6 +125,11 @@ if(AMDiS_NEED_UMFPACK)
list(APPEND AMDIS_LIBRARY_DIRS ${BLAS_LIBRARY_DIR})
endif(AMDiS_NEED_UMFPACK)
#add directories for reinit
list(APPEND AMDIS_INCLUDE_DIRS ${AMDIS_INCLUDE_DIR}/reinit)
list(APPEND AMDIS_INCLUDE_DIRS ${AMDIS_INCLUDE_DIR}/compositeFEM)
if(${AMDIS_FIND_COMPONENTS} MATCHES umfpack )
if( NOT AMDiS_NEED_UMFPACK )
set( AMDiS_umfpack_FOUND FALSE)
......
......@@ -100,6 +100,7 @@ SET(AMDIS_SRC ${SOURCE_DIR}/AdaptBase.cc
${SOURCE_DIR}/Global.cc
${SOURCE_DIR}/GlobalDOFNumbering.cc
${SOURCE_DIR}/GlobalElementNumbering.cc
${SOURCE_DIR}/Initfile.cc
${SOURCE_DIR}/Lagrange.cc
${SOURCE_DIR}/LeafData.cc
${SOURCE_DIR}/Line.cc
......@@ -288,7 +289,7 @@ if(ENABLE_UMFPACK)
#look for umfpack, we need the headers only
find_file(UMFPACK_H umfpack.h
HINTS /usr/include /usr/include/suitesparse
HINTS /usr/include /usr/include/suitesparse /usr/include/ufsparse
DOC "headerfile umfpack.h for UMFPACK")
if( UMFPACK_H )
#construct the include path
......@@ -345,8 +346,9 @@ include_directories(${AMDiS_INCLUDE_DIRS})
add_library(amdis SHARED ${AMDIS_SRC} ${PARALLEL_DOMAIN_AMDIS_SRC})
add_library(compositeFEM SHARED ${COMPOSITE_FEM_SRC})
add_library(reinit STATIC ${REINIT_SRC})
target_link_libraries(compositeFEM amdis)
add_library(reinit SHARED ${REINIT_SRC})
#target_link_libraries(compositeFEM amdis)
#target_link_libraries(reinit amdis)
list(APPEND AMDiS_LIBS amdis ${Boost_LIBRARIES})
if(WIN32)
......@@ -361,9 +363,6 @@ if(ENABLE_MARMOT)
endif(ENABLE_MARMOT)
#dont change this destination. the GUI depends on it to guess the buildsystem
list(APPEND deb_add_dirs "lib/amdis")
install(TARGETS amdis compositeFEM
LIBRARY DESTINATION lib/amdis/ )
FILE(GLOB HEADERS "${SOURCE_DIR}/*.h")
INSTALL(FILES ${HEADERS}
......@@ -398,6 +397,20 @@ FILE(GLOB HEADERS "${SOURCE_DIR}/io/*.hh")
INSTALL(FILES ${HEADERS}
DESTINATION include/amdis/io)
FILE(GLOB HEADERS "${REINIT_SOURCE_DIR}/*.h")
INSTALL(FILES ${HEADERS}
DESTINATION include/amdis/reinit)
list(APPEND deb_add_dirs "include/amdis/reinit")
FILE(GLOB HEADERS "${COMPOSITE_SOURCE_DIR}/*.h")
INSTALL(FILES ${HEADERS}
DESTINATION include/amdis/compositeFEM)
list(APPEND deb_add_dirs "include/amdis/compositeFEM")
list(APPEND deb_add_dirs "lib/amdis")
install(TARGETS amdis compositeFEM reinit
LIBRARY DESTINATION lib/amdis/ )
configure_file(${AMDiS_SOURCE_DIR}/AMDiSConfig.cmake.in
${AMDiS_BINARY_DIR}/AMDISConfig.cmake
@ONLY
......
#include "Initfile.h"
#include <string>
#include <stdexcept>
#include <iostream>
#include <sstream>
using namespace std;
/// the small parser for the initfile. see description of read(Initfile&, istream&)
struct Parser {
Parser(const string& line) {
size_t pos= line.find(':');
if (pos == string::npos)
throw runtime_error("cannot find the delimiter ':' in line '"+line+"'");
name= line.substr(0, pos);
value= line.substr(pos+1, line.length() - (pos + 1));
// remove everything after the %
pos= value.find('%');
if (pos != string::npos) {
value= value.substr(0, pos);
}
}
string name;
string value;
};
Initfile* Initfile::singlett= NULL;
std::set< std::string > Initfile::fn_include_list;
/// initialize singleton object an global parameters
void Initfile::init(std::string in) {
initIntern();
singlett->clear();
fn_include_list.clear();
singlett->read(in);
singlett->getInternalParameters();
// initialize global strcutures using parameters
Global::init();
};
/// Fill an initfile from a file with filename fn
void Initfile::read(std::string fn) {
// read file if its not parsed already
if (fn_include_list.find(fn)==fn_include_list.end()) {
std::ifstream inputFile;
inputFile.open(fn.c_str(), std::ios::in);
if (!inputFile.is_open())
throw runtime_error("init-file cannot be opened for reading");
fn_include_list.insert(fn);
read(inputFile);
}
};
/// Fill an initfile from an input stream
void Initfile::read(istream& in) {
unsigned line_length= 256;
char swap[line_length];
in.getline(swap, line_length);
while (in.good()) {
std::string whitespaces= " \t\r\f";
std::string sw(swap);
size_t pos0= sw.find_first_not_of(whitespaces);
if (pos0!=std::string::npos && sw[pos0]!='%' && sw[pos0]!='#' && sw[pos0]!=0) {
// parse line and extract map: tag->value
Parser parser(sw);
operator[](parser.name)= parser.value;
} else if (sw[pos0]=='#' && static_cast<size_t>(sw.find("#include"))==pos0) {
// include file by '#include "filename"' or '#include <filename>'
size_t pos= sw.find_first_not_of(whitespaces,std::string("#include").size()+1);
size_t epos= 0;
std::string fn= "";
std::stringstream errorMsg;
switch (char c= swap[pos++]) {
case '<':
c= '>';
case '\"':
whitespaces+= c;
epos= sw.find_first_of(whitespaces, pos);
fn= sw.substr(pos,epos-pos);
if (sw[epos]!=c) {
errorMsg << "filename in #include not terminated by " << c;
throw std::runtime_error(errorMsg.str());
}
break;
default:
throw std::runtime_error("no filename given for #include");
}
read(fn);
}
in.getline(swap, line_length);
}
};
/// read standard values for output and information of parameter-values
void Initfile::getInternalParameters()
{
int val= 10;
get("level of information", val, 0);
msgInfo= val;
val= 1;
get("WAIT", val, 0);
msgWait= val;
val= 1;
get("parameter information", val, 0);
paramInfo= val;
if (msgInfo==0)
paramInfo= 0;
};
/// print all parameters to std::cout
void Initfile::printParameters() {
initIntern();
Initfile::iterator it;
for (it= singlett->begin(); it!=singlett->end(); it++)
std::cout << (*it).first << " => " << (*it).second << std::endl;
};
/// Write data-map to initfile
void Initfile::write(ostream& out) {
Initfile::iterator it;
for (it= begin() ; it!=end(); it++)
out << (*it).first << ": " << (*it).second << std::endl;
};
/// Write data-map to initfile
void Initfile::write(std::string fn) {
std::ofstream outFile;
outFile.open(fn.c_str(), std::ios::out);
if (!outFile.is_open())
throw runtime_error("init-file cannot be opened for writing");
write(outFile);
};
#ifndef INITFILE_H
#define INITFILE_H
#include <fstream>
#include <sstream>
#include <string>
#include <map>
#include <list>
#include <set>
#include <vector>
#include <stdexcept>
#include <iostream>
#include <typeinfo>
#include "FixVec.h"
#include <boost/algorithm/string/trim.hpp>
#include <boost/lexical_cast.hpp>
using namespace AMDiS;
namespace InitfileInternal {
/// Exceptions
struct WrongVectorSize : std::runtime_error {
WrongVectorSize(std::string m):std::runtime_error(m) {}
};
struct NoDelim : std::runtime_error {
NoDelim(std::string m):std::runtime_error(m) {}
};
struct WrongVectorFormat : std::runtime_error {
WrongVectorFormat(std::string m):std::runtime_error(m) {}
};
template< typename T >
struct WrongValueFormat : std::runtime_error {
static std::string name(int ) { return "int"; }
static std::string name(bool ) { return "bool"; }
static std::string name(double ) { return "double"; }
static std::string name(unsigned int ) { return "unsigned int"; }
template< typename G >
static std::string name(G ) { return std::string(typeid(G).name()); }
WrongValueFormat(std::string value): std::runtime_error(std::string("cannot convert '") + value + std::string("' into <")+ name(T())+">" )
{}
};
/// trim std::string
inline std::string trim(const std::string& oldStr) {
std::string swap(oldStr);
boost::algorithm::trim(swap);
return swap;
}
/// return the delimiter or throw an exception if there is no known delimiter in value
size_t checkDelim(const std::string& value, const std::string& delims) {
size_t pos(std::string::npos);
for (unsigned i= 0; i<delims.length(); ++i) {
pos= value.find(delims[i]);
if (pos!=std::string::npos)
return i;
}
throw NoDelim("cannot detect the delimiter in " + value);
return 0;
}
/** parse an container from tag tag. The Container must have the properties:
* - type value_type
* - member function push_back
*/
template< typename Container >
inline void getContainer(const std::string val_, Container& c) {
// accepted brackets and delimiters for vector input
std::string begBrackets= "{[(";
std::string endBrackets= "}])";
std::string delims= ",;";
c.clear();
std::string val= trim(val_);
size_t pos= begBrackets.find(val[0]);
if( pos == std::string::npos )
throw WrongVectorFormat("cannot convert '" + val + "' into a list. No leading bracket found!");
if( val[val.length() - 1] != endBrackets[pos] )
throw WrongVectorFormat("begin and end bracket are different in value '" + val + "'");
size_t oldPos= 1;
size_t curDelim= 0;
typedef typename Container::value_type ValueType;
ValueType swap;
try {
curDelim= checkDelim(val, delims);
pos= val.find(delims[curDelim], oldPos);
while( pos != std::string::npos ) {
std::string curWord= val.substr(oldPos, pos - 1);
oldPos= pos + 1;
convert(curWord, swap);
c.push_back(swap);
pos= val.find(delims[curDelim], oldPos);
}
//last entry
std::string curWord= val.substr(oldPos, val.length() - oldPos-1);
convert(curWord, swap);
c.push_back(swap);
} catch (NoDelim nd) {
std::string curWord= val.substr(1, val.length()-2);
curWord = trim(curWord);
if(curWord.length()>0) {
// container with one entry
convert(curWord, swap);
c.push_back(swap);
}
}
}
/// convert string to string
inline void convert(const std::string valStr, std::string& value) {
value= trim(valStr);
}
/// convert string to intrinsic type
template< typename T >
inline void convert(const std::string valStr, T& value) {
using boost::lexical_cast;
try {
value = lexical_cast< T >(trim(valStr));
}catch(boost::bad_lexical_cast e) {
throw WrongValueFormat< T >(valStr);
}
}
/// convert string to WorldVector
template< typename T >
inline void convert(const std::string valStr, WorldVector<T>& c) {
std::vector<T> temp_vec;
getContainer(valStr, temp_vec);
if (static_cast<int>(temp_vec.size())!=c.getSize())
throw WrongVectorSize("wrong number of entries for WorldVector");
for (unsigned i= 0; i<temp_vec.size(); ++i)
c[i]= temp_vec[i];
}
/// convert string to std::list using begBrackets, endBrackets and delims
template< typename T >
inline void convert(const std::string valStr, std::list< T >& value) {
getContainer(valStr, value);
}
/// convert string to std::vector using begBrackets, endBrackets and delims
template< typename T >
inline void convert(const std::string valStr, std::vector< T >& value) {
getContainer(valStr, value);
}
/// convert value of arbitrary type to string using stringstream and operator<< for type
template< typename T >
inline void convert(const T value, std::string& valStr) {
std::stringstream ss;
ss << value;
valStr= ss.str();
}
/// convert WorldVector to string
template< typename T >
inline void convert(const WorldVector<T>& c, std::string& valStr) {
std::vector<T> temp_vec(c.getSize());
for (unsigned i= 0; i<temp_vec.size(); ++i)
temp_vec[i]= c[i];
convert(temp_vec, valStr);
}
} // end namespace InitfileInternal
/** The entry in an initfile. This helper class was constructed to allow calls like
* val = data.get(tag)
* for arbitrary types of val. At current stage, only double and bool is supported
*/
struct InitEntry {
///the value as string
std::string valStr;
/// initialize with value as string
InitEntry(std::string v= ""):
valStr(v) {}
/// cast string to type T
template< typename T >
operator T() const { T t; convert(valStr, t); return t;}
};
/// output-stream for std::list
template< typename T >
std::ostream& operator<<(std::ostream& o, const std::list< T >& l) {
typename std::list< T >::const_iterator it= l.begin();
o << "[";
for(unsigned i= 0; it!=l.end() && i<l.size(); ++i) {
o << *it << (i<l.size()-1?", ":"");
++it;
}
o << "]";
return o;
}
/// output-stream for std::vector
template< typename T >
std::ostream& operator<<(std::ostream& o, const std::vector< T >& l) {
typename std::vector< T >::const_iterator it= l.begin();
o << "[";
for(unsigned i= 0; it!=l.end() && i<l.size(); ++i) {
o << *it << (i<l.size()-1?", ":"");
++it;
}
o << "]";
return o;
}
/** Basis data container as a map of tag on a value as strings. The container throws an exception, if the tag was not found.
*/
struct Initfile : public std::map< std::string, std::string > {
typedef std::map< std::string, std::string > super;
/// Exceptions
struct TagNotFound : std::invalid_argument {
TagNotFound(std::string m):std::invalid_argument(m) {}
};
/** initialize init-file from file with filename in, read data and save it to singleton-map
* @param in: filename string
*/
static void init(std::string in);
/** Static get routine for getting parameter-values from init-file initialized in init()-method.
* Cast the value to the desired type using std::stringstream.
* @param tag: The tag to look for
* @param value: The result.
* @param debug_info: msgInfo for current parameter. (0..no printing, 1..print missing parameter info, 2..print parameter value) [optional]
*/
template< typename T >
static void get(const std::string tag, T& value, int debug_info= -1) {
using namespace InitfileInternal;
initIntern();
if (debug_info==-1)
debug_info= singlett->getMsgInfo();
try {
std::string valStr(singlett->checkedGet(tag));
valStr= trim(valStr);
convert(valStr, value);
if (debug_info==2)
std::cout << "Parameter '" << tag << "' initialized with: " << value << std::endl;
} catch (TagNotFound ia) {
if (debug_info>=1)
std::cout << ia.what() << std::endl;
}
}
/// return InitEntry object for tag tag
static InitEntry get(const std::string tag) {
using namespace InitfileInternal;
int debug_info= singlett->getMsgInfo();
InitEntry result;
try {
std::string valStr(singlett->checkedGet(tag));
valStr= trim(valStr);
result= InitEntry(valStr);
} catch (TagNotFound ia) {
if (debug_info>=1)
std::cout << ia.what() << std::endl;
}
return result;
}
/// update map tag->value_old to tag->value in singleton
template< typename T >
static void set(const std::string tag, T& value, int debug_info= -1) {
using namespace InitfileInternal;
initIntern();
if (debug_info==-1)
debug_info= singlett->getMsgInfo();
std::string swap= "";
convert(value, swap);
(*singlett)[trim(tag)]= swap;
// update msg parameters msgInfo, msgWait, paramInfo
singlett->getInternalParameters();
if (debug_info==2)
std::cout << "Parameter '" << tag << "' set to: " << value << std::endl;
}
/// add map tag->value to data in singleton
template< typename T >
static void add(const std::string tag, T& value, int debug_info= -1) {
set(tag, value, debug_info);
}
/// Returns specified info level
static int getMsgInfo()
{
return (singlett!=NULL) ? singlett->msgInfo : 0;
}
/// Returns specified wait value
static int getMsgWait()
{
return (singlett!=NULL) ? singlett->msgWait : 0;
}
/// Checks whether parameters are initialized. if not, call init()
static bool initialized()
{
return (singlett!=NULL);
}
/// return pointer to singleton
static Initfile *getSingleton()
{
return singlett;
}
/// print all data in singleton to std::cout
static void printParameters();
/// clear data in singleton
static void clearData()
{
initIntern();
singlett->clear();
}
/// save singlett-data to file with filename fn
static void save(std::string fn)
{
initIntern();
singlett->write(fn);
}
protected:
Initfile() : msgInfo(10), msgWait(1), paramInfo(1) {}
static void initIntern() {
if (singlett == NULL)
singlett= new Initfile;
}
/// list of processed files
static std::set< std::string > fn_include_list;
/// pointer to the singleton that contains the data
static Initfile* singlett;
/// return the value of the given tag or throws an exception if the tag does not exist
std::string checkedGet(const std::string& tag) const {
super::const_iterator it= find(tag);
if (it==end())
throw TagNotFound("there is no tag '"+ tag + "'");
return it->second;
}
/** Fill the initfile from an input stream.
* @param in: the stream to fill the data from.
* Current dataformat: tag:value
* Comment char: percent '%'
* Include files: #include "filename" or #include <filename>
*/
void read(std::istream& in);
/// Fill the initfile from a file with filename fn
void read(std::string fn);
/** Write data-map to initfile
* @param out: the stream to fill the data in.
*/
void write(std::ostream& out);
/// Write data-map to initfile with filename fn
void write(std::string fn);
/// read parameters for msgInfo, msgWait, paramInfo
void getInternalParameters();
int msgInfo, msgWait, paramInfo;
};
#endif
......@@ -340,41 +340,41 @@ namespace AMDiS {
return(key);
if (s[pos] == '#') {
if (static_cast<int>(s.find("#include")) == pos) {
/****************************************************************************/
/* another init file has to be included */
/****************************************************************************/
pos += strlen("#include");
pos = s.find_first_not_of(" \t\f\r");
i = 0;
switch (c = s[pos++]) {
case '<':
c = '>';
case '\"':
h += c;
epos = s.find_first_not_of(h, pos);
fn = s.substr(pos,epos-1);
if (s[epos] != c) {
ERROR("aFilename of include not terminated by %c\n", c);
ERROR("skipping line %d of file %s\n", nLine, aFilename.c_str());
return("");
}
break;
default:
ERROR("no aFilename of include file found\n");
ERROR("skipping line %d of file %s\n", nLine, aFilename.c_str());
return("");
}
read(fn);
return("");
} else {
ERROR("# must not be the first character on a line; except #include\n");
return("");
}
// if (static_cast<int>(s.find("#include")) == pos) {
// /****************************************************************************/