RSC  0.16.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-2016 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  bool
155  set(const std::string& name, const T& value) throw ();
156 };
157 
167 RSC_EXPORT Properties
168 operator<<(const Properties& left, const Properties& right);
169 
170 template<typename Ch, typename Tr>
171 std::basic_ostream<Ch, Tr>&
172 operator<<(std::basic_ostream<Ch, Tr>& stream,
173  const std::pair<std::string, boost::any>& property);
174 
175 template<typename Ch, typename Tr>
176 std::basic_ostream<Ch, Tr>&
177 operator<<(std::basic_ostream<Ch, Tr>& stream, const Properties& properties);
178 
179 // Properties implementation
180 
181 template<typename T>
182 T Properties::get(const std::string& name) const {
183  const_iterator it;
184  if ((it = find(name)) == end()) {
185  throw NoSuchObject(
186  (boost::format("no such property `%1%'") % name).str());
187  }
188 
189  try {
190  return boost::any_cast<T>(it->second);
191  } catch (const boost::bad_any_cast&) {
192  std::cerr
193  << (boost::format(
194  "properties: type mismatch in get for `%1%': requested: %2%; actual: %3%")
195  % name % typeName<T> () % typeName(it->second.type()))
196  << std::endl;
197  throw;
198  }
199 }
200 
201 template<typename T>
202 T Properties::get(const std::string& name, const T& default_) const {
203  const_iterator it;
204  if ((it = find(name)) == end()) {
205  return default_;
206  }
207 
208  try {
209  return boost::any_cast<T>(it->second);
210  } catch (const boost::bad_any_cast&) {
211  std::cerr << (boost::format(
212  "properties type mismatch in get for `%1%': requested: %2%; actual: %3%")
213  % name % typeName<T> () % typeName(it->second.type())) << std::endl;
214  throw;
215  }
216 }
217 
218 template<typename T>
219 T Properties::getAs(const std::string& name) const {
220  std::string value = get<std::string>(name);
221  try {
222  return boost::lexical_cast<T>(value);
223  } catch (const std::bad_cast&) {
224  std::cerr
225  << (boost::format(
226  "properties: type conversion failure in getAs for `%1%': requested: %2%; value: \"%3%\"")
227  % name % typeName<T> () % value)
228  << std::endl;
229  throw;
230  }
231 }
232 
233 template<typename T>
234 T Properties::getAs(const std::string& name, const T& default_) const {
235  if (has(name)) {
236  return getAs<T>(name);
237  } else {
238  return default_;
239  }
240 }
241 
242 template<typename Target, typename T>
243 bool Properties::set(const std::string& name, const T& value) throw () {
244  erase(name);
245  return insert(std::make_pair(name, static_cast<Target> (value))).second;
246 }
247 
248 // free function implementations
249 
250 template<typename Ch, typename Tr>
251 std::basic_ostream<Ch, Tr>&
252 operator<<(std::basic_ostream<Ch, Tr>& stream, const Properties& properties) {
253  stream << "p{ ";
254 
255  for (Properties::const_iterator it = properties.begin(); it
256  != properties.end();) {
257  stream << it->first << ": ";
258 
259  if (it->second.type() == typeid(std::string)) {
260  stream << "\"" << boost::any_cast<std::string>(it->second) << "\"";
261  } else if (it->second.type() == typeid(bool)) {
262  stream << boost::any_cast<bool>(it->second);
263  } else if (it->second.type() == typeid(int)) {
264  stream << boost::any_cast<int>(it->second);
265  } else if (it->second.type() == typeid(unsigned int)) {
266  stream << boost::any_cast<unsigned int>(it->second);
267  } else if (it->second.type() == typeid(double)) {
268  stream << boost::any_cast<double>(it->second);
269  } else {
270  stream << "<" + typeName(it->second.type()) + ">"; // TODO this sucks
271  }
272 
273  stream << ((++it) != properties.end() ? ", " : "");
274  }
275 
276  stream << " }";
277 
278  return stream;
279 }
280 
281 }
282 }
bool set(const std::string &name, const T &value)
Sets a new property in the map.
Definition: Properties.h:243
std::string typeName(const std::type_info &type)
Returns a (demangled) string representation of type.
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:182
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:219
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