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