contrib/mul/mbl/mbl_data_wrapper_mixer.txx
Go to the documentation of this file.
00001 // This is mul/mbl/mbl_data_wrapper_mixer.txx
00002 #ifndef mbl_data_wrapper_mixer_txx_
00003 #define mbl_data_wrapper_mixer_txx_
00004 //:
00005 // \file
00006 
00007 #include "mbl_data_wrapper_mixer.h"
00008 
00009 #include <vcl_iostream.h>
00010 #include <vcl_cstdlib.h>
00011 #include <vcl_cassert.h>
00012 
00013 //: Default constructor
00014 template<class T>
00015 mbl_data_wrapper_mixer<T>::mbl_data_wrapper_mixer()
00016   : n_(0),index_(0),current_wrapper_(0)
00017 {
00018 }
00019 
00020 //: Constructor
00021 template<class T>
00022 mbl_data_wrapper_mixer<T>::mbl_data_wrapper_mixer(mbl_data_wrapper<T> **wrapper, unsigned long n_wrappers)
00023 {
00024   set(wrapper,n_wrappers);
00025 }
00026 
00027 //: Constructor
00028 template<class T>
00029 mbl_data_wrapper_mixer<T>::mbl_data_wrapper_mixer(vcl_vector<mbl_data_wrapper<T> *> wrapper)
00030 {
00031   set(&wrapper[0],wrapper.size());
00032 }
00033 
00034 //: Constructor
00035 template<class T>
00036 mbl_data_wrapper_mixer<T>::mbl_data_wrapper_mixer(mbl_data_wrapper<T>& wrapper1,
00037                                                   mbl_data_wrapper<T>& wrapper2)
00038 {
00039   vcl_vector<mbl_data_wrapper<T>*> w(2);
00040   w[0] = &wrapper1;
00041   w[1] = &wrapper2;
00042   set(&w[0],w.size());
00043 }
00044 
00045 //: Initialise to return elements from data[i]
00046 template<class T>
00047 void mbl_data_wrapper_mixer<T>::set(mbl_data_wrapper<T> **wrapper, unsigned long n_wrappers)
00048 {
00049   assert (n_wrappers != ((unsigned long)-1)); // a common mistake
00050   wrapper_.resize(n_wrappers);
00051   n_       = 0;
00052   for (unsigned long i=0;i<n_wrappers;++i)
00053   {
00054     wrapper_[i] = wrapper[i];
00055     n_ += wrapper[i]->size();
00056   }
00057   current_wrapper_ = 0;
00058   wrapper_[0]->reset();
00059   set_index(0);
00060 }
00061 
00062 //: Default destructor
00063 template<class T>
00064 mbl_data_wrapper_mixer<T>::~mbl_data_wrapper_mixer()
00065 {
00066 }
00067 
00068 //: Number of objects available
00069 template<class T>
00070 unsigned long mbl_data_wrapper_mixer<T>::size() const
00071 {
00072   return n_;
00073 }
00074 
00075 //: Reset so that current() returns first object
00076 template<class T>
00077 void mbl_data_wrapper_mixer<T>::reset()
00078 {
00079   index_=0;
00080   current_wrapper_=0;
00081   if (wrapper_.size()>0) wrapper_[0]->reset();
00082 }
00083 
00084 //: Return current object
00085 template<class T>
00086 const T& mbl_data_wrapper_mixer<T>::current()
00087 {
00088   return wrapper_[current_wrapper_]->current();
00089 }
00090 
00091 //: Move to next object, returning true if is valid
00092 template<class T>
00093 bool mbl_data_wrapper_mixer<T>::next()
00094 {
00095   index_++;
00096 
00097   // Increment current and check for end of data in current wrapper
00098   if (index_<n_ && !wrapper_[current_wrapper_]->next())
00099   {
00100     // Find next non-empty wrapper
00101     if (current_wrapper_<(wrapper_.size()-1)) current_wrapper_++;
00102 
00103     while (current_wrapper_<(wrapper_.size()-1) && wrapper_[current_wrapper_]->size()==0)
00104       current_wrapper_++;
00105 
00106     wrapper_[current_wrapper_]->reset();
00107   }
00108 
00109   return index_<n_;
00110 }
00111 
00112 //: Return current index
00113 template<class T>
00114 unsigned long mbl_data_wrapper_mixer<T>::index() const
00115 {
00116   return index_;
00117 }
00118 
00119 //: Create copy on heap and return base pointer
00120 template<class T>
00121 mbl_data_wrapper< T >* mbl_data_wrapper_mixer<T>::clone() const
00122 {
00123   return new mbl_data_wrapper_mixer<T>(*this);
00124 }
00125 
00126 //: Move to element n
00127 //  First example has index 0
00128 template<class T>
00129 void mbl_data_wrapper_mixer<T>::set_index(unsigned long n)
00130 {
00131   assert(n != ((unsigned)-1));
00132   if (n>=n_)
00133   {
00134     vcl_cerr<<"mbl_data_wrapper_mixer<T>::set_index(n) :\n"
00135             <<"  n = "<<n<<" not in range 0<=n<"<<size()<<vcl_endl;
00136     vcl_abort();
00137   }
00138 
00139   index_=n;
00140 
00141   // Determine which wrapper to use
00142   current_wrapper_=0;
00143   unsigned long sum_n = wrapper_[0]->size();
00144   while (index_>=sum_n)
00145     { current_wrapper_++; sum_n += wrapper_[current_wrapper_]->size(); }
00146   unsigned long offset = index_ - (sum_n - wrapper_[current_wrapper_]->size());
00147   wrapper_[current_wrapper_]->set_index(offset);
00148 }
00149 
00150 template <class T>
00151 bool mbl_data_wrapper_mixer<T>::is_class(vcl_string const& s) const
00152 {
00153   return s==is_a(); // no ref to parent's is_class() since that is pure virtual
00154 }
00155 
00156 
00157 #undef MBL_DATA_WRAPPER_MIXER_INSTANTIATE
00158 #define MBL_DATA_WRAPPER_MIXER_INSTANTIATE(T) \
00159 VCL_DEFINE_SPECIALIZATION vcl_string mbl_data_wrapper_mixer<T >::is_a() const \
00160 { return vcl_string("mbl_data_wrapper_mixer<" #T ">"); } \
00161 template class mbl_data_wrapper_mixer< T >
00162 
00163 #endif // mbl_data_wrapper_mixer_txx_