Main MRPT website > C++ reference
MRPT logo
stl_extensions.h
Go to the documentation of this file.
1 /* +---------------------------------------------------------------------------+
2  | The Mobile Robot Programming Toolkit (MRPT) C++ library |
3  | |
4  | http://www.mrpt.org/ |
5  | |
6  | Copyright (C) 2005-2012 University of Malaga |
7  | |
8  | This software was written by the Machine Perception and Intelligent |
9  | Robotics Lab, University of Malaga (Spain). |
10  | Contact: Jose-Luis Blanco <jlblanco@ctima.uma.es> |
11  | |
12  | This file is part of the MRPT project. |
13  | |
14  | MRPT is free software: you can redistribute it and/or modify |
15  | it under the terms of the GNU General Public License as published by |
16  | the Free Software Foundation, either version 3 of the License, or |
17  | (at your option) any later version. |
18  | |
19  | MRPT is distributed in the hope that it will be useful, |
20  | but WITHOUT ANY WARRANTY; without even the implied warranty of |
21  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
22  | GNU General Public License for more details. |
23  | |
24  | You should have received a copy of the GNU General Public License |
25  | along with MRPT. If not, see <http://www.gnu.org/licenses/>. |
26  | |
27  +---------------------------------------------------------------------------+ */
28 #ifndef stl_extensions_H
29 #define stl_extensions_H
30 
32 #include <mrpt/utils/CStream.h>
34 
35 #include <set>
36 #include <map>
37 #include <list>
38 #include <cctype> // tolower
39 
40 // These are "STL extensions" but have their own files for clarity
43 #include <mrpt/utils/bimap.h>
45 #include <mrpt/utils/traits_map.h>
46 
47 
48 namespace mrpt
49 {
50  namespace utils
51  {
52  /** \addtogroup stlext_grp STL extensions and metaprogramming
53  * \ingroup mrpt_base_grp
54  * @{ */
55 
56  using namespace mrpt::utils::metaprogramming;
57  using std::for_each;
58  using std::string;
59 
60 
61  #define MRPTSTL_SERIALIZABLE_SEQ_CONTAINER( CONTAINER ) \
62  /** Template method to serialize a sequential STL container */ \
63  template <class T,class _Ax> \
64  CStream& operator << (CStream& out, const CONTAINER<T,_Ax> &obj) \
65  { \
66  out << string(#CONTAINER) << TTypeName<T>::get(); \
67  out << static_cast<uint32_t>(obj.size()); \
68  for_each( obj.begin(), obj.end(), ObjectWriteToStream(&out) ); \
69  return out; \
70  } \
71  /** Template method to deserialize a sequential STL container */ \
72  template <class T,class _Ax> \
73  CStream& operator >> (CStream& in, CONTAINER<T,_Ax> &obj) \
74  { \
75  obj.clear(); \
76  string pref,stored_T; \
77  in >> pref; \
78  if (pref!=#CONTAINER) THROW_EXCEPTION(format("Error: serialized container %s<%s>'s preambles is wrong: '%s'",#CONTAINER,TTypeName<T>::get().c_str(),pref.c_str() )) \
79  in >> stored_T; \
80  if (stored_T != TTypeName<T>::get() ) THROW_EXCEPTION(format("Error: serialized container %s< %s != %s >",#CONTAINER,stored_T.c_str(),TTypeName<T>::get().c_str() )) \
81  uint32_t n; \
82  in >> n; \
83  obj.resize(n); \
84  for_each( obj.begin(), obj.end(), ObjectReadFromStream(&in) ); \
85  return in; \
86  }
87 
88 
89  #define MRPTSTL_SERIALIZABLE_ASSOC_CONTAINER( CONTAINER ) \
90  /** Template method to serialize an associative STL container */ \
91  template <class K,class V, class _Pr, class _Alloc> \
92  CStream& operator << (CStream& out, const CONTAINER<K,V,_Pr,_Alloc> &obj) \
93  { \
94  out << string(#CONTAINER) << TTypeName<K>::get() << TTypeName<V>::get(); \
95  out << static_cast<uint32_t>(obj.size()); \
96  for (typename CONTAINER<K,V,_Pr,_Alloc>::const_iterator it=obj.begin();it!=obj.end();++it) \
97  out << it->first << it->second; \
98  return out; \
99  } \
100  /** Template method to deserialize an associative STL container */ \
101  template <class K,class V, class _Pr, class _Alloc> \
102  CStream& operator >> (CStream& in, CONTAINER<K,V,_Pr,_Alloc> &obj) \
103  { \
104  obj.clear(); \
105  string pref,stored_K,stored_V; \
106  in >> pref; \
107  if (pref!=#CONTAINER) THROW_EXCEPTION(format("Error: serialized container %s<%s,%s>'s preamble is wrong: '%s'",#CONTAINER, TTypeName<K>::get().c_str(), TTypeName<V>::get().c_str() ,pref.c_str())) \
108  in >> stored_K; \
109  if (stored_K != TTypeName<K>::get()) THROW_EXCEPTION(format("Error: serialized container %s key type %s != %s",#CONTAINER,stored_K.c_str(), TTypeName<K>::get().c_str())) \
110  in >> stored_V; \
111  if (stored_V != TTypeName<V>::get()) THROW_EXCEPTION(format("Error: serialized container %s value type %s != %s",#CONTAINER,stored_V.c_str(), TTypeName<V>::get().c_str())) \
112  uint32_t n; \
113  in >> n; \
114  for (uint32_t i=0;i<n;i++) \
115  { \
116  K key_obj; \
117  in >> key_obj; \
118  /* Create an pair (Key, empty), then read directly into the ".second": */ \
119  typename CONTAINER<K,V,_Pr,_Alloc>::iterator it_new = obj.insert(obj.begin(), std::make_pair(key_obj, V()) ); \
120  in >> it_new->second; \
121  } \
122  return in; \
123  }
124 
125  MRPTSTL_SERIALIZABLE_SEQ_CONTAINER(std::vector) // Serialization for std::vector
126  MRPTSTL_SERIALIZABLE_SEQ_CONTAINER(std::deque) // Serialization for std::deque
127  MRPTSTL_SERIALIZABLE_SEQ_CONTAINER(std::list) // Serialization for std::list
128 
129  MRPTSTL_SERIALIZABLE_ASSOC_CONTAINER(std::map) // Serialization for std::map
130  MRPTSTL_SERIALIZABLE_ASSOC_CONTAINER(std::multimap) // Serialization for std::multimap
131 
132 
133  #define MRPTSTL_SERIALIZABLE_SIMPLE_ASSOC_CONTAINER( CONTAINER ) \
134  /** Template method to serialize an associative STL container */ \
135  template <class K,class _Pr,class _Alloc> \
136  CStream& operator << (CStream& out, const CONTAINER<K,_Pr,_Alloc> &obj) \
137  { \
138  out << string(#CONTAINER) << TTypeName<K>::get(); \
139  out << static_cast<uint32_t>(obj.size()); \
140  for (typename CONTAINER<K,_Pr,_Alloc>::const_iterator it=obj.begin();it!=obj.end();++it) \
141  out << *it; \
142  return out; \
143  } \
144  /** Template method to deserialize an associative STL container */ \
145  template <class K,class _Pr,class _Alloc> \
146  CStream& operator >> (CStream& in, CONTAINER<K,_Pr,_Alloc> &obj) \
147  { \
148  obj.clear(); \
149  string pref,stored_K; \
150  in >> pref; \
151  if (pref!=#CONTAINER) THROW_EXCEPTION(format("Error: serialized container %s<%s>'s preamble is wrong: '%s'",#CONTAINER, TTypeName<K>::get().c_str(),pref.c_str())) \
152  in >> stored_K; \
153  if (stored_K != TTypeName<K>::get()) THROW_EXCEPTION(format("Error: serialized container %s key type %s != %s",#CONTAINER,stored_K.c_str(), TTypeName<K>::get().c_str())) \
154  uint32_t n; \
155  in >> n; \
156  for (uint32_t i=0;i<n;i++) \
157  { \
158  K key_obj; \
159  in >> key_obj; \
160  obj.insert(key_obj); \
161  } \
162  return in; \
163  }
164 
165  MRPTSTL_SERIALIZABLE_SIMPLE_ASSOC_CONTAINER(std::set) // Serialization for std::set
166  MRPTSTL_SERIALIZABLE_SIMPLE_ASSOC_CONTAINER(std::multiset) // Serialization for std::multiset
167 
168 
169  /** Template method to serialize a STL pair */
170  template <class T1,class T2>
171  CStream& operator << (CStream& out, const std::pair<T1,T2> &obj)
172  {
173  out << string("std::pair") << TTypeName<T1>::get() << TTypeName<T2>::get();
174  out << obj.first << obj.second;
175  return out;
176  }
177  /** Template method to deserialize a STL pair */
178  template <class T1,class T2>
179  CStream& operator >> (CStream& in, std::pair<T1,T2> &obj)
180  {
181  string pref,stored_K,stored_V;
182  in >> pref;
183  if (pref!="std::pair") THROW_EXCEPTION(format("Error: serialized std::pair<%s,%s>'s preamble is wrong: '%s'", TTypeName<T1>::get().c_str(), TTypeName<T2>::get().c_str() ,pref.c_str()))
184  in >> stored_K;
185  if (stored_K != TTypeName<T1>::get()) THROW_EXCEPTION(format("Error: serialized std::pair first type %s != %s",stored_K.c_str(), TTypeName<T1>::get().c_str()))
186  in >> stored_V;
187  if (stored_V != TTypeName<T2>::get()) THROW_EXCEPTION(format("Error: serialized std::pair second type %s != %s",stored_V.c_str(), TTypeName<T2>::get().c_str()))
188  in >> obj.first >> obj.second;
189  return in;
190  }
191 
192 
193  /** Returns the index of the value "T" in the container "vect" (std::vector,std::deque,etc), or string::npos if not found.
194  */
195  template <class T,class CONTAINER>
196  size_t find_in_vector(const T &value, const CONTAINER &vect)
197  {
198  typename CONTAINER::const_iterator last = vect.end();
199  for (typename CONTAINER::const_iterator i=vect.begin();i!=last;++i)
200  if (*i==value) return std::distance(vect.begin(),i);
201  return std::string::npos;
202  }
203 
204  /** Calls the standard "erase" method of a STL container, but also returns an iterator to the next element in the container (or ::end if none) */
205  template <class T> inline typename std::list<T>::iterator erase_return_next(std::list<T> &cont, typename std::list<T>::iterator &it)
206  {
207  return cont.erase(it);
208  }
209  //! \overload
210  template <class K,class V> inline typename std::map<K,V>::iterator erase_return_next(std::map<K,V> &cont, typename std::map<K,V>::iterator &it)
211  {
212  typename std::map<K,V>::iterator itRet = it; ++itRet;
213  cont.erase(it);
214  return itRet;
215  }
216  //! \overload
217  template <class K,class V> inline typename std::multimap<K,V>::iterator erase_return_next(std::multimap<K,V> &cont, typename std::multimap<K,V>::iterator &it)
218  {
219  typename std::multimap<K,V>::iterator itRet = it; ++itRet;
220  cont.erase(it);
221  return itRet;
222  }
223  //! \overload
224  template <class T> inline typename std::set<T>::iterator erase_return_next(std::set<T> &cont, typename std::set<T>::iterator &it)
225  {
226  typename std::set<T>::iterator itRet = it; ++itRet;
227  cont.erase(it);
228  return itRet;
229  }
230 
231  /** Generates a string for a vector in the format [A,B,C,...] to std::cout, and the fmt string for <b>each</b> vector element. */
232  template <typename T>
233  std::string sprintf_vector(const char *fmt, const std::vector<T> &V )
234  {
235  std::string ret = "[";
236  const size_t N = V.size();
237  for (size_t i=0;i<N;i++)
238  {
239  ret+= format(fmt,V[i]);
240  if (i!=(N-1)) ret+= ",";
241  }
242  ret+="]";
243  return ret;
244  }
245  /// @overload
246  template <typename Derived>
247  std::string sprintf_vector(const char *fmt, const Eigen::MatrixBase<Derived> &V )
248  {
249  std::string ret = "[";
250  const size_t N = V.size();
251  for (size_t i=0;i<N;i++)
252  {
253  ret+= format(fmt,V[i]);
254  if (i!=(N-1)) ret+= ",";
255  }
256  ret+="]";
257  return ret;
258  }
259 
260  /** Prints a vector in the format [A,B,C,...] to std::cout, and the fmt string for <b>each</b> vector element. */
261  template <typename T>
262  void printf_vector(const char *fmt, const std::vector<T> &V ) {
263  std::cout << sprintf_vector(fmt, V);
264  }
265 
266  /** A case-insensitive comparator struct for usage within STL containers, eg: map<string,string,ci_less>
267  */
268  struct ci_less : std::binary_function<std::string,std::string,bool>
269  {
270  // case-independent (ci) compare_less binary function
271  struct nocase_compare : public std::binary_function<char,char,bool> {
272  bool operator()(const char c1, const char c2) const { return tolower(c1)<tolower(c2); }
273  };
274  bool operator() (const std::string & s1, const std::string & s2) const {
275  return std::lexicographical_compare(s1.begin(),s1.end(), s2.begin(),s2.end(), nocase_compare());
276  }
277  }; // end of ci_less
278 
279  /** @} */ // end of grouping
280 
281  } // End of namespace
282 } // End of namespace
283 #endif



Page generated by Doxygen 1.8.3 for MRPT 0.9.6 SVN: at Fri Feb 15 22:05:02 EST 2013