Luna/luna/NumberParsing.cpp

114 lines
2.3 KiB
C++
Raw Normal View History

2022-11-19 14:43:09 +00:00
#include <NumberParsing.h>
usize _atou(const char** str)
{
usize val = 0;
while (_isdigit(**str))
{
val = (10 * val) + (**str - '0');
(*str)++;
}
return val;
}
isize _atos(const char** str)
{
bool neg = false;
isize val = 0;
switch (**str)
{
case '-':
neg = true;
(*str)++;
break;
case '+': (*str)++; break;
default: break;
}
while (_isdigit(**str))
{
val = (10 * val) + (**str - '0');
(*str)++;
}
return neg ? -val : val;
}
static bool is_valid_digit_for_base(int base, char c)
2022-11-19 14:43:09 +00:00
{
if (base <= 10)
{
if (!_isdigit(c)) return false; // Bases lower than 10 only use decimal digits.
if ((c - '0') < base) return true;
return false;
}
else
{
if (!_isalnum(c)) return false; // Any valid base (2-36) only uses 0-9 and a-z.
if (_isdigit(c)) return true; // Any base higher than decimal will include all decimal digits.
bool lower = _islower(c);
if (((c - lower ? 'a' : 'A') + 10) < base) return true;
return false;
}
}
2022-11-19 14:43:09 +00:00
// This function assumes you have called is_valid_digit_for_base() to validate the digit first.
static isize parse_digit_unchecked(char c)
{
if (_isdigit(c)) return c - '0';
if (_islower(c)) return (c - 'a') + 10;
return (c - 'A') + 10;
}
2022-11-19 14:43:09 +00:00
usize _strtou(const char* str, const char** endptr, int base)
{
usize val = 0;
2022-11-19 14:43:09 +00:00
while (_isspace(*str)) str++;
if ((base == 0 || base == 16) && *str == '0')
{
str++;
if (_tolower(*str) == 'x')
{
base = 16;
str++;
}
else if (base == 0)
base = 8;
}
else if (base == 0)
base = 10;
while (is_valid_digit_for_base(base, *str))
2022-11-19 14:43:09 +00:00
{
val = (base * val) + parse_digit_unchecked(*str);
2022-11-19 14:43:09 +00:00
str++;
}
if (endptr) *endptr = str;
return val;
}
isize _strtoi(const char* str, const char** endptr, int base)
{
bool negative = false;
while (_isspace(*str)) str++;
if (*str == '-' || *str == '+')
{
if (*str == '-') negative = true;
str++;
}
usize rc = _strtou(str, endptr,
base); // FIXME: Check for overflow (the unsigned usize value might not fit into a signed isize)
2022-11-19 14:43:09 +00:00
return negative ? -(isize)rc : (isize)rc;
2022-11-19 14:43:09 +00:00
}