Commits

Sebastian Freundt  committed a92b789 Merge

Merge branch 'feat/default' into next

* feat/default:
minor, go straight to time massaging in massage_strpdt() when no strpd_s field is set
Revert "minor, leave a note about our massaging business in strpdt_s objects"
minor, leave a note about our massaging business in strpdt_s objects
minor, don't check (or set) nanosecond field, nothing is below that in the hierarchy
minor, instead of checking strpt_s values for 0, check their set field (h_set, m_set, ...)
minor, split up strpt_s' component_set field into h_set, m_set, etc.
hygiene, follow strpt_s' union wrap of flags field in strpd_s
hygiene, wrap strpt_s flags in union named flags
minor, provide a massage routine for strpdt_s objects filling in missing values according to global `now'
hygiene, provide and use singletons (now_tv() and now_tm()) to obtain the current date/time, ...
chore, provide handy helper with(){} in nifty.h
hygiene, move comments where they belong
hygiene, don't expose __trans_dtfmt()
hygiene, don't expose __trans_dfmt()

  • Participants
  • Parent commits ebb6951, e93fc85

Comments (0)

Files changed (9)

File lib/date-core-strpf.h

 	signed int c;
 	signed int w;
 	/* general flags */
-	struct {
-		unsigned int ab:1;
-		unsigned int bizda:1;
-		unsigned int d_dcnt_p:1;
-		unsigned int c_wcnt_p:1;
-		unsigned int wk_cnt:2;/*%C,%W,%U,%V*/
-		unsigned int real_y_in_q:1;
+	union {
+		unsigned int u;
+		struct {
+			unsigned int ab:1;
+			unsigned int bizda:1;
+			unsigned int d_dcnt_p:1;
+			unsigned int c_wcnt_p:1;
+			unsigned int wk_cnt:2;/*%C,%W,%U,%V*/
+			unsigned int real_y_in_q:1;
+		};
 	} flags;
 	signed int b;
 	signed int q;

File lib/date-core.c

 	return DT_DUNK;
 }
 
-DEFUN void
+static void
 __trans_dfmt(const char **fmt)
 {
 	if (UNLIKELY(*fmt == NULL)) {
 			}
 		}
 	}
-	/* set the end pointer */
 	res = __guess_dtyp(d);
 out:
+	/* set the end pointer */
 	if (ep != NULL) {
 		*ep = (char*)sp;
 	}

File lib/date-core.h

 
 /* functions that really shouldn't be exposed */
 /**
- * Transform named format strings in FMT to their flag notation.
- * E.g. ymd -> %F */
-DECLF void __trans_dfmt(const char **fmt);
-
-/**
  * Get the week count of D in the year when weeks start at WDAYS_FROM. */
 DECLF int __ymd_get_wcnt(dt_ymd_t d, int wdays_from);
 

File lib/dt-core.c

 static const char bizsihms_dflt[] = "%dbT%T";
 static const char bizdahms_dflt[] = "%Y-%m-%dbT%T";
 
-DEFUN void
+static void
 __trans_dtfmt(const char **fmt)
 {
 	if (UNLIKELY(*fmt == NULL)) {
 	return;
 }
 
+static struct timeval
+now_tv(void)
+{
+/* singleton, gives a consistent `now' throughout the whole run */
+	static struct timeval tv;
+
+	if (LIKELY(tv.tv_sec)) {
+		/* perfect */
+		;
+	} else if (gettimeofday(&tv, NULL) < 0) {
+		/* big cinema :( */
+		tv = (struct timeval){0U, 0U};
+	}
+	return tv;
+}
+
+static struct tm
+now_tm(void)
+{
+/* singleton, gives a consistent `now' throughout the whole run */
+	static struct tm tm;
+	struct timeval tv;
+
+	if (LIKELY(tm.tm_year)) {
+		/* sit back and relax */
+		;
+	} else if ((tv = now_tv()).tv_sec == 0U) {
+		/* big cinema :( */
+		tm = (struct tm){0U};
+	} else {
+		ffff_gmtime(&tm, tv.tv_sec);
+	}
+	return tm;
+}
+
+static struct strpdt_s
+massage_strpdt(struct strpdt_s d)
+{
+/* the reason we do this separately is that we don't want to bother
+ * the pieces of code that use the guesser for different reasons */
+	if (UNLIKELY(d.sd.y == 0U)) {
+		static const struct strpd_s d0 = {};
+		struct tm now = now_tm();
+
+		if (UNLIKELY(memcmp(&d.sd, &d0, sizeof(d0)) == 0U)) {
+			goto msgg_time;
+		}
+
+		d.sd.y = now.tm_year;
+		if (LIKELY(d.sd.m)) {
+			goto out;
+		}
+		d.sd.m = now.tm_mon;
+		if (LIKELY(d.sd.d)) {
+			goto out;
+		}
+		d.sd.d = now.tm_mday;
+
+	msgg_time:
+		/* same for time values, but obtain those through now_tv() */
+		if (UNLIKELY(!d.st.flags.h_set)) {
+			struct timeval tv = now_tv();
+
+			d.st.h = (tv.tv_sec % 86400U) / 60U / 60U;
+			if (LIKELY(d.st.flags.m_set)) {
+				goto out;
+			}
+			d.st.m = (tv.tv_sec % 3600U) / 60U;
+			if (LIKELY(d.st.flags.s_set)) {
+				goto out;
+			}
+			d.st.s = (tv.tv_sec % 60U);
+		}
+	}
+out:
+	return d;
+}
+
 #if defined WITH_LEAP_SECONDS
 static zidx_t
 leaps_before(struct dt_dt_s d)
 		res.sexy = d.i;
 	} else {
 		/* assign d and t types using date and time core routines */
+		d = massage_strpdt(d);
 		res.d = __guess_dtyp(d.sd);
 		res.t = __guess_ttyp(d.st);
 
 dt_datetime(dt_dttyp_t outtyp)
 {
 	struct dt_dt_s res = dt_dt_initialiser();
-	struct timeval tv;
 	const dt_dtyp_t outdtyp = (dt_dtyp_t)outtyp;
 
-	if (gettimeofday(&tv, NULL) < 0) {
-		return res;
-	}
-
 	switch (outdtyp) {
 	case DT_YMD:
 	case DT_YMCW: {
-		struct tm tm;
-		ffff_gmtime(&tm, tv.tv_sec);
+		struct tm tm = now_tm();
 		switch (outdtyp) {
 		case DT_YMD:
 			res.d.ymd.y = tm.tm_year;
 	}
 	case DT_DAISY:
 		/* time_t's base is 1970-01-01, which is daisy 19359 */
-		res.d.daisy = tv.tv_sec / 86400U + DAISY_UNIX_BASE;
+		with (struct timeval tv = now_tv()) {
+			res.d.daisy = tv.tv_sec / 86400U + DAISY_UNIX_BASE;
+		}
 		break;
 
 	case DT_MD:
 	}
 
 	/* time assignment */
-	{
+	with (struct timeval tv = now_tv()) {
 		unsigned int tonly = tv.tv_sec % 86400U;
 		res.t.hms.h = tonly / SECS_PER_HOUR;
 		tonly %= SECS_PER_HOUR;

File lib/dt-core.h

 
 /* more specific but still useful functions */
 /**
- * Transform named format strings in FMT to their flag notation.
- * E.g. ymd -> %FT%T */
-DECLF void __trans_dtfmt(const char **fmt);
-
-/**
  * Convert a dt_dt_s to an epoch difference, based on the Unix epoch. */
 extern dt_ssexy_t dt_to_unix_epoch(struct dt_dt_s);
 
 # define countof(x)	(sizeof(x) / sizeof(*x))
 #endif	/* !countof */
 
+#if !defined with
+# define with(args...)	for (args, *__ep__ = (void*)1; __ep__; __ep__ = 0)
+#endif	/* !with */
+
 #endif	/* INCLUDED_nifty_h_ */

File lib/time-core-strpf.c

 			;
 		} else if ((sp[0] | casebit) == 'p' &&
 			   (sp[1] | casebit) == 'm') {
-			d->am_pm_bit = 1;
+			d->flags.am_pm_bit = 1;
 		} else {
 			goto fucked;
 		}
 	/* check if components got set */
 	switch (s.spfl) {
 	case DT_SPFL_N_TSTD:
+		d->flags.h_set = 1;
+		d->flags.m_set = 1;
+		d->flags.s_set = 1;
+		break;
 	case DT_SPFL_N_HOUR:
+		d->flags.h_set = 1;
+		break;
 	case DT_SPFL_N_MIN:
+		d->flags.m_set = 1;
+		break;
 	case DT_SPFL_N_SEC:
+		d->flags.s_set = 1;
+		break;
 	case DT_SPFL_N_NANO:
-		d->component_set = 1;
+		d->flags.ns_set = 1;
+		break;
 	default:
 		break;
 	}

File lib/time-core-strpf.h

 	signed int s;
 	signed int ns;
 	union {
-		unsigned int flags;
+		unsigned int u;
 		struct {
 			/* 0 for am, 1 for pm */
 			unsigned int am_pm_bit:1;
-			/* 0 if no component has been set, 1 otherwise */
-			unsigned int component_set:1;
+
+			unsigned int h_set:1;
+			unsigned int m_set:1;
+			unsigned int s_set:1;
+			unsigned int ns_set:1;
 		};
-	};
+	} flags;
 };
 
 

File lib/time-core.c

 {
 	struct dt_t_s res;
 
-	if (UNLIKELY(!t.component_set)) {
+	if (UNLIKELY(!(t.flags.h_set || t.flags.m_set ||
+		       t.flags.s_set || t.flags.ns_set))) {
 		goto fucked;
 	}
 	if (UNLIKELY(t.h < 0)) {
 	res.hms.h = t.h;
 	res.hms.ns = t.ns;
 
-	if (t.am_pm_bit) {
+	if (t.flags.am_pm_bit) {
 		/* pm */
 		res.hms.h += 12;
 		res.hms.h %= HOURS_PER_DAY;