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://www.mrpt.org/                                |
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                 /** \addtogroup stlext_grp STL extensions and metaprogramming
00053                   * \ingroup mrpt_base_grp
00054                   * @{ */
00055 
00056                 using namespace mrpt::utils::metaprogramming;
00057                 using std::for_each;
00058                 using std::string;
00059 
00060 
00061                 #define MRPTSTL_SERIALIZABLE_SEQ_CONTAINER( CONTAINER )  \
00062                         /** Template method to serialize a sequential STL container  */ \
00063                         template <class T,class _Ax> \
00064                         CStream& operator << (CStream& out, const CONTAINER<T,_Ax> &obj) \
00065                         { \
00066                                 out << string(#CONTAINER) << TTypeName<T>::get(); \
00067                                 out << static_cast<uint32_t>(obj.size()); \
00068                                 for_each( obj.begin(), obj.end(), ObjectWriteToStream(&out) ); \
00069                                 return out; \
00070                         } \
00071                         /** Template method to deserialize a sequential STL container */ \
00072                         template <class T,class _Ax>  \
00073                         CStream& operator >> (CStream& in, CONTAINER<T,_Ax> &obj) \
00074                         { \
00075                                 obj.clear(); \
00076                                 string pref,stored_T; \
00077                                 in >> pref; \
00078                                 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() )) \
00079                                 in >> stored_T; \
00080                                 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() )) \
00081                                 uint32_t n; \
00082                                 in >> n; \
00083                                 obj.resize(n); \
00084                                 for_each( obj.begin(), obj.end(), ObjectReadFromStream(&in) ); \
00085                                 return in; \
00086                         }
00087 
00088 
00089                 #define MRPTSTL_SERIALIZABLE_ASSOC_CONTAINER( CONTAINER )  \
00090                         /** Template method to serialize an associative STL container  */ \
00091                         template <class K,class V, class _Pr, class _Alloc> \
00092                         CStream& operator << (CStream& out, const CONTAINER<K,V,_Pr,_Alloc> &obj) \
00093                         { \
00094                                 out << string(#CONTAINER) << TTypeName<K>::get() << TTypeName<V>::get(); \
00095                                 out << static_cast<uint32_t>(obj.size()); \
00096                                 for (typename CONTAINER<K,V,_Pr,_Alloc>::const_iterator it=obj.begin();it!=obj.end();++it) \
00097                                         out << it->first << it->second; \
00098                                 return out; \
00099                         } \
00100                         /** Template method to deserialize an associative STL container */ \
00101                         template <class K,class V, class _Pr, class _Alloc>  \
00102                         CStream& operator >> (CStream& in, CONTAINER<K,V,_Pr,_Alloc> &obj) \
00103                         { \
00104                                 obj.clear(); \
00105                                 string pref,stored_K,stored_V; \
00106                                 in >> pref; \
00107                                 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())) \
00108                                 in >> stored_K; \
00109                                 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())) \
00110                                 in >> stored_V; \
00111                                 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())) \
00112                                 uint32_t n; \
00113                                 in >> n; \
00114                                 for (uint32_t i=0;i<n;i++) \
00115                                 { \
00116                                         K       key_obj; \
00117                                         in >> key_obj; \
00118                                         /* Create an pair (Key, empty), then read directly into the ".second": */ \
00119                                         typename CONTAINER<K,V,_Pr,_Alloc>::iterator it_new = obj.insert(obj.begin(), std::make_pair(key_obj, V()) ); \
00120                                         in >> it_new->second; \
00121                                 } \
00122                                 return in; \
00123                         }
00124 
00125                 MRPTSTL_SERIALIZABLE_SEQ_CONTAINER(std::vector)         // Serialization for std::vector
00126                 MRPTSTL_SERIALIZABLE_SEQ_CONTAINER(std::deque)          // Serialization for std::deque
00127                 MRPTSTL_SERIALIZABLE_SEQ_CONTAINER(std::list)           // Serialization for std::list
00128 
00129                 MRPTSTL_SERIALIZABLE_ASSOC_CONTAINER(std::map)          // Serialization for std::map
00130                 MRPTSTL_SERIALIZABLE_ASSOC_CONTAINER(std::multimap)     // Serialization for std::multimap
00131 
00132 
00133                 #define MRPTSTL_SERIALIZABLE_SIMPLE_ASSOC_CONTAINER( CONTAINER )  \
00134                         /** Template method to serialize an associative STL container  */ \
00135                         template <class K,class _Pr,class _Alloc> \
00136                         CStream& operator << (CStream& out, const CONTAINER<K,_Pr,_Alloc> &obj) \
00137                         { \
00138                                 out << string(#CONTAINER) << TTypeName<K>::get(); \
00139                                 out << static_cast<uint32_t>(obj.size()); \
00140                                 for (typename CONTAINER<K,_Pr,_Alloc>::const_iterator it=obj.begin();it!=obj.end();++it) \
00141                                         out << *it; \
00142                                 return out; \
00143                         } \
00144                         /** Template method to deserialize an associative STL container */ \
00145                         template <class K,class _Pr,class _Alloc>  \
00146                         CStream& operator >> (CStream& in, CONTAINER<K,_Pr,_Alloc> &obj) \
00147                         { \
00148                                 obj.clear(); \
00149                                 string pref,stored_K; \
00150                                 in >> pref; \
00151                                 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())) \
00152                                 in >> stored_K; \
00153                                 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())) \
00154                                 uint32_t n; \
00155                                 in >> n; \
00156                                 for (uint32_t i=0;i<n;i++) \
00157                                 { \
00158                                         K       key_obj; \
00159                                         in >> key_obj; \
00160                                         obj.insert(key_obj); \
00161                                 } \
00162                                 return in; \
00163                         }
00164 
00165                 MRPTSTL_SERIALIZABLE_SIMPLE_ASSOC_CONTAINER(std::set)           // Serialization for std::set
00166                 MRPTSTL_SERIALIZABLE_SIMPLE_ASSOC_CONTAINER(std::multiset)      // Serialization for std::multiset
00167 
00168 
00169                 /** Template method to serialize a STL pair */
00170                 template <class T1,class T2>
00171                 CStream& operator << (CStream& out, const std::pair<T1,T2> &obj)
00172                 {
00173                         out << string("std::pair") << TTypeName<T1>::get() << TTypeName<T2>::get();
00174                         out << obj.first << obj.second;
00175                         return out;
00176                 }
00177                 /** Template method to deserialize a STL pair */
00178                 template <class T1,class T2>
00179                 CStream& operator >> (CStream& in, std::pair<T1,T2> &obj)
00180                 {
00181                         string pref,stored_K,stored_V;
00182                         in >> pref;
00183                         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()))
00184                         in >> stored_K;
00185                         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()))
00186                         in >> stored_V;
00187                         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()))
00188                         in >> obj.first >> obj.second;
00189                         return in;
00190                 }
00191 
00192 
00193                 /** Returns the index of the value "T" in the container "vect" (std::vector,std::deque,etc), or string::npos if not found.
00194                   */
00195                 template <class T,class CONTAINER>
00196                 size_t find_in_vector(const T &value, const CONTAINER &vect)
00197                 {
00198                         typename CONTAINER::const_iterator last = vect.end();
00199                         for (typename CONTAINER::const_iterator i=vect.begin();i!=last;++i)
00200                                 if (*i==value) return std::distance(vect.begin(),i);
00201                         return std::string::npos;
00202                 }
00203 
00204                 /** 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) */
00205                 template <class T> inline typename std::list<T>::iterator erase_return_next(std::list<T> &cont, typename std::list<T>::iterator &it)
00206                 {
00207                         return cont.erase(it);
00208                 }
00209                 //! \overload
00210                 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)
00211                 {
00212                         typename std::map<K,V>::iterator itRet = it; ++itRet;
00213                         cont.erase(it);
00214                         return itRet;
00215                 }
00216                 //! \overload
00217                 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)
00218                 {
00219                         typename std::multimap<K,V>::iterator itRet = it; ++itRet;
00220                         cont.erase(it);
00221                         return itRet;
00222                 }
00223                 //! \overload
00224                 template <class T> inline typename std::set<T>::iterator erase_return_next(std::set<T> &cont, typename std::set<T>::iterator &it)
00225                 {
00226                         typename std::set<T>::iterator itRet = it; ++itRet;
00227                         cont.erase(it);
00228                         return itRet;
00229                 }
00230 
00231                 /** 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. */
00232                 template <typename T>
00233                 std::string sprintf_vector(const char *fmt, const std::vector<T> &V )
00234                 {
00235                         std::string ret = "[";
00236                         const size_t N = V.size();
00237                         for (size_t i=0;i<N;i++)
00238                         {
00239                                 ret+= format(fmt,V[i]);
00240                                 if (i!=(N-1)) ret+= ",";
00241                         }
00242                         ret+="]";
00243                         return ret;
00244                 }
00245                 /// @overload
00246                 template <typename Derived>
00247                 std::string sprintf_vector(const char *fmt, const Eigen::MatrixBase<Derived> &V )
00248                 {
00249                         std::string ret = "[";
00250                         const size_t N = V.size();
00251                         for (size_t i=0;i<N;i++)
00252                         {
00253                                 ret+= format(fmt,V[i]);
00254                                 if (i!=(N-1)) ret+= ",";
00255                         }
00256                         ret+="]";
00257                         return ret;
00258                 }
00259 
00260                 /** Prints a vector in the format [A,B,C,...] to std::cout, and the fmt string for <b>each</b> vector element. */
00261                 template <typename T>
00262                 void printf_vector(const char *fmt, const std::vector<T> &V ) {
00263                         std::cout << sprintf_vector(fmt, V);
00264                 }
00265 
00266                 /** A case-insensitive comparator struct for usage within STL containers, eg: map<string,string,ci_less>
00267                   */
00268                 struct ci_less : std::binary_function<std::string,std::string,bool>
00269                 {
00270                         // case-independent (ci) compare_less binary function
00271                         struct nocase_compare : public std::binary_function<char,char,bool> {
00272                                 bool operator()(const char c1, const char c2) const { return tolower(c1)<tolower(c2); }
00273                         };
00274                         bool operator() (const std::string & s1, const std::string & s2) const {
00275                                 return std::lexicographical_compare(s1.begin(),s1.end(), s2.begin(),s2.end(), nocase_compare());
00276                         }
00277                 }; // end of ci_less
00278 
00279                 /** @} */  // end of grouping
00280 
00281         } // End of namespace
00282 } // End of namespace
00283 #endif



Page generated by Doxygen 1.7.5 for MRPT 0.9.5 SVN: at Thu Oct 13 21:25:36 UTC 2011