1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 1999-2021 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING.  If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25 
26 #if ! defined (octave_oct_time_h)
27 #define octave_oct_time_h 1
28 
29 #include "octave-config.h"
30 
31 #include <ctime>
32 
33 #include <iosfwd>
34 #include <string>
35 
36 static inline double
as_double(time_t sec,long usec)37 as_double (time_t sec, long usec)
38 {
39   // Unix time will be exactly representable as a double for more than
40   // 100 million years, so no worry there, and microseconds has a
41   // range of 0-1e6, so we are safe there as well.
42 
43   return (static_cast<double> (sec) + static_cast<double> (usec) / 1.0e6);
44 }
45 
46 namespace octave
47 {
48   namespace sys
49   {
50     class base_tm;
51 
52     class
53     OCTAVE_API
54     time
55     {
56     public:
57 
time(void)58       time (void)
59         : ot_unix_time (0), ot_usec (0) { stamp (); }
60 
time(time_t t)61       time (time_t t)
62         : ot_unix_time (t), ot_usec (0) { }
63 
time(time_t t,long us)64       time (time_t t, long us)
65         : ot_unix_time (t), ot_usec ()
66       {
67         long rem, extra;
68 
69         if (us >= 0)
70           {
71             rem = us % 1000000;
72             extra = (us - rem) / 1000000;
73           }
74         else
75           {
76             us = -us;
77             rem = us % 1000000;
78             extra = - (1 + (us - rem) / 1000000);
79             rem = 1000000 - us % 1000000;
80           }
81 
82         ot_usec = rem;
83         ot_unix_time += extra;
84       }
85 
86       time (double d);
87 
88       time (const base_tm& tm);
89 
time(const time & ot)90       time (const time& ot)
91         : ot_unix_time (ot.ot_unix_time), ot_usec (ot.ot_usec) { }
92 
93       time& operator = (const time& ot)
94       {
95         if (this != &ot)
96           {
97             ot_unix_time = ot.ot_unix_time;
98             ot_usec = ot.ot_usec;
99           }
100 
101         return *this;
102       }
103 
104       ~time (void) = default;
105 
106       void stamp (void);
107 
double_value(void)108       double double_value (void) const
109       {
110         return as_double (ot_unix_time, ot_usec);
111       }
112 
unix_time(void)113       time_t unix_time (void) const { return ot_unix_time; }
114 
usec(void)115       long usec (void) const { return ot_usec; }
116 
117       std::string ctime (void) const;
118 
119       friend std::ostream& operator << (std::ostream& os, const time& ot);
120 
121     private:
122 
123       // Seconds since the epoch.
124       time_t ot_unix_time;
125 
126       // Additional microseconds.
127       long ot_usec;
128     };
129 
130     inline bool
131     operator == (const time& t1, const time& t2)
132     {
133       return (t1.unix_time () == t2.unix_time () && t1.usec () == t2.usec ());
134     }
135 
136     inline bool
137     operator != (const time& t1, const time& t2)
138     {
139       return ! (t1 == t2);
140     }
141 
142     inline bool
143     operator < (const time& t1, const time& t2)
144     {
145       if (t1.unix_time () < t2.unix_time ())
146         return true;
147       else if (t1.unix_time () > t2.unix_time ())
148         return false;
149       else if (t1.usec () < t2.usec ())
150         return true;
151       else
152         return false;
153     }
154 
155     inline bool
156     operator <= (const time& t1, const time& t2)
157     {
158       return (t1 < t2 || t1 == t2);
159     }
160 
161     inline bool
162     operator > (const time& t1, const time& t2)
163     {
164       if (t1.unix_time () > t2.unix_time ())
165         return true;
166       else if (t1.unix_time () < t2.unix_time ())
167         return false;
168       else if (t1.usec () > t2.usec ())
169         return true;
170       else
171         return false;
172     }
173 
174     inline bool
175     operator >= (const time& t1, const time& t2)
176     {
177       return (t1 > t2 || t1 == t2);
178     }
179 
180     inline time
181     operator + (const time& t1, const time& t2)
182     {
183       return time (t1.unix_time () + t2.unix_time (),
184                    t1.usec () + t2.usec ());
185     }
186 
187     class
188     OCTAVE_API
189     base_tm
190     {
191     public:
192 
base_tm(void)193       base_tm (void)
194         : m_usec (0), m_sec (0), m_min (0), m_hour (0),
195           m_mday (0), m_mon (0), m_year (0), m_wday (0),
196           m_yday (0), m_isdst (0), m_gmtoff (0), m_zone ("unknown")
197       { }
198 
base_tm(const base_tm & tm)199       base_tm (const base_tm& tm)
200         : m_usec (tm.m_usec), m_sec (tm.m_sec), m_min (tm.m_min),
201           m_hour (tm.m_hour), m_mday (tm.m_mday), m_mon (tm.m_mon),
202           m_year (tm.m_year), m_wday (tm.m_wday), m_yday (tm.m_yday),
203           m_isdst (tm.m_isdst), m_gmtoff (tm.m_gmtoff), m_zone (tm.m_zone)
204       { }
205 
206       base_tm& operator = (const base_tm& tm)
207       {
208         if (this != &tm)
209           {
210             m_usec = tm.m_usec;
211             m_sec = tm.m_sec;
212             m_min = tm.m_min;
213             m_hour = tm.m_hour;
214             m_mday = tm.m_mday;
215             m_mon = tm.m_mon;
216             m_year = tm.m_year;
217             m_wday = tm.m_wday;
218             m_yday = tm.m_yday;
219             m_isdst = tm.m_isdst;
220             m_gmtoff = tm.m_gmtoff;
221             m_zone = tm.m_zone;
222           }
223 
224         return *this;
225       }
226 
227       virtual ~base_tm (void) = default;
228 
usec(void)229       int usec (void) const { return m_usec; }
sec(void)230       int sec (void) const { return m_sec; }
min(void)231       int min (void) const { return m_min; }
hour(void)232       int hour (void) const { return m_hour; }
mday(void)233       int mday (void) const { return m_mday; }
mon(void)234       int mon (void) const { return m_mon; }
year(void)235       int year (void) const { return m_year; }
wday(void)236       int wday (void) const { return m_wday; }
yday(void)237       int yday (void) const { return m_yday; }
isdst(void)238       int isdst (void) const { return m_isdst; }
gmtoff(void)239       long gmtoff (void) const { return m_gmtoff; }
zone(void)240       std::string zone (void) const { return m_zone; }
241 
242       base_tm& usec (int v);
243       base_tm& sec (int v);
244       base_tm& min (int v);
245       base_tm& hour (int v);
246       base_tm& mday (int v);
247       base_tm& mon (int v);
248       base_tm& year (int v);
249       base_tm& wday (int v);
250       base_tm& yday (int v);
251       base_tm& isdst (int v);
252       base_tm& gmtoff (long v);
253       base_tm& zone (const std::string& s);
254 
255       std::string strftime (const std::string& fmt) const;
256 
asctime(void)257       std::string asctime (void) const
258       { return strftime ("%a %b %d %H:%M:%S %Y\n"); }
259 
260     protected:
261 
262       // Microseconds after the second (0, 999999).
263       int m_usec;
264 
265       // Seconds after the minute (0, 61).
266       int m_sec;
267 
268       // Minutes after the hour (0, 59).
269       int m_min;
270 
271       // Hours since midnight (0, 23).
272       int m_hour;
273 
274       // Day of the month (1, 31).
275       int m_mday;
276 
277       // Months since January (0, 11).
278       int m_mon;
279 
280       // Years since 1900.
281       int m_year;
282 
283       // Days since Sunday (0, 6).
284       int m_wday;
285 
286       // Days since January 1 (0, 365).
287       int m_yday;
288 
289       // Daylight saving time flag.
290       int m_isdst;
291 
292       // Time zone.
293       long m_gmtoff;
294 
295       // Time zone.
296       std::string m_zone;
297 
298       void init (void *p);
299     };
300 
301     class
302     OCTAVE_API
303     localtime : public base_tm
304     {
305     public:
306 
localtime(void)307       localtime (void)
308         : base_tm () { init (time ()); }
309 
localtime(const time & ot)310       localtime (const time& ot)
311         : base_tm () { init (ot); }
312 
localtime(const localtime & t)313       localtime (const localtime& t)
314         : base_tm (t) { }
315 
316       localtime& operator = (const localtime& t)
317       {
318         base_tm::operator = (t);
319         return *this;
320       }
321 
322       ~localtime (void) = default;
323 
324     private:
325 
326       void init (const time& ot);
327     };
328 
329     class
330     OCTAVE_API
331     gmtime : public base_tm
332     {
333     public:
334 
gmtime(void)335       gmtime (void)
336         : base_tm () { init (time ()); }
337 
gmtime(const time & ot)338       gmtime (const time& ot)
339         : base_tm () { init (ot); }
340 
341       gmtime& operator = (const gmtime& t)
342       {
343         base_tm::operator = (t);
344         return *this;
345       }
346 
347       ~gmtime (void) = default;
348 
349     private:
350 
351       void init (const time& ot);
352     };
353 
354     class
355     OCTAVE_API
356     strptime : public base_tm
357     {
358     public:
359 
strptime(const std::string & str,const std::string & fmt)360       strptime (const std::string& str, const std::string& fmt)
361         : base_tm (), nchars (0)
362       {
363         init (str, fmt);
364       }
365 
strptime(const strptime & s)366       strptime (const strptime& s)
367         : base_tm (s), nchars (s.nchars) { }
368 
369       strptime& operator = (const strptime& s)
370       {
371         base_tm::operator = (s);
372         nchars = s.nchars;
373         return *this;
374       }
375 
characters_converted(void)376       int characters_converted (void) const { return nchars; }
377 
378       ~strptime (void) = default;
379 
380     private:
381 
382       int nchars;
383 
384       void init (const std::string& str, const std::string& fmt);
385     };
386 
387     class
388     OCTAVE_API
389     cpu_time
390     {
391     public:
392 
393       friend class resource_usage;
394 
cpu_time(void)395       cpu_time (void)
396         : m_usr_sec (0), m_sys_sec (0), m_usr_usec (0), m_sys_usec (0)
397       {
398         stamp ();
399       }
400 
cpu_time(const cpu_time & tm)401       cpu_time (const cpu_time& tm)
402         : m_usr_sec (tm.m_usr_sec), m_sys_sec (tm.m_sys_sec),
403           m_usr_usec (tm.m_usr_usec), m_sys_usec (tm.m_sys_usec)
404       { }
405 
406       cpu_time& operator = (const cpu_time& tm)
407       {
408         if (&tm != this)
409           {
410             m_usr_sec = tm.m_usr_sec;
411             m_sys_sec = tm.m_sys_sec;
412             m_usr_usec = tm.m_usr_usec;
413             m_sys_usec = tm.m_sys_usec;
414           }
415 
416         return *this;
417       }
418 
419       void stamp (void);
420 
user(void)421       double user (void) const
422       {
423         return as_double (m_usr_sec, m_usr_usec);
424       }
425 
system(void)426       double system (void) const
427       {
428         return as_double (m_sys_sec, m_sys_usec);
429       }
430 
user_sec(void)431       time_t user_sec (void) const { return m_usr_sec; }
user_usec(void)432       long user_usec (void) const { return m_usr_usec; }
433 
system_sec(void)434       time_t system_sec (void) const { return m_sys_sec; }
system_usec(void)435       long system_usec (void) const { return m_sys_usec; }
436 
437     private:
438 
439       time_t m_usr_sec;
440       time_t m_sys_sec;
441 
442       long m_usr_usec;
443       long m_sys_usec;
444 
cpu_time(time_t usr_sec,time_t sys_sec,long usr_usec,long sys_usec)445       cpu_time (time_t usr_sec, time_t sys_sec, long usr_usec, long sys_usec)
446         : m_usr_sec (usr_sec), m_sys_sec (sys_sec),
447           m_usr_usec (usr_usec), m_sys_usec (sys_usec)
448       { }
449     };
450 
451     class
452     resource_usage
453     {
454     public:
455 
resource_usage(void)456       resource_usage (void)
457         : m_cpu (), m_maxrss (0), m_ixrss (0), m_idrss (0),
458           m_isrss (0), m_minflt (0), m_majflt (0), m_nswap (0),
459           m_inblock (0), m_oublock (0), m_msgsnd (0), m_msgrcv (0),
460           m_nsignals (0), m_nvcsw (0), m_nivcsw (0)
461       {
462         stamp ();
463       }
464 
resource_usage(const resource_usage & ru)465       resource_usage (const resource_usage& ru)
466         : m_cpu (ru.m_cpu), m_maxrss (ru.m_maxrss),
467           m_ixrss (ru.m_ixrss), m_idrss (ru.m_idrss),
468           m_isrss (ru.m_isrss), m_minflt (ru.m_minflt),
469           m_majflt (ru.m_majflt), m_nswap (ru.m_nswap),
470           m_inblock (ru.m_inblock), m_oublock (ru.m_oublock),
471           m_msgsnd (ru.m_msgsnd), m_msgrcv (ru.m_msgrcv),
472           m_nsignals (ru.m_nsignals), m_nvcsw (ru.m_nvcsw),
473           m_nivcsw (ru.m_nivcsw)
474       { }
475 
476       resource_usage& operator = (const resource_usage& ru)
477       {
478         if (&ru != this)
479           {
480             m_cpu = ru.m_cpu;
481 
482             m_maxrss = ru.m_maxrss;
483             m_ixrss = ru.m_ixrss;
484             m_idrss = ru.m_idrss;
485             m_isrss = ru.m_isrss;
486             m_minflt = ru.m_minflt;
487             m_majflt = ru.m_majflt;
488             m_nswap = ru.m_nswap;
489             m_inblock = ru.m_inblock;
490             m_oublock = ru.m_oublock;
491             m_msgsnd = ru.m_msgsnd;
492             m_msgrcv = ru.m_msgrcv;
493             m_nsignals = ru.m_nsignals;
494             m_nvcsw = ru.m_nvcsw;
495             m_nivcsw = ru.m_nivcsw;
496           }
497 
498         return *this;
499       }
500 
501       void stamp (void);
502 
cpu(void)503       cpu_time cpu (void) const { return m_cpu; }
504 
maxrss(void)505       long maxrss (void) const { return m_maxrss; }
ixrss(void)506       long ixrss (void) const { return m_ixrss; }
idrss(void)507       long idrss (void) const { return m_idrss; }
isrss(void)508       long isrss (void) const { return m_isrss; }
minflt(void)509       long minflt (void) const { return m_minflt; }
majflt(void)510       long majflt (void) const { return m_majflt; }
nswap(void)511       long nswap (void) const { return m_nswap; }
inblock(void)512       long inblock (void) const { return m_inblock; }
oublock(void)513       long oublock (void) const { return m_oublock; }
msgsnd(void)514       long msgsnd (void) const { return m_msgsnd; }
msgrcv(void)515       long msgrcv (void) const { return m_msgrcv; }
nsignals(void)516       long nsignals (void) const { return m_nsignals; }
nvcsw(void)517       long nvcsw (void) const { return m_nvcsw; }
nivcsw(void)518       long nivcsw (void) const { return m_nivcsw; }
519 
520     private:
521 
522       cpu_time m_cpu;
523 
524       long m_maxrss;
525       long m_ixrss;
526       long m_idrss;
527       long m_isrss;
528       long m_minflt;
529       long m_majflt;
530       long m_nswap;
531       long m_inblock;
532       long m_oublock;
533       long m_msgsnd;
534       long m_msgrcv;
535       long m_nsignals;
536       long m_nvcsw;
537       long m_nivcsw;
538     };
539   }
540 }
541 
542 #endif
543