# HG changeset patch # User Gustavo J. A. M. Carneiro # Date 1224611087 -3600 # Node ID c157b27d008350f79d074bc9317372d53aee1fd9 # Parent d5baf90cf1d8f782dcb9c7303c2a458b52ca7756 Add a general purpose sequence number class diff -r d5baf90cf1d8 -r c157b27d0083 src/contrib/seq-num.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/contrib/seq-num.cc Tue Oct 21 18:44:47 2008 +0100 @@ -0,0 +1,104 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ + +#ifdef RUN_SELF_TESTS + +#include "seq-num.h" +#include "ns3/test.h" + + +namespace ns3 { + +class SeqNumTest : public ns3::Test { +private: +public: + SeqNumTest (); + virtual bool RunTests (void); +}; + +SeqNumTest::SeqNumTest () + : ns3::Test ("SeqNum") +{} + +bool +SeqNumTest::RunTests (void) +{ + bool result = true; + + { + SeqNum32 num1 (3), num2 (5); + uint32_t value; + + value = num1 + num2; + NS_TEST_ASSERT_EQUAL (value, 8); + + num1 += num2; + NS_TEST_ASSERT_EQUAL (num1, 8); + + ++num1; + NS_TEST_ASSERT_EQUAL (num1, 9); + + --num1; + NS_TEST_ASSERT_EQUAL (num1, 8); + + num1++; + NS_TEST_ASSERT_EQUAL (num1, 9); + + num1--; + NS_TEST_ASSERT_EQUAL (num1, 8); + + } + + { + SeqNum16 num1 (60900), num2 (5), num3 (10000); + + NS_TEST_ASSERT (num1 == num1); + + NS_TEST_ASSERT (num2 != num1); + + NS_TEST_ASSERT (num3 > num2); + NS_TEST_ASSERT (num3 >= num2); + NS_TEST_ASSERT (num1 < num3); + NS_TEST_ASSERT (num1 <= num3); + + NS_TEST_ASSERT (num1 < num2); + NS_TEST_ASSERT (num1 <= num2); + NS_TEST_ASSERT (num2 > num1); + NS_TEST_ASSERT (num2 >= num1); + + NS_TEST_ASSERT (num1+num2 > num1); + NS_TEST_ASSERT (num1+num2 >= num1); + NS_TEST_ASSERT (num1 < num1+num2); + NS_TEST_ASSERT (num1 <= num1+num2); + + NS_TEST_ASSERT (num1 < num1+num3); + NS_TEST_ASSERT (num1 <= num1+num3); + NS_TEST_ASSERT (num1+num3 > num1); + NS_TEST_ASSERT (num1+num3 >= num1); + } + + { + NS_TEST_ASSERT_EQUAL ((SeqNum16 (1000) + SeqNum16 (6000)) - SeqNum16 (1000), 6000); + NS_TEST_ASSERT_EQUAL ((SeqNum16 (60000) + SeqNum16 (6000)) - SeqNum16 (60000), 6000); + NS_TEST_ASSERT_EQUAL (SeqNum16 (1000) - SeqNum16 (6000), -5000); + NS_TEST_ASSERT_EQUAL ((SeqNum16 (60000) + SeqNum16 (1000)) - SeqNum16 (65000), -4000); + } + + { + SeqNum32 num1 (3); + + NS_TEST_ASSERT_EQUAL (num1 + 10, 13); + num1 += -1; + NS_TEST_ASSERT_EQUAL (num1, 2); + + NS_TEST_ASSERT_EQUAL (num1 - (num1 - 100), 100); + } + + return result; +} + +static SeqNumTest gSeqNumTest; + +}; // namespace + + +#endif /* RUN_SELF_TESTS */ diff -r d5baf90cf1d8 -r c157b27d0083 src/contrib/seq-num.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/contrib/seq-num.h Tue Oct 21 18:44:47 2008 +0100 @@ -0,0 +1,207 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +// +// Copyright (c) 2008 INESC Porto +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as +// published by the Free Software Foundation; +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Author: Gustavo J. A. M. Carneiro +// + +#ifndef __NS3_SEQ_NUM_H__ +#define __NS3_SEQ_NUM_H__ + +#include +#include + +namespace ns3 { + +template +class SeqNum +{ +public: + SeqNum () + : m_value (0) + {} + + explicit SeqNum (NUMERIC_TYPE value) + : m_value (value) + {} + + operator NUMERIC_TYPE () const + { + return m_value; + } + + SeqNum& operator= (NUMERIC_TYPE value) + { + m_value = value; + return *this; + } + + // prefix ++ + SeqNum operator++ () + { + m_value++; + return *this; + } + + // postfix ++ + SeqNum operator++ (int) + { + SeqNum retval (m_value); + m_value++; + return retval; + } + + // prefix -- + SeqNum operator-- () + { + m_value--; + return *this; + } + + // postfix -- + SeqNum operator-- (int) + { + SeqNum retval (m_value); + m_value--; + return retval; + } + + SeqNum& operator+= (SIGNED_TYPE value) + { + m_value += value; + return *this; + } + + SeqNum& operator-= (SIGNED_TYPE value) + { + m_value -= value; + return *this; + } + + SeqNum operator + (const SeqNum &other) + { + return SeqNum (m_value + other.m_value); + } + + + SeqNum operator + (SIGNED_TYPE delta) + { + return SeqNum (m_value + delta); + } + + SeqNum operator - (SIGNED_TYPE delta) + { + return SeqNum (m_value - delta); + } + + + SIGNED_TYPE operator - (const SeqNum &other) + { + static const NUMERIC_TYPE maxValue = std::numeric_limits::max (); + static const NUMERIC_TYPE halfMaxValue = std::numeric_limits::max () / 2; + if (m_value > other.m_value) + { + NUMERIC_TYPE diff = m_value - other.m_value; + if (diff < halfMaxValue) + { + return static_cast (diff); + } + else + { + // |------------|------------| + // ==== === + // ^ ^ + // other.m_value m_value + return -(static_cast (maxValue - m_value + 1 + other.m_value)); + } + } + else + { + NUMERIC_TYPE diff = other.m_value - m_value; + if (diff < halfMaxValue) + { + // |------------|------------| + // ======== + // ^ ^ + // m_value other.m_value + return -(static_cast (diff)); + } + else + { + // |------------|------------| + // ==== === + // ^ ^ + // m_value other.m_value + return static_cast (maxValue - other.m_value + 1 + m_value); + } + } + } + + + // Here is the critical part, how the comparison is made taking into + // account wrap-around. From RFC 3626: + // + // The sequence number S1 is said to be "greater than" the sequence + // number S2 if: + // + // S1 > S2 AND S1 - S2 <= MAXVALUE/2 OR + // + // S2 > S1 AND S2 - S1 > MAXVALUE/2 + bool operator > (const SeqNum &other) + { + static const NUMERIC_TYPE halfMaxValue = std::numeric_limits::max () / 2; + + return (((m_value > other.m_value) && (m_value - other.m_value) <= halfMaxValue) + || ((other.m_value > m_value) && (other.m_value - m_value) > halfMaxValue)); + } + + bool operator == (const SeqNum &other) + { + return (m_value == other.m_value); + } + + bool operator != (const SeqNum &other) + { + return (m_value != other.m_value); + } + + bool operator <= (const SeqNum &other) + { + return (!this->operator> (other)); + } + + bool operator >= (const SeqNum &other) + { + return (this->operator> (other) || this->operator== (other)); + } + + bool operator < (const SeqNum &other) + { + return !this->operator> (other) && m_value != other.m_value; + } + +private: + NUMERIC_TYPE m_value; +}; + +typedef SeqNum SeqNum32; +typedef SeqNum SeqNum16; + +} // namespace ns3 + +#endif + + diff -r d5baf90cf1d8 -r c157b27d0083 src/contrib/wscript --- a/src/contrib/wscript Mon Oct 20 18:59:57 2008 +0100 +++ b/src/contrib/wscript Tue Oct 21 18:44:47 2008 +0100 @@ -21,6 +21,7 @@ 'delay-jitter-estimation.cc', 'attribute-iterator.cc', 'config-store.cc', + 'seq-num.cc', ] headers = bld.create_obj('ns3header') @@ -31,6 +32,7 @@ 'gnuplot.h', 'delay-jitter-estimation.h', 'config-store.h', + 'seq-num.h', ] if bld.env()['ENABLE_GTK_CONFIG_STORE']: