17 #include <boost/optional.hpp>    41             boost::optional<alps::hdf5::archive> try_open_ar(
const std::string& fname, 
const char* mode)
    46                         std::ifstream f(fname.c_str(),std::ios::binary);
    47                         if(!f.good()) 
return boost::none;
    48                         static const char hdf5_checksum[]={char(137),72,68,70,13,10,26,10};
    49                         char firstbytes[
sizeof(hdf5_checksum)];
    50                         f.read(firstbytes, 
sizeof(firstbytes));
    51                         if(!f.good() || memcmp(hdf5_checksum, firstbytes, 
sizeof(firstbytes))!=0) 
return boost::none;
    61             template <
typename MAP_T>
    62             void ini_file_to_map(
const std::string& ini_name, MAP_T& map)
    64                 detail::iniparser parser(ini_name);
    65                 for(
const detail::iniparser::kv_pair& kv: parser()) {
    67                     std::string key=kv.first;
    68                     if (!key.empty() && key[0]==
'.') key.erase(0,1);
    76                 const std::string& strparam_val_;
    79                 typedef bool result_type;
    82                     strparam_val_(strparam_val), dictval_(dval)
    85                 template <
typename BOUND_T>
    86                 result_type operator()(
const BOUND_T& bound_val)
 const    88                     boost::optional<BOUND_T> maybe_val=detail::parse_string<BOUND_T>::apply(strparam_val_);
    89                     if (!maybe_val) 
return false;
   102             static const char Default_help_description[]=
"Print help message";
   106             : 
dictionary(), raw_kv_content_(), td_map_(), err_status_(), origins_(), help_header_()
   108             read_ini_file_(inifile);
   109             if (!
defined(
"help")) 
define(
"help", Default_help_description);
   122             initialize_(argc, argv, hdf5_path);
   123             if (!
defined(
"help")) 
define(
"help", Default_help_description);
   129             return origins_.data().size()-origins_type::INIFILES;
   135             return origins_.data()[origins_type::INIFILES+n];
   140             return origins_.data()[origins_type::ARGV0];
   145             if (!this->
is_restored()) 
throw std::runtime_error(
"The parameters object is not restored from an archive");
   146             return origins_.data()[origins_type::ARCHNAME];
   151             help_header_=message;
   152             if (!
defined(
"help")) 
define(
"help", Default_help_description);
   156         bool params::has_unused_(std::ostream& out, 
const std::string* prefix_ptr)
 const   159             for(
const strmap::value_type& kv: raw_kv_content_) {
   160                 bool relevant = !prefix_ptr  
   161                                 || (prefix_ptr->empty() ? kv.first.find(
'.')==std::string::npos 
   162                                                         : kv.first.find(*prefix_ptr+
".")==0);   
   163                 if (relevant && !this->
exists(kv.first)) {
   164                     unused.push_back(kv.first+
" = "+kv.second);
   167             if (!unused.empty()) {
   168                 out << 
"The following arguments are supplied, but never referenced:\n";
   169                 std::copy(unused.begin(), unused.end(), std::ostream_iterator<std::string>(out,
"\n"));
   171             return !unused.empty();
   176             return has_unused_(out, &subsection);
   181             return has_unused_(out, 0);
   186             out << help_header_ << 
"\nAvailable options:\n";
   188             typedef std::pair<std::string, std::string> nd_pair; 
   189             typedef std::vector<nd_pair> nd_vector;
   190             nd_vector name_and_description;
   191             name_and_description.resize(td_map_.size());
   192             std::string::size_type names_column_width=0;
   195             for(
const td_map_type::value_type& tdp: td_map_) {
   196                 const std::string name_and_type=tdp.first + 
" (" +  tdp.second.typestr() + 
"):";
   197                 if (names_column_width<name_and_type.size()) names_column_width=name_and_type.size();
   199                 std::ostringstream ostr;
   201                 ostr << tdp.second.descr();
   202                 if (this->
exists(tdp.first) && tdp.first!=
"help") {
   203                     ostr << 
" (default value: ";
   204                     print(ostr, (*
this)[tdp.first], 
true) << 
")";
   207                 int defnum=tdp.second.defnumber();
   208                 if (defnum<0 || static_cast<unsigned int>(defnum)>=name_and_description.size()) {
   209                     std::ostringstream errmsg;
   210                     errmsg << 
"Invalid entry in parameters object.\n"   211                            << 
"name='" << tdp.first
   212                            << 
"' defnumber=" << defnum;
   213                     throw std::logic_error(errmsg.str());
   215                 name_and_description[defnum]=std::make_pair(name_and_type, ostr.str());
   219             std::ostream::fmtflags oldfmt=out.flags();
   221             names_column_width += 4;
   222             for(
const nd_pair& ndp: name_and_description) {
   223                 out << std::left << std::setw(names_column_width) << ndp.first << ndp.second << 
"\n";
   232             return this->exists<bool>(
"help") && (*
this)[
"help"].as<
bool>();
   244             if (this->
ok()) 
return false;
   245             std::copy(err_status_.begin(), err_status_.end(), std::ostream_iterator<std::string>(out,
"\n"));
   249         void params::initialize_(
int argc, 
const char* 
const * argv, 
const char* hdf5_path)
   252             typedef std::string::size_type size_type;
   253             const size_type& npos=std::string::npos;
   255             using boost::optional;
   258             origins_.data()[origins_type::ARGV0].assign(argv[0]);
   261             std::vector<string> all_args(argv+1,argv+argc);
   262             std::stringstream cmd_options;
   263             std::vector<string> ini_files;
   264             optional<string> restored_from_archive;
   265             bool file_args_mode=
false;
   266             for(
const string& arg: all_args) {
   267                 if (file_args_mode) {
   268                     ini_files.push_back(arg);
   271                 size_type key_end=arg.find(
'=');
   272                 size_type key_begin=0;
   273                 if (arg.substr(0,2)==
"--") {
   279                 } 
else if  (arg.substr(0,1)==
"-") {
   282                 if (0==key_begin && npos==key_end) {
   284                         optional<alps::hdf5::archive> maybe_ar=try_open_ar(arg, 
"r");
   286                             if (restored_from_archive) {
   287                                 throw archive_conflict(
"More than one archive is specified in command line",
   288                                                        *restored_from_archive, arg);
   290                             maybe_ar->set_context(hdf5_path);
   291                             this->
load(*maybe_ar);
   292                             origins_.data()[origins_type::ARCHNAME]=arg;
   293                             restored_from_archive=arg;
   298                     ini_files.push_back(arg);
   302                     cmd_options << arg.substr(key_begin) << 
"=true\n";
   304                     cmd_options << arg.substr(key_begin) << 
"\n";
   307             for (
auto fname: ini_files) {
   308                 read_ini_file_(fname);
   314             std::ofstream tmpstream(tmpfile_name.c_str());
   315             tmpstream << cmd_options.rdbuf();
   317             ini_file_to_map(tmpfile_name, raw_kv_content_);
   319             if (restored_from_archive) {
   329                 for (
auto& kv: *
this) {
   330                     const auto& key=kv.first;
   331                     auto raw_kv_it=raw_kv_content_.find(key);
   332                     if (raw_kv_it != raw_kv_content_.end()) {
   333                         bool ok=
apply_visitor(parse_visitor(raw_kv_it->second, const_cast<dictionary::value_type&>(kv.second)), kv.second);
   335                             const auto typestr=td_map_[key].typestr();
   343         void params::read_ini_file_(
const std::string& inifile)
   345             ini_file_to_map(inifile, raw_kv_content_);
   346             origins_.data().push_back(inifile);
   351             td_map_type::const_iterator it=td_map_.find(name);
   352             return (td_map_.end()==it)? std::string() : it->second.descr();
   361                 (lhs.raw_kv_content_ == rhs.raw_kv_content_) &&
   362                 (lhs.td_map_ == rhs.td_map_) &&
   363                 (lhs.err_status_ == rhs.err_status_) &&
   364                 (lhs.help_header_ == rhs.help_header_) &&
   365                 (lhs_dict==rhs_dict);
   374             std::vector<std::string> raw_keys, raw_vals;
   375             raw_keys.reserve(raw_kv_content_.size());
   376             raw_vals.reserve(raw_kv_content_.size());
   377             for(
const strmap::value_type& kv: raw_kv_content_) {
   378                 raw_keys.push_back(kv.first);
   379                 raw_vals.push_back(kv.second);
   381             ar[context+
"@ini_keys"] << raw_keys;
   382             ar[context+
"@ini_values"] << raw_vals;
   383             ar[context+
"@status"] << err_status_;
   384             ar[context+
"@origins"]  << origins_.data();
   385             ar[context+
"@help_header"]  << help_header_;
   388             for(
const std::string& key: keys) {
   389                 td_map_type::const_iterator it=td_map_.find(key);
   391                 if (it!=td_map_.end()) {
   392                     ar[key+
"@description"] << it->second.descr();
   393                     ar[key+
"@defnumber"] << it->second.defnumber();
   400             newpar.dictionary::load(ar);
   404             ar[context+
"@status"] >> newpar.err_status_;
   405             ar[context+
"@origins"]  >> newpar.origins_.data();
   406             newpar.origins_.check();
   407             ar[context+
"@help_header"]  >> newpar.help_header_;
   411                 typedef std::vector<std::string> stringvec;
   412                 stringvec raw_keys, raw_vals;
   413                 ar[context+
"@ini_keys"] >> raw_keys;
   414                 ar[context+
"@ini_values"] >> raw_vals;
   415                 if (raw_keys.size()!=raw_vals.size()) {
   416                     throw std::invalid_argument(
"params::load(): invalid ini-file data in HDF5 (size mismatch)");
   418                 stringvec::const_iterator key_it=raw_keys.begin();
   419                 stringvec::const_iterator val_it=raw_vals.begin();
   420                 for (; key_it!=raw_keys.end(); ++key_it, ++val_it) {
   421                     strmap::const_iterator insloc=newpar.raw_kv_content_.insert(newpar.raw_kv_content_.end(), std::make_pair(*key_it, *val_it));
   422                     if (insloc->second!=*val_it) {
   423                         throw std::invalid_argument(
"params::load(): invalid ini-file data in HDF5 (repeated key '"+insloc->first+
"')");
   428             for(
const std::string& key: keys) {
   429                 const std::string d_attr=key+
"@description";
   430                 const std::string num_attr=key+
"@defnumber";
   440                         throw std::runtime_error(
"Invalid HDF5 format: missing attribute "+ num_attr);
   444                     if (newpar.
end()==it) {
   445                         throw std::logic_error(
"params::load(): loading the dictionary"   446                                                " missed key '"+key+
"'??");
   448                     std::string typestr=
apply_visitor(detail::make_typestr(), it);
   449                     newpar.td_map_.insert(std::make_pair(key, detail::td_type(typestr, descr, dn)));
   460             template <
typename T>
   461             inline std::ostream& operator<<(std::ostream& strm, const std::vector<T>& vec)
   463                 typedef std::vector<T> vtype;
   464                 typedef typename vtype::const_iterator itype;
   467                 itype it=vec.begin();
   468                 const itype 
end=vec.end();
   472                     for (++it; end!=it; ++it) {
   483             s << 
"[alps::params]"   484               << 
" origins=" << p.origins_.data() << 
" status=" << p.err_status_
   487                 s << kv.first << 
"=" << kv.second << 
"\n";
   489             s << 
"[alps::params] Dictionary:\n";
   491                 const std::string& key=it->first;
   493                 s << key << 
" = " << val;
   495                 if (tdit!=p.td_map_.end()) {
   496                     s << 
" descr='" << tdit->second.descr()
   497                       << 
"' typestring='" << tdit->second.typestr() << 
"'"   498                       << 
"' defnum=" << tdit->second.defnumber();
 bool ok() const 
No-errors status. 
 
bool has_unused(std::ostream &out) const 
True if there are parameters supplied but not defined; prints them out. 
 
bool operator==(const params &rhs) const 
Returns true if the objects are identical. 
 
Parse sectioned INI file or HDF5 or command line, provide the results as dictionary. 
 
friend std::ostream & operator<<(std::ostream &, const params &)
Prints parameters to a stream in an unspecified format. 
 
void save(alps::hdf5::archive &) const 
Saves parameter object to an archive. 
 
bool defined(const std::string &name) const 
Check whether a parameter was ever defined. 
 
bool is_attribute(std::string path) const 
 
params & define(const std::string &name, const std::string &descr)
Defines a parameter; returns false on error, and records the error in the object. ...
 
const_iterator begin() const 
Const-iterator to the beginning of the contained map. 
 
std::ostream & print_help(std::ostream &) const 
Print help to the given stream. 
 
void broadcast(C const &c, P &p, int r=0)
 
void swap(params &p1, params &p2)
 
std::string get_ini_name(int n) const 
Access to ini file names (if any); returns empty string if out of range. 
 
Encapsulation of an MPI communicator and some communicator-related operations. 
 
void load(alps::hdf5::archive &)
Loads parameter object form an archive. 
 
F::result_type apply_visitor(F &visitor, dictionary::const_iterator it)
Const-access visitor to a value by an iterator. 
 
int get_ini_name_count() const 
Returns the number of ini file names. 
 
params()
Default ctor: creates an empty parameters object. 
 
const std::string get_descr(const std::string &name) const 
Returns a string describing the parameter (or an empty string) 
 
std::string origin_name(const params &p)
Convenience function to obtain the "origin" filename associated with the parameters object...
 
std::string get_archive_name() const 
Convenience method: returns the archive name the object has been restored from, or throws...
 
Exception type: attempt to restore from 2 archives. 
 
bool has_missing() const 
True if there are missing or wrong-type parameters. 
 
params & description(const std::string &message)
Sets a description for the help message and introduces "--help" flag (if not already defined) ...
 
void save(alps::hdf5::archive &ar) const 
Save the dictionary to an archive. 
 
std::string get_basename(const std::string &path)
Returns the base name of the file (removing leading directories) 
 
bool is_restored() const 
Conveninece method: true if the object was restored from an archive. 
 
std::ostream & print(std::ostream &s, const dict_value &dv, bool terse)
 
std::string get_context() const 
 
Header for object-oriented interface to MPI for std::pair. 
 
std::vector< std::string > list_children(std::string path) const 
 
std::string temporary_filename(const std::string &prefix)
Generate a reasonably unique file name with a given prefix. 
 
Exception for value mismatch. 
 
const_iterator end() const 
Const-iterator to the end of the contained map. 
 
void broadcast(const communicator &comm, T *vals, std::size_t count, int root)
Broadcasts array vals of a primitive type T, length count on communicator comm with root root ...
 
bool exists(const std::string &key) const 
Check if a key exists and has a value (without creating the key) 
 
std::string get_argv0() const 
Access to argv[0] (returns empty string if unknown) 
 
friend void swap(params &p1, params &p2)
 
const_iterator find(const std::string &key) const 
Obtain read-only iterator to a name. 
 
detail::None None
"Empty value" type 
 
map_type::const_iterator const_iterator
 
Header for object-oriented interface to MPI for std::map. 
 
bool help_requested() const 
True if user requested help.