GH-589: improve printing of sub-microsecond intervals

This commit is contained in:
Jon Siwek 2019-09-23 18:12:50 -07:00
parent 916491e2b4
commit f287d9abe8
6 changed files with 137 additions and 51 deletions

View file

@ -666,6 +666,17 @@ IntervalVal::IntervalVal(double quantity, double units) :
void IntervalVal::ValDescribe(ODesc* d) const
{
using unit_word = std::pair<double, const char*>;
constexpr std::array<unit_word, 6> units = {
unit_word{ Days, "day" },
unit_word{ Hours, "hr" },
unit_word{ Minutes, "min" },
unit_word{ Seconds, "sec" },
unit_word{ Milliseconds, "msec" },
unit_word{ Microseconds, "usec" },
};
double v = val.double_val;
if ( v == 0.0 )
@ -674,31 +685,55 @@ void IntervalVal::ValDescribe(ODesc* d) const
return;
}
int did_one = 0;
bool did_one = false;
constexpr auto last_idx = units.size() - 1;
#define DO_UNIT(unit, name) \
if ( v >= unit || v <= -unit ) \
{ \
double num = double(int(v / unit)); \
if ( num != 0.0 ) \
{ \
if ( did_one++ ) \
d->SP(); \
d->Add(num); \
d->SP(); \
d->Add(name); \
if ( num != 1.0 && num != -1.0 ) \
d->Add("s"); \
v -= num * unit; \
} \
auto approx_equal = [](double a, double b, double tolerance = 1e-6) -> bool
{
auto v = a - b;
return v < 0 ? -v < tolerance : v < tolerance;
};
for ( size_t i = 0; i < units.size(); ++i )
{
auto unit = units[i].first;
auto word = units[i].second;
double to_print = 0;
if ( i == last_idx )
{
to_print = v / unit;
if ( approx_equal(to_print, 0) )
{
if ( ! did_one )
d->Add("0 secs");
break;
}
}
else
{
if ( ! (v >= unit || v <= -unit) )
continue;
double num = static_cast<double>(static_cast<int64_t>(v / unit));
v -= num * unit;
to_print = num;
}
if ( did_one )
d->SP();
d->Add(to_print);
d->SP();
d->Add(word);
if ( ! approx_equal(to_print, 1) && ! approx_equal(to_print, -1) )
d->Add("s");
did_one = true;
}
DO_UNIT(Days, "day")
DO_UNIT(Hours, "hr")
DO_UNIT(Minutes, "min")
DO_UNIT(Seconds, "sec")
DO_UNIT(Milliseconds, "msec")
DO_UNIT(Microseconds, "usec")
}
PortVal* PortManager::Get(uint32_t port_num) const