chiark / gitweb /
calendarspec: sub-second support, v3
authorHristo Venev <hristo@venev.name>
Mon, 16 Nov 2015 08:15:05 +0000 (10:15 +0200)
committerSven Eden <yamakuzure@gmx.net>
Wed, 17 May 2017 13:22:13 +0000 (15:22 +0200)
src/basic/parse-util.c
src/basic/parse-util.h
src/basic/time-util.c

index e503559..6e24bde 100644 (file)
@@ -492,3 +492,39 @@ int safe_atod(const char *s, double *ret_d) {
         *ret_d = (double) d;
         return 0;
 }
+
+int parse_fractional_part_u(const char **p, size_t digits, unsigned *res) {
+        size_t i;
+        unsigned val = 0;
+        const char *s;
+
+        s = *p;
+
+        /* accept any number of digits, strtoull is limted to 19 */
+        for(i=0; i < digits; i++,s++) {
+                if (*s < '0' || *s > '9') {
+                        if (i == 0)
+                                return -EINVAL;
+
+                        /* too few digits, pad with 0 */
+                        for (; i < digits; i++)
+                                val *= 10;
+
+                        break;
+                }
+
+                val *= 10;
+                val += *s - '0';
+        }
+
+        /* maybe round up */
+        if (*s >= '5' && *s <= '9')
+                val++;
+
+        s += strspn(s, DIGITS);
+
+        *p = s;
+        *res = val;
+
+        return 0;
+}
index 6706a29..567535c 100644 (file)
@@ -93,3 +93,5 @@ static inline int safe_atoli(const char *s, long int *ret_u) {
 #endif
 
 int safe_atod(const char *s, double *ret_d);
+
+int parse_fractional_part_u(const char **s, size_t digits, unsigned *res);
index f225094..34061fe 100644 (file)
@@ -27,6 +27,7 @@
 #include "fd-util.h"
 #include "fileio.h"
 #include "fs-util.h"
+#include "parse-util.h"
 #include "path-util.h"
 #include "string-util.h"
 #include "strv.h"
@@ -666,29 +667,18 @@ int parse_timestamp(const char *t, usec_t *usec) {
 
 parse_usec:
         {
-                char *end;
-                unsigned long long val;
-                size_t l;
+                unsigned add;
 
                 k++;
-                if (*k < '0' || *k > '9')
+                r = parse_fractional_part_u(&k, 6, &add);
+                if (r < 0)
                         return -EINVAL;
 
-                /* base 10 instead of base 0, .09 is not base 8 */
-                errno = 0;
-                val = strtoull(k, &end, 10);
-                if (*end || errno)
+                if (*k)
                         return -EINVAL;
 
-                l = end-k;
-
-                /* val has l digits, make them 6 */
-                for (; l < 6; l++)
-                        val *= 10;
-                for (; l > 6; l--)
-                        val /= 10;
+                x_usec = add;
 
-                x_usec = val;
         }
 
 from_tm: