aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChloe Kudryavtsev <code@toast.bunkerlabs.net>2023-05-12 16:53:08 -0400
committerChloe Kudryavtsev <code@toast.bunkerlabs.net>2023-05-12 16:53:08 -0400
commit2d2617b63706b8781418565330d23449701b3a71 (patch)
treed23b163114289f7a5d4bed749b916603f244319e /src
parentinvestigating... (diff)
big updates
ok I figured out what the problem was, I think? put is nice too now, no more conversions eh also offsets are nice, makes iterating way easier
Diffstat (limited to 'src')
-rw-r--r--src/date.h5
-rw-r--r--src/time.c14
-rw-r--r--src/tm.c126
-rw-r--r--src/util.c44
4 files changed, 93 insertions, 96 deletions
diff --git a/src/date.h b/src/date.h
index de0eb2b..3661421 100644
--- a/src/date.h
+++ b/src/date.h
@@ -5,14 +5,11 @@
// util.c
JanetBuffer *strftime_buffer(const char *format, const struct tm *tm, JanetBuffer *buffer);
-struct tm *jd_tm_from_dict(JanetDictView dict);
-JanetTable *jd_tm_to_table(struct tm *tm);
// time.c
extern const JanetRegExt jd_time_cfuns[];
time_t *jd_gettime(Janet *argv, int32_t n);
time_t *jd_maketime(void);
-JANET_CFUN(jd_dict_time);
JANET_CFUN(jd_gmtime);
JANET_CFUN(jd_localtime);
JANET_CFUN(jd_time);
@@ -21,8 +18,6 @@ JANET_CFUN(jd_time);
extern const JanetRegExt jd_tm_cfuns[];
struct tm *jd_gettm(Janet *argv, int32_t n);
struct tm *jd_maketm(void);
-JANET_CFUN(jd_dict_tm);
JANET_CFUN(jd_mktime);
JANET_CFUN(jd_mktime_inplace);
JANET_CFUN(jd_strftime);
-JANET_CFUN(jd_tm_dict);
diff --git a/src/time.c b/src/time.c
index 64096c7..2993030 100644
--- a/src/time.c
+++ b/src/time.c
@@ -6,7 +6,6 @@
static JanetMethod jd_time_methods[] = {
{"gmtime", jd_gmtime},
{"localtime", jd_localtime},
- {"todict", jd_dict_time},
{NULL, NULL},
};
@@ -25,8 +24,9 @@ static int jd_time_get(void *p, Janet key, Janet *out) {
}
// time_t is always a UTC-representation
+// we hard-code the offset because of a macOS bug
static void jd_time_tostring(void *p, JanetBuffer *buffer) {
- strftime_buffer("%F %T.000 UTC", localtime(p), buffer);
+ strftime_buffer("%F %T.000 +0000", gmtime(p), buffer);
}
static const JanetAbstractType jd_time_t = {
@@ -50,15 +50,6 @@ time_t *jd_maketime(void) {
return janet_abstract(&jd_time_t, sizeof(time_t));
}
-JANET_FN(jd_dict_time,
- "(dict->time {...})",
- "") {
- janet_fixarity(argc, 1);
- JanetDictView dict = janet_getdictionary(argv, 0);
- struct tm *tm = jd_tm_from_dict(dict);
- return janet_wrap_abstract(tm);
-}
-
JANET_FN(jd_gmtime,
"(gmtime (time))",
"") {
@@ -92,7 +83,6 @@ JANET_FN(jd_time,
}
const JanetRegExt jd_time_cfuns[] = {
- JANET_REG("dict->time", jd_dict_time),
JANET_REG("gmtime", jd_gmtime),
JANET_REG("localtime", jd_localtime),
JANET_REG("time", jd_time),
diff --git a/src/tm.c b/src/tm.c
index 5d2abff..d078def 100644
--- a/src/tm.c
+++ b/src/tm.c
@@ -8,7 +8,6 @@ static JanetMethod jd_tm_methods[] = {
{"mktime!", jd_mktime_inplace},
{"normalize", jd_mktime_inplace},
{"strftime", jd_strftime},
- {"todict", jd_tm_dict},
{NULL, NULL},
};
@@ -20,6 +19,24 @@ static int jd_tm_compare(void *lhs, void *rhs) {
return difftime(lhv, rhv);
}
+// C99 specifies ALL fields to be int
+struct jd_tm_key {
+ const char *key;
+ const size_t off;
+};
+static const struct jd_tm_key jd_tm_keys[] = {
+ {"sec", offsetof(struct tm, tm_sec)},
+ {"min", offsetof(struct tm, tm_min)},
+ {"hour", offsetof(struct tm, tm_hour)},
+ {"mday", offsetof(struct tm, tm_mday)},
+ {"mon", offsetof(struct tm, tm_mon)},
+ {"year", offsetof(struct tm, tm_year)},
+ {"wday", offsetof(struct tm, tm_wday)},
+ {"yday", offsetof(struct tm, tm_yday)},
+ {"isdst", offsetof(struct tm, tm_isdst)},
+ {NULL, 0},
+};
+
static int jd_tm_get(void *p, Janet key, Janet *out) {
if (!janet_checktype(key, JANET_KEYWORD)) {
return 0;
@@ -30,32 +47,89 @@ static int jd_tm_get(void *p, Janet key, Janet *out) {
return 1;
}
- // piggyback off jd_tm_to_table
- JanetTable *tb = jd_tm_to_table(p);
- *out = janet_table_rawget(tb, key);
+ const struct jd_tm_key *ptr = jd_tm_keys;
+ while (ptr->key) {
+ if (janet_keyeq(key, ptr->key)) {
+ int val = *((int*)(p + ptr->off));
+
+ // exceptional values
+ if (janet_keyeq(key, "year")) {
+ val += 1900;
+ } else if (janet_keyeq(key, "isdst")) {
+ *out = val ? (val > 0 ? janet_wrap_true() : janet_ckeywordv("detect")) : janet_wrap_false();
+ return 1;
+ }
+
+ *out = janet_wrap_integer(val);
+ return 1;
+ }
+ ptr++;
+ }
return janet_checktype(*out, JANET_NIL);
}
-
-static const char* jd_tm_keys[] = {
- "sec", "min", "hour", "mday", "mon", "year", "wday", "yday", NULL,
-};
static Janet jd_tm_next(void *p, Janet key) {
(void) p;
- const char **ptr = jd_tm_keys;
- while (*ptr) {
- if (janet_keyeq(key, *ptr)) {
- return *(++ptr) ? janet_ckeywordv(*ptr) : janet_wrap_nil();
+ const struct jd_tm_key *ptr = jd_tm_keys;
+ while (ptr->key) {
+ if (janet_keyeq(key, ptr->key)) {
+ return (++ptr)->key ? janet_ckeywordv(ptr->key) : janet_wrap_nil();
+ }
+ ptr++;
+ }
+ return janet_ckeywordv(jd_tm_keys[0].key);
+}
+
+static void jd_tm_put(void *data, Janet key, Janet value) {
+ // note that keyword, boolean are only valid for isdst
+ if (!janet_checktypes(value, JANET_TFLAG_NUMBER | JANET_TFLAG_KEYWORD | JANET_TFLAG_BOOLEAN)) {
+ janet_panicf("expected function or number, got %t", value);
+ }
+ const struct jd_tm_key *ptr = jd_tm_keys;
+ while (ptr->key) {
+ if (janet_keyeq(key, ptr->key)) {
+ int *loc = (int*)(data + ptr->off);
+ if (janet_keyeq(key, "year")) {
+ *loc = janet_unwrap_integer(value) - 1900;
+ } else if (janet_keyeq(key, "isdst")) {
+ *loc = janet_keyeq(value, "detect") ? -1 : (janet_truthy(value) ? 1 : 0);
+ } else {
+ *loc = janet_unwrap_integer(value);
+ }
+ return;
}
ptr++;
}
- return janet_ckeywordv(jd_tm_keys[0]);
+
+ janet_panicf("tried to write to invalid field: %v", key);
}
-// struct tm can represent non-UTC
-// it does not keep TZ information so we can't display it without potentially lying
+#define MAX_INT_STRLEN 1024
static void jd_tm_tostring(void *p, JanetBuffer *buffer) {
- strftime_buffer("%F %T.000", p, buffer);
+ janet_buffer_push_cstring(buffer, "{");
+ char buf[MAX_INT_STRLEN];
+
+ const struct jd_tm_key *ptr = jd_tm_keys;
+ while (ptr->key) {
+ int *loc = (int*)(p + ptr->off);
+ janet_buffer_push_cstring(buffer, ":");
+ janet_buffer_push_cstring(buffer, ptr->key);
+ janet_buffer_push_cstring(buffer, " ");
+
+ // exceptional values
+ if (!strcmp(ptr->key, "year")) {
+ snprintf(buf, MAX_INT_STRLEN, "%d", *loc + 1900);
+ } else if (!strcmp(ptr->key, "isdst")) {
+ strcpy(buf, *loc ? (*loc > 0 ? "true" : ":detect") : "false");
+ } else {
+ snprintf(buf, MAX_INT_STRLEN, "%d", *loc);
+ }
+ janet_buffer_push_cstring(buffer, buf);
+
+ if ((++ptr)->key) janet_buffer_push_cstring(buffer, " ");
+ }
+
+ janet_buffer_push_cstring(buffer, "}");
}
static const JanetAbstractType jd_tm_t = {
@@ -63,7 +137,7 @@ static const JanetAbstractType jd_tm_t = {
NULL,
NULL,
jd_tm_get,
- NULL,
+ jd_tm_put,
NULL,
NULL,
jd_tm_tostring,
@@ -81,14 +155,6 @@ struct tm *jd_maketm(void) {
return janet_abstract(&jd_tm_t, sizeof(struct tm));
}
-JANET_FN(jd_dict_tm,
- "",
- "") {
- janet_fixarity(argc, 1);
- JanetDictView dict = janet_getdictionary(argv, 0);
- return janet_wrap_abstract(jd_tm_from_dict(dict));
-}
-
JANET_FN(jd_mktime,
"",
"") {
@@ -111,14 +177,6 @@ JANET_FN(jd_mktime_inplace,
return janet_wrap_abstract(time);
}
-JANET_FN(jd_tm_dict,
- "",
- "") {
- janet_fixarity(argc, 1);
- struct tm *tm = jd_gettm(argv, 0);
- return janet_wrap_table(jd_tm_to_table(tm));
-}
-
// strftime
struct strftime_format {
const char *keyword;
@@ -155,10 +213,8 @@ JANET_FN(jd_strftime,
}
const JanetRegExt jd_tm_cfuns[] = {
- JANET_REG("dict->tm", jd_dict_tm),
JANET_REG("mktime", jd_mktime),
JANET_REG("mktime!", jd_mktime_inplace),
JANET_REG("strftime", jd_strftime),
- JANET_REG("tm->dict", jd_tm_dict),
JANET_REG_END
};
diff --git a/src/util.c b/src/util.c
index 95d3ded..bc26163 100644
--- a/src/util.c
+++ b/src/util.c
@@ -12,47 +12,3 @@ JanetBuffer *strftime_buffer(const char *format, const struct tm *tm, JanetBuffe
buffer->count = written + offset; // does not include \0, but we don't want it anyway
return buffer;
}
-
-static inline void tm_set_dict(JanetDictView dict, char *key, int *v) {
- Janet k = janet_dictionary_get(dict.kvs, dict.cap, janet_ckeywordv(key));
- *v = janet_checktype(k, JANET_NUMBER) ? janet_unwrap_integer(k) : 0;
-}
-struct tm *jd_tm_from_dict(JanetDictView dict) {
- struct tm *tm = jd_maketm();
-
- tm_set_dict(dict, "sec", &tm->tm_sec);
- tm_set_dict(dict, "min", &tm->tm_min);
- tm_set_dict(dict, "hour", &tm->tm_hour);
- tm_set_dict(dict, "mday", &tm->tm_mday);
- tm_set_dict(dict, "mon", &tm->tm_mon);
- Janet year = janet_dictionary_get(dict.kvs, dict.cap, janet_ckeywordv("year"));
- tm->tm_year = janet_checktype(year, JANET_NUMBER) ? janet_unwrap_integer(year) - 1900 : 0;
- tm_set_dict(dict, "wday", &tm->tm_wday);
- tm_set_dict(dict, "yday", &tm->tm_yday);
- Janet isdst = janet_dictionary_get(dict.kvs, dict.cap, janet_ckeywordv("isdst"));
- tm->tm_isdst = janet_keyeq(isdst, "detect") ? -1 : (janet_truthy(isdst) ? 1 : 0);
-
- return tm;
-}
-
-#define PUTV(T, K, V) janet_table_put(T, janet_ckeywordv(K), V)
-#define PUT(T, K, V) PUTV(T, K, janet_wrap_integer(V))
-JanetTable *jd_tm_to_table(struct tm *tm) {
- JanetTable *out = janet_table(9);
-
- PUT(out, "sec", tm->tm_sec);
- PUT(out, "min", tm->tm_min);
- PUT(out, "hour", tm->tm_hour);
- PUT(out, "mday", tm->tm_mday);
- PUT(out, "mon", tm->tm_mon);
- PUT(out, "year", tm->tm_year + 1900);
- PUT(out, "wday", tm->tm_wday);
- PUT(out, "yday", tm->tm_yday);
- if (tm->tm_isdst < 0) {
- PUTV(out, "isdst", janet_ckeywordv("detect"));
- } else {
- PUTV(out, "isdst", tm->tm_isdst ? janet_wrap_true() : janet_wrap_false());
- }
-
- return out;
-}