[PATCH v2 2/3] lib: strtox: implement new simple_strtofract

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



We have no floating point support in barebox and no strtod. Still some
user interaction could benefit from being able to supply command
arguments or device parameters in a format with decimal points.

This new simple_strtofract() function parses a fixed point format consisting
of a 32 bit integer and 32 bit fractional part and returns it multiplied
by a division argument. e.g.

  simple_strtofract("1.02", NULL, 1000) == 1020

Signed-off-by: Ahmad Fatoum <a.fatoum@xxxxxxxxxxxxxx>
---
v1 -> v2:
  - no change
---
 include/linux/kernel.h |  1 +
 lib/strtox.c           | 57 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 58 insertions(+)

diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index cd7dac73f93a..dd108ba0abf7 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -92,6 +92,7 @@ extern unsigned long simple_strtoul(const char *,char **,unsigned int);
 extern long simple_strtol(const char *,char **,unsigned int);
 extern unsigned long long simple_strtoull(const char *,char **,unsigned int);
 extern long long simple_strtoll(const char *,char **,unsigned int);
+extern s64 simple_strtofract(const char *cp, char **endp, u32 division);
 
 /* The `const' in roundup() prevents gcc-3.3 from calling __divdi3 */
 #define roundup(x, y) (					\
diff --git a/lib/strtox.c b/lib/strtox.c
index 76927743a72c..5ef0f0923a9e 100644
--- a/lib/strtox.c
+++ b/lib/strtox.c
@@ -78,3 +78,60 @@ long long simple_strtoll(const char *cp, char **endp, unsigned int base)
 	return simple_strtoull(cp, endp, base);
 }
 EXPORT_SYMBOL(simple_strtoll);
+
+static unsigned int simple_strtouint(const char *cp, char **endp, unsigned int base)
+{
+	unsigned int ret;
+
+	ret = simple_strtoull(cp, endp, base);
+	if (ret != (unsigned int)ret) {
+		if (endp)
+			*endp = (char *)cp;
+		return  0;
+	}
+
+	return ret;
+}
+
+s64 simple_strtofract(const char *cp, char **endp, u32 division)
+{
+	char *end = (char *)cp;
+	s64 integer, fract, scale, result = 0;
+	int fract_len = 0, sign = 1;
+
+	switch (*cp) {
+	case '-':
+		sign = -1;
+		fallthrough;
+	case '+':
+		cp++;
+	}
+
+	if (!isdigit(*cp))
+		goto out;
+
+	integer = simple_strtouint(cp, &end, 10);
+	if (end == cp)
+		goto out;
+
+	if (*end == '.' || *end == ',') {
+		cp = end + 1;
+		fract = simple_strtouint(cp, &end, 10);
+		fract_len = end - cp;
+	}
+
+	result = integer * division;
+
+	scale = 1;
+	for (int i = 0; i < fract_len; i++)
+		scale *= 10;
+	if (fract_len > 0)
+		result += (fract * division) / scale;
+
+out:
+	if (endp)
+		*endp = end;
+
+	return sign * result;
+}
+EXPORT_SYMBOL(simple_strtofract);
-- 
2.39.2





[Index of Archives]     [Linux Embedded]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux