mirror of https://github.com/flysand7/ciabatta.git
separate out conv stuff
This commit is contained in:
parent
4d4449a5d9
commit
bc443e31c3
|
@ -37,10 +37,9 @@
|
||||||
|
|
||||||
#include "intrin.h"
|
#include "intrin.h"
|
||||||
|
|
||||||
#include "util.c"
|
|
||||||
|
|
||||||
// Dependencies
|
// Dependencies
|
||||||
#include "decfloat/decfloat.c"
|
#include "util.c"
|
||||||
|
#include "conv/decfloat/decfloat.c"
|
||||||
|
|
||||||
// Platform-independent stuff
|
// Platform-independent stuff
|
||||||
#include "fmt/gen_fmt.c"
|
#include "fmt/gen_fmt.c"
|
||||||
|
@ -49,7 +48,10 @@
|
||||||
#include "math/gen_math.c"
|
#include "math/gen_math.c"
|
||||||
#include "math/ieee754.c"
|
#include "math/ieee754.c"
|
||||||
#include "math/round.c"
|
#include "math/round.c"
|
||||||
#include "conv/conversion.c"
|
#include "conv/digits.c"
|
||||||
|
#include "conv/strpfx.c"
|
||||||
|
#include "conv/int.c"
|
||||||
|
#include "conv/float.c"
|
||||||
#include "stdlib/algorithm.c"
|
#include "stdlib/algorithm.c"
|
||||||
#include "stdlib/multibyte.c"
|
#include "stdlib/multibyte.c"
|
||||||
#include "stdlib/random.c"
|
#include "stdlib/random.c"
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
|
||||||
|
static inline bool isbase(int c, int base) {
|
||||||
|
int val = 0;
|
||||||
|
if(isdigit(c)) {
|
||||||
|
val = c-'0';
|
||||||
|
}
|
||||||
|
else if(islower(c)) {
|
||||||
|
val = c-'a'+10;
|
||||||
|
}
|
||||||
|
else if(isupper(c)) {
|
||||||
|
val = c-'A'+10;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return val < base;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline intl todigit(int c) {
|
||||||
|
int val = 0;
|
||||||
|
if(isdigit(c)) {
|
||||||
|
val = c-'0';
|
||||||
|
}
|
||||||
|
else if(islower(c)) {
|
||||||
|
val = c-'a'+10;
|
||||||
|
}
|
||||||
|
else if(isupper(c)) {
|
||||||
|
val = c-'A'+10;
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,130 @@
|
||||||
|
|
||||||
|
|
||||||
|
static f64 strtod_generic(const char *restrict nptr, char **restrict endptr) {
|
||||||
|
const char *restrict str = nptr;
|
||||||
|
bool conv_performed = false;
|
||||||
|
f64 value = 0.0;
|
||||||
|
f64 coef = 1.0;
|
||||||
|
// Skip space on the beginning
|
||||||
|
while(isspace(*str)) {
|
||||||
|
++str;
|
||||||
|
}
|
||||||
|
// Check for inf and nan
|
||||||
|
if(strpfx_i(str, "INF")) {
|
||||||
|
str += sizeof "INF"-1;
|
||||||
|
value = HUGE_VAL;
|
||||||
|
conv_performed = true;
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
if(strpfx_i(str, "INFINITY")) {
|
||||||
|
str += sizeof "INFINITY"-1;
|
||||||
|
value = HUGE_VAL;
|
||||||
|
conv_performed = true;
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
if(strpfx_i(str, "NAN")) {
|
||||||
|
str += sizeof "NAN"-1;
|
||||||
|
value = NAN;
|
||||||
|
conv_performed = true;
|
||||||
|
if(*str == '(') {
|
||||||
|
while(*str != ')') {
|
||||||
|
++str;
|
||||||
|
}
|
||||||
|
++str;
|
||||||
|
}
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
// Parse C float
|
||||||
|
if(*str == '+') {
|
||||||
|
++str;
|
||||||
|
}
|
||||||
|
else if(*str == '-') {
|
||||||
|
coef = -1.;
|
||||||
|
++str;
|
||||||
|
}
|
||||||
|
int base = 10;
|
||||||
|
if(strpfx_i(str, "0X")) {
|
||||||
|
str += sizeof "0X"-1;
|
||||||
|
base = 16;
|
||||||
|
}
|
||||||
|
// Parse the whole part
|
||||||
|
while(isbase(*str, base)) {
|
||||||
|
long digit = todigit(*str);
|
||||||
|
value = 10.0*value + (f64)digit;
|
||||||
|
++str;
|
||||||
|
}
|
||||||
|
if(*str != '.') {
|
||||||
|
value = 0.0;
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
++str;
|
||||||
|
// Parse the fractional part
|
||||||
|
long exp = 1;
|
||||||
|
while(isbase(*str, base)) {
|
||||||
|
long digit = todigit(*str);
|
||||||
|
f64 fract = (f64)digit;
|
||||||
|
long cexp = exp;
|
||||||
|
while(cexp-- != 0) {
|
||||||
|
fract /= (f64)base;
|
||||||
|
}
|
||||||
|
value += fract;
|
||||||
|
++exp;
|
||||||
|
++str;
|
||||||
|
}
|
||||||
|
// Parse the exponent
|
||||||
|
if((base == 10 && strpfx_i(str, "E"))
|
||||||
|
|| (base == 16 && strpfx_i(str, "P")))
|
||||||
|
{
|
||||||
|
++str;
|
||||||
|
long exp = 0;
|
||||||
|
long exp_coef = 1;
|
||||||
|
if(*str == '+') {
|
||||||
|
++str;
|
||||||
|
}
|
||||||
|
else if(*str == '-') {
|
||||||
|
exp_coef = -1;
|
||||||
|
++str;
|
||||||
|
}
|
||||||
|
while(isdigit(*str)) {
|
||||||
|
exp = 10*exp + (long)(*str-'0');
|
||||||
|
++str;
|
||||||
|
}
|
||||||
|
if(exp_coef == 1) {
|
||||||
|
while(exp--!=0) value = value * base;
|
||||||
|
}
|
||||||
|
else if(exp_coef == -1) {
|
||||||
|
while(exp--!=0) value = value / base;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!isfinite(value)) {
|
||||||
|
errno = ERANGE;
|
||||||
|
value = coef*HUGE_VAL;
|
||||||
|
}
|
||||||
|
conv_performed = true;
|
||||||
|
finish:
|
||||||
|
if(endptr != NULL) {
|
||||||
|
if(conv_performed) {
|
||||||
|
*endptr = (char *)str;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
*endptr = (char *)nptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return coef*value;
|
||||||
|
}
|
||||||
|
|
||||||
|
f64 strtod(const char *restrict nptr, char **restrict endptr) {
|
||||||
|
return strtod_generic(nptr, endptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
f32 strtof(const char *restrict nptr, char **restrict endptr) {
|
||||||
|
return (f32)strtod_generic(nptr, endptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
fl64 strtold(const char *restrict nptr, char **restrict endptr) {
|
||||||
|
return (fl64)strtod_generic(nptr, endptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
f64 atof(const char *nptr) {
|
||||||
|
return strtod(nptr, (char **)NULL);
|
||||||
|
}
|
|
@ -1,46 +1,4 @@
|
||||||
|
|
||||||
static bool isbase(int c, int base) {
|
|
||||||
int val = 0;
|
|
||||||
if(isdigit(c)) {
|
|
||||||
val = c-'0';
|
|
||||||
}
|
|
||||||
else if(islower(c)) {
|
|
||||||
val = c-'a'+10;
|
|
||||||
}
|
|
||||||
else if(isupper(c)) {
|
|
||||||
val = c-'A'+10;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return val < base;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool strprefix_i(char const *restrict str, char const *restrict prefix) {
|
|
||||||
while(*prefix != 0) {
|
|
||||||
if(*str == 0) break;
|
|
||||||
if(toupper(*str) != toupper(*prefix)) return false;
|
|
||||||
++prefix;
|
|
||||||
++str;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called only when isbase(c, base) for some base in range
|
|
||||||
static long todigit(int c) {
|
|
||||||
int val = 0;
|
|
||||||
if(isdigit(c)) {
|
|
||||||
val = c-'0';
|
|
||||||
}
|
|
||||||
else if(islower(c)) {
|
|
||||||
val = c-'a'+10;
|
|
||||||
}
|
|
||||||
else if(isupper(c)) {
|
|
||||||
val = c-'A'+10;
|
|
||||||
}
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
static intull strtoi_generic(const char *restrict nptr,
|
static intull strtoi_generic(const char *restrict nptr,
|
||||||
char **restrict endptr,
|
char **restrict endptr,
|
||||||
int inbase,
|
int inbase,
|
||||||
|
@ -77,7 +35,7 @@ static intull strtoi_generic(const char *restrict nptr,
|
||||||
}
|
}
|
||||||
// See if we need to parse base in C-like format
|
// See if we need to parse base in C-like format
|
||||||
// then set the base accordingly
|
// then set the base accordingly
|
||||||
if(strprefix_i(str, "0X")) {
|
if(strpfx_i(str, "0X")) {
|
||||||
++str;
|
++str;
|
||||||
if(base == 16 || base == 0) {
|
if(base == 16 || base == 0) {
|
||||||
++str;
|
++str;
|
||||||
|
@ -140,119 +98,6 @@ static intull strtoi_generic(const char *restrict nptr,
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static double strtod_generic(const char *restrict nptr, char **restrict endptr) {
|
|
||||||
const char *restrict str = nptr;
|
|
||||||
bool conv_performed = false;
|
|
||||||
double value = 0.0;
|
|
||||||
double coef = 1.0;
|
|
||||||
// Skip space on the beginning
|
|
||||||
while(isspace(*str)) {
|
|
||||||
++str;
|
|
||||||
}
|
|
||||||
// Check for inf and nan
|
|
||||||
if(strprefix_i(str, "INF")) {
|
|
||||||
str += sizeof "INF"-1;
|
|
||||||
value = HUGE_VAL;
|
|
||||||
conv_performed = true;
|
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
if(strprefix_i(str, "INFINITY")) {
|
|
||||||
str += sizeof "INFINITY"-1;
|
|
||||||
value = HUGE_VAL;
|
|
||||||
conv_performed = true;
|
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
if(strprefix_i(str, "NAN")) {
|
|
||||||
str += sizeof "NAN"-1;
|
|
||||||
value = NAN;
|
|
||||||
conv_performed = true;
|
|
||||||
if(*str == '(') {
|
|
||||||
while(*str != ')') {
|
|
||||||
++str;
|
|
||||||
}
|
|
||||||
++str;
|
|
||||||
}
|
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
// Parse C float
|
|
||||||
if(*str == '+') {
|
|
||||||
++str;
|
|
||||||
}
|
|
||||||
else if(*str == '-') {
|
|
||||||
coef = -1.;
|
|
||||||
++str;
|
|
||||||
}
|
|
||||||
int base = 10;
|
|
||||||
if(strprefix_i(str, "0X")) {
|
|
||||||
str += sizeof "0X"-1;
|
|
||||||
base = 16;
|
|
||||||
}
|
|
||||||
// Parse the whole part
|
|
||||||
while(isbase(*str, base)) {
|
|
||||||
long digit = todigit(*str);
|
|
||||||
value = 10.0*value + (double)digit;
|
|
||||||
++str;
|
|
||||||
}
|
|
||||||
if(*str != '.') {
|
|
||||||
value = 0.0;
|
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
++str;
|
|
||||||
// Parse the fractional part
|
|
||||||
long exp = 1;
|
|
||||||
while(isbase(*str, base)) {
|
|
||||||
long digit = todigit(*str);
|
|
||||||
double fract = (double)digit;
|
|
||||||
long cexp = exp;
|
|
||||||
while(cexp-- != 0) {
|
|
||||||
fract /= (double)base;
|
|
||||||
}
|
|
||||||
value += fract;
|
|
||||||
++exp;
|
|
||||||
++str;
|
|
||||||
}
|
|
||||||
// Parse the exponent
|
|
||||||
if((base == 10 && strprefix_i(str, "E"))
|
|
||||||
|| (base == 16 && strprefix_i(str, "P")))
|
|
||||||
{
|
|
||||||
++str;
|
|
||||||
long exp = 0;
|
|
||||||
long exp_coef = 1;
|
|
||||||
if(*str == '+') {
|
|
||||||
++str;
|
|
||||||
}
|
|
||||||
else if(*str == '-') {
|
|
||||||
exp_coef = -1;
|
|
||||||
++str;
|
|
||||||
}
|
|
||||||
while(isdigit(*str)) {
|
|
||||||
exp = 10*exp + (long)(*str-'0');
|
|
||||||
++str;
|
|
||||||
}
|
|
||||||
if(exp_coef == 1) {
|
|
||||||
while(exp--!=0) value = value * base;
|
|
||||||
}
|
|
||||||
else if(exp_coef == -1) {
|
|
||||||
while(exp--!=0) value = value / base;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!isfinite(value)) {
|
|
||||||
errno = ERANGE;
|
|
||||||
value = coef*HUGE_VAL;
|
|
||||||
}
|
|
||||||
conv_performed = true;
|
|
||||||
finish:
|
|
||||||
if(endptr != NULL) {
|
|
||||||
if(conv_performed) {
|
|
||||||
*endptr = (char *)str;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
*endptr = (char *)nptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return coef*value;
|
|
||||||
}
|
|
||||||
|
|
||||||
intl strtol(const char *restrict nptr, char **restrict endptr, int base) {
|
intl strtol(const char *restrict nptr, char **restrict endptr, int base) {
|
||||||
intull int_max = (intull)LONG_MAX;
|
intull int_max = (intull)LONG_MAX;
|
||||||
intl coef;
|
intl coef;
|
||||||
|
@ -292,10 +137,6 @@ intull strtoull(const char *restrict nptr, char **restrict endptr, int base) {
|
||||||
return strtoi_generic(nptr, endptr, base, NULL, int_max);
|
return strtoi_generic(nptr, endptr, base, NULL, int_max);
|
||||||
}
|
}
|
||||||
|
|
||||||
double atof(const char *nptr) {
|
|
||||||
return strtod(nptr, (char **)NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
int atoi(const char *nptr) {
|
int atoi(const char *nptr) {
|
||||||
return (int)strtol(nptr, (char **)NULL, 10);
|
return (int)strtol(nptr, (char **)NULL, 10);
|
||||||
}
|
}
|
||||||
|
@ -308,18 +149,6 @@ long long int atoll(const char *nptr) {
|
||||||
return strtoll(nptr, (char **)NULL, 10);
|
return strtoll(nptr, (char **)NULL, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
double strtod(const char *restrict nptr, char **restrict endptr) {
|
|
||||||
return strtod_generic(nptr, endptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
float strtof(const char *restrict nptr, char **restrict endptr) {
|
|
||||||
return (float)strtod_generic(nptr, endptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
long double strtold(const char *restrict nptr, char **restrict endptr) {
|
|
||||||
return (long double)strtod_generic(nptr, endptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
char *itoa(int value, char *str, int base) {
|
char *itoa(int value, char *str, int base) {
|
||||||
int sign = 0;
|
int sign = 0;
|
||||||
if(value < 0) {
|
if(value < 0) {
|
|
@ -0,0 +1,10 @@
|
||||||
|
|
||||||
|
static bool strpfx_i(char const *restrict str, char const *restrict prefix) {
|
||||||
|
while(*prefix != 0) {
|
||||||
|
if(*str == 0) break;
|
||||||
|
if(toupper(*str) != toupper(*prefix)) return false;
|
||||||
|
++prefix;
|
||||||
|
++str;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -32,9 +32,12 @@ typedef unsigned int intu;
|
||||||
typedef unsigned long int intul;
|
typedef unsigned long int intul;
|
||||||
typedef unsigned long long int intull;
|
typedef unsigned long long int intull;
|
||||||
|
|
||||||
|
typedef float f32;
|
||||||
|
typedef double f64;
|
||||||
|
typedef long double fl64;
|
||||||
|
|
||||||
typedef wchar_t wchar;
|
typedef wchar_t wchar;
|
||||||
|
|
||||||
#define COUNTOF(arr) (sizeof (arr) / sizeof ((arr)[0]))
|
|
||||||
#define IN_RANGE(start, v, end) ((start) <= (v) && (v) <= (end))
|
#define IN_RANGE(start, v, end) ((start) <= (v) && (v) <= (end))
|
||||||
|
|
||||||
#define CONCAT(a,b) a ## b
|
#define CONCAT(a,b) a ## b
|
||||||
|
|
Loading…
Reference in New Issue