00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
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>
00039
00040 namespace mrpt
00041 {
00042 namespace utils
00043 {
00044 using namespace mrpt::utils::metaprogramming;
00045 using std::for_each;
00046 using std::string;
00047
00048
00049 #define MRPTSTL_SERIALIZABLE_SEQ_CONTAINER( CONTAINER ) \
00050 \
00051 template <class T> \
00052 CStream& operator << (CStream& out, const CONTAINER<T> &obj) \
00053 { \
00054 out << string(#CONTAINER) << TTypeName<T>::get(); \
00055 out << static_cast<uint32_t>(obj.size()); \
00056 for_each( obj.begin(), obj.end(), ObjectWriteToStream(&out) ); \
00057 return out; \
00058 } \
00059 \
00060 template <class T> \
00061 CStream& operator >> (CStream& in, CONTAINER<T> &obj) \
00062 { \
00063 obj.clear(); \
00064 string pref,stored_T; \
00065 in >> pref; \
00066 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() )) \
00067 in >> stored_T; \
00068 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() )) \
00069 uint32_t n; \
00070 in >> n; \
00071 obj.resize(n); \
00072 for_each( obj.begin(), obj.end(), ObjectReadFromStream(&in) ); \
00073 return in; \
00074 }
00075
00076
00077 #define MRPTSTL_SERIALIZABLE_ASSOC_CONTAINER( CONTAINER ) \
00078 \
00079 template <class K,class V> \
00080 CStream& operator << (CStream& out, const CONTAINER<K,V> &obj) \
00081 { \
00082 out << string(#CONTAINER) << TTypeName<K>::get() << TTypeName<V>::get(); \
00083 out << static_cast<uint32_t>(obj.size()); \
00084 for (typename CONTAINER<K,V>::const_iterator it=obj.begin();it!=obj.end();++it) \
00085 out << it->first << it->second; \
00086 return out; \
00087 } \
00088 \
00089 template <class K,class V> \
00090 CStream& operator >> (CStream& in, CONTAINER<K,V> &obj) \
00091 { \
00092 obj.clear(); \
00093 string pref,stored_K,stored_V; \
00094 in >> pref; \
00095 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())) \
00096 in >> stored_K; \
00097 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())) \
00098 in >> stored_V; \
00099 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())) \
00100 uint32_t n; \
00101 in >> n; \
00102 for (uint32_t i=0;i<n;i++) \
00103 { \
00104 K key_obj; \
00105 in >> key_obj; \
00106 \
00107 typename CONTAINER<K,V>::iterator it_new = obj.insert(obj.begin(), std::make_pair(key_obj, V()) ); \
00108 in >> it_new->second; \
00109 } \
00110 return in; \
00111 }
00112
00113 MRPTSTL_SERIALIZABLE_SEQ_CONTAINER(std::vector)
00114 MRPTSTL_SERIALIZABLE_SEQ_CONTAINER(std::deque)
00115 MRPTSTL_SERIALIZABLE_SEQ_CONTAINER(std::list)
00116
00117 MRPTSTL_SERIALIZABLE_ASSOC_CONTAINER(std::map)
00118 MRPTSTL_SERIALIZABLE_ASSOC_CONTAINER(std::multimap)
00119
00120
00121 #define MRPTSTL_SERIALIZABLE_SIMPLE_ASSOC_CONTAINER( CONTAINER ) \
00122 \
00123 template <class K> \
00124 CStream& operator << (CStream& out, const CONTAINER<K> &obj) \
00125 { \
00126 out << string(#CONTAINER) << TTypeName<K>::get(); \
00127 out << static_cast<uint32_t>(obj.size()); \
00128 for (typename CONTAINER<K>::const_iterator it=obj.begin();it!=obj.end();++it) \
00129 out << *it; \
00130 return out; \
00131 } \
00132 \
00133 template <class K> \
00134 CStream& operator >> (CStream& in, CONTAINER<K> &obj) \
00135 { \
00136 obj.clear(); \
00137 string pref,stored_K; \
00138 in >> pref; \
00139 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())) \
00140 in >> stored_K; \
00141 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())) \
00142 uint32_t n; \
00143 in >> n; \
00144 for (uint32_t i=0;i<n;i++) \
00145 { \
00146 K key_obj; \
00147 in >> key_obj; \
00148 obj.insert(key_obj); \
00149 } \
00150 return in; \
00151 }
00152
00153 MRPTSTL_SERIALIZABLE_SIMPLE_ASSOC_CONTAINER(std::set)
00154 MRPTSTL_SERIALIZABLE_SIMPLE_ASSOC_CONTAINER(std::multiset)
00155
00156
00157
00158 template <class T1,class T2>
00159 CStream& operator << (CStream& out, const std::pair<T1,T2> &obj)
00160 {
00161 out << string("std::pair") << TTypeName<T1>::get() << TTypeName<T2>::get();
00162 out << obj.first << obj.second;
00163 return out;
00164 }
00165
00166 template <class T1,class T2>
00167 CStream& operator >> (CStream& in, std::pair<T1,T2> &obj)
00168 {
00169 string pref,stored_K,stored_V;
00170 in >> pref;
00171 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()))
00172 in >> stored_K;
00173 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()))
00174 in >> stored_V;
00175 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()))
00176 in >> obj.first >> obj.second;
00177 return in;
00178 }
00179
00180
00181
00182
00183
00184 template <class T>
00185 class list_searchable : public std::list<T>
00186 {
00187 public:
00188 virtual ~list_searchable() { std::list<T>::clear(); }
00189
00190 void insert( const T &o ) { std::list<T>::push_back(o); }
00191
00192 typename std::list<T>::iterator find( const T& i ) {
00193 return std::find(std::list<T>::begin(),std::list<T>::end(),i);
00194 }
00195
00196 typename std::list<T>::const_iterator find( const T& i ) const {
00197 return std::find(std::list<T>::begin(),std::list<T>::end(),i);
00198 }
00199
00200
00201 template <typename PTR>
00202 typename std::list<T>::iterator find_ptr_to( const PTR ptr )
00203 {
00204 for (typename std::list<T>::iterator it=std::list<T>::begin();it!=std::list<T>::end();it++)
00205 if (it->pointer()==ptr)
00206 return it;
00207 return std::list<T>::end();
00208 }
00209
00210
00211 template <typename PTR>
00212 typename std::list<T>::const_iterator find_ptr_to( const PTR ptr ) const
00213 {
00214 for (typename std::list<T>::const_iterator it=std::list<T>::begin();it!=std::list<T>::end();it++)
00215 if (it->pointer()==ptr)
00216 return it;
00217 return std::list<T>::end();
00218 }
00219
00220 };
00221
00222
00223
00224
00225 template <class T>
00226 size_t find_in_vector(const T &value, const std::vector<T> &vect)
00227 {
00228 for (size_t i=0;i<vect.size();i++)
00229 if (vect[i]==value) return i;
00230 return std::string::npos;
00231 }
00232
00233
00234
00235 template <class CONTAINER>
00236 typename CONTAINER::iterator erase_return_next(CONTAINER &cont, typename CONTAINER::iterator &it)
00237 {
00238 typename CONTAINER::iterator itRet = it;
00239 ++itRet;
00240 cont.erase(it);
00241 return itRet;
00242 }
00243
00244
00245 template <typename T>
00246 std::string sprintf_vector(const char *fmt, const std::vector<T> &V )
00247 {
00248 std::string ret = "[";
00249 size_t N = V.size();
00250 for (size_t i=0;i<N;i++)
00251 {
00252 ret+= format(fmt,V[i]);
00253 if (i!=(N-1)) ret+= ",";
00254 }
00255 ret+="]";
00256 return ret;
00257 }
00258
00259
00260 template <typename T>
00261 void printf_vector(const char *fmt, const std::vector<T> &V ) {
00262 std::cout << sprintf_vector(fmt, V);
00263 }
00264
00265
00266
00267
00268
00269 template <typename T>
00270 class circular_buffer
00271 {
00272 private:
00273 std::vector<T> m_data;
00274 const size_t m_size;
00275 size_t m_next_read,m_next_write;
00276
00277 public:
00278 circular_buffer(const size_t size) :
00279 m_data(size),
00280 m_size(size),
00281 m_next_read(0),
00282 m_next_write(0)
00283 {
00284 if (m_size<=2) throw std::invalid_argument("size must be >2");
00285 }
00286 virtual ~circular_buffer() { }
00287
00288
00289
00290
00291 void push(T d) {
00292 m_data[m_next_write++]=d;
00293 if (m_next_write==m_size) m_next_write=0;
00294
00295 if (m_next_write==m_next_read)
00296 throw std::out_of_range("push: circular_buffer is full");
00297 }
00298
00299
00300
00301
00302 void push_ref(const T &d) {
00303 m_data[m_next_write++]=d;
00304 if (m_next_write==m_size) m_next_write=0;
00305
00306 if (m_next_write==m_next_read)
00307 throw std::out_of_range("push: circular_buffer is full");
00308 }
00309
00310
00311
00312
00313 void push_many(T *array_elements, size_t count) {
00314 while (count--)
00315 push(*array_elements++);
00316 }
00317
00318
00319
00320
00321 T pop() {
00322 if (m_next_read==m_next_write)
00323 throw std::out_of_range("pop: circular_buffer is empty");
00324
00325 const size_t i = m_next_read++;
00326 if (m_next_read==m_size) m_next_read=0;
00327 return m_data[i];
00328 }
00329
00330
00331
00332
00333 void pop(T &out_val) {
00334 if (m_next_read==m_next_write)
00335 throw std::out_of_range("pop: circular_buffer is empty");
00336
00337 out_val=m_data[m_next_read++];
00338 if (m_next_read==m_size) m_next_read=0;
00339 }
00340
00341
00342
00343
00344 void pop_many(T *out_array, size_t count) {
00345 while (count--)
00346 pop(*out_array++);
00347 }
00348
00349
00350
00351
00352 size_t size() const {
00353 if (m_next_write>=m_next_read)
00354 return m_next_write-m_next_read;
00355 else return m_next_write + (m_size-m_next_read);
00356 }
00357
00358
00359
00360
00361 size_t capacity() const {
00362 return m_size;
00363 }
00364
00365
00366
00367 size_t available() const {
00368 return (capacity()-size())-1;
00369 }
00370
00371
00372 void clear() {
00373 m_next_write = m_next_read = 0;
00374 }
00375
00376 };
00377
00378
00379
00380 struct ci_less : std::binary_function<std::string,std::string,bool>
00381 {
00382
00383 struct nocase_compare : public std::binary_function<char,char,bool> {
00384 bool operator()(const char c1, const char c2) const { return tolower(c1)<tolower(c2); }
00385 };
00386 bool operator() (const std::string & s1, const std::string & s2) const {
00387 return std::lexicographical_compare(s1.begin(),s1.end(), s2.begin(),s2.end(), nocase_compare());
00388 }
00389 };
00390
00391 }
00392 }
00393 #endif