forked from lijiext/lammps
318 lines
12 KiB
C++
318 lines
12 KiB
C++
// -*- c++ -*-
|
|
|
|
// This file is part of the Collective Variables module (Colvars).
|
|
// The original version of Colvars and its updates are located at:
|
|
// https://github.com/colvars/colvars
|
|
// Please update all Colvars source files before making any changes.
|
|
// If you wish to distribute your changes, please submit them to the
|
|
// Colvars repository at GitHub.
|
|
|
|
#ifndef COLVARPARSE_H
|
|
#define COLVARPARSE_H
|
|
|
|
#include <cstring>
|
|
#include <string>
|
|
|
|
#include "colvarmodule.h"
|
|
#include "colvarvalue.h"
|
|
|
|
|
|
/// \file colvarparse.h Parsing functions for collective variables
|
|
|
|
|
|
/// \brief Base class containing parsing functions; all objects which
|
|
/// need to parse input inherit from this
|
|
class colvarparse {
|
|
|
|
protected:
|
|
|
|
/// \brief List of legal keywords for this object: this is updated
|
|
/// by each call to colvarparse::get_keyval() or
|
|
/// colvarparse::key_lookup()
|
|
std::list<std::string> allowed_keywords;
|
|
|
|
/// \brief List of delimiters for the values of each keyword in the
|
|
/// configuration string; all keywords will be stripped of their
|
|
/// values before the keyword check is performed
|
|
std::list<size_t> data_begin_pos;
|
|
|
|
/// \brief List of delimiters for the values of each keyword in the
|
|
/// configuration string; all keywords will be stripped of their
|
|
/// values before the keyword check is performed
|
|
std::list<size_t> data_end_pos;
|
|
|
|
/// \brief Whether or not to accumulate data_begin_pos and
|
|
/// data_end_pos in key_lookup(); it may be useful to disable
|
|
/// this after the constructor is called, because other files may be
|
|
/// read (e.g. restart) that would mess up the registry; in any
|
|
/// case, nothing serious happens until check_keywords() is invoked
|
|
/// (which should happen only right after construction)
|
|
bool save_delimiters;
|
|
|
|
/// \brief Add a new valid keyword to the list
|
|
void add_keyword(char const *key);
|
|
|
|
/// \brief Remove all the values from the config string
|
|
void strip_values(std::string &conf);
|
|
|
|
/// \brief Configuration string of the object
|
|
std::string config_string;
|
|
|
|
public:
|
|
|
|
|
|
inline colvarparse()
|
|
: save_delimiters(true)
|
|
{
|
|
init();
|
|
}
|
|
|
|
/// Constructor that stores the object's config string
|
|
inline colvarparse(const std::string& conf)
|
|
: save_delimiters(true)
|
|
{
|
|
init(conf);
|
|
}
|
|
|
|
/// Set the object ready to parse a new configuration string
|
|
inline void init()
|
|
{
|
|
config_string.clear();
|
|
clear_keyword_registry();
|
|
}
|
|
|
|
/// Set a new config string for this object
|
|
inline void init(const std::string& conf)
|
|
{
|
|
if (! config_string.size()) {
|
|
init();
|
|
config_string = conf;
|
|
}
|
|
}
|
|
|
|
inline const std::string& get_config()
|
|
{
|
|
return config_string;
|
|
}
|
|
|
|
/// How a keyword is parsed in a string
|
|
enum Parse_Mode {
|
|
/// \brief(default) Read the first instance of a keyword (if
|
|
/// any), report its value, and print a warning when there is more
|
|
/// than one
|
|
parse_normal,
|
|
/// \brief Like parse_normal, but don't send any message to the log
|
|
/// (useful e.g. in restart files when such messages are very
|
|
/// numerous and redundant)
|
|
parse_silent
|
|
};
|
|
|
|
/// \brief Check that all the keywords within "conf" are in the list
|
|
/// of allowed keywords; this will invoke strip_values() first and
|
|
/// then loop over all words
|
|
int check_keywords(std::string &conf, char const *key);
|
|
|
|
/// \brief Use this after parsing a config string (note that check_keywords() calls it already)
|
|
void clear_keyword_registry();
|
|
|
|
public:
|
|
|
|
/// \fn get_keyval bool const get_keyval (std::string const &conf,
|
|
/// char const *key, _type_ &value, _type_ const &def_value,
|
|
/// Parse_Mode const parse_mode) \brief Helper function to parse
|
|
/// keywords in the configuration and get their values
|
|
///
|
|
/// In normal circumstances, you should use either version the
|
|
/// get_keyval function. Both of them look for the C string "key"
|
|
/// in the C++ string "conf", and assign the corresponding value (if
|
|
/// available) to the variable "value" (first version), or assign as
|
|
/// many values as found to the vector "values" (second version).
|
|
///
|
|
/// If "key" is found but no value is associated to it, the default
|
|
/// value is provided (either one copy or as many copies as the
|
|
/// current length of the vector "values" specifies). A message
|
|
/// will print, unless parse_mode is equal to parse_silent. The
|
|
/// return value of both forms of get_keyval is true if "key" is
|
|
/// found (with or without value), and false when "key" is absent in
|
|
/// the string "conf". If there is more than one instance of the
|
|
/// keyword, a warning will be raised; instead, to loop over
|
|
/// multiple instances key_lookup() should be invoked directly.
|
|
///
|
|
/// If you introduce a new data type, add two new instances of this
|
|
/// functions, or insert this type in the \link colvarvalue \endlink
|
|
/// wrapper class (colvarvalue.h).
|
|
|
|
bool get_keyval(std::string const &conf,
|
|
char const *key,
|
|
int &value,
|
|
int const &def_value = (int)0,
|
|
Parse_Mode const parse_mode = parse_normal);
|
|
bool get_keyval(std::string const &conf,
|
|
char const *key,
|
|
size_t &value,
|
|
size_t const &def_value = (size_t)0,
|
|
Parse_Mode const parse_mode = parse_normal);
|
|
bool get_keyval(std::string const &conf,
|
|
char const *key,
|
|
long &value,
|
|
long const &def_value = 0,
|
|
Parse_Mode const parse_mode = parse_normal);
|
|
bool get_keyval(std::string const &conf,
|
|
char const *key,
|
|
std::string &value,
|
|
std::string const &def_value = std::string(""),
|
|
Parse_Mode const parse_mode = parse_normal);
|
|
bool get_keyval(std::string const &conf,
|
|
char const *key,
|
|
cvm::real &value,
|
|
cvm::real const &def_value = (cvm::real)0.0,
|
|
Parse_Mode const parse_mode = parse_normal);
|
|
bool get_keyval(std::string const &conf,
|
|
char const *key,
|
|
cvm::rvector &value,
|
|
cvm::rvector const &def_value = cvm::rvector(),
|
|
Parse_Mode const parse_mode = parse_normal);
|
|
bool get_keyval(std::string const &conf,
|
|
char const *key,
|
|
cvm::quaternion &value,
|
|
cvm::quaternion const &def_value = cvm::quaternion(),
|
|
Parse_Mode const parse_mode = parse_normal);
|
|
bool get_keyval(std::string const &conf,
|
|
char const *key,
|
|
colvarvalue &value,
|
|
colvarvalue const &def_value = colvarvalue(colvarvalue::type_notset),
|
|
Parse_Mode const parse_mode = parse_normal);
|
|
bool get_keyval(std::string const &conf,
|
|
char const *key,
|
|
bool &value,
|
|
bool const &def_value = false,
|
|
Parse_Mode const parse_mode = parse_normal);
|
|
bool get_keyval(std::string const &conf,
|
|
char const *key,
|
|
std::vector<int> &values,
|
|
std::vector<int> const &def_values = std::vector<int>(0, (int)0),
|
|
Parse_Mode const parse_mode = parse_normal);
|
|
bool get_keyval(std::string const &conf,
|
|
char const *key,
|
|
std::vector<size_t> &values,
|
|
std::vector<size_t> const &def_values = std::vector<size_t>(0, (size_t)0),
|
|
Parse_Mode const parse_mode = parse_normal);
|
|
bool get_keyval(std::string const &conf,
|
|
char const *key,
|
|
std::vector<long> &values,
|
|
std::vector<long> const &def_values = std::vector<long>(0, (long)0),
|
|
Parse_Mode const parse_mode = parse_normal);
|
|
bool get_keyval(std::string const &conf,
|
|
char const *key,
|
|
std::vector<std::string> &values,
|
|
std::vector<std::string> const &def_values = std::vector<std::string>(0, std::string("")),
|
|
Parse_Mode const parse_mode = parse_normal);
|
|
bool get_keyval(std::string const &conf,
|
|
char const *key,
|
|
std::vector<cvm::real> &values,
|
|
std::vector<cvm::real> const &def_values = std::vector<cvm::real>(0, (cvm::real)0.0),
|
|
Parse_Mode const parse_mode = parse_normal);
|
|
bool get_keyval(std::string const &conf,
|
|
char const *key,
|
|
std::vector<cvm::rvector> &values,
|
|
std::vector<cvm::rvector> const &def_values = std::vector<cvm::rvector>(0, cvm::rvector()),
|
|
Parse_Mode const parse_mode = parse_normal);
|
|
bool get_keyval(std::string const &conf,
|
|
char const *key,
|
|
std::vector<cvm::quaternion> &values,
|
|
std::vector<cvm::quaternion> const &def_values = std::vector<cvm::quaternion>(0, cvm::quaternion()),
|
|
Parse_Mode const parse_mode = parse_normal);
|
|
bool get_keyval(std::string const &conf,
|
|
char const *key,
|
|
std::vector<colvarvalue> &values,
|
|
std::vector<colvarvalue> const &def_values = std::vector<colvarvalue>(0, colvarvalue(colvarvalue::type_notset)),
|
|
Parse_Mode const parse_mode = parse_normal);
|
|
|
|
protected:
|
|
|
|
// Templates
|
|
template<typename TYPE> bool _get_keyval_scalar_(std::string const &conf,
|
|
char const *key,
|
|
TYPE &value,
|
|
TYPE const &def_value,
|
|
Parse_Mode const parse_mode);
|
|
bool _get_keyval_scalar_string_(std::string const &conf,
|
|
char const *key,
|
|
std::string &value,
|
|
std::string const &def_value,
|
|
Parse_Mode const parse_mode);
|
|
|
|
template<typename TYPE> bool _get_keyval_vector_(std::string const &conf,
|
|
char const *key,
|
|
std::vector<TYPE> &values,
|
|
std::vector<TYPE> const &def_values,
|
|
Parse_Mode const parse_mode);
|
|
|
|
public:
|
|
|
|
/// \brief Return a lowercased copy of the string
|
|
static inline std::string to_lower_cppstr(std::string const &in)
|
|
{
|
|
std::string out = "";
|
|
for (size_t i = 0; i < in.size(); i++) {
|
|
out.append(1, (char) ::tolower(in[i]) );
|
|
}
|
|
return out;
|
|
}
|
|
|
|
/// \brief Helper class to read a block of the type "key { ... }"
|
|
/// from a stream and store it in a string
|
|
///
|
|
/// Useful on restarts, where the file is too big to be loaded in a
|
|
/// string by key_lookup; it can only check that the keyword is
|
|
/// correct and the block is properly delimited by braces, not
|
|
/// skipping other blocks
|
|
class read_block {
|
|
|
|
std::string const key;
|
|
std::string * const data;
|
|
|
|
public:
|
|
inline read_block(std::string const &key_in, std::string &data_in)
|
|
: key(key_in), data(&data_in)
|
|
{}
|
|
inline ~read_block() {}
|
|
friend std::istream & operator >> (std::istream &is, read_block const &rb);
|
|
};
|
|
|
|
|
|
/// Accepted white space delimiters, used in key_lookup()
|
|
static std::string const white_space;
|
|
|
|
/// \brief Low-level function for parsing configuration strings;
|
|
/// automatically adds the requested keyword to the list of valid
|
|
/// ones. \param conf the content of the configuration file or one
|
|
/// of its blocks \param key the keyword to search within "conf" \param
|
|
/// data (optional) holds the string provided after "key", if any
|
|
/// \param save_pos (optional) stores the position of the keyword
|
|
/// within "conf", useful when doing multiple calls
|
|
bool key_lookup(std::string const &conf,
|
|
char const *key,
|
|
std::string &data = dummy_string,
|
|
size_t &save_pos = dummy_pos);
|
|
|
|
/// Used as a default argument by key_lookup
|
|
static std::string dummy_string;
|
|
/// Used as a default argument by key_lookup
|
|
static size_t dummy_pos;
|
|
|
|
/// \brief Works as std::getline() but also removes everything
|
|
/// between a comment character and the following newline
|
|
static std::istream & getline_nocomments(std::istream &is,
|
|
std::string &s,
|
|
char const delim = '\n');
|
|
|
|
/// Check if the content of the file has matching braces
|
|
bool brace_check(std::string const &conf,
|
|
size_t const start_pos = 0);
|
|
|
|
};
|
|
|
|
|
|
#endif
|