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