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; }
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; }
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; }
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); }
/** * 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; }
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; }
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; }
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; }
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; }
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; }
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)) {