From 45530120f2d547cbd4dfee72413582ca36d89115 Mon Sep 17 00:00:00 2001 From: "Peter D. Barnes, Jr." Date: Wed, 2 Apr 2014 18:47:04 -0700 Subject: [PATCH] Simplify output of Times in a specific unit; see Time::As () --- RELEASE_NOTES | 1 + src/core/model/nstime.h | 42 ++++++++++++++++ src/core/model/time.cc | 82 +++++++++++++----------------- src/core/test/time-test-suite.cc | 86 +++++++++++++++++++++++++++++++- 4 files changed, 162 insertions(+), 49 deletions(-) diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 137811897..9837883d1 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -22,6 +22,7 @@ Supported platforms New user-visible features ------------------------- +- Simplify output of Times in a specific unit; see Time::As () - Enable selection of high precision int64x64_t implementation at configure time, for debugging purposes. - A new LTE MAC downlink scheduling algorithm named Channel and QoS diff --git a/src/core/model/nstime.h b/src/core/model/nstime.h index 1d6f83f2d..1ca400216 100644 --- a/src/core/model/nstime.h +++ b/src/core/model/nstime.h @@ -33,6 +33,8 @@ namespace ns3 { +class TimeWithUnit; + /** * \ingroup core * \brief Simulation virtual time values and global simulation resolution. @@ -488,6 +490,20 @@ public: return Time (value); } + /** + * Attach a unit to a Time, to facilitate output in a specific unit. + * + * For example, + * \code + * Time t (3.14e9); // Pi seconds + * std::cout << t.As (Time::MS) << std::endl; + * \code + * will print ``+3140.0ms`` + * + * \param unit [in] The unit to use. + */ + TimeWithUnit As (const enum Unit unit) const; + private: /** * How to convert between other units and the current unit @@ -1022,6 +1038,32 @@ Ptr MakeTimeChecker (const Time min) return MakeTimeChecker (min, Time::Max ()); } +/** + * \ingroup time + * \brief A Time with attached unit, to facilitate output in that unit. + */ +class TimeWithUnit +{ +public: + /** + * Attach a unit to a Time + * + * \param [in] time The time. + * \param [in] unit The unit to use for output + */ + TimeWithUnit (const Time time, const Time::Unit unit) + : m_time (time), + m_unit (unit) + { }; + +private: + Time m_time; //!< The time + Time::Unit m_unit; //!< The unit to use in output + + /// Output streamer + friend std::ostream & operator << (std::ostream & os, const TimeWithUnit & time); + +}; // class TimeWithUnit } // namespace ns3 diff --git a/src/core/model/time.cc b/src/core/model/time.cc index 162bbb5c2..027106bf9 100644 --- a/src/core/model/time.cc +++ b/src/core/model/time.cc @@ -380,67 +380,53 @@ Time::GetResolution (void) } +TimeWithUnit +Time::As (const enum Unit unit) const +{ + return TimeWithUnit (*this, unit); +} + + std::ostream& operator<< (std::ostream& os, const Time & time) +{ + os << time.As (Time::GetResolution ()); + return os; +} + + +std::ostream & +operator << (std::ostream & os, const TimeWithUnit & timeU) { std::string unit; - Time::Unit res = Time::GetResolution (); - switch (res) + + switch (timeU.m_unit) { - case Time::S: - unit = "s"; - break; - case Time::MS: - unit = "ms"; - break; - case Time::US: - unit = "us"; - break; - case Time::NS: - unit = "ns"; - break; - case Time::PS: - unit = "ps"; - break; - case Time::FS: - unit = "fs"; - break; - case Time::MIN: - unit = "min"; - break; - case Time::H: - unit = "h"; - break; - case Time::D: - unit = "d"; - break; - case Time::Y: - unit = "y"; - break; + case Time::Y: unit = "y"; break; + case Time::D: unit = "d"; break; + case Time::H: unit = "h"; break; + case Time::MIN: unit = "min"; break; + case Time::S: unit = "s"; break; + case Time::MS: unit = "ms"; break; + case Time::US: unit = "us"; break; + case Time::NS: unit = "ns"; break; + case Time::PS: unit = "ps"; break; + case Time::FS: unit = "fs"; break; + case Time::LAST: + default: NS_ABORT_MSG ("can't be reached"); unit = "unreachable"; break; } - int64_t v = time.ToInteger (res); - std::ios_base::fmtflags ff = os.flags (); - - os << std::setw (0) << std::left; - { // See bug 1737: gcc libstc++ 4.2 bug - if (v == 0) - { - os << '+'; - } - else - { - os << std::showpos; - } - } - os << v << ".0" << unit; - os.flags (ff); // Restore stream flags + int64x64_t v = timeU.m_time.To (timeU.m_unit); + os << v << unit; + return os; } + + std::istream& operator>> (std::istream& is, Time & time) { std::string value; diff --git a/src/core/test/time-test-suite.cc b/src/core/test/time-test-suite.cc index 88b1b8348..1b2053d5e 100644 --- a/src/core/test/time-test-suite.cc +++ b/src/core/test/time-test-suite.cc @@ -19,7 +19,14 @@ * Author: Mathieu Lacage * TimeStep support by Emmanuelle Laprise */ + +#include +#include +#include +#include + #include "ns3/nstime.h" +#include "ns3/int64x64.h" #include "ns3/test.h" using namespace ns3; @@ -150,13 +157,90 @@ TimesWithSignsTestCase::DoTeardown (void) { } + +class TimeIntputOutputTestCase : public TestCase +{ +public: + TimeIntputOutputTestCase (); +private: + virtual void DoRun (void); + void Check (const std::string & str); +}; + +TimeIntputOutputTestCase::TimeIntputOutputTestCase () + : TestCase ("Input,output from,to strings") +{ +} + +void +TimeIntputOutputTestCase::Check (const std::string & str) +{ + std::stringstream ss (str); + Time time; + ss >> time; + ss << time; + bool pass = (str == ss.str ()); + + std::cout << GetParent ()->GetName () << " InputOutput: " + << (pass ? "pass " : "FAIL ") + << "\"" << str << "\""; + if (!pass) + { + std::cout << ", got " << ss.str (); + } + std::cout << std::endl; +} + +void +TimeIntputOutputTestCase::DoRun (void) +{ + std::cout << std::endl; + std::cout << GetParent ()->GetName () << " InputOutput: " << GetName () + << std::endl; + + Check ("2ns"); + Check ("+3.1us"); + Check ("-4.2ms"); + Check ("5.3s"); + Check ("6.4min"); + Check ("7.5h"); + Check ("8.6d"); + Check ("10.8y"); + + Time t (3.141592654e9); // Pi seconds + + std::cout << GetParent ()->GetName () << " InputOutput: " + << "example: raw: " << t + << std::endl; + + std::cout << GetParent ()->GetName () << " InputOutput: " + << std::fixed << std::setprecision (9) + << "example: in s: " << t.As (Time::S) + << std::endl; + + std::cout << GetParent ()->GetName () << " InputOutput: " + << std::setprecision (6) + << "example: in ms: " << t.As (Time::MS) + << std::endl; + + std::cout << GetParent ()->GetName () << " InputOutput: " + << "example: Get ns: " << t.GetNanoSeconds () + << std::endl; + + std::cout << std::endl; +} + static class TimeTestSuite : public TestSuite { public: TimeTestSuite () : TestSuite ("time", UNIT) { - AddTestCase (new TimeSimpleTestCase (), TestCase::QUICK); AddTestCase (new TimesWithSignsTestCase (), TestCase::QUICK); + AddTestCase (new TimeIntputOutputTestCase (), TestCase::QUICK); + // This should be last, since it changes the resolution + AddTestCase (new TimeSimpleTestCase (), TestCase::QUICK); } } g_timeTestSuite; + +