1 // Copyright (C) 2021 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <ditto/logger.h>
16 #include <ditto/sampler.h>
17 
TimespecToNanos(const timespec & t)18 int64_t TimespecToNanos(const timespec& t) {
19   return t.tv_sec * 1e9 + t.tv_nsec;
20 }
21 
TimespecToDoubleNanos(const timespec & t)22 double TimespecToDoubleNanos(const timespec& t) {
23   return static_cast<double>(TimespecToNanos(t));
24 }
25 
TimespecToNanos(const std::vector<timespec> & tv)26 std::vector<int64_t> TimespecToNanos(const std::vector<timespec>& tv) {
27   std::vector<int64_t> nsv;
28   nsv.reserve(tv.size());
29   for (const auto& it : tv) nsv.push_back(TimespecToNanos(it));
30   return nsv;
31 }
32 
TimespecToDoubleNanos(const std::vector<timespec> & tv)33 std::vector<double> TimespecToDoubleNanos(const std::vector<timespec>& tv) {
34   std::vector<double> nsv;
35   nsv.reserve(tv.size());
36   for (const auto& it : tv) nsv.push_back(TimespecToDoubleNanos(it));
37   return nsv;
38 }
39 
NanosToTimespec(const int64_t t_ns)40 timespec NanosToTimespec(const int64_t t_ns) {
41   timespec result;
42   result.tv_sec = t_ns / 1e9;
43   result.tv_nsec = t_ns % static_cast<int64_t>(1e9);
44   return result;
45 }
46 
MicrosToTimespec(const int64_t t_us)47 timespec MicrosToTimespec(const int64_t t_us) {
48   timespec result;
49   result.tv_sec = t_us / 1e6;
50   result.tv_nsec = (t_us % static_cast<int64_t>(1e6)) * static_cast<int64_t>(1e3);
51   return result;
52 }
53 
operator ==(const timespec & t1,const timespec & t2)54 bool operator==(const timespec& t1, const timespec& t2) {
55   return t1.tv_sec == t2.tv_sec && t1.tv_nsec == t2.tv_nsec;
56 }
57 
operator !=(const timespec & t1,const timespec & t2)58 bool operator!=(const timespec& t1, const timespec& t2) {
59   return !(t1 == t2);
60 }
61 
operator <(const timespec & t1,const timespec & t2)62 bool operator<(const timespec& t1, const timespec& t2) {
63   return ((t1.tv_sec < t2.tv_sec) || (t1.tv_sec == t2.tv_sec && t1.tv_nsec < t2.tv_nsec));
64 }
65 
operator <=(const timespec & t1,const timespec & t2)66 bool operator<=(const timespec& t1, const timespec& t2) {
67   return t1 == t2 || t1 < t2;
68 }
69 
operator >(const timespec & t1,const timespec & t2)70 bool operator>(const timespec& t1, const timespec& t2) {
71   return !(t1 <= t2);
72 }
73 
operator >=(const timespec & t1,const timespec & t2)74 bool operator>=(const timespec& t1, const timespec& t2) {
75   return t1 == t2 || t1 > t2;
76 }
77 
78 // Return the value of t1 - t2, if t1 >= t2 or fail.
operator -(const timespec & t1,const timespec & t2)79 timespec operator-(const timespec& t1, const timespec& t2) {
80   timespec result = {0, 0};
81   if (t1 < t2) {
82     LOGF("Subtraction cannot return negative timespec values");
83   } else {
84     result.tv_sec = t1.tv_sec - t2.tv_sec;
85     if (t1.tv_nsec < t2.tv_nsec) {
86       result.tv_sec--;
87       result.tv_nsec = 1e9 - t2.tv_nsec + t1.tv_nsec;
88     } else {
89       result.tv_nsec = t1.tv_nsec - t2.tv_nsec;
90     }
91   }
92   return result;
93 }
94 
operator +(const timespec & t1,const timespec & t2)95 timespec operator+(const timespec& t1, const timespec& t2) {
96   timespec result = {0, 0};
97   result.tv_sec = t1.tv_sec + t2.tv_sec;
98   if (t1.tv_nsec + t2.tv_nsec >= 1e9) {
99     result.tv_sec++;
100     result.tv_nsec = t1.tv_nsec + t2.tv_nsec - 1e9;
101   } else {
102     result.tv_nsec = t1.tv_nsec + t2.tv_nsec;
103   }
104   return result;
105 }
106 
operator /(const timespec & t1,uint64_t t2_ns)107 timespec operator/(const timespec& t1, uint64_t t2_ns) {
108   if (t2_ns == 0) LOGF("Division by 0 for timespec");
109 
110   auto t1_ns = TimespecToNanos(t1);
111 
112   return NanosToTimespec(t1_ns / t2_ns);
113 }
114 
operator /(const timespec & t1,const timespec & t2)115 timespec operator/(const timespec& t1, const timespec& t2) {
116   return t1 / TimespecToNanos(t2);
117 }
118 
TimespecToString(const timespec & ts)119 std::string TimespecToString(const timespec& ts) {
120   std::stringstream ss;
121   ss << ts.tv_sec << '.' << std::setfill('0') << std::setw(9) << ts.tv_nsec;
122   return ss.str();
123 }
124