[vlc-commits] variables: improve rational values parsing
Rémi Denis-Courmont
git at videolan.org
Sat Apr 2 18:15:44 CEST 2016
vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Sat Apr 2 19:13:57 2016 +0300| [8af0d6b579b44bb0e50ccf4c7ac15750e52b72d3] | committer: Rémi Denis-Courmont
variables: improve rational values parsing
- handle fractions with slash or colon,
- return exact value for decimal (but non-binary) number,
- do not treat leading zeroes as octal value indicator,
- handle and reduce corner cases.
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=8af0d6b579b44bb0e50ccf4c7ac15750e52b72d3
---
src/misc/variables.c | 85 ++++++++++++++++++++++++++++----------------------
1 file changed, 47 insertions(+), 38 deletions(-)
diff --git a/src/misc/variables.c b/src/misc/variables.c
index d480ebd..65163d5 100644
--- a/src/misc/variables.c
+++ b/src/misc/variables.c
@@ -32,7 +32,6 @@
# include <search.h>
#endif
#include <assert.h>
-#include <float.h>
#include <math.h>
#include <limits.h>
@@ -1290,56 +1289,66 @@ int (var_InheritURational)(vlc_object_t *object,
unsigned *num, unsigned *den,
const char *var)
{
- /* */
- *num = 0;
- *den = 0;
-
- /* */
- char *tmp = var_InheritString(object, var);
- if (!tmp)
+ char *str = var_InheritString(object, var);
+ if (str == NULL)
goto error;
- char *next;
- unsigned n = strtol(tmp, &next, 0);
- unsigned d = strtol(*next ? &next[1] : "0", NULL, 0);
+ char *sep;
+ unsigned n = strtoul(str, &sep, 10);
+ unsigned d;
- if (*next == '.') {
- /* Interpret as a (finite positive) float number */
- const int ubits = CHAR_BIT * sizeof (unsigned);
- int exp;
- double f = frexp(us_atof(tmp), &exp);
+ switch (*sep) {
+ case '\0':
+ /* Decimal integer */
+ d = 1;
+ break;
- if (!isgreaterequal(f, 0.))
- goto error; /* negative or not a number */
+ case ':':
+ case '/':
+ /* Decimal fraction */
+ d = strtoul(sep + 1, &sep, 10);
+ if (*sep != '\0')
+ goto error;
+ break;
+
+ case '.': {
+ /* Decimal number */
+ unsigned char c;
- if (exp <= 1 - ubits) {
- n = 0; /* too small */
d = 1;
- } else if (exp <= 0) {
- n = floor(scalbn(f, ubits - 1 + exp));
-#if (FLT_RADIX != 2)
-# error Floating point configuration not supported.
-#endif
- d = 1u << (ubits - 1);
- } else if (exp <= ubits) {
- n = floor(scalbn(f, ubits));
- d = 1u << (ubits - exp);
- } else
- goto error; /* too big */
- } else if ( *next == '\0' ) {
- /* plain integer given */
- *num = n;
- *den = 1;
+ while ((c = *(++sep)) != '\0') {
+ c -= '0';
+
+ if (c >= 10)
+ goto error;
+
+ n = n * 10 + c;
+ d *= 10;
+ }
+ break;
+ }
+
+ default:
+ goto error;
}
- if (n > 0 && d > 0)
+ free(str);
+
+ if (n == 0) {
+ *num = 0;
+ *den = d ? 1 : 0;
+ } else if (d == 0) {
+ *num = 1;
+ *den = 0;
+ } else
vlc_ureduce(num, den, n, d, 0);
- free(tmp);
return VLC_SUCCESS;
error:
- free(tmp);
+ free(str);
+ *num = 0;
+ *den = 0;
return VLC_EGENERIC;
}
More information about the vlc-commits
mailing list