libidx
/home/rex/ebltrunk/core/libidx/include/smart.hpp
00001 /***************************************************************************
00002  *   Copyright (C) 2011 by Pierre Sermanet *
00003  *   pierre.sermanet@gmail.com *
00004  *   All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions are met:
00008  *     * Redistributions of source code must retain the above copyright
00009  *       notice, this list of conditions and the following disclaimer.
00010  *     * Redistributions in binary form must reproduce the above copyright
00011  *       notice, this list of conditions and the following disclaimer in the
00012  *       documentation and/or other materials provided with the distribution.
00013  *     * Redistribution under a license not approved by the Open Source
00014  *       Initiative (http://www.opensource.org) must display the
00015  *       following acknowledgement in all advertising material:
00016  *        This product includes software developed at the Courant
00017  *        Institute of Mathematical Sciences (http://cims.nyu.edu).
00018  *     * The names of the authors may not be used to endorse or promote products
00019  *       derived from this software without specific prior written permission.
00020  *
00021  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
00022  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00023  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00024  * DISCLAIMED. IN NO EVENT SHALL ThE AUTHORS BE LIABLE FOR ANY
00025  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00026  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00027  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00028  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00029  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00030  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00031  ***************************************************************************/
00032 
00033 #ifndef SMART_HPP_
00034 #define SMART_HPP__
00035 
00036 namespace ebl {
00037 
00038   // smart vector //////////////////////////////////////////////////////////////
00039 
00040   template <class T>
00041   svector<T>::svector() {
00042   }
00043 
00044   template <class T>
00045   svector<T>::svector(const svector<T> &other) {
00046     this->copy(other);
00047     //EDEBUG("copied " << other << " into this: " << *this);
00048   }
00049 
00050   template <class T>
00051   svector<T>::svector(uint n) : std::vector<T*>(n, NULL) {
00052   }
00053 
00054   template <class T>
00055   svector<T>::~svector() {
00056     clear();
00057   }
00058 
00059   template <class T>
00060   void svector<T>::clear() {
00061     unlock_all();
00062     std::vector<T*>::clear();
00063   }
00064 
00065   template <class T>
00066   void svector<T>::clear(uint i) {
00067     T *e = std::vector<T*>::operator[](i);
00068     if (e) {
00069       //EDEBUG("clearing element " << i << " " << *e);
00070       e->unlock();
00071       std::vector<T*>::operator[](i) = NULL;
00072     }
00073   }
00074 
00075   template <class T>
00076   T& svector<T>::operator[](uint i) {
00077 #ifdef __DEBUG__
00078     if (i >= this->size())
00079       eblerror("trying to access element " << i << " in vector of size "
00080                << this->size());
00081 #endif
00082     return *(std::vector<T*>::operator[](i));
00083   }
00084 
00085   // template <class T>
00086   // const T& svector<T>::operator[](uint i) const {
00087   //   return *(std::vector<T*>::operator[](i));
00088   // }
00089 
00090   template <class T>
00091   const T& svector<T>::at_const(uint i) const {
00092     return *(std::vector<T*>::operator[](i));
00093   }
00094 
00095   template <class T>
00096   bool svector<T>::exists(uint i) const {
00097     if (i >= std::vector<T*>::size()) return false;
00098     return std::vector<T*>::operator[](i) != NULL;
00099   }
00100 
00101   template <class T>
00102   uint svector<T>::size_existing() const {
00103     uint n = 0;
00104     typename std::vector<T*>::const_iterator cit = std::vector<T*>::begin();
00105     for (; cit != std::vector<T*>::end(); ++cit)
00106       if (*cit != NULL) n++;
00107     return n;
00108   }
00109 
00110   template <class T>
00111   void svector<T>::remove(uint i) {
00112     if (i >= this->size())
00113       eblerror("cannot remove element " << i << " when vector has only "
00114                << this->size() << " elements");
00115     it = this->begin() + i;
00116     if (*it != NULL) (*it)->unlock();
00117     this->erase(it);
00118   }
00119 
00120   template <class T>
00121   void svector<T>::remove(uint start, uint end) {
00122     if (end >= this->size())
00123       eblerror("cannot remove elements from " << start << " to " << end
00124                << " when vector has only " << this->size() << " elements");
00125     unlock_range(start, end);
00126     it = this->begin() + start;
00127     typename std::vector<T*>::iterator itend = this->begin() + end;
00128     itend++; // include last element
00129     this->erase(it, itend);
00130   }
00131 
00132   template <class T>
00133   void svector<T>::remove_empty() {
00134     for (uint i = 0; i < this->size(); ) {
00135       if (!exists(i)) this->remove(i);
00136       else i++;
00137     }
00138   }
00139 
00140   template <class T>
00141   void svector<T>::push_front(T &e) {
00142     e.lock();
00143     std::vector<T*>::insert(std::vector<T*>::begin(), 1, &e);
00144   }
00145 
00146   template <class T>
00147   void svector<T>::push_front_new(T &e) {
00148     T *n = new T(e);
00149     n->lock();
00150     std::vector<T*>::insert(std::vector<T*>::begin(), 1, n);
00151   }
00152 
00153   template <class T>
00154   void svector<T>::push_back(T *e) {
00155     if (e) e->lock();
00156     std::vector<T*>::push_back(e);
00157   }
00158 
00159   template <class T>
00160   void svector<T>::push_back(T &e) {
00161     e.lock();
00162     std::vector<T*>::push_back(&e);
00163   }
00164 
00165   template <class T>
00166   void svector<T>::push_back_new(const T &e) {
00167     T *n = new T(e);
00168     //EDEBUG("pushing back " << e << " into new element " << *n);
00169     n->lock();
00170     std::vector<T*>::push_back(n);
00171   }
00172 
00173   template <class T>
00174   void svector<T>::push_back_new(const T *e) {
00175     T *n = new T(*e);
00176     //EDEBUG("pushing back " << e << " into new element " << *n);
00177     n->lock();
00178     std::vector<T*>::push_back(n);
00179   }
00180 
00181   template <class T>
00182   void svector<T>::push_back(std::vector<T*> &v) {
00183     for (it = v.begin(); it != v.end(); ++it) {
00184       (*it)->lock();
00185       std::vector<T*>::push_back(*it);
00186     }
00187   }
00188 
00189   template <class T>
00190   void svector<T>::push_back(svector<T> &v) {
00191     for (it = v.begin(); it != v.end(); ++it) {
00192       if (*it != NULL) {
00193         (*it)->lock();
00194         std::vector<T*>::push_back(*it);
00195       } else push_back_empty();
00196     }
00197   }
00198 
00199   template <class T>
00200   void svector<T>::push_back_new(const svector<T> &v) {
00201     typename std::vector<T*>::const_iterator cit = v.begin();
00202     for ( ; cit != v.end(); ++cit) {
00203       if (*cit != NULL) push_back_new(*cit);
00204       else push_back_empty();
00205     }
00206   }
00207 
00208   template <class T>
00209   void svector<T>::set(T &o, uint i) {
00210     T* &e = this->at(i);
00211     if (e) e->unlock();
00212     o.lock();
00213     e = &o;
00214   }
00215 
00216   template <class T>
00217   void svector<T>::set_new(T &o, uint i) {
00218     T* &e = this->at(i);
00219     if (e) e->unlock();
00220     T *n = new T(o);
00221     n->lock();
00222     e = n;
00223   }
00224 
00225   // template <class T>
00226   // svector<T>& svector<T>::operator=(svector<T> &other) {
00227   //   if ((void*) &other != (void*) this) {
00228   //     this->clear();
00229   //     this->push_back(other);
00230   //   }
00231   //   return *this;
00232   // }
00233 
00234   template <class T>
00235   void svector<T>::operator=(svector<T> other) {
00236     if ((void*) &other != (void*) this) {
00237       this->clear();
00238       this->push_back(other);
00239     }
00240     // return *this;
00241   }
00242 
00243   template <class T>
00244   void svector<T>::push_back_empty() {
00245     std::vector<T*>::push_back(NULL);
00246   }
00247 
00248   template <class T>
00249   void svector<T>::swap(uint i, uint j) {
00250     T *tmp = std::vector<T*>::at(j);
00251     std::vector<T*>::at(j) = std::vector<T*>::at(i);
00252     std::vector<T*>::at(i) = tmp;
00253   }
00254 
00255   template <class T>
00256   svector<T> svector<T>::copy() {
00257     svector<T> c;
00258     for (it = std::vector<T*>::begin(); it != std::vector<T*>::end(); ++it)
00259       c.push_back(*it);
00260     return c;
00261   }
00262 
00263   template <class T>
00264   void svector<T>::copy(const svector<T> &other) {
00265     this->clear();
00266     for (typename svector<T>::const_iterator i = other.begin();
00267          i != other.end(); ++i)
00268       if (i.exists()) this->push_back_new(*i);
00269       else this->push_back_empty();
00270   }
00271 
00272   template <class T>
00273   void svector<T>::copy(svector<T> &other) {
00274     this->clear();
00275     for (typename svector<T>::iterator i = other.begin();
00276          i != other.end(); ++i)
00277       if (i.exists()) this->push_back(i.ptr());
00278       else this->push_back_empty();
00279   }
00280 
00281   template <class T>
00282   svector<T> svector<T>::narrow(uint n, uint offset) {
00283     if (offset + n > this->size())
00284       eblerror("out-of-bounds narrow of size " << n << " starting at offset "
00285                << offset << " in " << *this);
00286     svector<T> m;
00287     for (typename svector<T>::iterator i = this->begin() + offset;
00288          i != this->begin() + offset + n; ++i)
00289       if (i.exists()) m.push_back(*i);
00290       else m.push_back_empty();
00291     return m;
00292   }
00293 
00294   template <class T>
00295   void svector<T>::resize_default(uint n) {
00296     for (uint i = this->size(); i < n; ++i)
00297       this->push_back(new T);
00298   }
00299 
00300   template <class T>
00301   void svector<T>::randomize() {
00302     typename std::vector<T*>::iterator b = ((std::vector<T*>*)this)->begin();
00303     typename std::vector<T*>::iterator e = ((std::vector<T*>*)this)->end();
00304     std::random_shuffle(b, e);
00305   }
00306 
00307   template <class T>
00308   typename svector<T>::iterator svector<T>::begin(uint off) {
00309     return iterator(std::vector<T*>::begin() + off);
00310   }
00311 
00312   template <class T>
00313   typename svector<T>::const_iterator svector<T>::begin(uint off) const {
00314     return const_iterator(std::vector<T*>::begin() + off);
00315   }
00316 
00317   // internal methods //////////////////////////////////////////////////////////
00318 
00319   template <class T>
00320   void svector<T>::lock_all() {
00321     for (it = this->begin(); it != this->end(); ++it)
00322       if (*it != NULL) (*it)->lock();
00323   }
00324 
00325   template <class T>
00326   void svector<T>::unlock_all() {
00327     for (it = this->begin(); it != this->end(); ++it)
00328       if (*it != NULL) (*it)->unlock();
00329   }
00330 
00331   template <class T>
00332   void svector<T>::unlock_range(uint start, uint end) {
00333     for (it = this->begin() + start; it != this->begin() + end; ++it)
00334       if (*it != NULL) (*it)->unlock();
00335   }
00336 
00337   // svector iterator //////////////////////////////////////////////////////////
00338 
00339   template <class T>
00340   svector<T>::iterator::iterator() {
00341   }
00342 
00343   template <class T>
00344   svector<T>::iterator::iterator(typename std::vector<T*>::iterator &it)
00345     : std::vector<T*>::iterator(it) {
00346   }
00347 
00348   template <class T>
00349   svector<T>::iterator::iterator(typename std::vector<T*>::iterator it)
00350     : std::vector<T*>::iterator(it) {
00351   }
00352 
00353   template <class T>
00354   svector<T>::iterator::~iterator() {
00355   }
00356 
00357   template <class T>
00358   T& svector<T>::iterator::operator*() {
00359 #if __WINDOWS__ == 1
00360     return **(this->_Ptr);
00361 #else
00362         return **(this->_M_current);
00363 #endif
00364   }
00365 
00366   template <class T>
00367   T* svector<T>::iterator::operator->() {
00368 #if __WINDOWS__ == 1
00369           return *(this->_Ptr);
00370 #else
00371     return *(this->_M_current);
00372 #endif
00373   }
00374 
00375   template <class T>
00376   T* svector<T>::iterator::ptr() {
00377 #if __WINDOWS__ == 1
00378           return *(this->_Ptr);
00379 #else
00380     return *(this->_M_current);
00381 #endif
00382   }
00383 
00384   template <class T>
00385   bool svector<T>::iterator::exists() const {
00386 #if __WINDOWS__ == 1
00387         return *(this->_Ptr) != NULL;
00388 #else
00389     return *(this->_M_current) != NULL;
00390 #endif
00391   }
00392 
00393   // svector const_iterator ////////////////////////////////////////////////////
00394 
00395   template <class T>
00396   svector<T>::const_iterator::const_iterator() {
00397   }
00398 
00399   template <class T>
00400   svector<T>::const_iterator::
00401   const_iterator(typename std::vector<T*>::const_iterator &it)
00402     : std::vector<T*>::const_iterator(it) {
00403   }
00404 
00405   template <class T>
00406   svector<T>::const_iterator::
00407   const_iterator(typename std::vector<T*>::const_iterator it)
00408     : std::vector<T*>::const_iterator(it) {
00409   }
00410 
00411   template <class T>
00412   svector<T>::const_iterator::~const_iterator() {
00413   }
00414 
00415   template <class T>
00416   const T& svector<T>::const_iterator::operator*() const {
00417 #if __WINDOWS__ == 1
00418         return **(this->_Ptr);
00419 #else
00420     return **(this->_M_current);
00421 #endif
00422   }
00423 
00424   template <class T>
00425   const T* svector<T>::const_iterator::operator->() const {
00426 #if __WINDOWS__ == 1
00427         return *(this->_Ptr);
00428 #else
00429     return *(this->_M_current);
00430 #endif
00431   }
00432 
00433   template <class T>
00434   const T* svector<T>::const_iterator::ptr() const {
00435 #if __WINDOWS__ == 1
00436           return *(this->_Ptr);
00437 #else
00438     return *(this->_M_current);
00439 #endif
00440   }
00441 
00442   template <class T>
00443   bool svector<T>::const_iterator::exists() const {
00444 #if __WINDOWS__ == 1
00445           return *(this->_Ptr) != NULL;
00446 #else
00447     return *(this->_M_current) != NULL;
00448 #endif
00449   }
00450 
00451   // printing //////////////////////////////////////////////////////////////////
00452 
00453   template <class T, class stream>
00454   stream& operator<<(stream &o, const svector<T> &v) {
00455     o << "[ ";
00456     for (typename svector<T>::const_iterator i = v.begin();
00457          i != v.end(); ++i) {
00458       if (i.exists())
00459         o << (const T&)*i << " ";
00460       else
00461         o << " null ";
00462     }
00463     o << "]";
00464     return o;
00465   }
00466 
00467   template <class T, class stream>
00468   stream& operator<<(stream &o, svector<T> &v) {
00469     o << "[ ";
00470     for (typename svector<T>::iterator i = v.begin();
00471          i != v.end(); ++i) {
00472       if (i.exists())
00473         o << (T&)*i << " ";
00474       else
00475         o << " null ";
00476     }
00477     o << "]";
00478     return o;
00479   }
00480 
00481 } // namespace ebl
00482 
00483 #endif /* SMART_HPP_ */