aboutsummaryrefslogtreecommitdiffstats
path: root/src/string.c
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2011-12-19 02:59:31 +0000
committerDavid Robillard <d@drobilla.net>2011-12-19 02:59:31 +0000
commit2469c739d87d6a2bb0c9b9c1e2b2c69b0e981b97 (patch)
treeac764f783837a0fe2e1ec56a439e3acb318dd918 /src/string.c
parent085fe30c4c8dcdd2e2d38451813e0d7d5543acfc (diff)
downloadserd-2469c739d87d6a2bb0c9b9c1e2b2c69b0e981b97.tar.gz
serd-2469c739d87d6a2bb0c9b9c1e2b2c69b0e981b97.tar.bz2
serd-2469c739d87d6a2bb0c9b9c1e2b2c69b0e981b97.zip
Add serd_strtod(), serd_node_new_decimal(), and serd_node_new_integer() for
locale-independent numeric node parsing/serialising. git-svn-id: http://svn.drobilla.net/serd/trunk@260 490d8e77-9747-427b-9fa3-0b8f29cee8a0
Diffstat (limited to 'src/string.c')
-rw-r--r--src/string.c55
1 files changed, 55 insertions, 0 deletions
diff --git a/src/string.c b/src/string.c
index f747c530..35a3bbc8 100644
--- a/src/string.c
+++ b/src/string.c
@@ -16,6 +16,8 @@
#include "serd_internal.h"
+#include <math.h>
+
SERD_API
const uint8_t*
serd_strerror(SerdStatus st)
@@ -56,3 +58,56 @@ serd_strlen(const uint8_t* str, size_t* n_bytes, SerdNodeFlags* flags)
}
return n_chars;
}
+
+static inline double
+read_sign(const char** sptr)
+{
+ double sign = 1.0;
+ switch (**sptr) {
+ case '-': sign = -1.0;
+ case '+': ++(*sptr);
+ default: return sign;
+ }
+}
+
+SERD_API
+double
+serd_strtod(const char* str, char** endptr)
+{
+ double result = 0.0;
+
+ // Point s at the first non-whitespace character
+ const char* s = str;
+ while (is_space(*s)) { ++s; }
+
+ // Read leading sign if necessary
+ const double sign = read_sign(&s);
+
+ // Parse integer part
+ for (; is_digit(*s); ++s) {
+ result = (result * 10.0) + (*s - '0');
+ }
+
+ // Parse fractional part
+ if (*s == '.') {
+ double denom = 10.0;
+ for (++s; is_digit(*s); ++s) {
+ result += (*s - '0') / denom;
+ denom *= 10.0;
+ }
+ }
+
+ // Parse exponent
+ if (*s == 'e' || *s == 'E') {
+ ++s;
+ double expt = 0.0;
+ double expt_sign = read_sign(&s);
+ for (; is_digit(*s); ++s) {
+ expt = (expt * 10.0) + (*s - '0');
+ }
+ result *= pow(10, expt * expt_sign);
+ }
+
+ *endptr = (char*)s;
+ return result * sign;
+}