diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2025-03-30 17:27:52 -0400 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2025-03-30 17:27:52 -0400 |
| commit | 8cba6c3c24c2122c843aa0feaa26fd6e5c2412e2 (patch) | |
| tree | ae0583da790de2416f03a27e9f94953be7d4a803 /src/stdlib | |
| parent | d853d7b8dc1586f6b2fad3bf05998bfbe935b8f3 (diff) | |
Deprecate built-in Moment datatype in favor of a `time` module
Diffstat (limited to 'src/stdlib')
| -rw-r--r-- | src/stdlib/datatypes.h | 3 | ||||
| -rw-r--r-- | src/stdlib/integers.c | 16 | ||||
| -rw-r--r-- | src/stdlib/integers.h | 2 | ||||
| -rw-r--r-- | src/stdlib/moments.c | 323 | ||||
| -rw-r--r-- | src/stdlib/moments.h | 44 | ||||
| -rw-r--r-- | src/stdlib/optionals.c | 1 | ||||
| -rw-r--r-- | src/stdlib/optionals.h | 1 | ||||
| -rw-r--r-- | src/stdlib/paths.c | 18 | ||||
| -rw-r--r-- | src/stdlib/paths.h | 6 | ||||
| -rw-r--r-- | src/stdlib/tomo.h | 1 |
10 files changed, 21 insertions, 394 deletions
diff --git a/src/stdlib/datatypes.h b/src/stdlib/datatypes.h index 40b4712a..22cee673 100644 --- a/src/stdlib/datatypes.h +++ b/src/stdlib/datatypes.h @@ -109,9 +109,6 @@ typedef struct { } Path_t; #define OptionalPath_t Path_t -typedef struct timeval Moment_t; -#define OptionalMoment_t Moment_t - typedef struct RNGState_t* RNG_t; typedef struct MutexedData_s { diff --git a/src/stdlib/integers.c b/src/stdlib/integers.c index c5764d46..8086239d 100644 --- a/src/stdlib/integers.c +++ b/src/stdlib/integers.c @@ -597,24 +597,24 @@ public void Int32$deserialize(FILE *in, void *outval, Array_t*, const TypeInfo_t { \ Optional##KindOfInt##_t i = info->current; \ if (!i.is_none) { \ - KindOfInt##_t next; bool overflow = __builtin_add_overflow(i.i, info->step, &next); \ - if (overflow || (!info->last.is_none && (info->step >= 0 ? next > info->last.i : next < info->last.i))) \ + KindOfInt##_t next; bool overflow = __builtin_add_overflow(i.value, info->step, &next); \ + if (overflow || (!info->last.is_none && (info->step >= 0 ? next > info->last.value : next < info->last.value))) \ info->current = (Optional##KindOfInt##_t){.is_none=true}; \ else \ - info->current = (Optional##KindOfInt##_t){.i=next}; \ + info->current = (Optional##KindOfInt##_t){.value=next}; \ } \ return i; \ } \ public to_attr Closure_t KindOfInt ## $to(c_type first, c_type last, Optional ## KindOfInt ## _t step) { \ KindOfInt##Range_t *range = GC_MALLOC(sizeof(KindOfInt##Range_t)); \ - range->current = (Optional##KindOfInt##_t){.i=first}; \ - range->last = (Optional##KindOfInt##_t){.i=last}; \ - range->step = step.is_none ? (last >= first ? 1 : -1) : step.i; \ + range->current = (Optional##KindOfInt##_t){.value=first}; \ + range->last = (Optional##KindOfInt##_t){.value=last}; \ + range->step = step.is_none ? (last >= first ? 1 : -1) : step.value; \ return (Closure_t){.fn=_next_##KindOfInt, .userdata=range}; \ } \ public to_attr Closure_t KindOfInt ## $onward(c_type first, c_type step) { \ KindOfInt##Range_t *range = GC_MALLOC(sizeof(KindOfInt##Range_t)); \ - range->current = (Optional##KindOfInt##_t){.i=first}; \ + range->current = (Optional##KindOfInt##_t){.value=first}; \ range->last = (Optional##KindOfInt##_t){.is_none=true}; \ range->step = step; \ return (Closure_t){.fn=_next_##KindOfInt, .userdata=range}; \ @@ -628,7 +628,7 @@ public void Int32$deserialize(FILE *in, void *outval, Array_t*, const TypeInfo_t if (Int$compare_value(full_int, I(max_val)) > 0) { \ return (Optional ## KindOfInt ## _t){.is_none=true}; \ } \ - return (Optional ## KindOfInt ## _t){.i=KindOfInt##$from_int(full_int, true)}; \ + return (Optional ## KindOfInt ## _t){.value=KindOfInt##$from_int(full_int, true)}; \ } \ public CONSTFUNC c_type KindOfInt ## $gcd(c_type x, c_type y) { \ if (x == 0 || y == 0) return 0; \ diff --git a/src/stdlib/integers.h b/src/stdlib/integers.h index 779bee1f..a057327b 100644 --- a/src/stdlib/integers.h +++ b/src/stdlib/integers.h @@ -20,7 +20,7 @@ #define DEFINE_INT_TYPE(c_type, type_name) \ typedef struct { \ - c_type i; \ + c_type value; \ bool is_none:1; \ } Optional ## type_name ## _t; \ Text_t type_name ## $as_text(const void *i, bool colorize, const TypeInfo_t *type); \ diff --git a/src/stdlib/moments.c b/src/stdlib/moments.c deleted file mode 100644 index d1abdfbe..00000000 --- a/src/stdlib/moments.c +++ /dev/null @@ -1,323 +0,0 @@ -// Moment methods/type info -#include <ctype.h> -#include <gc.h> -#include <err.h> -#include <stdio.h> -#include <stdlib.h> -#include <time.h> -#include <unistd.h> - -#include "datatypes.h" -#include "math.h" -#include "moments.h" -#include "optionals.h" -#include "patterns.h" -#include "stdlib.h" -#include "text.h" -#include "util.h" - -static OptionalText_t _local_timezone = NONE_TEXT; - -#define WITH_TIMEZONE(tz, body) ({ if (tz.length >= 0) { \ - OptionalText_t old_timezone = _local_timezone; \ - Moment$set_local_timezone(tz); \ - body; \ - Moment$set_local_timezone(old_timezone); \ - } else { \ - body; \ - }}) - -public Text_t Moment$as_text(const void *moment, bool colorize, const TypeInfo_t*) -{ - if (!moment) - return Text("Moment"); - - struct tm info; - struct tm *final_info = localtime_r(&((Moment_t*)moment)->tv_sec, &info); - static char buf[256]; - size_t len = strftime(buf, sizeof(buf), "%c %Z", final_info); - Text_t text = Text$format("%.*s", (int)len, buf); - if (colorize) - text = Text$concat(Text("\x1b[36m"), text, Text("\x1b[m")); - return text; -} - -PUREFUNC public int32_t Moment$compare(const void *va, const void *vb, const TypeInfo_t*) -{ - Moment_t *a = (Moment_t*)va, *b = (Moment_t*)vb; - if (a->tv_sec != b->tv_sec) - return (a->tv_sec > b->tv_sec) - (a->tv_sec < b->tv_sec); - return (a->tv_usec > b->tv_usec) - (a->tv_usec < b->tv_usec); -} - -CONSTFUNC public bool Moment$is_none(const void *m, const TypeInfo_t*) -{ - return ((Moment_t*)m)->tv_usec < 0; -} - -public Moment_t Moment$now(void) -{ - struct timespec ts; - if (clock_gettime(CLOCK_REALTIME, &ts) != 0) - fail("Couldn't get the time!"); - return (Moment_t){.tv_sec=ts.tv_sec, .tv_usec=ts.tv_nsec/1000}; -} - -public Moment_t Moment$new(Int_t year, Int_t month, Int_t day, Int_t hour, Int_t minute, double second, OptionalText_t tz) -{ - struct tm info = { - .tm_min=Int32$from_int(minute, false), - .tm_hour=Int32$from_int(hour, false), - .tm_mday=Int32$from_int(day, false), - .tm_mon=Int32$from_int(month, false) - 1, - .tm_year=Int32$from_int(year, false) - 1900, - .tm_isdst=-1, - }; - - time_t t; - WITH_TIMEZONE(tz, t = mktime(&info)); - return (Moment_t){.tv_sec=t + (time_t)second, .tv_usec=(suseconds_t)(fmod(second, 1.0) * 1e9)}; -} - -public Moment_t Moment$after(Moment_t moment, double seconds, double minutes, double hours, Int_t days, Int_t weeks, Int_t months, Int_t years, OptionalText_t tz) -{ - double offset = seconds + 60.*minutes + 3600.*hours; - moment.tv_sec += (time_t)offset; - - struct tm info = {}; - WITH_TIMEZONE(tz, localtime_r(&moment.tv_sec, &info)); - - info.tm_mday += Int32$from_int(days, false) + 7*Int32$from_int(weeks, false); - info.tm_mon += Int32$from_int(months, false); - info.tm_year += Int32$from_int(years, false); - - time_t t = mktime(&info); - return (Moment_t){ - .tv_sec=t, - .tv_usec=moment.tv_usec + (suseconds_t)(fmod(offset, 1.0) * 1e9), - }; -} - -CONSTFUNC public double Moment$seconds_till(Moment_t now, Moment_t then) -{ - return (double)(then.tv_sec - now.tv_sec) + 1e-9*(double)(then.tv_usec - now.tv_usec); -} - -CONSTFUNC public double Moment$minutes_till(Moment_t now, Moment_t then) -{ - return Moment$seconds_till(now, then)/60.; -} - -CONSTFUNC public double Moment$hours_till(Moment_t now, Moment_t then) -{ - return Moment$seconds_till(now, then)/3600.; -} - -public void Moment$get( - Moment_t moment, Int_t *year, Int_t *month, Int_t *day, Int_t *hour, Int_t *minute, Int_t *second, - Int_t *nanosecond, Int_t *weekday, OptionalText_t tz) -{ - struct tm info = {}; - WITH_TIMEZONE(tz, localtime_r(&moment.tv_sec, &info)); - - if (year) *year = I(info.tm_year + 1900); - if (month) *month = I(info.tm_mon + 1); - if (day) *day = I(info.tm_mday); - if (hour) *hour = I(info.tm_hour); - if (minute) *minute = I(info.tm_min); - if (second) *second = I(info.tm_sec); - if (nanosecond) *nanosecond = I(moment.tv_usec); - if (weekday) *weekday = I(info.tm_wday + 1); -} - -public Int_t Moment$year(Moment_t moment, OptionalText_t tz) -{ - struct tm info = {}; - WITH_TIMEZONE(tz, localtime_r(&moment.tv_sec, &info)); - return I(info.tm_year + 1900); -} - -public Int_t Moment$month(Moment_t moment, OptionalText_t tz) -{ - struct tm info = {}; - WITH_TIMEZONE(tz, localtime_r(&moment.tv_sec, &info)); - return I(info.tm_mon + 1); -} - -public Int_t Moment$day_of_week(Moment_t moment, OptionalText_t tz) -{ - struct tm info = {}; - WITH_TIMEZONE(tz, localtime_r(&moment.tv_sec, &info)); - return I(info.tm_wday + 1); -} - -public Int_t Moment$day_of_month(Moment_t moment, OptionalText_t tz) -{ - struct tm info = {}; - WITH_TIMEZONE(tz, localtime_r(&moment.tv_sec, &info)); - return I(info.tm_mday); -} - -public Int_t Moment$day_of_year(Moment_t moment, OptionalText_t tz) -{ - struct tm info = {}; - WITH_TIMEZONE(tz, localtime_r(&moment.tv_sec, &info)); - return I(info.tm_yday); -} - -public Int_t Moment$hour(Moment_t moment, OptionalText_t tz) -{ - struct tm info = {}; - WITH_TIMEZONE(tz, localtime_r(&moment.tv_sec, &info)); - return I(info.tm_hour); -} - -public Int_t Moment$minute(Moment_t moment, OptionalText_t tz) -{ - struct tm info = {}; - WITH_TIMEZONE(tz, localtime_r(&moment.tv_sec, &info)); - return I(info.tm_min); -} - -public Int_t Moment$second(Moment_t moment, OptionalText_t tz) -{ - struct tm info = {}; - WITH_TIMEZONE(tz, localtime_r(&moment.tv_sec, &info)); - return I(info.tm_sec); -} - -public Int_t Moment$microsecond(Moment_t moment, OptionalText_t tz) -{ - (void)tz; - return I(moment.tv_usec); -} - -public Text_t Moment$format(Moment_t moment, Text_t fmt, OptionalText_t tz) -{ - struct tm info; - WITH_TIMEZONE(tz, localtime_r(&moment.tv_sec, &info)); - static char buf[256]; - size_t len = strftime(buf, sizeof(buf), Text$as_c_string(fmt), &info); - return Text$format("%.*s", (int)len, buf); -} - -public Text_t Moment$date(Moment_t moment, OptionalText_t tz) -{ - return Moment$format(moment, Text("%F"), tz); -} - -public Text_t Moment$time(Moment_t moment, bool seconds, bool am_pm, OptionalText_t tz) -{ - Text_t text; - if (seconds) - text = Moment$format(moment, am_pm ? Text("%l:%M:%S%P") : Text("%T"), tz); - else - text = Moment$format(moment, am_pm ? Text("%l:%M%P") : Text("%H:%M"), tz); - return Text$trim(text, Pattern(" "), true, true); -} - -public OptionalMoment_t Moment$parse(Text_t text, Text_t format) -{ - struct tm info = {.tm_isdst=-1}; - const char *str = Text$as_c_string(text); - const char *fmt = Text$as_c_string(format); - if (strstr(fmt, "%Z")) - fail("The %Z specifier is not supported for time parsing!"); - - char *invalid = strptime(str, fmt, &info); - if (!invalid || invalid[0] != '\0') - return NONE_MOMENT; - - long offset = info.tm_gmtoff; // Need to cache this because mktime() mutates it to local tz >:( - time_t t = mktime(&info); - return (Moment_t){.tv_sec=t + offset - info.tm_gmtoff}; -} - -static INLINE Text_t num_format(long n, const char *unit) -{ - if (n == 0) - return Text("now"); - return Text$format((n == 1 || n == -1) ? "%ld %s %s" : "%ld %ss %s", n < 0 ? -n : n, unit, n < 0 ? "ago" : "later"); -} - -public Text_t Moment$relative(Moment_t moment, Moment_t relative_to, OptionalText_t tz) -{ - struct tm info = {}; - struct tm relative_info = {}; - WITH_TIMEZONE(tz, { - localtime_r(&moment.tv_sec, &info); - localtime_r(&relative_to.tv_sec, &relative_info); - }); - - double second_diff = Moment$seconds_till(relative_to, moment); - if (info.tm_year != relative_info.tm_year && fabs(second_diff) > 365.*24.*60.*60.) - return num_format((long)info.tm_year - (long)relative_info.tm_year, "year"); - else if (info.tm_mon != relative_info.tm_mon && fabs(second_diff) > 31.*24.*60.*60.) - return num_format(12*((long)info.tm_year - (long)relative_info.tm_year) + (long)info.tm_mon - (long)relative_info.tm_mon, "month"); - else if (info.tm_yday != relative_info.tm_yday && fabs(second_diff) > 24.*60.*60.) - return num_format(round(second_diff/(24.*60.*60.)), "day"); - else if (info.tm_hour != relative_info.tm_hour && fabs(second_diff) > 60.*60.) - return num_format(round(second_diff/(60.*60.)), "hour"); - else if (info.tm_min != relative_info.tm_min && fabs(second_diff) > 60.) - return num_format(round(second_diff/(60.)), "minute"); - else { - if (fabs(second_diff) < 1e-6) - return num_format((long)(second_diff*1e9), "nanosecond"); - else if (fabs(second_diff) < 1e-3) - return num_format((long)(second_diff*1e6), "microsecond"); - else if (fabs(second_diff) < 1.0) - return num_format((long)(second_diff*1e3), "millisecond"); - else - return num_format((long)(second_diff), "second"); - } -} - -CONSTFUNC public Int64_t Moment$unix_timestamp(Moment_t moment) -{ - return (Int64_t)moment.tv_sec; -} - -CONSTFUNC public Moment_t Moment$from_unix_timestamp(Int64_t timestamp) -{ - return (Moment_t){.tv_sec=(time_t)timestamp}; -} - -public void Moment$set_local_timezone(OptionalText_t tz) -{ - if (tz.length >= 0) { - setenv("TZ", Text$as_c_string(tz), 1); - } else { - unsetenv("TZ"); - } - _local_timezone = tz; - tzset(); -} - -public Text_t Moment$get_local_timezone(void) -{ - if (_local_timezone.length < 0) { - static char buf[PATH_MAX]; - ssize_t len = readlink("/etc/localtime", buf, sizeof(buf)); - if (len < 0) - fail("Could not get local tz!"); - - char *zoneinfo = strstr(buf, "/zoneinfo/"); - if (zoneinfo) - _local_timezone = Text$from_str(zoneinfo + strlen("/zoneinfo/")); - else - fail("Could not resolve local tz!"); - } - return _local_timezone; -} - -public const TypeInfo_t Moment$info = { - .size=sizeof(Moment_t), - .align=__alignof__(Moment_t), - .metamethods={ - .as_text=Moment$as_text, - .compare=Moment$compare, - .is_none=Moment$is_none, - }, -}; - -// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0 diff --git a/src/stdlib/moments.h b/src/stdlib/moments.h deleted file mode 100644 index ff6d4119..00000000 --- a/src/stdlib/moments.h +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once - -// Moment objects - -#include <stdint.h> - -#include "datatypes.h" -#include "integers.h" -#include "optionals.h" -#include "types.h" -#include "util.h" - -Text_t Moment$as_text(const void *moment, bool colorize, const TypeInfo_t *type); -PUREFUNC int32_t Moment$compare(const void *a, const void *b, const TypeInfo_t *type); -CONSTFUNC public bool Moment$is_none(const void *m, const TypeInfo_t*); -Moment_t Moment$now(void); -Moment_t Moment$new(Int_t year, Int_t month, Int_t day, Int_t hour, Int_t minute, double second, OptionalText_t timezone); -Moment_t Moment$after(Moment_t moment, double seconds, double minutes, double hours, Int_t days, Int_t weeks, Int_t months, Int_t years, OptionalText_t timezone); -CONSTFUNC double Moment$seconds_till(Moment_t now, Moment_t then); -CONSTFUNC double Moment$minutes_till(Moment_t now, Moment_t then); -CONSTFUNC double Moment$hours_till(Moment_t now, Moment_t then); -Int_t Moment$year(Moment_t moment, OptionalText_t timezone); -Int_t Moment$month(Moment_t moment, OptionalText_t timezone); -Int_t Moment$day_of_week(Moment_t moment, OptionalText_t timezone); -Int_t Moment$day_of_month(Moment_t moment, OptionalText_t timezone); -Int_t Moment$day_of_year(Moment_t moment, OptionalText_t timezone); -Int_t Moment$hour(Moment_t moment, OptionalText_t timezone); -Int_t Moment$minute(Moment_t moment, OptionalText_t timezone); -Int_t Moment$second(Moment_t moment, OptionalText_t timezone); -Int_t Moment$microsecond(Moment_t moment, OptionalText_t timezone); -Text_t Moment$format(Moment_t moment, Text_t fmt, OptionalText_t timezone); -Text_t Moment$date(Moment_t moment, OptionalText_t timezone); -Text_t Moment$time(Moment_t moment, bool seconds, bool am_pm, OptionalText_t timezone); -OptionalMoment_t Moment$parse(Text_t text, Text_t format); -Text_t Moment$relative(Moment_t moment, Moment_t relative_to, OptionalText_t timezone); -CONSTFUNC Int64_t Moment$unix_timestamp(Moment_t moment); -CONSTFUNC Moment_t Moment$from_unix_timestamp(Int64_t timestamp); -void Moment$set_local_timezone(OptionalText_t timezone); -Text_t Moment$get_local_timezone(void); - -extern const TypeInfo_t Moment$info; - -// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0 - diff --git a/src/stdlib/optionals.c b/src/stdlib/optionals.c index 462b2df2..db2c477f 100644 --- a/src/stdlib/optionals.c +++ b/src/stdlib/optionals.c @@ -7,7 +7,6 @@ #include "datatypes.h" #include "integers.h" #include "metamethods.h" -#include "moments.h" #include "nums.h" #include "patterns.h" #include "text.h" diff --git a/src/stdlib/optionals.h b/src/stdlib/optionals.h index 94e4d900..8d25c5f1 100644 --- a/src/stdlib/optionals.h +++ b/src/stdlib/optionals.h @@ -16,7 +16,6 @@ #define NONE_TABLE ((OptionalTable_t){.entries.length=-1}) #define NONE_CLOSURE ((OptionalClosure_t){.fn=NULL}) #define NONE_TEXT ((OptionalText_t){.length=-1}) -#define NONE_MOMENT ((OptionalMoment_t){.tv_usec=-1}) #define NONE_PATH ((Path_t){.type=PATH_NONE}) PUREFUNC bool is_null(const void *obj, const TypeInfo_t *non_optional_type); diff --git a/src/stdlib/paths.c b/src/stdlib/paths.c index c7b560b9..05575620 100644 --- a/src/stdlib/paths.c +++ b/src/stdlib/paths.c @@ -255,28 +255,28 @@ public bool Path$can_execute(Path_t path) #endif } -public OptionalMoment_t Path$modified(Path_t path, bool follow_symlinks) +public OptionalInt64_t Path$modified(Path_t path, bool follow_symlinks) { struct stat sb; int status = path_stat(path, follow_symlinks, &sb); - if (status != 0) return NONE_MOMENT; - return (Moment_t){.tv_sec=sb.st_mtime}; + if (status != 0) return NONE_INT64; + return (OptionalInt64_t){.value=(int64_t)sb.st_mtime}; } -public OptionalMoment_t Path$accessed(Path_t path, bool follow_symlinks) +public OptionalInt64_t Path$accessed(Path_t path, bool follow_symlinks) { struct stat sb; int status = path_stat(path, follow_symlinks, &sb); - if (status != 0) return NONE_MOMENT; - return (Moment_t){.tv_sec=sb.st_atime}; + if (status != 0) return NONE_INT64; + return (OptionalInt64_t){.value=(int64_t)sb.st_atime}; } -public OptionalMoment_t Path$changed(Path_t path, bool follow_symlinks) +public OptionalInt64_t Path$changed(Path_t path, bool follow_symlinks) { struct stat sb; int status = path_stat(path, follow_symlinks, &sb); - if (status != 0) return NONE_MOMENT; - return (Moment_t){.tv_sec=sb.st_ctime}; + if (status != 0) return NONE_INT64; + return (OptionalInt64_t){.value=(int64_t)sb.st_ctime}; } static void _write(Path_t path, Array_t bytes, int mode, int permissions) diff --git a/src/stdlib/paths.h b/src/stdlib/paths.h index 02afc494..9be81bdf 100644 --- a/src/stdlib/paths.h +++ b/src/stdlib/paths.h @@ -28,9 +28,9 @@ bool Path$is_symlink(Path_t path); bool Path$can_read(Path_t path); bool Path$can_write(Path_t path); bool Path$can_execute(Path_t path); -OptionalMoment_t Path$modified(Path_t path, bool follow_symlinks); -OptionalMoment_t Path$accessed(Path_t path, bool follow_symlinks); -OptionalMoment_t Path$changed(Path_t path, bool follow_symlinks); +OptionalInt64_t Path$modified(Path_t path, bool follow_symlinks); +OptionalInt64_t Path$accessed(Path_t path, bool follow_symlinks); +OptionalInt64_t Path$changed(Path_t path, bool follow_symlinks); void Path$write(Path_t path, Text_t text, int permissions); void Path$write_bytes(Path_t path, Array_t bytes, int permissions); void Path$append(Path_t path, Text_t text, int permissions); diff --git a/src/stdlib/tomo.h b/src/stdlib/tomo.h index 567e5d14..16e5ec57 100644 --- a/src/stdlib/tomo.h +++ b/src/stdlib/tomo.h @@ -17,7 +17,6 @@ #include "integers.h" #include "memory.h" #include "metamethods.h" -#include "moments.h" #include "mutexeddata.h" #include "nums.h" #include "optionals.h" |
