A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
sequence-number.h
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 //
3 // Copyright (c) 2008-2010 INESC Porto
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License version 2 as
7 // published by the Free Software Foundation;
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 //
18 // Author: Gustavo J. A. M. Carneiro <gjc@inescporto.pt> <gjcarneiro@gmail.com>
19 //
20 
21 #ifndef NS3_SEQ_NUM_H
22 #define NS3_SEQ_NUM_H
23 
24 #include <limits>
25 #include <iostream>
26 #include <stdint.h>
27 
28 namespace ns3 {
29 
51 template<typename NUMERIC_TYPE, typename SIGNED_TYPE>
53 {
54 public:
56  : m_value (0)
57  {}
58 
63  explicit SequenceNumber (NUMERIC_TYPE value)
64  : m_value (value)
65  {}
66 
67  // copy contructor
69  : m_value (value.m_value)
70  {}
71 
72  // assignment from a plain number
73  SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>& operator= (NUMERIC_TYPE value)
74  {
75  m_value = value;
76  return *this;
77  }
78 
79  // assignment from a sequence number
80  SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>& operator= (SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> const &value)
81  {
82  m_value = value.m_value;
83  return *this;
84  }
85 
86 #if 0
87  // a SequenceNumber implicitly converts to a plain number, but not the other way around
88  operator NUMERIC_TYPE () const
89  {
90  return m_value;
91  }
92 #endif
93 
98  NUMERIC_TYPE GetValue () const
99  {
100  return m_value;
101  }
102 
103  // prefix ++
105  {
106  m_value++;
107  return *this;
108  }
109 
110  // postfix ++
111  SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> operator++ (int)
112  {
113  SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> retval (m_value);
114  m_value++;
115  return retval;
116  }
117 
118  // prefix --
119  SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> operator-- ()
120  {
121  m_value--;
122  return *this;
123  }
124 
125  // postfix --
126  SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> operator-- (int)
127  {
128  SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> retval (m_value);
129  m_value--;
130  return retval;
131  }
132 
133  SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>& operator+= (SIGNED_TYPE value)
134  {
135  m_value += value;
136  return *this;
137  }
138 
139  SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>& operator-= (SIGNED_TYPE value)
140  {
141  m_value -= value;
142  return *this;
143  }
144 
145  SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> operator + (const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> &other) const
146  {
147  return SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> (m_value + other.m_value);
148  }
149 
150  SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> operator + (SIGNED_TYPE delta) const
151  {
152  return SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> (m_value + delta);
153  }
154 
155  SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> operator - (SIGNED_TYPE delta) const
156  {
157  return SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> (m_value - delta);
158  }
159 
160  SIGNED_TYPE operator - (const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> &other) const
161  {
162  static const NUMERIC_TYPE maxValue = std::numeric_limits<NUMERIC_TYPE>::max ();
163  static const NUMERIC_TYPE halfMaxValue = std::numeric_limits<NUMERIC_TYPE>::max () / 2;
164  if (m_value > other.m_value)
165  {
166  NUMERIC_TYPE diff = m_value - other.m_value;
167  if (diff < halfMaxValue)
168  {
169  return static_cast<SIGNED_TYPE> (diff);
170  }
171  else
172  {
173  // |------------|------------|
174  // ==== ===
175  // ^ ^
176  // other.m_value m_value
177  return -(static_cast<SIGNED_TYPE> (maxValue - m_value + 1 + other.m_value));
178  }
179  }
180  else
181  {
182  NUMERIC_TYPE diff = other.m_value - m_value;
183  if (diff < halfMaxValue)
184  {
185  // |------------|------------|
186  // ========
187  // ^ ^
188  // m_value other.m_value
189  return -(static_cast<SIGNED_TYPE> (diff));
190  }
191  else
192  {
193  // |------------|------------|
194  // ==== ===
195  // ^ ^
196  // m_value other.m_value
197  return static_cast<SIGNED_TYPE> (maxValue - other.m_value + 1 + m_value);
198  }
199  }
200  }
201 
202 
203  // Here is the critical part, how the comparison is made taking into
204  // account wrap-around. From RFC 3626:
205  //
206  // The sequence number S1 is said to be "greater than" the sequence
207  // number S2 if:
208  //
209  // S1 > S2 AND S1 - S2 <= MAXVALUE/2 OR
210  //
211  // S2 > S1 AND S2 - S1 > MAXVALUE/2
212  bool operator > (const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> &other) const
213  {
214  static const NUMERIC_TYPE halfMaxValue = std::numeric_limits<NUMERIC_TYPE>::max () / 2;
215 
216  return (((m_value > other.m_value) && (m_value - other.m_value) <= halfMaxValue)
217  || ((other.m_value > m_value) && (other.m_value - m_value) > halfMaxValue));
218  }
219 
220  bool operator == (const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> &other) const
221  {
222  return (m_value == other.m_value);
223  }
224 
225  bool operator != (const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> &other) const
226  {
227  return (m_value != other.m_value);
228  }
229 
230  bool operator <= (const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> &other) const
231  {
232  return (!this->operator> (other));
233  }
234 
235  bool operator >= (const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> &other) const
236  {
237  return (this->operator> (other) || this->operator== (other));
238  }
239 
240  bool operator < (const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> &other) const
241  {
242  return !this->operator> (other) && m_value != other.m_value;
243  }
244 
245 
246  template<typename NUMERIC_TYPE2, typename SIGNED_TYPE2>
247  friend std::ostream & operator<< (std::ostream& os, const SequenceNumber<NUMERIC_TYPE2, SIGNED_TYPE2> &val);
248 
249  template<typename NUMERIC_TYPE2, typename SIGNED_TYPE2>
250  friend std::istream & operator >> (std::istream &is, const SequenceNumber<NUMERIC_TYPE2, SIGNED_TYPE2> &val);
251 
252 private: // unimplemented operators
253  SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>& operator+= (SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> const &value);
254  SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>& operator-= (SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> const &value);
255  SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> operator* (const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>& b) const;
256  SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> operator/ (const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>& b) const;
257  SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> operator% (const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>& b) const;
258  bool operator ! () const;
259  bool operator && (const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>& b) const;
260  bool operator || (const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>& b) const;
261  SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> operator~ () const;
262  SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> operator& (const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>& b) const;
263  SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> operator| (const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>& b) const;
264  SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> operator^ (const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>& b) const;
265  SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> operator<< (const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>& b) const;
266  SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> operator>> (const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>& b) const;
267  int operator* ();
268  //SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>* operator& ();
269 
270 private:
271  NUMERIC_TYPE m_value;
272 };
273 
274 
275 template<typename NUMERIC_TYPE, typename SIGNED_TYPE>
276 std::ostream &
277 operator<< (std::ostream& os, const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> &val)
278 {
279  os << val.m_value;
280  return os;
281 }
282 
283 template<typename NUMERIC_TYPE, typename SIGNED_TYPE>
284 std::istream & operator >> (std::istream &is, const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE> &val)
285 {
286  is >> val.m_value;
287  return is;
288 }
289 
290 
291 typedef SequenceNumber<uint32_t, int32_t> SequenceNumber32;
292 typedef SequenceNumber<uint16_t, int16_t> SequenceNumber16;
293 
294 } // namespace ns3
295 
296 #endif /* NS3_SEQ_NUM_H */
297 
298 
std::istream & operator>>(std::istream &is, Angles &a)
Definition: angles.cc:49
NUMERIC_TYPE GetValue() const
Extracts the numeric value of the sequence number.
Generic "sequence number" class.
SequenceNumber(NUMERIC_TYPE value)
Constructs a SequenceNumber with the given value.