|
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 |
|
30 |
template<typename NUMERIC_TYPE, typename SIGNED_TYPE> |
31 |
class SeqNum |
32 |
{ |
33 |
public: |
34 |
SeqNum () |
35 |
: m_value (0) |
36 |
{} |
37 |
|
38 |
// contruct from a plain number; but the contructor is _explicit_, so not called automatically, ever. |
39 |
explicit SeqNum (NUMERIC_TYPE value) |
40 |
: m_value (value) |
41 |
{} |
42 |
|
43 |
// copy contructor |
44 |
SeqNum (SeqNum<NUMERIC_TYPE, SIGNED_TYPE> const &value) |
45 |
: m_value (value.m_value) |
46 |
{} |
47 |
|
48 |
// assignment from a plain number |
49 |
SeqNum<NUMERIC_TYPE, SIGNED_TYPE>& operator= (NUMERIC_TYPE value) |
50 |
{ |
51 |
m_value = value; |
52 |
return *this; |
53 |
} |
54 |
|
55 |
// assignment from a sequence number |
56 |
SeqNum<NUMERIC_TYPE, SIGNED_TYPE>& operator= (SeqNum<NUMERIC_TYPE, SIGNED_TYPE> const &value) |
57 |
{ |
58 |
m_value = value.m_value; |
59 |
return *this; |
60 |
} |
61 |
|
62 |
#if 0 |
63 |
// a SeqNum implicitly converts to a plain number, but not the other way around |
64 |
operator NUMERIC_TYPE () const |
65 |
{ |
66 |
return m_value; |
67 |
} |
68 |
#endif |
69 |
|
70 |
NUMERIC_TYPE GetValue () const |
71 |
{ |
72 |
return m_value; |
73 |
} |
74 |
|
75 |
// prefix ++ |
76 |
SeqNum<NUMERIC_TYPE, SIGNED_TYPE> operator++ () |
77 |
{ |
78 |
m_value++; |
79 |
return *this; |
80 |
} |
81 |
|
82 |
// postfix ++ |
83 |
SeqNum<NUMERIC_TYPE, SIGNED_TYPE> operator++ (int) |
84 |
{ |
85 |
SeqNum<NUMERIC_TYPE, SIGNED_TYPE> retval (m_value); |
86 |
m_value++; |
87 |
return retval; |
88 |
} |
89 |
|
90 |
// prefix -- |
91 |
SeqNum<NUMERIC_TYPE, SIGNED_TYPE> operator-- () |
92 |
{ |
93 |
m_value--; |
94 |
return *this; |
95 |
} |
96 |
|
97 |
// postfix -- |
98 |
SeqNum<NUMERIC_TYPE, SIGNED_TYPE> operator-- (int) |
99 |
{ |
100 |
SeqNum<NUMERIC_TYPE, SIGNED_TYPE> retval (m_value); |
101 |
m_value--; |
102 |
return retval; |
103 |
} |
104 |
|
105 |
SeqNum<NUMERIC_TYPE, SIGNED_TYPE>& operator+= (SIGNED_TYPE value) |
106 |
{ |
107 |
m_value += value; |
108 |
return *this; |
109 |
} |
110 |
|
111 |
SeqNum<NUMERIC_TYPE, SIGNED_TYPE>& operator-= (SIGNED_TYPE value) |
112 |
{ |
113 |
m_value -= value; |
114 |
return *this; |
115 |
} |
116 |
|
117 |
SeqNum<NUMERIC_TYPE, SIGNED_TYPE> operator + (const SeqNum<NUMERIC_TYPE, SIGNED_TYPE> &other) |
118 |
{ |
119 |
return SeqNum<NUMERIC_TYPE, SIGNED_TYPE> (m_value + other.m_value); |
120 |
} |
121 |
|
122 |
SeqNum<NUMERIC_TYPE, SIGNED_TYPE> operator + (SIGNED_TYPE delta) |
123 |
{ |
124 |
return SeqNum<NUMERIC_TYPE, SIGNED_TYPE> (m_value + delta); |
125 |
} |
126 |
|
127 |
SeqNum<NUMERIC_TYPE, SIGNED_TYPE> operator - (SIGNED_TYPE delta) |
128 |
{ |
129 |
return SeqNum<NUMERIC_TYPE, SIGNED_TYPE> (m_value - delta); |
130 |
} |
131 |
|
132 |
SIGNED_TYPE operator - (const SeqNum<NUMERIC_TYPE, SIGNED_TYPE> &other) |
133 |
{ |
134 |
static const NUMERIC_TYPE maxValue = std::numeric_limits<NUMERIC_TYPE>::max (); |
135 |
static const NUMERIC_TYPE halfMaxValue = std::numeric_limits<NUMERIC_TYPE>::max () / 2; |
136 |
if (m_value > other.m_value) |
137 |
{ |
138 |
NUMERIC_TYPE diff = m_value - other.m_value; |
139 |
if (diff < halfMaxValue) |
140 |
{ |
141 |
return static_cast<SIGNED_TYPE> (diff); |
142 |
} |
143 |
else |
144 |
{ |
145 |
// |------------|------------| |
146 |
// ==== === |
147 |
// ^ ^ |
148 |
// other.m_value m_value |
149 |
return -(static_cast<SIGNED_TYPE> (maxValue - m_value + 1 + other.m_value)); |
150 |
} |
151 |
} |
152 |
else |
153 |
{ |
154 |
NUMERIC_TYPE diff = other.m_value - m_value; |
155 |
if (diff < halfMaxValue) |
156 |
{ |
157 |
// |------------|------------| |
158 |
// ======== |
159 |
// ^ ^ |
160 |
// m_value other.m_value |
161 |
return -(static_cast<SIGNED_TYPE> (diff)); |
162 |
} |
163 |
else |
164 |
{ |
165 |
// |------------|------------| |
166 |
// ==== === |
167 |
// ^ ^ |
168 |
// m_value other.m_value |
169 |
return static_cast<SIGNED_TYPE> (maxValue - other.m_value + 1 + m_value); |
170 |
} |
171 |
} |
172 |
} |
173 |
|
174 |
|
175 |
// Here is the critical part, how the comparison is made taking into |
176 |
// account wrap-around. From RFC 3626: |
177 |
// |
178 |
// The sequence number S1 is said to be "greater than" the sequence |
179 |
// number S2 if: |
180 |
// |
181 |
// S1 > S2 AND S1 - S2 <= MAXVALUE/2 OR |
182 |
// |
183 |
// S2 > S1 AND S2 - S1 > MAXVALUE/2 |
184 |
bool operator > (const SeqNum<NUMERIC_TYPE, SIGNED_TYPE> &other) |
185 |
{ |
186 |
static const NUMERIC_TYPE halfMaxValue = std::numeric_limits<NUMERIC_TYPE>::max () / 2; |
187 |
|
188 |
return (((m_value > other.m_value) && (m_value - other.m_value) <= halfMaxValue) |
189 |
|| ((other.m_value > m_value) && (other.m_value - m_value) > halfMaxValue)); |
190 |
} |
191 |
|
192 |
bool operator == (const SeqNum<NUMERIC_TYPE, SIGNED_TYPE> &other) |
193 |
{ |
194 |
return (m_value == other.m_value); |
195 |
} |
196 |
|
197 |
bool operator != (const SeqNum<NUMERIC_TYPE, SIGNED_TYPE> &other) |
198 |
{ |
199 |
return (m_value != other.m_value); |
200 |
} |
201 |
|
202 |
bool operator <= (const SeqNum<NUMERIC_TYPE, SIGNED_TYPE> &other) |
203 |
{ |
204 |
return (!this->operator> (other)); |
205 |
} |
206 |
|
207 |
bool operator >= (const SeqNum<NUMERIC_TYPE, SIGNED_TYPE> &other) |
208 |
{ |
209 |
return (this->operator> (other) || this->operator== (other)); |
210 |
} |
211 |
|
212 |
bool operator < (const SeqNum<NUMERIC_TYPE, SIGNED_TYPE> &other) |
213 |
{ |
214 |
return !this->operator> (other) && m_value != other.m_value; |
215 |
} |
216 |
|
217 |
|
218 |
template<typename NUMERIC_TYPE2, typename SIGNED_TYPE2> |
219 |
friend std::ostream & operator<< (std::ostream& os, const SeqNum<NUMERIC_TYPE2, SIGNED_TYPE2> &val); |
220 |
|
221 |
template<typename NUMERIC_TYPE2, typename SIGNED_TYPE2> |
222 |
friend std::istream & operator >> (std::istream &is, const SeqNum<NUMERIC_TYPE2, SIGNED_TYPE2> &val); |
223 |
|
224 |
private: // unimplemented operators |
225 |
SeqNum<NUMERIC_TYPE, SIGNED_TYPE>& operator+= (SeqNum<NUMERIC_TYPE, SIGNED_TYPE> const &value); |
226 |
SeqNum<NUMERIC_TYPE, SIGNED_TYPE>& operator-= (SeqNum<NUMERIC_TYPE, SIGNED_TYPE> const &value); |
227 |
SeqNum<NUMERIC_TYPE, SIGNED_TYPE> operator* (const SeqNum<NUMERIC_TYPE, SIGNED_TYPE>& b) const; |
228 |
SeqNum<NUMERIC_TYPE, SIGNED_TYPE> operator/ (const SeqNum<NUMERIC_TYPE, SIGNED_TYPE>& b) const; |
229 |
SeqNum<NUMERIC_TYPE, SIGNED_TYPE> operator% (const SeqNum<NUMERIC_TYPE, SIGNED_TYPE>& b) const; |
230 |
bool operator ! () const; |
231 |
bool operator && (const SeqNum<NUMERIC_TYPE, SIGNED_TYPE>& b) const; |
232 |
bool operator || (const SeqNum<NUMERIC_TYPE, SIGNED_TYPE>& b) const; |
233 |
SeqNum<NUMERIC_TYPE, SIGNED_TYPE> operator~ () const; |
234 |
SeqNum<NUMERIC_TYPE, SIGNED_TYPE> operator& (const SeqNum<NUMERIC_TYPE, SIGNED_TYPE>& b) const; |
235 |
SeqNum<NUMERIC_TYPE, SIGNED_TYPE> operator| (const SeqNum<NUMERIC_TYPE, SIGNED_TYPE>& b) const; |
236 |
SeqNum<NUMERIC_TYPE, SIGNED_TYPE> operator^ (const SeqNum<NUMERIC_TYPE, SIGNED_TYPE>& b) const; |
237 |
SeqNum<NUMERIC_TYPE, SIGNED_TYPE> operator<< (const SeqNum<NUMERIC_TYPE, SIGNED_TYPE>& b) const; |
238 |
SeqNum<NUMERIC_TYPE, SIGNED_TYPE> operator>> (const SeqNum<NUMERIC_TYPE, SIGNED_TYPE>& b) const; |
239 |
int operator* (); |
240 |
SeqNum<NUMERIC_TYPE, SIGNED_TYPE>* operator& (); |
241 |
|
242 |
private: |
243 |
NUMERIC_TYPE m_value; |
244 |
}; |
245 |
|
246 |
|
247 |
template<typename NUMERIC_TYPE, typename SIGNED_TYPE> |
248 |
std::ostream & |
249 |
operator<< (std::ostream& os, const SeqNum<NUMERIC_TYPE, SIGNED_TYPE> &val) |
250 |
{ |
251 |
os << val.m_value; |
252 |
return os; |
253 |
} |
254 |
|
255 |
template<typename NUMERIC_TYPE, typename SIGNED_TYPE> |
256 |
std::istream & operator >> (std::istream &is, const SeqNum<NUMERIC_TYPE, SIGNED_TYPE> &val) |
257 |
{ |
258 |
is >> val.m_value; |
259 |
return is; |
260 |
} |
261 |
|
262 |
|
263 |
typedef SeqNum<uint32_t, int32_t> SeqNum32; |
264 |
typedef SeqNum<uint16_t, int16_t> SeqNum16; |
265 |
|
266 |
} // namespace ns3 |
267 |
|
268 |
#endif |
269 |
|
270 |
|