00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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 tt_increment(X) ++(X)
00043 # define tt_increase(X, Y...) ((X) += (Y))
00044 # else // ! ENABLE_INFO
00045 # define tt_increment(X) (void) 0
00046 # define tt_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
00063 {
00064 if (not end)
00065 {
00066 tt_increase(lhs_total_, fill(win1_, next1_, iterable_->last1_,
00067 window_size));
00068 tt_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 tt_advance(Counter, N) \
00084 do \
00085 { \
00086 tt_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 tt_advance(rhs_total_, 2);
00100 else if (win2_.empty())
00101 tt_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 tt_increase(lhs_total_,
00119 fill(win1_, next1_, iterable_->last1_, 1));
00120 tt_increase(rhs_total_,
00121 fill(win2_, next2_, iterable_->last2_, 1));
00122 }
00123 else
00124 {
00125 if (current_)
00126 tt_advance(rhs_total_, 2);
00127 else
00128 tt_advance(lhs_total_, 1);
00129 }
00130 tt_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 tt_advance
00151 # undef tt_increment
00152 # undef tt_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 }
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 }
00273
00274 }
00275
00276 }
00277
00278 #endif // ! WIFI_FRAME_FILTER_WINDOWED_MERGE_HXX_