DEFUN struct dt_dt_s __strpdt_std(const char *str, char **ep) { /* code dupe, see __strpd_std() */ struct dt_dt_s res = dt_dt_initialiser(); struct strpdt_s d = strpdt_initialiser(); const char *sp; if ((sp = str) == NULL) { goto out; } /* check for epoch notation */ if (*sp == '@') { /* yay, epoch */ const char *tmp; d.i = strtoi(++sp, &tmp); if (UNLIKELY(d.i == -1 && sp == tmp)) { sp--; } else { /* let's make a DT_SEXY */ res.typ = DT_SEXY; res.sxepoch = d.i; } goto out; } /* read the year */ if ((d.sd.y = strtoi_lim(sp, &sp, DT_MIN_YEAR, DT_MAX_YEAR)) < 0 || *sp++ != '-') { sp = str; goto try_time; } /* check for ywd dates */ if (UNLIKELY(*sp == 'W')) { /* brilliant */ if ((sp++, d.sd.c = strtoi_lim(sp, &sp, 0, 53)) < 0 || *sp++ != '-') { goto try_time; } d.sd.flags.c_wcnt_p = 1; d.sd.flags.wk_cnt = YWD_ISOWK_CNT; goto dow; } /* read the month */ if ((d.sd.m = strtoi_lim(sp, &sp, 0, 12)) < 0 || *sp++ != '-') { sp = str; goto out; } /* read the day or the count */ if ((d.sd.d = strtoi_lim(sp, &sp, 0, 31)) < 0) { /* didn't work, f**k off */ sp = str; goto out; } /* check the date type */ switch (*sp) { case '-': /* it is a YMCW date */ if ((d.sd.c = d.sd.d) > 5) { /* nope, it was bollocks */ break; } d.sd.d = 0; dow: if ((d.sd.w = strtoi_lim(++sp, &sp, 0, 7)) < 0) { /* didn't work, f**k off */ sp = str; goto out; } /* fix up d.sd.w right away */ d.sd.w = d.sd.w ?: DT_SUNDAY; break; case 'B': /* it's a bizda/YMDU before ultimo date */ d.sd.flags.ab = BIZDA_BEFORE; case 'b': /* it's a bizda/YMDU after ultimo date */ d.sd.flags.bizda = 1; d.sd.b = d.sd.d; d.sd.d = 0; sp++; break; default: /* we don't care */ break; } /* guess what we're doing */ if ((res.d = __guess_dtyp(d.sd)).typ == DT_DUNK) { /* not much use parsing on */ goto out; } /* check for the d/t separator */ switch (*sp) { case 'T': case ' ': case '\t': /* could be a time, could be something, else * make sure we leave a mark */ str = sp++; break; default: /* should be a no-op */ dt_make_d_only(&res, res.d.typ); goto out; } try_time: /* and now parse the time */ if ((d.st.h = strtoi_lim(sp, &sp, 0, 23)) < 0) { sp = str; goto out; } else if (*sp != ':') { goto eval_time; } else if ((d.st.m = strtoi_lim(++sp, &sp, 0, 59)) < 0) { d.st.m = 0; goto eval_time; } else if (*sp != ':') { goto eval_time; } else if ((d.st.s = strtoi_lim(++sp, &sp, 0, 60)) < 0) { d.st.s = 0; } else if (*sp != '.') { goto eval_time; } else if ((d.st.ns = strtoi_lim(++sp, &sp, 0, 999999999)) < 0) { d.st.ns = 0; goto eval_time; } eval_time: res.t.hms.h = d.st.h; res.t.hms.m = d.st.m; res.t.hms.s = d.st.s; if (res.d.typ > DT_DUNK) { const char *tp; dt_make_sandwich(&res, res.d.typ, DT_HMS); /* check for the zone stuff */ if ((d.zdiff = try_zone(sp, &tp))) { res = __fixup_zdiff(res, d.zdiff); } else if (tp > sp) { res.znfxd = 1U; } sp = tp; } else { dt_make_t_only(&res, DT_HMS); } out: /* res.typ coincides with DT_SANDWICH_D_ONLY() if we jumped here */ if (ep != NULL) { *ep = (char*)sp; } return res; }
DEFUN struct dt_d_s __strpd_std(const char *str, char **ep) { /* code dupe, see __strpdt_std() */ struct dt_d_s res; struct strpd_s d; const char *sp; if ((sp = str) == NULL) { goto out; } d = strpd_initialiser(); /* read the year */ if ((d.y = strtoi_lim(sp, &sp, DT_MIN_YEAR, DT_MAX_YEAR)) < 0 || *sp++ != '-') { goto f****d; } /* check for ywd dates */ if (UNLIKELY(*sp == 'W')) { /* brilliant */ if ((sp++, d.c = strtoi_lim(sp, &sp, 0, 53)) < 0 || *sp++ != '-') { goto f****d; } d.flags.c_wcnt_p = 1; d.flags.wk_cnt = YWD_ISOWK_CNT; goto dow; } /* read the month */ if ((d.m = strtoi_lim(sp, &sp, 0, GREG_MONTHS_P_YEAR)) < 0 || *sp++ != '-') { goto f****d; } /* read the day or the count */ if ((d.d = strtoi_lim(sp, &sp, 0, 31)) < 0) { /* didn't work, f**k off */ goto f****d; } /* check the date type */ switch (*sp) { case '-': /* it is a YMCW date */ if ((d.c = d.d) > 5) { /* nope, it was bollocks */ break; } d.d = 0; sp++; dow: if ((d.w = strtoi_lim(sp, &sp, 0, GREG_DAYS_P_WEEK)) < 0) { /* didn't work, f**k off */ goto f****d; } break; case 'B': /* it's a bizda/YMDU before ultimo date */ d.flags.ab = BIZDA_BEFORE; case 'b': /* it's a bizda/YMDU after ultimo date */ d.flags.bizda = 1; d.b = d.d; d.d = 0; sp++; break; default: /* we don't care */ break; } /* guess what we're doing */ res = __guess_dtyp(d); out: if (ep != NULL) { *ep = (char*)sp; } return res; f****d: if (ep != NULL) { *ep = (char*)str; } return dt_d_initialiser(); }