libzahl

big integer library
git clone git://git.suckless.org/libzahl
Log | Files | Refs | README | LICENSE

zsets.c (1038B)


      1 /* See LICENSE file for copyright and license details. */
      2 #include "internals.h"
      3 
      4 #include <ctype.h>
      5 
      6 #ifdef __GNUC__
      7 # pragma GCC diagnostic ignored "-Wswitch-default"
      8 #endif
      9 
     10 
     11 int
     12 zsets(z_t a, const char *str)
     13 {
     14 	unsigned long long int temp = 0;
     15 	int neg = (*str == '-');
     16 	const char *str_end;
     17 
     18 	str += neg || (*str == '+');
     19 
     20 	if (check(!*str)) {
     21 		errno = EINVAL;
     22 		return -1;
     23 	}
     24 	for (str_end = str; *str_end; str_end++) {
     25 		if (check(!isdigit(*str_end))) {
     26 			errno = EINVAL;
     27 			return -1;
     28 		}
     29 	}
     30 
     31 	SET_SIGNUM(a, 0);
     32 
     33 	zset(libzahl_tmp_str_num, libzahl_const_1e19);
     34 	switch ((str_end - str) % 19) {
     35 		while (*str) {
     36 			zmul(a, a, libzahl_const_1e19);
     37 			temp = 0;
     38 #define X(n)\
     39 		case n:\
     40 			temp *= 10, temp += *str++ & 15;
     41 			X(0) X(18) X(17) X(16) X(15) X(14) X(13) X(12) X(11)
     42 			X(10) X(9) X(8) X(7) X(6) X(5) X(4) X(3) X(2) X(1)
     43 #undef X
     44 			if (!temp)
     45 				continue;
     46 			libzahl_tmp_str_num->chars[0] = (zahl_char_t)temp;
     47 			zadd(a, a, libzahl_tmp_str_num);
     48 		}
     49 	}
     50 
     51 	if (unlikely(neg))
     52 		SET_SIGNUM(a, -zsignum(a));
     53 	return 0;
     54 }