From e6d24a68ba902f96c317f0329de4d61032177e6b Mon Sep 17 00:00:00 2001 From: Cliff Click Date: Mon, 10 Aug 2026 11:11:18 -0700 Subject: Chapter 31: Software Drawing, Time, and Graphical Games Co-authored-by: Hsiang-Ying Fu <66062782+fuhsnn@users.noreply.github.com> Co-authored-by: fuhsnn <66062782+fuhsnn@users.noreply.github.com> Co-authored-by: Symious <14933944+symious@users.noreply.github.com> Co-authored-by: Jun Kawasaki Co-authored-by: Claude Opus 5 --- src/main/c/simple_time.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 src/main/c/simple_time.c (limited to 'src/main/c/simple_time.c') diff --git a/src/main/c/simple_time.c b/src/main/c/simple_time.c new file mode 100644 index 00000000..2e579922 --- /dev/null +++ b/src/main/c/simple_time.c @@ -0,0 +1,61 @@ +#define _POSIX_C_SOURCE 200809L +#include +#include +#include + +// Fixed-width bridge; no native struct layout or retained Simple pointers. +static int64_t clock_value(clockid_t clock, int64_t scale) { + struct timespec t; + if (clock_gettime(clock,&t)) return -1; + if (t.tv_sec>INT64_MAX/scale || t.tv_secINT64_MAX-fraction) { errno=EOVERFLOW; return -1; } + return base+fraction; +} +int64_t simple_time_now(void) { return clock_value(CLOCK_REALTIME,1000); } +int64_t simple_time_mono(void) { return clock_value(CLOCK_MONOTONIC,1000); } +int64_t simple_time_nano(void) { return clock_value(CLOCK_MONOTONIC,1000000000); } +int32_t simple_time_sleep(int64_t ms, int32_t absolute) { + if (ms<0) { errno=EINVAL; return -1; } + struct timespec t={ms/1000,(ms%1000)*1000000}; + int result; + if (!absolute) { + // Retry the remaining duration after signals; no busy waiting. + do { result=nanosleep(&t,&t); } while (result && errno==EINTR); + return result; + } + do { result=clock_nanosleep(CLOCK_MONOTONIC,TIMER_ABSTIME,&t,NULL); } while (result==EINTR); + if (result) { errno=result; return -1; } + return 0; +} +static int leap(int y) { return y%4==0 && (y%100!=0 || y%400==0); } +static int local_fields(int64_t ms, struct tm *local, struct tm *utc) { + tzset(); + int64_t sec=ms/1000; + if (ms%1000<0) --sec; + time_t t=(time_t)sec; + if ((int64_t)t!=sec || !localtime_r(&t,local) || !gmtime_r(&t,utc)) return -1; + if (local->tm_year < -1899 || local->tm_year > 8099) { errno=EOVERFLOW; return -1; } + return 0; +} +int32_t simple_time_local(int64_t ms, int64_t *out) { + struct tm t,u; + if (local_fields(ms,&t,&u)) return -1; + int days=t.tm_yday-u.tm_yday; + if (t.tm_year>u.tm_year) days+=365+leap(u.tm_year+1900); + if (t.tm_year0; + return 0; +} +int32_t simple_time_zone(int64_t ms, char *out, uint32_t capacity) { + struct tm t,u; + if (!capacity || local_fields(ms,&t,&u)) return -1; + return (int32_t)strftime(out,capacity,"%Z",&t); +} -- cgit v1.2.3