Beispiel #1
0
static dt_dttyp_t
determine_durtype(struct dt_dt_s d1, struct dt_dt_s d2, durfmt_t f)
{
	/* the type-multiplication table looks like:
	 *
	 * -   D   T   DT
	 * D   d   x   d
	 * T   x   t   x
	 * DT  d   x   s
	 *
	 * where d means a ddur type, t a tdur type and s is DT_SEXY */

	if ((dt_sandwich_only_d_p(d1) || dt_sandwich_only_d_p(d2)) &&
	    (dt_sandwich_only_t_p(d1) || dt_sandwich_only_t_p(d2))) {
		;
	} else if (dt_sandwich_only_d_p(d1) || dt_sandwich_only_d_p(d2)) {
		if (f.has_week && (f.has_mon || f.has_year)) {
			return (dt_dttyp_t)DT_YMCW;
		} else if (f.has_mon || f.has_year) {
			return (dt_dttyp_t)DT_YMD;
		} else if (f.has_day && f.has_biz) {
			return (dt_dttyp_t)DT_BIZSI;
		} else if (f.has_day || f.has_week || f.flags == 0) {
			return (dt_dttyp_t)DT_DAISY;
		} else {
			return (dt_dttyp_t)DT_MD;
		}
	} else if ((dt_sandwich_only_t_p(d1) && dt_sandwich_only_t_p(d2)) ||
		   (dt_sandwich_p(d1) && dt_sandwich_p(d2))) {
		return (dt_dttyp_t)DT_SEXY;
	}
	return DT_UNK;
}
Beispiel #2
0
static bool
__in_range_p(struct dt_dt_s now, const struct dseq_clo_s *clo)
{
	if (!dt_sandwich_only_t_p(now)) {
		if (clo->dir > 0) {
			return dt_dt_in_range_p(now, clo->fst, clo->lst) == 1;
		} else if (clo->dir < 0) {
			return dt_dt_in_range_p(now, clo->lst, clo->fst) == 1;
		}
	}
	/* otherwise perform a simple range check */
	if (clo->dir > 0) {
		if (clo->fst.t.u < clo->lst.t.u) {
			/* dseq A B  with A < B */
			return now.t.u >= clo->fst.t.u &&
				now.t.u <= clo->lst.t.u;
		} else {
			/* dseq A B  with A > B and wrap-around,
			 * carries have kindly been stored in d.u */
			return now.t.u <= clo->lst.t.u || now.d.u == 0U;
		}
	} else if (clo->dir < 0) {
		if (clo->fst.t.u > clo->lst.t.u) {
			/* counting down from A to B */
			return now.t.u <= clo->fst.t.u &&
				now.t.u >= clo->lst.t.u;
		} else {
			/* count down from A to B with wrap around,
			 * carries have kindly been stored in d.u */
			return now.t.u >= clo->lst.t.u || now.d.u == 0U;
		}
	}
	return false;
}
Beispiel #3
0
static bool
__in_range_p(struct dt_dt_s now, struct dseq_clo_s *clo)
{
	if (!dt_sandwich_only_t_p(now)) {
		if (clo->dir > 0) {
			return dt_dt_in_range_p(now, clo->fst, clo->lst);
		} else if (clo->dir < 0) {
			return dt_dt_in_range_p(now, clo->lst, clo->fst);
		}
	}
	/* otherwise perform a simple range check */
	if (clo->dir > 0) {
		if (now.t.u >= clo->fst.t.u && now.t.u <= clo->lst.t.u) {
			return true;
		} else if (clo->fst.t.u >= clo->lst.t.u) {
			return now.t.u <= clo->lst.t.u || now.d.daisydur == 0;
		}
	} else if (clo->dir < 0) {
		if (now.t.u <= clo->fst.t.u && now.t.u >= clo->lst.t.u) {
			return true;
		} else if (clo->fst.t.u <= clo->lst.t.u) {
			return now.t.u >= clo->lst.t.u || now.d.daisydur == 0;
		}
	}
	return false;
}
Beispiel #4
0
static int
__cmp(struct dt_dt_s stream, struct dt_dt_s cell)
{
/* special promoting/demoting version of dt_dtcmp()
 * if CELL is d-only or t-only, demote STREAM */
	if (dt_sandwich_only_d_p(cell)) {
		return dt_dcmp(stream.d, cell.d);
	} else if (dt_sandwich_only_t_p(cell)) {
		return dt_tcmp(stream.t, cell.t);
	}
	return dt_dtcmp(stream, cell);
}
Beispiel #5
0
/**
 * Return a dt object that forgot about DT's zone and uses ZONE instead. */
DEFUN struct dt_dt_s
dtz_forgetz(struct dt_dt_s d, zif_t zone)
{
	struct dt_dt_s res;
	dt_ssexy_t d_unix;

	if (dt_sandwich_only_d_p(d) || dt_sandwich_only_t_p(d)) {
		return d;
	}

	/* convert date/time part to unix stamp */
	d_unix = ____to_unix_epoch(d);
	d_unix = zif_utc_time(zone, d_unix);

	/* convert the date part back */
	if (d.typ > (dt_dttyp_t)DT_DUNK && d.typ < (dt_dttyp_t)DT_NDTYP) {
		int32_t sexy = __pos_mod(d_unix, 86400);

		/* temporarily go daisy */
		res.d.typ = DT_DAISY;
		res.d.daisy = d_unix / 86400 + DAISY_UNIX_BASE;
		res.d = dt_dconv(d.d.typ, res.d);

		/* set the other flags too */
		res.sandwich = d.sandwich;
		res.dur = 0;
		res.neg = 0;

		/* convert the time part back */
		res.t.hms.s = sexy % 60;
		res.t.hms.m = (sexy % 3600) / 60;
		res.t.hms.h = sexy / 3600;
		res.t.hms.ns = d.t.hms.ns;

		res.t.typ = DT_HMS;
		res.t.dur = 0;
		res.t.neg = 0;
		res.t.carry = 0;

	} else if (d.typ == DT_SEXY) {
		res.typ = DT_SEXY;
		res.sandwich = 0;
		res.dur = 0;
		res.neg = 0;
		res.sxepoch = d_unix;

	} else {
		res = dt_dt_initialiser();
	}
	return res;
}
Beispiel #6
0
static int
__get_dir(struct dt_dt_s d, const struct dseq_clo_s *clo)
{
	if (!dt_sandwich_only_t_p(d)) {
		/* trial addition to to see where it goes */
		struct dt_dt_s tmp = __seq_next(d, clo);
		return dt_dtcmp(tmp, d);
	}
	if (clo->ite->dv > 0) {
		return 1;
	} else if (clo->ite->dv < 0) {
		return -1;
	}
	return 0;
}
Beispiel #7
0
static struct dt_dt_s
date_add(struct dt_dt_s d, struct dt_dtdur_s dur[], size_t ndur)
{
	int32_t carries = d.d.u;

	for (size_t i = 0; i < ndur; i++) {
		d = dt_dtadd(d, dur[i]);
		/* keep track of carries */
		carries += d.t.carry;
	}
	if (UNLIKELY(dt_sandwich_only_t_p(d))) {
		d.d.u = carries;
	}
	return d;
}
Beispiel #8
0
static int
test_t_only_no_fmt(void)
{
	static const char str[] = "12:34:56";
	struct dt_dt_s d;
	int res = 0;

	/* 12:34:56 (using no format) */
	fprintf(stderr, "testing %s ...\n", str);
	d = dt_strpdt(str, NULL, NULL);

	CHECK(!d.sandwich,
	      "  NOT A SANDWICH ... but should be\n");
	CHECK(!dt_sandwich_only_t_p(d), "  TYPE is not a t-only\n");
	CHECK(d.typ != DT_SANDWICH_UNK,
	      "  TYPE DIFFERS %u ... should be %u\n",
	      (unsigned int)d.typ,
	      (unsigned int)DT_SANDWICH_UNK);
	CHECK(d.t.typ != DT_HMS,
	      "  TIME TYPE DIFFERS %u ... should be %u\n",
	      (unsigned int)d.t.typ,
	      (unsigned int)DT_HMS);
	CHECK(d.d.u,
	      "  DATE COMPONENT NOT NAUGHT %" PRIu64 "\n",
	      (uint64_t)d.d.u);
	CHECK(d.dur, "  DURATION BIT SET\n");
	CHECK(d.neg, "  NEGATED BIT SET\n");
	CHECK(d.t.dur, "  TIME DURATION BIT SET\n");
	CHECK(d.t.neg, "  TIME DURATION BIT SET\n");

	CHECK(d.t.hms.h != 12,
		"  HOUR %u ... should be 12\n",
	      (unsigned int)d.t.hms.h);
	CHECK(d.t.hms.m != 34,
	      "  MINUTE %u ... should be 34\n",
	      (unsigned int)d.t.hms.m);
	CHECK(d.t.hms.s != 56,
	      "  SECOND %u ... should be 56\n",
	      (unsigned int)d.t.hms.s);
	CHECK(d.t.hms.ns != 0,
	      "  NANOSECOND %u ... should be 0\n",
	      (unsigned int)d.t.hms.ns);
	/* make sure the padding leaves no garbage */
	CHECK_RES(res, d.t.hms.u & ~0x1f3f3f3fffffff,
		  "  PADDING NOT NAUGHT %x\n",
		  (unsigned int)(d.t.hms.u & ~0x1f3f3f3fffffff));
	return res;
}
Beispiel #9
0
static inline struct dt_dt_s
dt_conv_to_sexy(struct dt_dt_s dt)
{
	if (dt.typ == DT_SEXY) {
		return dt;
	} else if (dt_sandwich_only_t_p(dt)) {
		dt.sxepoch = (dt.t.hms.h * 60 + dt.t.hms.m) * 60 + dt.t.hms.s;
	} else if (dt_sandwich_p(dt) || dt_sandwich_only_d_p(dt)) {
		dt.sxepoch = __to_unix_epoch(dt);
	} else {
		dt = dt_dt_initialiser();
	}
	/* make sure we hand out sexies */
	dt.typ = DT_SEXY;
	return dt;
}
Beispiel #10
0
static void
proc_line(struct prln_ctx_s ctx, char *line, size_t llen)
{
	struct dt_dt_s d;

	do {
		char buf[64U];
		char *sp, *tp;
		char *bp = buf;
		const char *const ep = buf + sizeof(buf);

		/* find first occurrence then */
		d = dt_io_find_strpdt2(
			line, llen, ctx.ndl, &sp, &tp, ctx.fromz);
		/* print line, first thing */
		safe_write(ctx.outfd, line, llen);

		/* extend by separator */
		*bp++ = '\001';
		/* check if line matches */
		if (!dt_unk_p(d)) {
			/* match! */
			if (!dt_sandwich_only_t_p(d)) {
				bp += dt_strfdt(bp, ep - bp, "%F", d);
			}
			*bp++ = '\001';
			if (!dt_sandwich_only_d_p(d)) {
				bp += dt_strfdt(bp, ep - bp, "%T", d);
			}
		} else {
			/* just two empty fields then, innit? */
			*bp++ = '\001';
		}
		/* finalise the line and print */
		*bp++ = '\n';
		safe_write(ctx.outfd, buf, bp - buf);
	} while (0);
	return;
}
Beispiel #11
0
int
main(int argc, char *argv[])
{
	static struct dt_dtdur_s ite_p1;
	yuck_t argi[1U];
	struct dt_dt_s tmp;
	char **ifmt;
	size_t nifmt;
	char *ofmt;
	dt_dttyp_t tgttyp;
	int rc = 0;
	struct dseq_clo_s clo = {
		.ite = &ite_p1,
		.nite = 1,
		.altite = NULL,
		.naltite = 0,
		.ss = 0,
		.dir = 0,
		.flags = 0,
	};

	if (yuck_parse(argi, argc, argv)) {
		rc = 1;
		goto out;
	}
	/* assign ofmt/ifmt */
	ofmt = argi->format_arg;
	if (argi->backslash_escapes_flag) {
		dt_io_unescape(ofmt);
	}
	nifmt = argi->input_format_nargs;
	ifmt = argi->input_format_args;

	if (argi->from_locale_arg) {
		setilocale(argi->from_locale_arg);
	}
	if (argi->locale_arg) {
		setflocale(argi->locale_arg);
	}

	if (argi->base_arg) {
		struct dt_dt_s base = dt_strpdt(argi->base_arg, NULL, NULL);
		dt_set_base(base);
	}

	for (size_t i = 0; i < argi->skip_nargs; i++) {
		clo.ss = set_skip(clo.ss, argi->skip_args[i]);
	}

	if (argi->alt_inc_arg) {
		struct __strpdtdur_st_s st = __strpdtdur_st_initialiser();

		do {
			if (dt_io_strpdtdur(&st, argi->alt_inc_arg) < 0) {
				if (!argi->quiet_flag) {
					error("Error: \
cannot parse duration string `%s'", argi->alt_inc_arg);
				}
				rc = 1;
				goto out;
			}
		} while (__strpdtdur_more_p(&st));
		/* assign values */
		clo.altite = st.durs;
		clo.naltite = st.ndurs;
	}

	switch (argi->nargs) {
		struct dt_dt_s fst, lst;
	default:
		yuck_auto_help(argi);
		rc = 1;
		goto out;

	case 2:
		lst = dt_io_strpdt(argi->args[1U], ifmt, nifmt, NULL);
		if (dt_unk_p(lst)) {
			if (!argi->quiet_flag) {
				dt_io_warn_strpdt(argi->args[1U]);
			}
			rc = 1;
			goto out;
		} else if (UNLIKELY(lst.fix) && !argi->quiet_flag) {
			rc = 2;
		}
		/* fallthrough */
	case 1:
		fst = dt_io_strpdt(argi->args[0U], ifmt, nifmt, NULL);
		if (dt_unk_p(fst)) {
			if (!argi->quiet_flag) {
				dt_io_warn_strpdt(argi->args[0U]);
			}
			rc = 1;
			goto out;
		} else if (UNLIKELY(fst.fix) && !argi->quiet_flag) {
			rc = 2;
		}

		/* check the input arguments and do the sane thing now
		 * if it's all dates, use DURD iterator
		 * if it's all times, use DURS/DURM/DURH iterators
		 * if one of them is a dt, promote the other */
		if (dt_sandwich_only_d_p(fst)) {
			/* emulates old dseq(1) */
			if (argi->nargs == 1U) {
				lst.d = dt_date(fst.d.typ);
				dt_make_d_only(&lst, fst.d.typ);
			}
			clo.ite->d = dt_make_ddur(DT_DURD, 1);
		} else if (dt_sandwich_only_t_p(fst)) {
			/* emulates old tseq(1) */
			if (argi->nargs == 1U) {
				lst.t = dt_time();
				dt_make_t_only(&lst, DT_HMS);
			}
		} else if (dt_sandwich_p(fst)) {
			if (argi->nargs == 1U) {
				lst = dt_datetime(fst.typ);
				dt_make_sandwich(&lst, fst.d.typ, DT_HMS);
			}
			clo.ite->d = dt_make_ddur(DT_DURD, 1);
		} else {
			error("\
don't know how to handle single argument case");
			rc = 1;
			goto out;
		}
		goto make_compat;

	case 3: {
		struct __strpdtdur_st_s st = __strpdtdur_st_initialiser();

		/* get lower bound */
		fst = dt_io_strpdt(argi->args[0U], ifmt, nifmt, NULL);
		if (dt_unk_p(fst)) {
			if (!argi->quiet_flag) {
				dt_io_warn_strpdt(argi->args[0U]);
			}
			rc = 1;
			goto out;
		} else if (UNLIKELY(fst.fix) && !argi->quiet_flag) {
			rc = 2;
		}

		/* get increment */
		do {
			if (dt_io_strpdtdur(&st, argi->args[1U]) < 0) {
				error("Error: \
cannot parse duration string `%s'", argi->args[1U]);
				rc = 1;
				goto out;
			}
		} while (__strpdtdur_more_p(&st));
		/* assign values */
		clo.ite = st.durs;
		clo.nite = st.ndurs;
		clo.flags |= CLO_FL_FREE_ITE;

		/* get upper bound */
		lst = dt_io_strpdt(argi->args[2U], ifmt, nifmt, NULL);
		if (dt_unk_p(lst)) {
			if (!argi->quiet_flag) {
				dt_io_warn_strpdt(argi->args[2U]);
			}
			rc = 1;
			goto out;
		} else if (UNLIKELY(lst.fix) && !argi->quiet_flag) {
			rc = 2;
		}
		goto make_compat;
	}

	make_compat:
		if (LIKELY(fst.typ == lst.typ)) {
			clo.fst = fst;
			clo.lst = lst;
		} else {
			clo.fst = fst;
			clo.lst = dt_dtconv(fst.typ, lst);
		}
		break;
	}

	/* promote the args maybe */
	if ((dt_sandwich_only_d_p(clo.fst) && dt_sandwich_only_t_p(clo.lst)) ||
	    (dt_sandwich_only_t_p(clo.fst) && dt_sandwich_only_d_p(clo.lst))) {
		error("\
cannot mix dates and times as arguments");
		rc = 1;
		goto out;
	} else if (dt_sandwich_only_d_p(clo.fst) && dt_sandwich_p(clo.lst)) {