Commit | Line | Data |
---|---|---|
0e23f538 TJ |
1 | /* |
2 | The software in this package is distributed under the GNU General | |
3 | Public License version 2 (with a special exception described below). | |
4 | ||
5 | A copy of GNU General Public License (GPL) is included in this distribution, | |
6 | in the file COPYING.GPL. | |
7 | ||
8 | As a special exception, if other files instantiate templates or use macros | |
9 | or inline functions from this file, or you compile this file and link it | |
10 | with other works to produce a work based on this file, this file | |
11 | does not by itself cause the resulting work to be covered | |
12 | by the GNU General Public License. | |
13 | ||
14 | However the source code for this file must still be made available | |
15 | in accordance with section (3) of the GNU General Public License. | |
16 | ||
17 | This exception does not invalidate any other reasons why a work based | |
18 | on this file might be covered by the GNU General Public License. | |
19 | */ | |
1b5dfd98 TJ |
20 | /** @file |
21 | * @brief time related functions. | |
22 | * | |
23 | * @copyright Copyright © 2001-2008 by Intra2net AG | |
1b5dfd98 TJ |
24 | * |
25 | */ | |
26 | ||
e93545dd GE |
27 | #include <string> |
28 | #include <sstream> | |
29 | #include <iostream> | |
30 | #include <iomanip> | |
f1499910 GE |
31 | #include <bitset> |
32 | #include <stdexcept> | |
1b5dfd98 TJ |
33 | #include <iterator> |
34 | #include <algorithm> | |
e93545dd GE |
35 | |
36 | #include <time.h> | |
96d0be2e | 37 | #include <unistd.h> |
5efd35b1 | 38 | #include <string.h> |
e93545dd GE |
39 | #include <sys/timeb.h> |
40 | ||
41 | #include <timefunc.hxx> | |
42 | #include <i18n.h> | |
43 | ||
96d0be2e TJ |
44 | |
45 | // define missing POSIX.1b constants... | |
46 | ||
47 | #ifndef CLOCK_REALTIME | |
48 | #define CLOCK_REALTIME 0 | |
49 | #endif | |
50 | #ifndef CLOCK_MONOTONIC | |
51 | #define CLOCK_MONOTONIC 1 | |
52 | #endif | |
53 | ||
54 | ||
55 | ||
e93545dd GE |
56 | using namespace std; |
57 | ||
58 | double prec_time(void) | |
59 | { | |
60 | struct timeb tb; | |
61 | double ret; | |
62 | ||
63 | ftime(&tb); | |
64 | ||
65 | ret=tb.time+(static_cast<float>(tb.millitm)/1000); | |
66 | ||
67 | return ret; | |
68 | } | |
69 | ||
70 | // converts ISO-DATE: 2003-06-13 | |
dad9e26f | 71 | time_t date_to_seconds(const std::string &date) |
e93545dd | 72 | { |
dad9e26f GE |
73 | time_t rtn = 0; |
74 | int year = -1, month = -1, day = -1; | |
e93545dd GE |
75 | |
76 | string::size_type pos = date.find("-"); | |
77 | if (pos == string::npos) | |
78 | return rtn; | |
79 | ||
80 | istringstream in(string(date,0,pos)); | |
81 | in >> year; | |
82 | year -= 1900; | |
83 | ||
84 | string dstr(date, pos+1); | |
85 | if ((pos = dstr.find("-")) == string::npos) | |
86 | return rtn; | |
87 | ||
88 | in.clear(); | |
89 | in.str(string(dstr, 0, pos)); | |
90 | in >> month; | |
91 | month -= 1; | |
92 | ||
93 | in.clear(); | |
94 | in.str(string(dstr, pos+1)); | |
95 | in >> day; | |
96 | ||
97 | if (year < 0 || month == -1 || day == -1) | |
98 | return rtn; | |
4cf3676b | 99 | |
e93545dd | 100 | struct tm tm_struct; |
4cf3676b | 101 | memset(&tm_struct, 0, sizeof(struct tm)); |
e93545dd GE |
102 | tm_struct.tm_year = year; |
103 | tm_struct.tm_mon = month; | |
104 | tm_struct.tm_mday = day; | |
105 | tm_struct.tm_isdst = -1; | |
106 | ||
107 | rtn = mktime (&tm_struct); | |
108 | return rtn; | |
109 | } | |
110 | ||
111 | string make_nice_time(int seconds) | |
112 | { | |
113 | ostringstream out; | |
114 | ||
115 | int days=seconds/86400; | |
116 | seconds%=86400; | |
117 | ||
c0368918 GE |
118 | int hours,minutes; |
119 | split_daysec(seconds,&hours,&minutes,&seconds); | |
120 | ||
c7bd7a65 CH |
121 | if (days>0) |
122 | out << days << " " << i18n_plural("day", "days", days) << ", "; | |
e93545dd GE |
123 | |
124 | out << setfill('0'); | |
125 | out << setw(2) << hours << ':' << setw(2) << minutes << ':' << setw(2) << seconds; | |
126 | ||
127 | return out.str(); | |
128 | } | |
129 | ||
7839bd53 | 130 | string format_full_time(time_t seconds) |
e93545dd GE |
131 | { |
132 | char buf[50]; | |
133 | memset (buf, 0, 50); | |
532d6b3a TJ |
134 | struct tm ta; |
135 | if (localtime_r((time_t *)&seconds, &ta) == NULL) | |
136 | memset (&ta, 0, sizeof(struct tm)); | |
e93545dd | 137 | |
532d6b3a | 138 | strftime (buf, 49, "%d.%m.%Y %H:%M", &ta); |
e93545dd GE |
139 | return string(buf); |
140 | } | |
f1499910 | 141 | |
25f3d405 CH |
142 | string format_date(time_t seconds) |
143 | { | |
144 | char buf[50]; | |
145 | memset (buf, 0, 50); | |
146 | struct tm ta; | |
147 | if (localtime_r((time_t *)&seconds, &ta) == NULL) | |
148 | memset (&ta, 0, sizeof(struct tm)); | |
149 | ||
150 | strftime (buf, 49, "%d.%m.%Y", &ta); | |
151 | return string(buf); | |
152 | } | |
153 | ||
87869870 GE |
154 | void seconds_to_hour_minute(int seconds, int *hour, int *minute) |
155 | { | |
156 | if (hour != NULL) { | |
157 | *hour = 0; | |
158 | while (seconds >= 3600) { | |
159 | seconds-=3600; | |
160 | (*hour)++; | |
161 | } | |
162 | } | |
163 | ||
164 | if (minute != NULL) { | |
165 | *minute = 0; | |
166 | while (seconds >= 60) { | |
167 | seconds-=60; | |
168 | (*minute)++; | |
169 | } | |
170 | } | |
171 | } | |
172 | ||
c0368918 GE |
173 | /** |
174 | * Split seconds into hours, minutes and seconds | |
175 | * @param [in] daysec Seconds since start of day | |
176 | * @param [out] outhours hours | |
177 | * @param [out] outminutes minutes | |
178 | * @param [out] outseconds seconds | |
179 | */ | |
180 | void split_daysec(int daysec, int *outhours, int *outminutes, int *outseconds) | |
181 | { | |
182 | int hours=daysec/3600; | |
183 | daysec%=3600; | |
184 | ||
185 | int minutes=daysec/60; | |
186 | daysec%=60; | |
187 | ||
188 | if (outhours) | |
189 | *outhours=hours; | |
190 | ||
191 | if (outminutes) | |
192 | *outminutes=minutes; | |
193 | ||
194 | if (outseconds) | |
195 | *outseconds=daysec; | |
196 | } | |
197 | ||
198 | std::string output_hour_minute(int hour, int minute, bool h_for_00, int seconds) | |
2c66f490 GE |
199 | { |
200 | ostringstream out; | |
201 | ||
202 | if (hour >= 0 && hour < 10) | |
203 | out << '0'; | |
204 | out << hour; | |
205 | ||
c0368918 | 206 | if (!h_for_00 || minute != 0 || seconds > 0) |
2c66f490 GE |
207 | { |
208 | out << ':'; | |
fe223928 | 209 | if (minute >= 0 && minute < 10) |
2c66f490 GE |
210 | out << '0'; |
211 | out << minute; | |
212 | } | |
213 | else | |
214 | out << 'h'; | |
215 | ||
c0368918 GE |
216 | if (seconds > 0) |
217 | { | |
218 | out << ':'; | |
219 | if (seconds > 0 && seconds < 10) | |
220 | out << '0'; | |
221 | out << seconds; | |
222 | } | |
223 | ||
2c66f490 GE |
224 | return out.str(); |
225 | } | |
4e157d1d TJ |
226 | |
227 | string get_month_name(unsigned char month) | |
228 | { | |
229 | string rtn; | |
230 | switch(month) { | |
231 | case 1: | |
232 | rtn = i18n("January"); | |
233 | break; | |
234 | case 2: | |
235 | rtn = i18n("February"); | |
236 | break; | |
237 | case 3: | |
238 | rtn = i18n("March"); | |
239 | break; | |
240 | case 4: | |
241 | rtn = i18n("April"); | |
242 | break; | |
243 | case 5: | |
244 | rtn = i18n("May"); | |
245 | break; | |
246 | case 6: | |
247 | rtn = i18n("June"); | |
248 | break; | |
249 | case 7: | |
250 | rtn = i18n("July"); | |
251 | break; | |
252 | case 8: | |
253 | rtn = i18n("August"); | |
254 | break; | |
255 | case 9: | |
256 | rtn = i18n("September"); | |
257 | break; | |
258 | case 10: | |
259 | rtn = i18n("October"); | |
260 | break; | |
261 | case 11: | |
262 | rtn = i18n("November"); | |
263 | break; | |
264 | case 12: | |
265 | rtn = i18n("December"); | |
266 | break; | |
267 | default: | |
268 | { | |
269 | ostringstream out; | |
270 | out << i18n("Illegal month:") << " " << month; | |
271 | rtn = out.str(); | |
272 | } | |
273 | } | |
274 | ||
275 | return rtn; | |
276 | } | |
1b5dfd98 TJ |
277 | |
278 | ||
279 | /* | |
280 | ** implementaion of Interval | |
281 | */ | |
282 | ||
d181c3bc TJ |
283 | |
284 | /** | |
285 | * @brief clears the interval (make it empty). | |
286 | */ | |
287 | void Interval::clear() | |
288 | { | |
289 | m_lower_bound = m_upper_bound = 0; | |
290 | } // eo Interval::clear() | |
291 | ||
292 | ||
1b5dfd98 TJ |
293 | /** |
294 | * @brief tests if there is some overlapping with another interval | |
295 | * @param other the other interval | |
296 | * @return @a true if the two intervals have a non empty intersection. | |
297 | */ | |
298 | bool Interval::intersects(const Interval& other) const | |
299 | { | |
300 | return | |
301 | // // other start within this: | |
302 | (other.m_lower_bound >= m_lower_bound and other.m_lower_bound < m_upper_bound ) | |
303 | // // other end within this: | |
304 | or (other.m_upper_bound > m_lower_bound and other.m_upper_bound <= m_upper_bound ) | |
305 | // // other contains this | |
306 | or (other.m_lower_bound <= m_lower_bound and other.m_upper_bound >= m_upper_bound ) | |
307 | ; | |
308 | } // eo Interval::intersects(const Interval&) | |
309 | ||
310 | ||
311 | /** | |
312 | * @brief tests if the current interval (fully) contains another one. | |
313 | * @param other the other interval. | |
314 | * @return @a true if the current interval fully contains the other interval. | |
315 | */ | |
316 | bool Interval::contains(const Interval& other) const | |
317 | { | |
318 | return (other.m_lower_bound >= m_lower_bound) | |
319 | and (other.m_upper_bound <= m_upper_bound) | |
320 | ; | |
321 | } // eo Interval::contains(const Interval& other) const | |
322 | ||
323 | ||
324 | /* | |
325 | ** implementation of Intervals: | |
326 | */ | |
327 | ||
328 | ||
329 | Intervals::Intervals() | |
330 | { | |
331 | } // eo Intervals::Intervals | |
332 | ||
333 | ||
d181c3bc TJ |
334 | void Intervals::clear() |
335 | { | |
336 | m_intervals.clear(); | |
337 | } // eo Intervals::clear() | |
338 | ||
1b5dfd98 TJ |
339 | /** |
340 | * @brief tests if one of the intervals of the list intersects with the given interval. | |
341 | * @param other the interval to check for intersection. | |
342 | * @return @a true if there is an intersection. | |
343 | */ | |
344 | bool Intervals::intersects(const Interval& other) const | |
345 | { | |
346 | for(const_iterator it= begin(); | |
347 | it != end(); | |
348 | ++it) | |
349 | { | |
350 | if ( it->intersects(other) ) | |
351 | { | |
352 | return true; | |
353 | } | |
354 | } | |
355 | return false; | |
356 | } // eo Intervals::intersects(const Interval&) const | |
357 | ||
358 | ||
359 | /** | |
360 | * @brief tests if we have at least one intersection with another Intervals instance. | |
361 | * @param other the other instance. | |
362 | * @return @a true if there is an intersection. | |
363 | */ | |
364 | bool Intervals::intersects(const Intervals& other) const | |
365 | { | |
366 | for(const_iterator it= begin(); | |
367 | it != end(); | |
368 | ++it) | |
369 | { | |
370 | if ( other.intersects( *it ) ) | |
371 | { | |
372 | return true; | |
373 | } | |
374 | } | |
375 | return false; | |
376 | } // eo Intervals::intersects(const Intervals&) const | |
377 | ||
378 | ||
379 | /** | |
380 | * @brief adds a new interval to the list. | |
381 | * @param new_frame the new interval. | |
382 | * | |
383 | * Adds the interval to the list and joins overlapping intervals. | |
ebc3b584 TJ |
384 | * |
385 | * @internal complexity O(n). | |
1b5dfd98 TJ |
386 | */ |
387 | void Intervals::add(const Interval& new_frame) | |
388 | { | |
389 | if (not new_frame.is_valid() or new_frame.empty()) | |
390 | { | |
391 | // well... we will not insert invalid or empty frames! | |
392 | return; | |
393 | } | |
394 | for (IntervalList::iterator it= m_intervals.begin(); | |
395 | it != m_intervals.end(); | |
396 | ++it) | |
397 | { | |
398 | Interval& current_frame = *it; | |
399 | if ( new_frame.m_lower_bound > current_frame.m_upper_bound ) | |
400 | { | |
401 | // new_frame begins later than current end; go on: | |
402 | continue; | |
403 | } | |
404 | // at this point: the begin of the new frame is less then the current end. | |
405 | // now let's determine how we can insert the new frame: | |
406 | ||
407 | if ( new_frame.m_upper_bound < current_frame.m_lower_bound ) | |
408 | { | |
409 | // new disjoint frame; insert it before the current frame: | |
410 | m_intervals.insert( it, new_frame ); | |
411 | // and we are done. | |
412 | return; | |
413 | } | |
414 | // at this point: the end of the new frame is >= current begin. | |
415 | if ( new_frame.m_upper_bound <= current_frame.m_upper_bound ) | |
416 | { | |
417 | // the end of the new frame is within our current frame; we need to combine | |
418 | if (new_frame.m_lower_bound < current_frame.m_lower_bound) | |
419 | { | |
420 | // the new interval starts earlier; we need to adjust our current frame: | |
421 | current_frame.m_lower_bound = new_frame.m_lower_bound; | |
80f30818 | 422 | current_frame.m_changed = true; |
1b5dfd98 TJ |
423 | } |
424 | // NOTE no "else" part needed since in that case our current frame already | |
425 | // contains the new one! | |
426 | ||
427 | // we are done: | |
428 | return; | |
429 | } | |
430 | // at this point: end of new frame > end of current frame | |
431 | // so we need to extend the current frame; at least the end. | |
432 | // But we need to deal with intersects of following frames... *sigh* | |
433 | ||
434 | // first the simple part: let's see if we need to move the start: | |
435 | if ( new_frame.m_lower_bound < current_frame.m_lower_bound) | |
436 | { | |
437 | // yes, we need to move the start: | |
438 | current_frame.m_lower_bound = new_frame.m_lower_bound; | |
80f30818 | 439 | current_frame.m_changed= true; |
1b5dfd98 TJ |
440 | } |
441 | ||
442 | // now let's extend the end: | |
443 | current_frame.m_upper_bound = new_frame.m_upper_bound; | |
80f30818 | 444 | current_frame.m_changed = true; |
1b5dfd98 TJ |
445 | |
446 | // well... let's walk through the following frames; looking for more joins...: | |
447 | IntervalList::iterator it2 = it; | |
448 | while( ++(it2=it) != m_intervals.end() | |
449 | and current_frame.m_upper_bound >= it2->m_lower_bound | |
450 | ) | |
451 | { | |
452 | Interval next_frame= *it2; | |
453 | if ( current_frame.m_upper_bound < next_frame.m_upper_bound ) | |
454 | { | |
455 | // in this case our end is within the next frame. | |
456 | // adjust our end. | |
457 | current_frame.m_upper_bound = next_frame.m_upper_bound; | |
458 | } | |
459 | // and remove the next frame since the current frame contains it (now): | |
460 | m_intervals.erase(it2); | |
461 | } | |
462 | // we are done! | |
463 | return; | |
464 | } | |
465 | // at this point: new frame starts later than the last frame ends | |
466 | // append the new frame: | |
467 | m_intervals.push_back( new_frame ); | |
468 | } // eo Intervals::add(const Interval&) | |
469 | ||
470 | ||
471 | /** | |
472 | * @brief subtracts a time interval from the list. | |
473 | * @param del_frame the time interval to subtract. | |
474 | * | |
475 | * removes the time interval from the list; cut off parts from or remove existing | |
476 | * intervals if they overlap. | |
ebc3b584 TJ |
477 | * |
478 | * @internal complexity O(n). | |
1b5dfd98 TJ |
479 | */ |
480 | void Intervals::sub(const Interval& del_frame) | |
481 | { | |
482 | if (not del_frame.is_valid() or del_frame.empty() ) | |
483 | { | |
484 | return; | |
485 | } | |
486 | for (IntervalList::iterator it= m_intervals.begin(); | |
487 | it != m_intervals.end(); | |
488 | ) | |
489 | { | |
490 | Interval& current_frame = *it; | |
491 | if ( del_frame.m_lower_bound >= current_frame.m_upper_bound ) | |
492 | { | |
493 | // del_frame begins later than current end; go on: | |
494 | ++it; | |
495 | continue; | |
496 | } | |
497 | // at this point: the begin of the del frame is less then the current end. | |
498 | if ( del_frame.m_upper_bound < current_frame.m_lower_bound ) | |
499 | { | |
500 | // end is before our start; nothing to do. | |
501 | return; | |
502 | } | |
503 | // at this point: the end of the del frame is >= current begin. | |
504 | if ( del_frame.m_upper_bound < current_frame.m_upper_bound ) | |
505 | { | |
506 | // del frame end point is within our interval. | |
507 | if ( del_frame.m_lower_bound > current_frame.m_lower_bound) | |
508 | { | |
509 | // the del frame is within our interval... we need to split: | |
510 | m_intervals.insert(it, Interval( current_frame.m_lower_bound, del_frame.m_lower_bound ) ); | |
511 | } | |
512 | // adjust start of current frame: | |
80f30818 TJ |
513 | if (current_frame.m_lower_bound < del_frame.m_upper_bound) |
514 | { | |
515 | current_frame.m_lower_bound= del_frame.m_upper_bound; | |
516 | current_frame.m_changed= true; | |
517 | } | |
1b5dfd98 TJ |
518 | // and we are done! |
519 | return; | |
520 | } | |
521 | // at this point the end of the del frame is >= current end | |
522 | if ( del_frame.m_lower_bound > current_frame.m_lower_bound ) | |
523 | { | |
524 | // a part of the current interval needs to be preserved.. | |
525 | // move the end. | |
526 | current_frame.m_upper_bound= del_frame.m_lower_bound; | |
80f30818 | 527 | current_frame.m_changed= true; |
1b5dfd98 TJ |
528 | // and continue with the next interval: |
529 | ++it; | |
530 | continue; | |
531 | } | |
532 | // at this point; the whole frame needs to be deleted.. | |
533 | if ( it == m_intervals.begin()) | |
534 | { | |
535 | m_intervals.erase(it); | |
536 | it= m_intervals.begin(); | |
537 | } | |
538 | else | |
539 | { | |
540 | IntervalList::iterator it2= it++; | |
541 | m_intervals.erase(it2); | |
542 | } | |
543 | } | |
544 | } // eo Intervals::sub(const Interval&) | |
545 | ||
546 | ||
547 | /** | |
548 | * @brief returns if we contain an interval. | |
549 | * @param other the interval to check. | |
550 | * @return @a true if we cover the given interval, too. | |
551 | */ | |
552 | bool Intervals::contains(const Interval& other) const | |
553 | { | |
554 | for(const_iterator it= begin(); | |
555 | it != end(); | |
556 | ++it) | |
557 | { | |
558 | if ( it->contains( other )) | |
559 | { | |
560 | return true; | |
561 | } | |
562 | } | |
563 | return false; | |
564 | } // eo Intervals::contains(const Interval&) const | |
565 | ||
566 | ||
567 | /** | |
e156de7c TJ |
568 | * @brief returns if we contain an exact interval. |
569 | * @param other the interval to check. | |
570 | * @return @a true if we axactly contains the given interval. | |
571 | * | |
572 | * @note thsi differs from contain in the way, that we return only @a true | |
573 | * iff we have the given interval in our list; not only cover it. | |
574 | */ | |
575 | bool Intervals::contains_exact(const Interval& other) const | |
576 | { | |
577 | for(const_iterator it= begin(); | |
578 | it != end(); | |
579 | ++it) | |
580 | { | |
581 | if ( *it == other) | |
582 | { | |
583 | return true; | |
584 | } | |
585 | } | |
586 | return false; | |
587 | } // eo Intervals::contains_exact(const Interval&)const | |
588 | ||
589 | ||
590 | /** | |
1b5dfd98 TJ |
591 | * @brief returns if we contain another interval combination. |
592 | * @param other the intervals to check. | |
593 | * @return @a true if we cover the given intervals, too. | |
594 | * | |
595 | * @internal we rely on the fact that the lists are sorted and contain | |
596 | * disjoint intervals. | |
ebc3b584 TJ |
597 | * |
598 | * So this method has a complexity of O(n). | |
1b5dfd98 TJ |
599 | */ |
600 | bool Intervals::contains(const Intervals& other) const | |
601 | { | |
602 | const_iterator my_it= begin(); | |
603 | const_iterator other_it= other.begin(); | |
604 | while( my_it != end() and other_it!= other.end() ) | |
605 | { | |
606 | // seek the first interval which contains the lower bound of the current other interval | |
607 | while (my_it != end() | |
608 | and my_it->m_lower_bound > other_it->m_lower_bound | |
609 | and other_it->m_lower_bound >= my_it->m_upper_bound | |
610 | ) | |
611 | { | |
612 | ++my_it; | |
613 | } | |
614 | if (my_it == end()) | |
615 | { | |
616 | break; | |
617 | } | |
618 | if (not my_it->contains( *other_it )) | |
619 | { | |
620 | // if we don't contain the current other; we're done: | |
621 | return false; | |
622 | } | |
623 | //else check the next other interval: | |
624 | ++other_it; | |
625 | } | |
626 | return (other_it == other.end()); | |
ebc3b584 | 627 | } // eo Intervals::contains(const Intervals&) const |
1b5dfd98 TJ |
628 | |
629 | ||
ebc3b584 TJ |
630 | /** |
631 | * @brief combines to interval combinates for equality | |
632 | * @param other the other instance. | |
633 | * @return @a true if the other is equal to the current. | |
634 | * | |
635 | * @internal since the lists are sorted, we compare the interval lists. | |
636 | * Thus we have a complexity of O(n). | |
637 | */ | |
1b5dfd98 TJ |
638 | bool Intervals::operator==(const Intervals& other) const |
639 | { | |
640 | // since we keep sorted lists: just compare the lists :-) | |
641 | return m_intervals == other.m_intervals; | |
642 | } // eo Intervals::operator==(const Intervals&) | |
643 | ||
644 | ||
645 | Intervals& Intervals::operator+=(const Interval& other) | |
646 | { | |
647 | add(other); | |
648 | return *this; | |
649 | } // eo operator+=(const Interval&) | |
650 | ||
651 | ||
652 | Intervals& Intervals::operator-=(const Interval& other) | |
653 | { | |
654 | sub(other); | |
655 | return *this; | |
656 | } // eo operator-=(const Interval&) | |
657 | ||
658 | ||
ebc3b584 TJ |
659 | /** |
660 | * @brief adds the intervals of a second instance to us. | |
661 | * @param other the other instance. | |
662 | * @return self reference (allow chaining). | |
663 | * | |
664 | * @internal since we do simple loops over the other and our intervals | |
665 | * we have a complexity of O(n^2). | |
666 | * | |
667 | * @todo optimize if complexity becomes a problem. | |
668 | */ | |
1b5dfd98 TJ |
669 | Intervals& Intervals::operator+=(const Intervals& other) |
670 | { | |
671 | for(const_iterator it= other.begin(); | |
672 | it != other.end(); | |
673 | ++it) | |
674 | { | |
675 | add( *it ); | |
676 | } | |
677 | return *this; | |
678 | } // eo operator+=(const Intervals&) | |
679 | ||
680 | ||
ebc3b584 TJ |
681 | /** |
682 | * @brief subtracts the intervals of a second instance from us. | |
683 | * @param other the other instance. | |
684 | * @return self reference (allow chaining). | |
685 | * | |
686 | * @internal since we do simple loops over the other and our intervals | |
687 | * we have a complexity of O(n^2). | |
688 | * | |
689 | * @todo optimize if complexity becomes a problem. | |
690 | */ | |
1b5dfd98 TJ |
691 | Intervals& Intervals::operator-=(const Intervals& other) |
692 | { | |
693 | if (&other == this) | |
694 | { | |
695 | m_intervals.clear(); | |
696 | } | |
697 | else | |
698 | { | |
699 | for(const_iterator it= other.begin(); | |
700 | it != other.end(); | |
701 | ++it) | |
702 | { | |
703 | sub( *it ); | |
704 | } | |
705 | } | |
706 | return *this; | |
707 | } // eo operator-=(const Intervals&) | |
96d0be2e TJ |
708 | |
709 | ||
710 | ||
711 | /* | |
712 | ** clock funcs: | |
713 | */ | |
714 | ||
715 | ||
716 | /** | |
717 | * @brief fetches the value from the monotonic clock source. | |
718 | * @param[out] seconds the seconds. | |
719 | * @param[out] nano_seconds the nano seconds. | |
720 | * @return @a true if the clock was successfully read. | |
721 | */ | |
722 | bool monotonic_clock_gettime(long int& seconds, long int& nano_seconds) | |
723 | { | |
724 | struct timespec tp[1]; | |
4b1afed1 | 725 | int res= clock_gettime (CLOCK_MONOTONIC, tp); |
96d0be2e TJ |
726 | if (0 == res) |
727 | { | |
728 | seconds= tp->tv_sec; | |
729 | nano_seconds= tp->tv_nsec; | |
730 | } | |
731 | return (res==0); | |
732 | } // eo monotonic_clock_gettime(long int&,long int&) | |
733 | ||
734 | ||
735 | /** | |
736 | * @brief fetches the value from the monotonic clock source. | |
b7e17426 GE |
737 | * @return the time since system start in nanoseconds, 0 if read was unsuccessful |
738 | */ | |
739 | long long monotonic_clock_gettime_nano() | |
740 | { | |
741 | long int seconds; | |
742 | long int nano_seconds; | |
743 | long long nano=0; | |
744 | ||
745 | if (monotonic_clock_gettime(seconds,nano_seconds)) | |
746 | { | |
747 | nano=seconds; | |
748 | nano*=1000000000LL; | |
749 | nano+=nano_seconds; | |
750 | } | |
751 | ||
752 | return nano; | |
753 | } | |
754 | ||
755 | /** | |
756 | * @brief fetches the value from the monotonic clock source. | |
96d0be2e TJ |
757 | * @param[out] seconds the seconds. |
758 | * @param[out] nano_seconds the nano seconds. | |
759 | * @return @a true if the clock was successfully read. | |
760 | */ | |
761 | bool realtime_clock_gettime(long int& seconds, long int& nano_seconds) | |
762 | { | |
763 | struct timespec tp[1]; | |
4b1afed1 | 764 | int res= clock_gettime(CLOCK_REALTIME, tp); |
96d0be2e TJ |
765 | if (0 == res) |
766 | { | |
767 | seconds= tp->tv_sec; | |
768 | nano_seconds= tp->tv_nsec; | |
769 | } | |
770 | return (res==0); | |
771 | } // eo realtime_clock_gettime(long int&,long int&) | |
772 | ||
773 | ||
8b5814e2 PG |
774 | namespace I2n { |
775 | ||
776 | namespace clock { | |
777 | ||
778 | namespace { | |
779 | ||
780 | static inline clockid_t | |
781 | clockid_of_flags (const enum type::id id, | |
782 | const enum type::variant var) | |
783 | { | |
784 | clockid_t cid = CLOCK_MONOTONIC_COARSE; | |
785 | ||
786 | switch (id) { | |
787 | ||
788 | default: | |
789 | case type::mono: { | |
790 | switch (var) { | |
791 | default: { | |
792 | break; | |
793 | } | |
794 | case type::raw: { | |
795 | cid = CLOCK_MONOTONIC_RAW; | |
796 | break; | |
797 | } | |
798 | case type::exact: { | |
799 | cid = CLOCK_MONOTONIC; | |
800 | break; | |
801 | } | |
802 | } | |
803 | break; | |
804 | } | |
805 | ||
806 | case type::real: { | |
807 | if (var == type::exact) { | |
808 | cid = CLOCK_REALTIME; | |
809 | } else { | |
810 | cid = CLOCK_REALTIME_COARSE; | |
811 | } | |
812 | break; | |
813 | } | |
814 | ||
815 | case type::boot: { | |
816 | if (var & type::exact) { | |
817 | cid = CLOCK_BOOTTIME; | |
818 | } | |
819 | break; | |
820 | } | |
821 | ||
822 | case type::cpu: { | |
823 | if (var == type::thread) { | |
824 | cid = CLOCK_THREAD_CPUTIME_ID; | |
825 | } else { | |
826 | cid = CLOCK_PROCESS_CPUTIME_ID; | |
827 | } | |
828 | break; | |
829 | } | |
830 | } /* [switch id] */ | |
831 | ||
832 | return cid; | |
833 | } | |
834 | ||
835 | static const struct timespec zero_time = { 0, 0 }; | |
836 | ||
837 | # define NANO (1000L * 1000 * 1000) | |
838 | ||
839 | } /* [namespace] */ | |
840 | ||
841 | Time::Time (const enum type::id id, const enum type::variant var) | |
842 | : value (zero_time) | |
843 | , id (id) | |
844 | , variant (var) | |
845 | , err (0) | |
846 | { } | |
847 | ||
848 | int64_t | |
849 | Time::as_nanosec (void) | |
850 | { return int64_t (this->value.tv_sec) * NANO + this->value.tv_nsec; } | |
851 | ||
852 | long | |
853 | Time::as_nanosec_L (void) /* likely to overflow */ | |
854 | { return static_cast<long>(this->as_nanosec ()); } | |
855 | ||
856 | void | |
857 | Time::unset (void) | |
858 | { this->value = zero_time; } | |
859 | ||
860 | bool | |
861 | Time::set (void) | |
862 | { | |
863 | struct timespec now; | |
864 | ||
865 | errno = 0; | |
866 | if (clock_gettime (clockid_of_flags (this->id, this->variant), &now) | |
867 | == -1) | |
868 | { | |
869 | this->err = errno; | |
870 | this->unset (); | |
871 | ||
872 | return false; | |
873 | } | |
874 | this->err = 0; | |
875 | this->value = now; | |
876 | ||
877 | return true; | |
878 | } | |
879 | ||
880 | boost::optional<Time> | |
881 | now (const enum type::id id, const enum type::variant var) | |
882 | { | |
883 | Time ret (id); | |
884 | ||
885 | if (!ret.set ()) { | |
886 | return boost::none; | |
887 | } | |
888 | ||
889 | return ret; | |
890 | } | |
891 | ||
892 | } /* [namespace clock] */ | |
893 | ||
894 | } /* [namespace I2n] */ | |
895 |