aboutsummaryrefslogtreecommitdiffstats
path: root/src/zsets.c
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2016-03-02 09:59:52 +0100
committerMattias Andrée <maandree@kth.se>2016-03-02 10:03:25 +0100
commita626bacf8e45af60727882250f9d3abeb15ff3cd (patch)
treeac2d8e6b806e8ffacdaa33b44279547ac0e32acf /src/zsets.c
parentSince zstr_length is a generalisation of zbits, add reference to each other in the man pages (diff)
downloadlibzahl-a626bacf8e45af60727882250f9d3abeb15ff3cd.tar.gz
libzahl-a626bacf8e45af60727882250f9d3abeb15ff3cd.tar.bz2
libzahl-a626bacf8e45af60727882250f9d3abeb15ff3cd.tar.xz
Add zsets and zstr
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to 'src/zsets.c')
-rw-r--r--src/zsets.c47
1 files changed, 47 insertions, 0 deletions
diff --git a/src/zsets.c b/src/zsets.c
new file mode 100644
index 0000000..12669b9
--- /dev/null
+++ b/src/zsets.c
@@ -0,0 +1,47 @@
+/* See LICENSE file for copyright and license details. */
+#include "internals"
+
+#include <errno.h>
+
+
+int
+zsets(z_t a, const char *str)
+{
+ unsigned long long int temp = 0;
+ int neg = (*str == '-');
+ const char *str_end;
+
+ str += neg || (*str == '+');
+
+ if (!*str) {
+ errno = EINVAL;
+ return -1;
+ }
+ for (str_end = str; *str_end; str_end++) {
+ if (!isdigit(*str_end)) {
+ errno = EINVAL;
+ return -1;
+ }
+ }
+
+ SET_SIGNUM(a, 0);
+
+ switch ((str_end - str) % 19) {
+ while (*str) {
+#define X(n)\
+ temp *= 10, temp += *str++ & 15;\
+ case n:
+ X(18) X(17) X(16) X(15) X(14) X(13) X(12) X(11) X(10)
+ X(9) X(8) X(7) X(6) X(5) X(4) X(3) X(2) X(1) X(0)
+#undef X
+ zmul(a, a, libzahl_const_1e19);
+ zsetu(libzahl_tmp_str_num, temp);
+ zadd(a, a, libzahl_tmp_str_num);
+ temp = 0;
+ }
+ }
+
+ if (neg)
+ SET_SIGNUM(a, -zsignum(a));
+ return 0;
+}