separate out conv stuff

This commit is contained in:
bumbread 2022-08-05 20:00:58 +11:00
parent 4d4449a5d9
commit bc443e31c3
8 changed files with 183 additions and 177 deletions

View File

@ -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"

32
src/conv/digits.c Normal file
View File

@ -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;
}

130
src/conv/float.c Normal file
View File

@ -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);
}

View File

@ -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) {

10
src/conv/strpfx.c Normal file
View File

@ -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;
}

View File

@ -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