RSC  0.19.0
Properties.h
Go to the documentation of this file.
1 /* ============================================================
2  *
3  * This file is part of the RSC project
4  *
5  * Copyright (C) 2010-2018 Jan Moringen
6  *
7  * This file may be licensed under the terms of the
8  * GNU Lesser General Public License Version 3 (the ``LGPL''),
9  * or (at your option) any later version.
10  *
11  * Software distributed under the License is distributed
12  * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
13  * express or implied. See the LGPL for the specific language
14  * governing rights and limitations.
15  *
16  * You should have received a copy of the LGPL along with this
17  * program. If not, go to http://www.gnu.org/licenses/lgpl.html
18  * or write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  * The development of this software was supported by:
22  * CoR-Lab, Research Institute for Cognition and Robotics
23  * Bielefeld University
24  *
25  * ============================================================ */
26 
27 #pragma once
28 
29 #include <string>
30 #include <map>
31 #include <utility>
32 #include <iostream>
33 
34 #include <boost/any.hpp>
35 #include <boost/lexical_cast.hpp>
36 #include <boost/format.hpp>
37 #include <boost/operators.hpp>
38 
39 #include "rsc/rscexports.h"
40 
41 #include "NoSuchObject.h"
42 #include "TypeStringTools.h"
43 
44 namespace rsc {
45 namespace runtime {
46 
57 class RSC_EXPORT Properties: public std::map<std::string, boost::any>,
58  public boost::equality_comparable<Properties> { // TODO left_shiftable from Boost.Operators
59  friend RSC_EXPORT Properties
60  operator<<(const Properties& properties1, const Properties& properties2);
61  template<typename Ch, typename Tr>
62  friend std::basic_ostream<Ch, Tr>
63  &
64  operator<<(std::basic_ostream<Ch, Tr>& stream,
65  const Properties& properties);
66 public:
67 
76  Properties&
77  operator<<=(const Properties& other); // TODO boost::left_shiftable
78 
90  bool operator==(const Properties& other) const;
91 
92  bool
93  has(const std::string& name) const throw (); // TODO check type
94 
99  template<typename T>
100  T
101  get(const std::string& name) const;
102 
106  template<typename T>
107  T
108  get(const std::string& name, const T& default_) const;
109 
122  template<typename T>
123  T getAs(const std::string& name) const;
124 
138  template<typename T>
139  T getAs(const std::string& name, const T& default_) const;
140 
153  template<typename Target, typename T>
154  Properties& set(const std::string& name, const T& value) throw ();
155 };
156 
166 RSC_EXPORT Properties
167 operator<<(const Properties& left, const Properties& right);
168 
169 template<typename Ch, typename Tr>
170 std::basic_ostream<Ch, Tr>&
171 operator<<(std::basic_ostream<Ch, Tr>& stream,
172  const std::pair<std::string, boost::any>& property);
173 
174 template<typename Ch, typename Tr>
175 std::basic_ostream<Ch, Tr>&
176 operator<<(std::basic_ostream<Ch, Tr>& stream, const Properties& properties);
177 
178 // Properties implementation
179 
180 template<typename T>
181 T Properties::get(const std::string& name) const {
182  const_iterator it;
183  if ((it = find(name)) == end()) {
184  throw NoSuchObject(
185  (boost::format("no such property `%1%'") % name).str());
186  }
187 
188  try {
189  return boost::any_cast<T>(it->second);
190  } catch (const boost::bad_any_cast&) {
191  std::cerr
192  << (boost::format(
193  "properties: type mismatch in get for `%1%': requested: %2%; actual: %3%")
194  % name % typeName<T> () % typeName(it->second.type()))
195  << std::endl;
196  throw;
197  }
198 }
199 
200 template<typename T>
201 T Properties::get(const std::string& name, const T& default_) const {
202  const_iterator it;
203  if ((it = find(name)) == end()) {
204  return default_;
205  }
206 
207  try {
208  return boost::any_cast<T>(it->second);
209  } catch (const boost::bad_any_cast&) {
210  std::cerr << (boost::format(
211  "properties type mismatch in get for `%1%': requested: %2%; actual: %3%")
212  % name % typeName<T> () % typeName(it->second.type())) << std::endl;
213  throw;
214  }
215 }
216 
217 template<typename T>
218 T Properties::getAs(const std::string& name) const {
219  std::string value = get<std::string>(name);
220  try {
221  return boost::lexical_cast<T>(value);
222  } catch (const std::bad_cast&) {
223  std::cerr
224  << (boost::format(
225  "properties: type conversion failure in getAs for `%1%': requested: %2%; value: \"%3%\"")
226  % name % typeName<T> () % value)
227  << std::endl;
228  throw;
229  }
230 }
231 
232 template<typename T>
233 T Properties::getAs(const std::string& name, const T& default_) const {
234  if (has(name)) {
235  return getAs<T>(name);
236  } else {
237  return default_;
238  }
239 }
240 
241 template<typename Target, typename T>
242 Properties& Properties::set(const std::string& name, const T& value) throw () {
243  insert(std::make_pair(name, static_cast<Target> (value)));
244  return *this;
245 }
246 
247 // free function implementations
248 
249 template<typename Ch, typename Tr>
250 std::basic_ostream<Ch, Tr>&
251 operator<<(std::basic_ostream<Ch, Tr>& stream, const Properties& properties) {
252  stream << "p{ ";
253 
254  for (Properties::const_iterator it = properties.begin(); it
255  != properties.end();) {
256  stream << it->first << ": ";
257 
258  if (it->second.type() == typeid(std::string)) {
259  stream << "\"" << boost::any_cast<std::string>(it->second) << "\"";
260  } else if (it->second.type() == typeid(bool)) {
261  stream << boost::any_cast<bool>(it->second);
262  } else if (it->second.type() == typeid(int)) {
263  stream << boost::any_cast<int>(it->second);
264  } else if (it->second.type() == typeid(unsigned int)) {
265  stream << boost::any_cast<unsigned int>(it->second);
266  } else if (it->second.type() == typeid(double)) {
267  stream << boost::any_cast<double>(it->second);
268  } else {
269  stream << "<" + typeName(it->second.type()) + ">"; // TODO this sucks
270  }
271 
272  stream << ((++it) != properties.end() ? ", " : "");
273  }
274 
275  stream << " }";
276 
277  return stream;
278 }
279 
280 }
281 }
std::string typeName(const std::type_info &type)
Returns a (demangled) string representation of type.
Properties & set(const std::string &name, const T &value)
Sets a new property in the map.
Definition: Properties.h:242
pair< _T1, _T2 > make_pair(_T1 __x, _T2 __y)
A convenience wrapper for creating a pair from two objects.
T get(const std::string &name) const
Definition: Properties.h:181
T getAs(const std::string &name) const
Parse the value of the property name as type T and return the parsed value.
Definition: Properties.h:218
bool operator==(const pair< _T1, _T2 > &__x, const pair< _T1, _T2 > &__y)
Two pairs of the same type are equal iff their members are equal.
Properties objects are basically glorified map<string, boost::any> objects.
Definition: Properties.h:57
ostream & operator<<(ostream &stream, const Printable &record)
Output operator on std::ostream for reference Printables.
Definition: Printable.cpp:56
This exception is thrown if a specified object does not exist.
Definition: NoSuchObject.h:43