Main MRPT website > C++ reference
MRPT logo

stl_extensions.h

Go to the documentation of this file.
00001 /* +---------------------------------------------------------------------------+
00002    |          The Mobile Robot Programming Toolkit (MRPT) C++ library          |
00003    |                                                                           |
00004    |                   http://mrpt.sourceforge.net/                            |
00005    |                                                                           |
00006    |   Copyright (C) 2005-2011  University of Malaga                           |
00007    |                                                                           |
00008    |    This software was written by the Machine Perception and Intelligent    |
00009    |      Robotics Lab, University of Malaga (Spain).                          |
00010    |    Contact: Jose-Luis Blanco  <jlblanco@ctima.uma.es>                     |
00011    |                                                                           |
00012    |  This file is part of the MRPT project.                                   |
00013    |                                                                           |
00014    |     MRPT is free software: you can redistribute it and/or modify          |
00015    |     it under the terms of the GNU General Public License as published by  |
00016    |     the Free Software Foundation, either version 3 of the License, or     |
00017    |     (at your option) any later version.                                   |
00018    |                                                                           |
00019    |   MRPT is distributed in the hope that it will be useful,                 |
00020    |     but WITHOUT ANY WARRANTY; without even the implied warranty of        |
00021    |     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         |
00022    |     GNU General Public License for more details.                          |
00023    |                                                                           |
00024    |     You should have received a copy of the GNU General Public License     |
00025    |     along with MRPT.  If not, see <http://www.gnu.org/licenses/>.         |
00026    |                                                                           |
00027    +---------------------------------------------------------------------------+ */
00028 #ifndef  stl_extensions_H
00029 #define  stl_extensions_H
00030 
00031 #include <mrpt/utils/CSerializable.h>
00032 #include <mrpt/utils/CStream.h>
00033 #include <mrpt/utils/metaprogramming.h>
00034 
00035 #include <set>
00036 #include <map>
00037 #include <list>
00038 #include <cctype>  // tolower
00039 
00040 // These are "STL extensions" but have their own files for clarity
00041 #include <mrpt/utils/circular_buffer.h>
00042 #include <mrpt/utils/list_searchable.h>
00043 #include <mrpt/utils/bimap.h>
00044 #include <mrpt/utils/map_as_vector.h>
00045 #include <mrpt/utils/traits_map.h>
00046 
00047 
00048 namespace mrpt
00049 {
00050         namespace utils
00051         {
00052                 using namespace mrpt::utils::metaprogramming;
00053                 using std::for_each;
00054                 using std::string;
00055 
00056 
00057                 #define MRPTSTL_SERIALIZABLE_SEQ_CONTAINER( CONTAINER )  \
00058                         /** Template method to serialize a sequential STL container  */ \
00059                         template <class T,class _Ax> \
00060                         CStream& operator << (CStream& out, const CONTAINER<T,_Ax> &obj) \
00061                         { \
00062                                 out << string(#CONTAINER) << TTypeName<T>::get(); \
00063                                 out << static_cast<uint32_t>(obj.size()); \
00064                                 for_each( obj.begin(), obj.end(), ObjectWriteToStream(&out) ); \
00065                                 return out; \
00066                         } \
00067                         /** Template method to deserialize a sequential STL container */ \
00068                         template <class T,class _Ax>  \
00069                         CStream& operator >> (CStream& in, CONTAINER<T,_Ax> &obj) \
00070                         { \
00071                                 obj.clear(); \
00072                                 string pref,stored_T; \
00073                                 in >> pref; \
00074                                 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() )) \
00075                                 in >> stored_T; \
00076                                 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() )) \
00077                                 uint32_t n; \
00078                                 in >> n; \
00079                                 obj.resize(n); \
00080                                 for_each( obj.begin(), obj.end(), ObjectReadFromStream(&in) ); \
00081                                 return in; \
00082                         }
00083 
00084 
00085                 #define MRPTSTL_SERIALIZABLE_ASSOC_CONTAINER( CONTAINER )  \
00086                         /** Template method to serialize an associative STL container  */ \
00087                         template <class K,class V, class _Pr, class _Alloc> \
00088                         CStream& operator << (CStream& out, const CONTAINER<K,V,_Pr,_Alloc> &obj) \
00089                         { \
00090                                 out << string(#CONTAINER) << TTypeName<K>::get() << TTypeName<V>::get(); \
00091                                 out << static_cast<uint32_t>(obj.size()); \
00092                                 for (typename CONTAINER<K,V,_Pr,_Alloc>::const_iterator it=obj.begin();it!=obj.end();++it) \
00093                                         out << it->first << it->second; \
00094                                 return out; \
00095                         } \
00096                         /** Template method to deserialize an associative STL container */ \
00097                         template <class K,class V, class _Pr, class _Alloc>  \
00098                         CStream& operator >> (CStream& in, CONTAINER<K,V,_Pr,_Alloc> &obj) \
00099                         { \
00100                                 obj.clear(); \
00101                                 string pref,stored_K,stored_V; \
00102                                 in >> pref; \
00103                                 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())) \
00104                                 in >> stored_K; \
00105                                 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())) \
00106                                 in >> stored_V; \
00107                                 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())) \
00108                                 uint32_t n; \
00109                                 in >> n; \
00110                                 for (uint32_t i=0;i<n;i++) \
00111                                 { \
00112                                         K       key_obj; \
00113                                         in >> key_obj; \
00114                                         /* Create an pair (Key, empty), then read directly into the ".second": */ \
00115                                         typename CONTAINER<K,V,_Pr,_Alloc>::iterator it_new = obj.insert(obj.begin(), std::make_pair(key_obj, V()) ); \
00116                                         in >> it_new->second; \
00117                                 } \
00118                                 return in; \
00119                         }
00120 
00121                 MRPTSTL_SERIALIZABLE_SEQ_CONTAINER(std::vector)         // Serialization for std::vector
00122                 MRPTSTL_SERIALIZABLE_SEQ_CONTAINER(std::deque)          // Serialization for std::deque
00123                 MRPTSTL_SERIALIZABLE_SEQ_CONTAINER(std::list)           // Serialization for std::list
00124 
00125                 MRPTSTL_SERIALIZABLE_ASSOC_CONTAINER(std::map)          // Serialization for std::map
00126                 MRPTSTL_SERIALIZABLE_ASSOC_CONTAINER(std::multimap)     // Serialization for std::multimap
00127 
00128 
00129                 #define MRPTSTL_SERIALIZABLE_SIMPLE_ASSOC_CONTAINER( CONTAINER )  \
00130                         /** Template method to serialize an associative STL container  */ \
00131                         template <class K,class _Pr,class _Alloc> \
00132                         CStream& operator << (CStream& out, const CONTAINER<K,_Pr,_Alloc> &obj) \
00133                         { \
00134                                 out << string(#CONTAINER) << TTypeName<K>::get(); \
00135                                 out << static_cast<uint32_t>(obj.size()); \
00136                                 for (typename CONTAINER<K,_Pr,_Alloc>::const_iterator it=obj.begin();it!=obj.end();++it) \
00137                                         out << *it; \
00138                                 return out; \
00139                         } \
00140                         /** Template method to deserialize an associative STL container */ \
00141                         template <class K,class _Pr,class _Alloc>  \
00142                         CStream& operator >> (CStream& in, CONTAINER<K,_Pr,_Alloc> &obj) \
00143                         { \
00144                                 obj.clear(); \
00145                                 string pref,stored_K; \
00146                                 in >> pref; \
00147                                 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())) \
00148                                 in >> stored_K; \
00149                                 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())) \
00150                                 uint32_t n; \
00151                                 in >> n; \
00152                                 for (uint32_t i=0;i<n;i++) \
00153                                 { \
00154                                         K       key_obj; \
00155                                         in >> key_obj; \
00156                                         obj.insert(key_obj); \
00157                                 } \
00158                                 return in; \
00159                         }
00160 
00161                 MRPTSTL_SERIALIZABLE_SIMPLE_ASSOC_CONTAINER(std::set)           // Serialization for std::set
00162                 MRPTSTL_SERIALIZABLE_SIMPLE_ASSOC_CONTAINER(std::multiset)      // Serialization for std::multiset
00163 
00164 
00165                 /** Template method to serialize a STL pair */
00166                 template <class T1,class T2>
00167                 CStream& operator << (CStream& out, const std::pair<T1,T2> &obj)
00168                 {
00169                         out << string("std::pair") << TTypeName<T1>::get() << TTypeName<T2>::get();
00170                         out << obj.first << obj.second;
00171                         return out;
00172                 }
00173                 /** Template method to deserialize a STL pair */
00174                 template <class T1,class T2>
00175                 CStream& operator >> (CStream& in, std::pair<T1,T2> &obj)
00176                 {
00177                         string pref,stored_K,stored_V;
00178                         in >> pref;
00179                         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()))
00180                         in >> stored_K;
00181                         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()))
00182                         in >> stored_V;
00183                         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()))
00184                         in >> obj.first >> obj.second;
00185                         return in;
00186                 }
00187 
00188 
00189                 /** Returns the index of the value "T" in the container "vect" (std::vector,std::deque,etc), or string::npos if not found.
00190                   */
00191                 template <class T,class CONTAINER>
00192                 size_t find_in_vector(const T &value, const CONTAINER &vect)
00193                 {
00194                         typename CONTAINER::const_iterator last = vect.end();
00195                         for (typename CONTAINER::const_iterator i=vect.begin();i!=last;++i)
00196                                 if (*i==value) return std::distance(vect.begin(),i);
00197                         return std::string::npos;
00198                 }
00199 
00200                 /** 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) */
00201                 template <class T> inline typename std::list<T>::iterator erase_return_next(std::list<T> &cont, typename std::list<T>::iterator &it)
00202                 {
00203                         return cont.erase(it);
00204                 }
00205                 //! \overload
00206                 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)
00207                 {
00208                         typename std::map<K,V>::iterator itRet = it; ++itRet;
00209                         cont.erase(it);
00210                         return itRet;
00211                 }
00212                 //! \overload
00213                 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)
00214                 {
00215                         typename std::multimap<K,V>::iterator itRet = it; ++itRet;
00216                         cont.erase(it);
00217                         return itRet;
00218                 }
00219                 //! \overload
00220                 template <class T> inline typename std::set<T>::iterator erase_return_next(std::set<T> &cont, typename std::set<T>::iterator &it)
00221                 {
00222                         typename std::set<T>::iterator itRet = it; ++itRet;
00223                         cont.erase(it);
00224                         return itRet;
00225                 }
00226                 //! \overload
00227                 template <class T> inline typename std::vector<T>::iterator erase_return_next(std::vector<T> &cont, typename std::vector<T>::iterator &it)
00228                 {
00229                         typename std::vector<T>::iterator itRet = it;
00230                         cont.erase(it);
00231                         return ++itRet;
00232                 }
00233 
00234                 /** 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. */
00235                 template <typename T>
00236                 std::string sprintf_vector(const char *fmt, const std::vector<T> &V )
00237                 {
00238                         std::string ret = "[";
00239                         const size_t N = V.size();
00240                         for (size_t i=0;i<N;i++)
00241                         {
00242                                 ret+= format(fmt,V[i]);
00243                                 if (i!=(N-1)) ret+= ",";
00244                         }
00245                         ret+="]";
00246                         return ret;
00247                 }
00248                 /// @overload
00249                 template <typename Derived>
00250                 std::string sprintf_vector(const char *fmt, const Eigen::MatrixBase<Derived> &V )
00251                 {
00252                         std::string ret = "[";
00253                         const size_t N = V.size();
00254                         for (size_t i=0;i<N;i++)
00255                         {
00256                                 ret+= format(fmt,V[i]);
00257                                 if (i!=(N-1)) ret+= ",";
00258                         }
00259                         ret+="]";
00260                         return ret;
00261                 }
00262 
00263                 /** Prints a vector in the format [A,B,C,...] to std::cout, and the fmt string for <b>each</b> vector element. */
00264                 template <typename T>
00265                 void printf_vector(const char *fmt, const std::vector<T> &V ) {
00266                         std::cout << sprintf_vector(fmt, V);
00267                 }
00268 
00269                 /** A case-insensitive comparator struct for usage within STL containers, eg: map<string,string,ci_less>
00270                   */
00271                 struct ci_less : std::binary_function<std::string,std::string,bool>
00272                 {
00273                         // case-independent (ci) compare_less binary function
00274                         struct nocase_compare : public std::binary_function<char,char,bool> {
00275                                 bool operator()(const char c1, const char c2) const { return tolower(c1)<tolower(c2); }
00276                         };
00277                         bool operator() (const std::string & s1, const std::string & s2) const {
00278                                 return std::lexicographical_compare(s1.begin(),s1.end(), s2.begin(),s2.end(), nocase_compare());
00279                         }
00280                 }; // end of ci_less
00281 
00282         } // End of namespace
00283 } // End of namespace
00284 #endif



Page generated by Doxygen 1.7.3 for MRPT 0.9.4 SVN:exported at Tue Jan 25 21:56:31 UTC 2011