Spicy
interval.h
1 // Copyright (c) 2020-2021 by the Zeek Project. See LICENSE for details.
2 
3 #pragma once
4 
5 #include <arpa/inet.h>
6 
7 #include <limits>
8 #include <memory>
9 #include <string>
10 #include <variant>
11 
12 #include <hilti/rt/extension-points.h>
13 #include <hilti/rt/fmt.h>
14 #include <hilti/rt/safe-int.h>
15 
16 namespace hilti::rt {
17 
22 class Interval {
23 public:
24  struct SecondTag {};
25  struct NanosecondTag {};
26 
27  Interval() = default;
28 
34  explicit Interval(hilti::rt::integer::safe<int64_t> nsecs, NanosecondTag /*unused*/) : _nsecs(nsecs) {}
35 
42  explicit Interval(double secs, SecondTag /*unused*/)
43  : _nsecs([&]() {
44  auto x = secs * 1'000'000'000;
45 
46  constexpr auto limits = std::numeric_limits<int64_t>();
47  if ( x < static_cast<double>(limits.min()) || static_cast<double>(limits.max()) < x )
48  throw OutOfRange("value cannot be represented as an interval");
49 
50  return integer::safe<int64_t>(x);
51  }()) {}
52 
53  Interval(const Interval&) = default;
54  Interval(Interval&&) noexcept = default;
55  ~Interval() = default;
56 
57  Interval& operator=(const Interval&) = default;
58  Interval& operator=(Interval&&) noexcept = default;
59 
61  double seconds() const { return _nsecs.Ref() / 1e9; }
62 
64  int64_t nanoseconds() const { return _nsecs.Ref(); }
65 
66  bool operator==(const Interval& other) const { return _nsecs == other._nsecs; }
67  bool operator!=(const Interval& other) const { return _nsecs != other._nsecs; }
68  bool operator<(const Interval& other) const { return _nsecs < other._nsecs; }
69  bool operator<=(const Interval& other) const { return _nsecs <= other._nsecs; }
70  bool operator>(const Interval& other) const { return _nsecs > other._nsecs; }
71  bool operator>=(const Interval& other) const { return _nsecs >= other._nsecs; }
72 
73  Interval operator+(const Interval& other) const { return Interval(_nsecs + other._nsecs, NanosecondTag()); }
74  Interval operator-(const Interval& other) const { return Interval(_nsecs - other._nsecs, NanosecondTag()); }
75 
76  Interval operator*(hilti::rt::integer::safe<std::int64_t> i) const { return Interval(_nsecs * i, NanosecondTag()); }
77 
78  Interval operator*(hilti::rt::integer::safe<std::uint64_t> i) const {
79  return Interval(_nsecs * i.Ref(), NanosecondTag());
80  }
81 
82  Interval operator*(double i) const { return Interval(integer::safe<int64_t>(_nsecs.Ref() * i), NanosecondTag()); }
83 
85  explicit operator bool() const { return _nsecs.Ref() != 0; }
86 
88  operator std::string() const {
89  int64_t secs = _nsecs / 1'000'000'000;
90  // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions)
91  double frac = (_nsecs.Ref() % 1'000'000'000) / 1e9;
92  return fmt("%.6fs", static_cast<double>(secs) + frac);
93  }
94 
95 private:
96  integer::safe<int64_t> _nsecs = 0;
97 };
98 
99 namespace detail::adl {
100 inline std::string to_string(const Interval& x, adl::tag /*unused*/) { return x; }
101 
102 } // namespace detail::adl
103 
104 inline std::ostream& operator<<(std::ostream& out, const Interval& x) {
105  out << to_string(x);
106  return out;
107 }
108 
109 } // namespace hilti::rt
Definition: interval.h:22
Definition: any.h:7
Interval(hilti::rt::integer::safe< int64_t > nsecs, NanosecondTag)
Definition: interval.h:34
Interval(double secs, SecondTag)
Definition: interval.h:42
Definition: interval.h:25
Definition: interval.h:24