/* vi: set sw=4 ts=4: */
/*
 * Utility routines.
 *
 * Copyright (C) 2018 Denys Vlasenko
 *
 * Licensed under GPLv2, see file LICENSE in this source tree.
 */
//config:config FLOAT_DURATION
//config:	bool "Enable fractional duration arguments"
//config:	default y
//config:	help
//config:	Allow sleep N.NNN, top -d N.NNN etc.

//kbuild:lib-$(CONFIG_SLEEP)   += duration.o
//kbuild:lib-$(CONFIG_TOP)     += duration.o
//kbuild:lib-$(CONFIG_TIMEOUT) += duration.o
//kbuild:lib-$(CONFIG_PING)    += duration.o
//kbuild:lib-$(CONFIG_PING6)   += duration.o
//kbuild:lib-$(CONFIG_WATCH)   += duration.o

#include "libbb.h"

static const struct suffix_mult duration_suffixes[] ALIGN_SUFFIX = {
	{ "s", 1 },
	{ "m", 60 },
	{ "h", 60*60 },
	{ "d", 24*60*60 },
	{ "", 0 }
};

#if ENABLE_FLOAT_DURATION
duration_t FAST_FUNC parse_duration_str(char *str)
{
	duration_t duration;

	if (strchr(str, '.')) {
		double d;
		char *pp;
		int len = strspn(str, "0123456789.");
		char sv = str[len];
		str[len] = '\0';
		errno = 0;
		d = strtod(str, &pp);
		if (errno || *pp)
			bb_show_usage();
		str += len;
		*str-- = sv;
		sv = *str;
		*str = '1';
		duration = d * xatoul_sfx(str, duration_suffixes);
		*str = sv;
	} else {
		duration = xatoul_sfx(str, duration_suffixes);
	}

	return duration;
}
void FAST_FUNC sleep_for_duration(duration_t duration)
{
	struct timespec ts;

	ts.tv_sec = MAXINT(typeof(ts.tv_sec));
	ts.tv_nsec = 0;
	if (duration >= 0 && duration < ts.tv_sec) {
		ts.tv_sec = duration;
		ts.tv_nsec = (duration - ts.tv_sec) * 1000000000;
	}
	do {
		errno = 0;
		nanosleep(&ts, &ts);
	} while (errno == EINTR);
}
#else
duration_t FAST_FUNC parse_duration_str(char *str)
{
	return xatou_range_sfx(str, 0, UINT_MAX, duration_suffixes);
}
#endif
