Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
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();
}