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(const 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  using 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 static_cast<double>(_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*(const hilti::rt::integer::safe<std::int64_t>& i) const {
77  return Interval(_nsecs * i, NanosecondTag());
78  }
79 
80  Interval operator*(const hilti::rt::integer::safe<std::uint64_t>& i) const {
81  return Interval(_nsecs * i.Ref(), NanosecondTag());
82  }
83 
84  Interval operator*(double i) const {
85  return Interval(integer::safe<int64_t>(static_cast<double>(_nsecs.Ref()) * i), NanosecondTag());
86  }
87 
89  explicit operator bool() const { return _nsecs.Ref() != 0; }
90 
92  operator std::string() const {
93  int64_t secs = _nsecs / 1'000'000'000;
94  // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions)
95  double frac = (_nsecs.Ref() % 1'000'000'000) / 1e9;
96  return fmt("%.6fs", static_cast<double>(secs) + frac);
97  }
98 
99 private:
100  integer::safe<int64_t> _nsecs = 0;
101 };
102 
103 namespace detail::adl {
104 inline std::string to_string(const Interval& x, adl::tag /*unused*/) { return x; }
105 
106 } // namespace detail::adl
107 
108 inline std::ostream& operator<<(std::ostream& out, const Interval& x) {
109  out << to_string(x);
110  return out;
111 }
112 
113 } // namespace hilti::rt
Definition: interval.h:22
Definition: any.h:7
Interval(double secs, SecondTag)
Definition: interval.h:42
Definition: interval.h:25
Definition: interval.h:24
Interval(const hilti::rt::integer::safe< int64_t > &nsecs, NanosecondTag)
Definition: interval.h:34