Falaise  4.0.1
SuperNEMO Software Toolkit
property_reader.h
Go to the documentation of this file.
1 //! \file property_reader.h
2 //! \brief Convenience functions for reading datatools::properties
3 //! \details The interface provided by datatools::properties often requires
4 //! significant boilerplate code to check for and extract values
5 //! associated with keys. The functions here help to minimize this
6 //! and assist in binding a struct to a properties definition
7 //
8 // Copyright (c) 2016 by Ben Morgan <Ben.Morgan@warwick.ac.uk>
9 // Copyright (c) 2016 by The University of Warwick
10 //
11 // This file is part of Falaise.
12 //
13 // Falaise is free software: you can redistribute it and/or modify
14 // it under the terms of the GNU General Public License as published by
15 // the Free Software Foundation, either version 3 of the License, or
16 // (at your option) any later version.
17 //
18 // Falaise is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 // GNU General Public License for more details.
22 //
23 // You should have received a copy of the GNU General Public License
24 // along with Falaise. If not, see <http://www.gnu.org/licenses/>.
25 
26 #ifndef FALAISE_PROPERTY_READER_H
27 #define FALAISE_PROPERTY_READER_H
28 
29 // Standard Library
30 #include <exception>
31 #include <string>
32 #include <vector>
33 
34 // Third Party
35 // - Bayeux
37 
38 // - Boost
39 #include <boost/mpl/contains.hpp>
40 #include <boost/mpl/vector.hpp>
41 #include <boost/utility/enable_if.hpp>
42 
43 // This Project
44 
45 namespace falaise {
46 
47 namespace config {
48 
49 // Exceptions
50 typedef std::logic_error WrongType;
51 typedef std::logic_error MissingKey;
52 
53 //! List of types that can be stored in and read from datatools::properties
54 typedef boost::mpl::vector<int, double, bool, std::string, std::vector<int>, std::vector<double>,
55  std::vector<bool>, // Also allow conversion to bitset?
56  std::vector<std::string>
57  // Path (to allow proper checking of "strings as
58  // paths"
59  // Quantity/Length/etc (to check reals with required unit,
60  // needs a bit of thought for behaviour, as units are
61  // converted, can probably just check dimension)
62  >
64 
65 //! Functions for visiting a property item and checking its type is valid
66 namespace type_check_visitor {
67 
68 namespace detail {
69 
70 bool visit_impl(const datatools::properties& p, const std::string& key, int);
71 bool visit_impl(const datatools::properties& p, const std::string& key, double);
72 bool visit_impl(const datatools::properties& p, const std::string& key, bool);
73 bool visit_impl(const datatools::properties& p, const std::string& key, std::string);
74 bool visit_impl(const datatools::properties& p, const std::string& key, std::vector<int>);
75 bool visit_impl(const datatools::properties& p, const std::string& key, std::vector<double>);
76 bool visit_impl(const datatools::properties& p, const std::string& key, std::vector<bool>);
77 bool visit_impl(const datatools::properties& p, const std::string& key, std::vector<std::string>);
78 } // namespace detail
79 
80 // Compile-time fail on any other type (needs improvement, but does the job
81 // for now (Look also at enable_if on return type (could use mpl vector of
82 // allowed types))
83 template <typename T>
84 bool visit(const datatools::properties& p, const std::string& key) {
85  // Static assert form - gives slightly clearer message...
86  static_assert(boost::mpl::contains<AllowedTypes, T>::type::value,
87  "Unsupported type for visitation");
88  return detail::visit_impl(p, key, T{});
89 }
90 } // namespace type_check_visitor
91 
92 // Units are converted automatically, but may want to assert that the given
93 // key has a unit and that this is of specific dimension
94 // The same for interpreting strings as paths...
95 
96 // This should throw on missing key or wrong type
97 template <typename T>
98 T getRequiredValue(const datatools::properties& p, const std::string& key) {
99  if (!p.has_key(key)) {
100  throw MissingKey("No key '" + key + "'");
101  }
102  if (!type_check_visitor::visit<T>(p, key)) {
103  throw WrongType("Key '" + key + "' has incorrect type");
104  }
105 
106  T tmp;
107  p.fetch(key, tmp);
108  return tmp;
109 }
110 
111 // This should throw when key is set, but has the wrong type
112 // Also consider rvalue for default.
113 template <typename T>
114 T getValueOrDefault(const datatools::properties& p, const std::string& key, T defaultValue) {
115  T tmp{defaultValue};
116 
117  if (p.has_key(key)) {
118  if (!type_check_visitor::visit<T>(p, key)) {
119  throw WrongType("Key '" + key + "' is set but has incorrect type");
120  }
121  p.fetch(key, tmp);
122  }
123  return tmp;
124 }
125 
126 } // namespace config
127 
128 } // namespace falaise
129 
130 #endif // FALAISE_PROPERTY_READER_H
std::logic_error MissingKey
Definition: property_reader.h:51
void fetch(const std::string &key_, bool &value_, int index_=0) const
bool visit_impl(const datatools::properties &p, const std::string &key, int)
T getValueOrDefault(const datatools::properties &p, const std::string &key, T defaultValue)
Definition: property_reader.h:114
bool has_key(const std::string &prop_key_) const
Definition: metadata_utils.h:35
bool visit(const datatools::properties &p, const std::string &key)
Definition: property_reader.h:84
T getRequiredValue(const datatools::properties &p, const std::string &key)
Definition: property_reader.h:98
boost::mpl::vector< int, double, bool, std::string, std::vector< int >, std::vector< double >, std::vector< bool >, std::vector< std::string > > AllowedTypes
List of types that can be stored in and read from datatools::properties.
Definition: property_reader.h:63
std::logic_error WrongType
Definition: property_reader.h:50