00001 /* 00002 Copyright 2003 by Marc J. Rochkind. All rights reserved. 00003 May be copied only for purposes and under conditions described 00004 on the Web page www.basepath.com/aup/copyright.htm. 00005 00006 The Example Files are provided "as is," without any warranty; 00007 without even the implied warranty of merchantability or fitness 00008 for a particular purpose. The author and his publisher are not 00009 responsible for any damages, direct or incidental, resulting 00010 from the use or non-use of these Example Files. 00011 00012 The Example Files may contain defects, and some contain deliberate 00013 coding mistakes that were included for educational reasons. 00014 You are responsible for determining if and how the Example Files 00015 are to be used. 00016 00017 */ 00018 #include "ux.hpp" 00019 #include <iomanip> 00020 00021 using namespace Ux; 00022 00023 /** 00024 Calls mktime. 00025 */ 00026 TimeSec TimeParts::get_secs(void) 00027 { 00028 time_t t; 00029 00030 errno = 0; 00031 if ((t = ::mktime(this)) == -1) { 00032 if (errno == 0) 00033 errno = EINVAL; // SUS defines no errno values -- make one up 00034 throw Error(errno); 00035 } 00036 return TimeSec(t); 00037 } 00038 00039 /** 00040 Calls asctime_t; optionally removes newline. 00041 */ 00042 const char *TimeParts::get_string(bool keep_nl) 00043 { 00044 errno = 0; 00045 if (::asctime_r(this, str.timestr) == NULL) { 00046 if (errno == 0) 00047 throw Error(EINVAL); // SUS defines no errno values -- make one up 00048 throw Error(errno); 00049 } 00050 if (!keep_nl) 00051 str.timestr[strlen(str.timestr) - 1] = '\0'; 00052 return str; 00053 } 00054 00055 /** 00056 Calls getdate. 00057 */ 00058 void TimeParts::set(const char *s) 00059 { 00060 struct tm *t; 00061 00062 if ((t = ::getdate(s)) == NULL) 00063 throw Error(getdate_err, EC_GETDATE); 00064 set(*t); 00065 } 00066 #if 0 00067 00068 void TimeParts::gmtime(const time_t *t) 00069 { 00070 time_t tx; 00071 00072 if (t == NULL) { 00073 tx = TimeSec::time(); 00074 t = &tx; 00075 } 00076 if (::gmtime_r(t, this) == NULL) 00077 throw Error(errno); 00078 } 00079 00080 void TimeParts::localtime(const time_t *t) 00081 { 00082 time_t tx; 00083 00084 if (t == NULL) { 00085 tx = TimeSec::time(); 00086 t = &tx; 00087 } 00088 if (::localtime_r(t, this) == NULL) 00089 throw Error(errno); 00090 } 00091 #endif 00092 00093 /** 00094 Sets parts according to local time (calling localtime_r) or GMT (calling gmtime_r). 00095 */ 00096 void TimeParts::set(time_t t, zone z) 00097 { 00098 if (z == zone_local) { 00099 if (::localtime_r(&t, this) == NULL) 00100 throw Error(errno); 00101 } 00102 else { 00103 if (::gmtime_r(&t, this) == NULL) 00104 throw Error(errno); 00105 } 00106 00107 } 00108 00109 /** 00110 Sets from another TimeParts or struct tm. 00111 */ 00112 void TimeParts::set(const struct tm& t) 00113 { 00114 tm_sec = t.tm_sec; 00115 tm_min = t.tm_min; 00116 tm_hour = t.tm_hour; 00117 tm_mday = t.tm_mday; 00118 tm_mon = t.tm_mon; 00119 tm_year = t.tm_year; 00120 tm_wday = t.tm_wday; 00121 tm_yday = t.tm_yday; 00122 tm_isdst = t.tm_isdst; 00123 str.set(); 00124 } 00125 00126 /** 00127 Sets parts from string according to format (calls strptime). 00128 */ 00129 char *TimeParts::set_fmt(const char *s, const char *format) 00130 { 00131 char *p; 00132 00133 errno = 0; 00134 if ((p = ::strptime(s, format, this)) == NULL) { 00135 if (errno == 0) 00136 errno = EINVAL; // SUS defines no errno values -- make one up 00137 throw Error(errno); 00138 } 00139 return p; 00140 } 00141 00142 /** 00143 Gets string from parts according to format (calls strftime). 00144 */ 00145 size_t TimeParts::get_fmt(char *buf, size_t bufsize, const char *format) 00146 { 00147 size_t n; 00148 00149 errno = 0; 00150 if ((n = ::strftime(buf, bufsize, format, this)) == 0) { 00151 if (errno == 0) 00152 errno = EINVAL; // SUS defines no errno values -- make one up 00153 throw Error(errno); 00154 } 00155 return n; 00156 } 00157 00158 /** 00159 Gets string from parts according to format; wide-character version (calls wstrftime). 00160 */ 00161 size_t TimeParts::get_fmtw(wchar_t *buf, size_t bufsize, const wchar_t *format) 00162 { 00163 size_t n; 00164 00165 errno = 0; 00166 if ((n = ::wcsftime(buf, bufsize, format, this)) == 0) { 00167 if (errno == 0) 00168 errno = EINVAL; // SUS defines no errno values -- make one up 00169 throw Error(errno); 00170 } 00171 return n; 00172 } 00173 00174 /** 00175 Sets string from TimeSec or time_t (calls ctime). Optionally removes newline. 00176 */ 00177 void TimeString::set(time_t t, bool keep_nl) 00178 { 00179 if (::ctime_r(&t, timestr) == NULL) 00180 throw Error(errno); 00181 if (!keep_nl) 00182 timestr[strlen(timestr) - 1] = '\0'; 00183 } 00184 00185 /** 00186 Constructor to set time to epoch or now. 00187 */ 00188 TimeSec::TimeSec(when w) 00189 { 00190 if (w == epoch) 00191 tt = 0; 00192 else 00193 tt = ::time(NULL); 00194 } 00195 00196 /** 00197 Subtracts TimeSec or time_t (calls difftime). 00198 */ 00199 double TimeSec::diff(time_t time0) 00200 { 00201 return ::difftime(tt, time0); 00202 } 00203 00204 /** 00205 Gets current or epoch time in msec (calls gettimeofday). 00206 */ 00207 TimeMsec::TimeMsec(when w) 00208 { 00209 if (w == epoch) { 00210 tv_sec = 0; 00211 tv_usec = 0; 00212 } 00213 else { 00214 errno = 0; 00215 if (::gettimeofday(this, NULL) != 0) { 00216 if (errno == 0) 00217 errno = EINVAL; // SUS defines no errno values -- make one up 00218 throw Error(errno); 00219 } 00220 } 00221 } 00222 00223 /** 00224 Gets TimeMsec as string. 00225 */ 00226 const char *TimeMsec::get_string(char *buf, size_t bufsize) 00227 { 00228 snprintf(buf, bufsize, "%lld.%.6ld", (long long)tv_sec, (long)tv_usec); 00229 return buf; 00230 } 00231 00232 /** 00233 Gets current or epoch time in nsec (calls gettimeofday). 00234 */ 00235 TimeNsec::TimeNsec(when w) 00236 { 00237 if (w == epoch) { 00238 tv_sec = 0; 00239 tv_nsec = 0; 00240 } 00241 else 00242 Clock().gettime(*this); 00243 } 00244 00245 /** 00246 Gets TimeNsec as string. 00247 */ 00248 const char *TimeNsec::get_string(char *buf, size_t bufsize) 00249 { 00250 snprintf(buf, bufsize, "%lld.%.9ld", (long long)tv_sec, (long)tv_nsec); 00251 return buf; 00252 } 00253 00254 /** 00255 Stream operator for timeval. 00256 */ 00257 std::ostream& Ux::operator<<(std::ostream& s, const timeval& t) 00258 { 00259 s << t.tv_sec << "." << setw(6) << setfill('0') << t.tv_usec; 00260 return s; 00261 } 00262 00263 /** 00264 Stream operator for timespec. 00265 */ 00266 std::ostream& Ux::operator<<(std::ostream& s, const timespec& t) 00267 { 00268 s << t.tv_sec << "." << setw(9) << setfill('0') << t.tv_nsec; 00269 return s; 00270 } 00271 00272 /** 00273 Calls clock_gettime. 00274 */ 00275 void Clock::gettime(TimeNsec& t) 00276 { 00277 if (::clock_gettime(clock_id, &t) == -1) 00278 throw Error(errno); 00279 } 00280 00281 /** 00282 Calls clock_getres. 00283 */ 00284 void Clock::getres(TimeNsec& res) 00285 { 00286 if (::clock_getres(clock_id, &res) == -1) 00287 throw Error(errno); 00288 } 00289 00290 /** 00291 Calls clock_settime. 00292 */ 00293 void Clock::settime(const TimeNsec& t) 00294 { 00295 if (::clock_settime(clock_id, &t) == -1) 00296 throw Error(errno); 00297 } 00298 00299 /** 00300 Calls clock_nanosleep; returns remaining time. 00301 */ 00302 void Clock::nanosleep(int flags, const TimeNsec& nsecs, const TimeNsec& remain) 00303 { 00304 #if _POSIX_CLOCK_SELECTION > 0 00305 int r; 00306 00307 if ((r = ::clock_nanosleep(clock_id, flags, &nsecs, &remain)) > 0) 00308 throw Error(r); 00309 #else 00310 throw Error(ENOSYS); 00311 #endif 00312 } 00313 00314 /** 00315 Calls clock_nanosleep; does not return remaining time. 00316 */ 00317 void Clock::nanosleep(int flags, const TimeNsec& nsecs) 00318 { 00319 #if _POSIX_CLOCK_SELECTION > 0 00320 int r; 00321 00322 if ((r = ::clock_nanosleep(clock_id, flags, &nsecs, NULL)) > 0) 00323 throw Error(r); 00324 #else 00325 throw Error(ENOSYS); 00326 #endif 00327 } 00328 00329 /** 00330 Calls nanosleep; returns remaining time. 00331 */ 00332 /* static */void Clock::nanosleep(const TimeNsec& nsecs, TimeNsec& remain) 00333 { 00334 int r; 00335 00336 if ((r = ::nanosleep(&nsecs, &remain)) > 0) 00337 throw Error(r); 00338 } 00339 00340 /** 00341 Calls nanosleep; does not return remaining time. 00342 */ 00343 /* static */void Clock::nanosleep(const TimeNsec& nsecs) 00344 { 00345 int r; 00346 00347 if ((r = ::nanosleep(&nsecs, NULL)) > 0) 00348 throw Error(r); 00349 } 00350 00351 /** 00352 Calls clock_getcpuclockid. 00353 */ 00354 /* static */void Clock::getcpuclockid(pid_t pid, Clock& clock) 00355 { 00356 #if _POSIX_CPUTIME > 0 00357 int r; 00358 00359 if ((r = ::clock_getcpuclockid(pid, &clock.clock_id)) > 0) 00360 throw Error(r); 00361 #else 00362 throw Error(ENOSYS); 00363 #endif 00364 } 00365 00366 /** 00367 Calls ::usleep. 00368 */ 00369 /* static */ void Clock::usleep(useconds_t usecs) 00370 { 00371 if (::usleep(usecs) == -1) 00372 throw Error(errno); 00373 } 00374 00375 /** 00376 Calls ::timer_create. 00377 */ 00378 void RealtimeTimer::create(const Clock& clock, struct sigevent *sig) 00379 { 00380 if (::timer_create(clock, sig, &timer_id) == -1) 00381 throw Error(errno); 00382 } 00383 00384 /** 00385 Calls ::timer_delete. 00386 */ 00387 void RealtimeTimer::del(void) 00388 { 00389 if (::timer_delete(timer_id) == -1) 00390 throw Error(errno); 00391 } 00392 00393 /** 00394 Calls ::timer_gettime. 00395 */ 00396 void RealtimeTimer::get(struct itimerspec& val) 00397 { 00398 if (::timer_gettime(timer_id, &val) == -1) 00399 throw Error(errno); 00400 } 00401 00402 /** 00403 Calls ::timer_settime. 00404 */ 00405 void RealtimeTimer::set(int flags, const struct itimerspec& val, struct itimerspec& oval) 00406 { 00407 if (::timer_settime(timer_id, flags, &val, &oval) == -1) 00408 throw Error(errno); 00409 } 00410 00411 /** 00412 Calls ::getitimer. 00413 */ 00414 void IntervalTimer::get(struct itimerval& val) 00415 { 00416 if (::getitimer(which_timer, &val) == -1) 00417 throw Error(errno); 00418 } 00419 00420 /** 00421 Calls ::setitimer. 00422 */ 00423 void IntervalTimer::set(const struct itimerval& val, struct itimerval& oval) 00424 { 00425 if (::setitimer(which_timer, &val, &oval) == -1) 00426 throw Error(errno); 00427 } 00428 00429 #if 0 00430 //#include <sys/time.h> 00431 void TimeMsec::now(void) 00432 { 00433 errno = 0; 00434 if (::gettimeofday(this, NULL) != 0) { 00435 if (errno == 0) 00436 errno = EINVAL; // SUS defines no errno values -- make one up 00437 throw Error(errno); 00438 } 00439 } 00440 00441 #endif