Line data Source code
1 : // Copyright (c) 2021 Made to Order Software Corp. All Rights Reserved
2 : //
3 : // https://snapwebsites.org/project/snapdev
4 : // contact@m2osw.com
5 : //
6 : // This program is free software; you can redistribute it and/or modify
7 : // it under the terms of the GNU General Public License as published by
8 : // the Free Software Foundation; either version 2 of the License, or
9 : // (at your option) any later version.
10 : //
11 : // This program is distributed in the hope that it will be useful,
12 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : // GNU General Public License for more details.
15 : //
16 : // You should have received a copy of the GNU General Public License along
17 : // with this program; if not, write to the Free Software Foundation, Inc.,
18 : // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 : #pragma once
20 :
21 : // C++ lib
22 : //
23 : #include <cmath>
24 : #include <cstdint>
25 : #include <iomanip>
26 : #include <iostream>
27 : #include <sstream>
28 :
29 :
30 : // C lib
31 : //
32 : #include <stdlib.h>
33 : #include <sys/time.h>
34 :
35 :
36 :
37 :
38 7 : inline bool valid_timespec(timespec const & t)
39 : {
40 7 : return t.tv_nsec < 1'000'000'000LL;
41 : }
42 :
43 :
44 64 : inline bool negative_timespec(timespec const & t)
45 : {
46 64 : return t.tv_sec < 0LL;
47 : }
48 :
49 :
50 44 : inline timespec operator - (timespec const & t)
51 : {
52 : // equivalen to `0 - t`
53 : //
54 44 : timespec result{ -t.tv_sec, -t.tv_nsec };
55 44 : if(result.tv_nsec < 0)
56 : {
57 43 : --result.tv_sec;
58 43 : result.tv_nsec += 1'000'000'000L;
59 : }
60 44 : return result;
61 : }
62 :
63 :
64 29 : inline timespec add_timespec(timespec const & lhs, timespec const & rhs)
65 : {
66 29 : bool const lneg(negative_timespec(lhs));
67 29 : bool const rneg(negative_timespec(rhs));
68 :
69 29 : timespec lp(lneg ? -lhs : lhs);
70 29 : timespec rp(rneg ? -rhs : rhs);
71 :
72 29 : timespec result = {};
73 :
74 29 : switch((lneg ? 1 : 0) + (rneg ? 2 : 0))
75 : {
76 12 : case 0: // positive + positive
77 12 : result.tv_sec = lp.tv_sec + rp.tv_sec;
78 12 : result.tv_nsec = lp.tv_nsec + rp.tv_nsec;
79 12 : break;
80 :
81 5 : case 1: // negative + positive
82 5 : result.tv_sec = rp.tv_sec - lp.tv_sec;
83 5 : result.tv_nsec = rp.tv_nsec - lp.tv_nsec;
84 5 : break;
85 :
86 10 : case 2: // positive + negative
87 10 : result.tv_sec = lp.tv_sec - rp.tv_sec;
88 10 : result.tv_nsec = lp.tv_nsec - rp.tv_nsec;
89 10 : break;
90 :
91 2 : case 3: // negative + negative
92 2 : result.tv_sec = lp.tv_sec + rp.tv_sec;
93 2 : result.tv_nsec = lp.tv_nsec + rp.tv_nsec;
94 2 : break;
95 :
96 : }
97 :
98 29 : if(result.tv_nsec < 0)
99 : {
100 3 : --result.tv_sec;
101 3 : result.tv_nsec += 1'000'000'000L;
102 : }
103 26 : else if(result.tv_nsec >= 1'000'000'000)
104 : {
105 5 : ++result.tv_sec;
106 5 : result.tv_nsec -= 1'000'000'000;
107 : }
108 :
109 29 : if(lneg && rneg)
110 : {
111 2 : result = -result;
112 : }
113 :
114 29 : return result;
115 : }
116 :
117 :
118 : // This one is not possible as a static function
119 : //inline operator bool (timespec const & t)
120 : //{
121 : // return t.tv_sec != 0 || tv.tv_nsec != 0;
122 : //}
123 :
124 :
125 11 : inline bool operator ! (timespec const & t)
126 : {
127 11 : return t.tv_sec == 0 && t.tv_nsec == 0;
128 : }
129 :
130 :
131 26 : inline timespec & operator <<= (timespec & lhs, std::int64_t nsec)
132 : {
133 26 : bool const neg(nsec < 0);
134 26 : if(neg)
135 : {
136 9 : nsec = -nsec;
137 : }
138 26 : lhs.tv_sec = static_cast<time_t>(nsec / 1'000'000'000LL);
139 26 : lhs.tv_nsec = static_cast<long>(llabs(nsec) % 1'000'000'000LL);
140 26 : if(neg)
141 : {
142 9 : lhs = -lhs;
143 : }
144 26 : return lhs;
145 : }
146 :
147 :
148 1 : inline std::int64_t operator >>= (timespec & t, std::int64_t & nsec)
149 : {
150 1 : nsec = t.tv_sec * 1'000'000'000LL + t.tv_nsec;
151 1 : return nsec;
152 : }
153 :
154 :
155 16 : inline timespec & operator <<= (timespec & lhs, double sec)
156 : {
157 16 : bool const neg(sec < 0.0);
158 16 : if(neg)
159 : {
160 1 : sec = -sec;
161 : }
162 16 : lhs.tv_sec = static_cast<time_t>(floor(sec));
163 16 : lhs.tv_nsec = static_cast<long>((sec - floor(sec)) * 1.0e9);
164 16 : if(neg)
165 : {
166 1 : lhs = -lhs;
167 : }
168 16 : return lhs;
169 : }
170 :
171 :
172 6 : inline std::int64_t operator >>= (timespec & t, double & nsec)
173 : {
174 6 : nsec = t.tv_sec + t.tv_nsec / 1'000'000'000.0;
175 6 : return nsec;
176 : }
177 :
178 :
179 19 : inline timespec & operator += (timespec & lhs, timespec const & rhs)
180 : {
181 19 : lhs = add_timespec(lhs, rhs);
182 19 : return lhs;
183 : }
184 :
185 :
186 6 : inline timespec & operator += (timespec & lhs, std::int64_t rhs)
187 : {
188 6 : timespec t;
189 6 : t <<= rhs;
190 6 : lhs += t;
191 6 : return lhs;
192 : }
193 :
194 :
195 1 : inline timespec & operator += (timespec & lhs, double rhs)
196 : {
197 1 : timespec t;
198 1 : t <<= rhs;
199 1 : lhs += t;
200 1 : return lhs;
201 : }
202 :
203 :
204 3 : inline timespec & operator ++ (timespec & lhs)
205 : {
206 3 : lhs += 1L;
207 3 : return lhs;
208 : }
209 :
210 :
211 1 : inline timespec operator ++ (timespec & lhs, int)
212 : {
213 1 : timespec result(lhs);
214 1 : lhs += 1L;
215 1 : return result;
216 : }
217 :
218 :
219 4 : inline timespec operator + (timespec const & lhs, timespec const & rhs)
220 : {
221 4 : timespec result(lhs);
222 4 : result += rhs;
223 4 : return result;
224 : }
225 :
226 :
227 2 : inline timespec operator + (timespec const & lhs, std::int64_t rhs)
228 : {
229 2 : timespec result;
230 2 : result <<= rhs;
231 2 : result += lhs;
232 2 : return result;
233 : }
234 :
235 :
236 1 : inline timespec operator + (timespec const & lhs, double rhs)
237 : {
238 1 : timespec result;
239 1 : result <<= rhs;
240 1 : result += lhs;
241 1 : return result;
242 : }
243 :
244 :
245 10 : inline timespec & operator -= (timespec & lhs, timespec const & rhs)
246 : {
247 10 : timespec const neg(-rhs);
248 10 : lhs = add_timespec(lhs, neg);
249 10 : return lhs;
250 : }
251 :
252 :
253 4 : inline timespec & operator -= (timespec & lhs, std::int64_t rhs)
254 : {
255 4 : timespec result;
256 4 : result <<= rhs;
257 4 : lhs -= result;
258 4 : return lhs;
259 : }
260 :
261 :
262 1 : inline timespec & operator -= (timespec & lhs, double rhs)
263 : {
264 1 : timespec result;
265 1 : result <<= rhs;
266 1 : lhs -= result;
267 1 : return lhs;
268 : }
269 :
270 :
271 3 : inline timespec & operator -- (timespec & lhs)
272 : {
273 3 : lhs -= 1L;
274 3 : return lhs;
275 : }
276 :
277 :
278 1 : inline timespec operator -- (timespec & lhs, int)
279 : {
280 1 : timespec result(lhs);
281 1 : lhs -= 1L;
282 1 : return result;
283 : }
284 :
285 :
286 3 : inline timespec operator - (timespec const & lhs, timespec const & rhs)
287 : {
288 3 : timespec result(lhs);
289 3 : result -= rhs;
290 3 : return result;
291 : }
292 :
293 :
294 1 : inline timespec operator - (timespec const & lhs, std::int64_t rhs)
295 : {
296 1 : timespec result;
297 1 : result <<= -rhs;
298 1 : result += lhs;
299 1 : return result;
300 : }
301 :
302 :
303 1 : inline timespec operator - (timespec const & lhs, double rhs)
304 : {
305 1 : timespec result;
306 1 : result <<= -rhs;
307 1 : result += lhs;
308 1 : return result;
309 : }
310 :
311 :
312 96 : int compare_timespec(timespec const & lhs, timespec const & rhs)
313 : {
314 96 : if(lhs.tv_sec == rhs.tv_sec)
315 : {
316 85 : return lhs.tv_nsec == rhs.tv_nsec
317 112 : ? 0
318 112 : : (lhs.tv_nsec < rhs.tv_nsec ? -1 : 1);
319 : }
320 :
321 11 : return lhs.tv_sec < rhs.tv_sec ? -1 : 1;
322 : }
323 :
324 :
325 19 : inline bool operator == (timespec const & lhs, timespec const & rhs)
326 : {
327 19 : return compare_timespec(lhs, rhs) == 0;
328 : }
329 :
330 :
331 2 : inline bool operator == (timespec const & lhs, std::int64_t rhs)
332 : {
333 2 : timespec t;
334 2 : t <<= rhs;
335 2 : return compare_timespec(lhs, t) == 0;
336 : }
337 :
338 :
339 2 : inline bool operator == (timespec const & lhs, double rhs)
340 : {
341 2 : timespec t;
342 2 : t <<= rhs;
343 2 : return compare_timespec(lhs, t) == 0;
344 : }
345 :
346 :
347 11 : inline bool operator != (timespec const & lhs, timespec const & rhs)
348 : {
349 11 : return compare_timespec(lhs, rhs) != 0;
350 : }
351 :
352 :
353 2 : inline bool operator != (timespec const & lhs, std::int64_t rhs)
354 : {
355 2 : timespec t;
356 2 : t <<= rhs;
357 2 : return compare_timespec(lhs, t) != 0;
358 : }
359 :
360 :
361 2 : inline bool operator != (timespec const & lhs, double rhs)
362 : {
363 2 : timespec t;
364 2 : t <<= rhs;
365 2 : return compare_timespec(lhs, t) != 0;
366 : }
367 :
368 :
369 11 : inline bool operator < (timespec const & lhs, timespec const & rhs)
370 : {
371 11 : return compare_timespec(lhs, rhs) == -1;
372 : }
373 :
374 :
375 2 : inline bool operator < (timespec const & lhs, std::int64_t rhs)
376 : {
377 2 : timespec t;
378 2 : t <<= rhs;
379 2 : return compare_timespec(lhs, t) == -1;
380 : }
381 :
382 :
383 1 : inline bool operator < (timespec const & lhs, double rhs)
384 : {
385 1 : timespec t;
386 1 : t <<= rhs;
387 1 : return compare_timespec(lhs, t) == -1;
388 : }
389 :
390 :
391 11 : inline bool operator <= (timespec const & lhs, timespec const & rhs)
392 : {
393 11 : return compare_timespec(lhs, rhs) <= 0;
394 : }
395 :
396 :
397 2 : inline bool operator <= (timespec const & lhs, std::int64_t rhs)
398 : {
399 2 : timespec t;
400 2 : t <<= rhs;
401 2 : return compare_timespec(lhs, t) <= 0;
402 : }
403 :
404 :
405 2 : inline bool operator <= (timespec const & lhs, double rhs)
406 : {
407 2 : timespec t;
408 2 : t <<= rhs;
409 2 : return compare_timespec(lhs, t) <= 0;
410 : }
411 :
412 :
413 11 : inline bool operator > (timespec const & lhs, timespec const & rhs)
414 : {
415 11 : return compare_timespec(lhs, rhs) == 1;
416 : }
417 :
418 :
419 2 : inline bool operator > (timespec const & lhs, std::int64_t rhs)
420 : {
421 2 : timespec t;
422 2 : t <<= rhs;
423 2 : return compare_timespec(lhs, t) == 1;
424 : }
425 :
426 :
427 1 : inline bool operator > (timespec const & lhs, double rhs)
428 : {
429 1 : timespec t;
430 1 : t <<= rhs;
431 1 : return compare_timespec(lhs, t) == 1;
432 : }
433 :
434 :
435 11 : inline bool operator >= (timespec const & lhs, timespec const & rhs)
436 : {
437 11 : return compare_timespec(lhs, rhs) >= 0;
438 : }
439 :
440 :
441 2 : inline bool operator >= (timespec const & lhs, std::int64_t rhs)
442 : {
443 2 : timespec t;
444 2 : t <<= rhs;
445 2 : return compare_timespec(lhs, t) >= 0;
446 : }
447 :
448 :
449 2 : inline bool operator >= (timespec const & lhs, double rhs)
450 : {
451 2 : timespec t;
452 2 : t <<= rhs;
453 2 : return compare_timespec(lhs, t) >= 0;
454 : }
455 :
456 :
457 : /** \brief Output a timespec to a basic_ostream.
458 : *
459 : * This function allows one to print out a timespec. By default the function
460 : * prints the timespec as a floating point.
461 : *
462 : * \todo
463 : * Look into the possibility to write the data as Y/M/D H:M:S.nanosecs
464 : *
465 : * \param[in] out The output stream where the timespec gets written.
466 : * \param[in] t The actual timespec that is to be printed.
467 : *
468 : * \return A reference to the basic_ostream object.
469 : */
470 : template<class E, class S>
471 3 : std::basic_ostream<E, S> & operator << (std::basic_ostream<E, S> & out, timespec const & t)
472 : {
473 : // write to a string buffer first
474 : //
475 6 : std::basic_ostringstream<E, S, std::allocator<E> > s;
476 :
477 : // setup the string output like the out stream
478 : //
479 3 : s.flags(out.flags());
480 3 : s.imbue(out.getloc());
481 3 : s.precision(out.precision());
482 3 : s << t.tv_sec << "." << std::setw(9) << std::setfill('0') << t.tv_nsec;
483 :
484 : // buffer is ready, display in output in one go
485 : //
486 6 : return out << s.str();
487 : }
488 :
489 :
490 :
491 :
492 : // vim: ts=4 sw=4 et
|