include/wipal/wifi/frame/filter/windowed_merge.hxx

00001 /*
00002  * WiPal - A library and a set of tools to manipulate wireless traces.
00003  * Copyright (C) 2007  Universite Pierre et Marie Curie - Paris 6
00004  *
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License as published by
00007  * the Free Software Foundation; either version 2 of the License, or
00008  * (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software
00017  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
00018  * MA  02110-1301  USA
00019  *
00020  * Author: Thomas Claveirole <thomas.claveirole@lip6.fr>
00021  */
00022 #ifndef WIFI_FRAME_FILTER_WINDOWED_MERGE_HXX_
00023 # define WIFI_FRAME_FILTER_WINDOWED_MERGE_HXX_
00024 
00025 # include <iostream>
00026 
00027 # include "windowed_merge.hh"
00028 
00029 # include <wipal/wifi/frame/filter/merge.hh>
00030 
00031 namespace wifi
00032 {
00033   namespace frame
00034   {
00035     namespace filter
00036     {
00037 
00038       namespace internals
00039       {
00040 
00041 # ifdef ENABLE_INFO
00042 #  define wp_increment(X)       ++(X)
00043 #  define wp_increase(X, Y...)  ((X) += (Y))
00044 # else // ! ENABLE_INFO
00045 #  define wp_increment(X)       (void) 0
00046 #  define wp_increase(X, Y...)  (void) (Y)
00047 # endif // ENABLE_INFO
00048 
00049         template <class HT, class I1, class I2, class B1, class B2>
00050         windowed_merge_iterator<HT, I1, I2, B1, B2>::
00051         windowed_merge_iterator(const iterable_type& i, bool end):
00052           iterable_ (&i),
00053           next1_ (end ? i.last1_ : i.first1_),
00054           next2_ (end ? i.last2_ : i.first2_),
00055           current_ (-1)
00056 # ifdef ENABLE_INFO
00057         , lhs_total_ (0),
00058           rhs_total_ (0),
00059           shared_ (0),
00060           total_ (0),
00061           sync_error_ (0)
00062 # endif // ENABLE_INFO
00063         {
00064           if (not end)
00065             {
00066               wp_increase(lhs_total_, fill(win1_, next1_, iterable_->last1_,
00067                                            window_size));
00068               wp_increase(rhs_total_, fill(win2_, next2_, iterable_->last2_,
00069                                            window_size));
00070               current_ = first_packet();
00071             }
00072         }
00073 
00074         template <class HT, class I1, class I2, class B1, class B2>
00075         bool
00076         windowed_merge_iterator<HT, I1, I2, B1, B2>::
00077         equal(const windowed_merge_iterator& rhs) const
00078         {
00079           return (next1_ == rhs.next1_ and win1_.size() == rhs.win1_.size() and
00080                   next2_ == rhs.next2_ and win2_.size() == rhs.win2_.size());
00081         }
00082 
00083 #define wp_advance(Counter, N)                                          \
00084         do                                                              \
00085           {                                                             \
00086             wp_increase(Counter, fill(win ## N ## _, next ## N ## _,    \
00087                                       iterable_->last ## N ## _, 1));   \
00088             win ## N ## _.pop_front();                                  \
00089           }                                                             \
00090         while (0)
00091 
00092         template <class HT, class I1, class I2, class B1, class B2>
00093         void
00094         windowed_merge_iterator<HT, I1, I2, B1, B2>::increment()
00095         {
00096           assert(current_ == 0 or current_ == 1);
00097 
00098           if (win1_.empty())
00099             wp_advance(rhs_total_, 2);
00100           else if (win2_.empty())
00101             wp_advance(lhs_total_, 1);
00102           else if (const optional_match r = match())
00103             {
00104 # ifdef ENABLE_INFO
00105               {
00106                 const tool::microseconds& t1 = r->first->microseconds();
00107                 const tool::microseconds& t2 = r->second->microseconds();
00108 
00109                 if (t1 > t2)
00110                   sync_error_ += mpz_class (t1 - t2).get_ui();
00111                 else
00112                   sync_error_ += mpz_class (t2 - t1).get_ui();
00113               }
00114               ++shared_;
00115 # endif // ENABLE_INFO
00116               win1_.erase(r->first);
00117               win2_.erase(r->second);
00118               wp_increase(lhs_total_,
00119                           fill(win1_, next1_, iterable_->last1_, 1));
00120               wp_increase(rhs_total_,
00121                           fill(win2_, next2_, iterable_->last2_, 1));
00122             }
00123           else
00124             {
00125               if (current_)
00126                 wp_advance(rhs_total_, 2);
00127               else
00128                 wp_advance(lhs_total_, 1);
00129             }
00130           wp_increment(total_);
00131 
00132           current_ = first_packet();
00133 
00134 # ifdef ENABLE_INFO
00135           if (current_ == -1)
00136             std::cerr << "INFO: " << shared_ << " frames shared by"
00137                                                 " both traces.\n"
00138                       << "INFO: Trace 1 has " << lhs_total_ << " frames ("
00139                       << (shared_ * 100.f / lhs_total_) << "% shared).\n"
00140                       << "INFO: Trace 2 has " << rhs_total_ << " frames ("
00141                       << (shared_ * 100.f / rhs_total_) << "% shared).\n"
00142                       << "INFO: Output has " << total_ << " frames ("
00143                       << (shared_ * 100.f / total_) << "% shared).\n"
00144                       << "INFO: Mean sync. error is "
00145                       << (sync_error_ / shared_) << " microseconds."
00146                       << std::endl;
00147 # endif // ENABLE_INFO
00148         }
00149 
00150 # undef wp_advance
00151 # undef wp_increment
00152 # undef wp_increase
00153 
00154         template <class HT, class I1, class I2, class B1, class B2>
00155         const typename windowed_merge_iterator<HT, I1, I2, B1, B2>::value_type&
00156         windowed_merge_iterator<HT, I1, I2, B1, B2>::get() const
00157         {
00158           assert(current_ == 0 or current_ == 1);
00159 
00160           if (current_)
00161             return win2_.front();
00162           else
00163             return win1_.front();
00164         }
00165 
00166         template <class HT, class I1, class I2, class B1, class B2>
00167         typename windowed_merge_iterator<HT, I1, I2, B1, B2>::value_type&
00168         windowed_merge_iterator<HT, I1, I2, B1, B2>::get()
00169         {
00170           assert(current_ == 0 or current_ == 1);
00171 
00172           if (current_)
00173             return win2_.front();
00174           else
00175             return win1_.front();
00176         }
00177 
00178         template <class HT, class I1, class I2, class B1, class B2>
00179         const typename windowed_merge_iterator<HT, I1, I2, B1, B2>::value_type*
00180         windowed_merge_iterator<HT, I1, I2, B1, B2>::get_ptr() const
00181         {
00182           assert(current_ == 0 or current_ == 1);
00183 
00184           if (current_)
00185             return & win2_.front();
00186           else
00187             return & win1_.front();
00188         }
00189 
00190         template <class HT, class I1, class I2, class B1, class B2>
00191         typename windowed_merge_iterator<HT, I1, I2, B1, B2>::value_type*
00192         windowed_merge_iterator<HT, I1, I2, B1, B2>::get_ptr()
00193         {
00194           assert(current_ == 0 or current_ == 1);
00195 
00196           if (current_)
00197             return & win2_.front();
00198           else
00199             return & win1_.front();
00200         }
00201 
00202         template <class HT, class I1, class I2, class B1, class B2>
00203         int
00204         windowed_merge_iterator<HT, I1, I2, B1, B2>::first_packet() const
00205         {
00206           const bool first_at_end       = win1_.empty();
00207           const bool second_at_end      = win2_.empty();
00208 
00209           if (first_at_end)
00210             return second_at_end ? -1 : 1;
00211           if (second_at_end)
00212             return 0;
00213 
00214           return win1_.front().microseconds() < win2_.front().microseconds() ?
00215             0 : 1;
00216         }
00217 
00218         template <class HT, class I1, class I2, class B1, class B2>
00219         template <class I>
00220         unsigned
00221         windowed_merge_iterator<HT, I1, I2, B1, B2>::
00222         fill(window_type&       w,
00223              I&                 i,
00224              const I&           last,
00225              size_t             n)
00226         {
00227           unsigned r;
00228 
00229           for (r = 0; r < n and i != last; ++r)
00230             w.push_back(*i++);
00231           return r;
00232         }
00233 
00234         template <class HT, class I1, class I2, class B1, class B2>
00235         typename windowed_merge_iterator<HT, I1, I2, B1, B2>::optional_match
00236         windowed_merge_iterator<HT, I1, I2, B1, B2>::match()
00237         {
00238           typedef internals::equal<HT>  equal;
00239 
00240           const value_type&     v = current_ ? win2_.front() : win1_.front();
00241           const win_iterator    f = current_ ? win1_.begin() : win2_.begin();
00242           const win_iterator    l = current_ ? win1_.end()  : win2_.end();
00243           const win_iterator    r =
00244             std::find(f, l, equal (v, iterable_->phy_end_));
00245 
00246           if (r == l)
00247             return boost::none_t ();
00248 
00249           return current_?
00250             match_type (r, win2_.begin()):
00251             match_type (win1_.begin(), r);
00252         }
00253 
00254       } // End of namespace internals.
00255 
00256       template <class HeaderType,
00257                 class InputIterator1,
00258                 class InputIterator2,
00259                 class Bottom>
00260       windowed_merge<HeaderType, InputIterator1, InputIterator2, Bottom>::
00261       windowed_merge(const InputIterator1& first1, const InputIterator1& last1,
00262                      const InputIterator2& first2, const InputIterator2& last2,
00263                      tool::endian::endianness   phy_end):
00264         phy_end_ (phy_end),
00265         first1_ (first1),
00266         last1_ (last1),
00267         first2_ (first2),
00268         last2_ (last2)
00269       {
00270       }
00271 
00272     } // End of namespace wifi::frame::filter.
00273 
00274   } // End of namespace wifi::frame.
00275 
00276 } // End of namespace wifi.
00277 
00278 #endif // ! WIFI_FRAME_FILTER_WINDOWED_MERGE_HXX_

Generated on Wed Jan 16 16:15:14 2008 for wipal by  doxygen 1.5.4