diff options
author | David Robillard <d@drobilla.net> | 2011-12-19 02:59:31 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2011-12-19 02:59:31 +0000 |
commit | 2469c739d87d6a2bb0c9b9c1e2b2c69b0e981b97 (patch) | |
tree | ac764f783837a0fe2e1ec56a439e3acb318dd918 /src/string.c | |
parent | 085fe30c4c8dcdd2e2d38451813e0d7d5543acfc (diff) | |
download | serd-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.c | 55 |
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; +} |