mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-09-24 20:18:29 +00:00
stdlib: Improve SDL_strtod
- Handle leading whitespace - Handle positive sign - Parse integer part as unsigned long long - Handle signed zero (this also applies to printf)
This commit is contained in:

committed by
Sam Lantinga

parent
a78f612d4b
commit
8092e35287
@@ -540,7 +540,7 @@ static size_t SDL_ScanLongW(const wchar_t *text, int count, int radix, long *val
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(HAVE_VSSCANF) || !defined(HAVE_STRTOUL) || !defined(HAVE_STRTOD)
|
#if !defined(HAVE_VSSCANF) || !defined(HAVE_STRTOUL)
|
||||||
static size_t SDL_ScanUnsignedLong(const char *text, int count, int radix, unsigned long *valuep)
|
static size_t SDL_ScanUnsignedLong(const char *text, int count, int radix, unsigned long *valuep)
|
||||||
{
|
{
|
||||||
const unsigned long ulong_max = ~0UL;
|
const unsigned long ulong_max = ~0UL;
|
||||||
@@ -608,7 +608,7 @@ static size_t SDL_ScanLongLong(const char *text, int count, int radix, long long
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(HAVE_VSSCANF) || !defined(HAVE_STRTOULL)
|
#if !defined(HAVE_VSSCANF) || !defined(HAVE_STRTOULL) || !defined(HAVE_STRTOD)
|
||||||
static size_t SDL_ScanUnsignedLongLong(const char *text, int count, int radix, unsigned long long *valuep)
|
static size_t SDL_ScanUnsignedLongLong(const char *text, int count, int radix, unsigned long long *valuep)
|
||||||
{
|
{
|
||||||
const unsigned long long ullong_max = ~0ULL;
|
const unsigned long long ullong_max = ~0ULL;
|
||||||
@@ -628,35 +628,40 @@ static size_t SDL_ScanUnsignedLongLong(const char *text, int count, int radix, u
|
|||||||
#if !defined(HAVE_VSSCANF) || !defined(HAVE_STRTOD)
|
#if !defined(HAVE_VSSCANF) || !defined(HAVE_STRTOD)
|
||||||
static size_t SDL_ScanFloat(const char *text, double *valuep)
|
static size_t SDL_ScanFloat(const char *text, double *valuep)
|
||||||
{
|
{
|
||||||
const char *textstart = text;
|
const char *text_start = text;
|
||||||
unsigned long lvalue = 0;
|
const char *number_start = text_start;
|
||||||
double value = 0.0;
|
double value = 0.0;
|
||||||
bool negative = false;
|
bool negative = false;
|
||||||
|
|
||||||
if (*text == '-') {
|
while (SDL_isspace(*text)) {
|
||||||
negative = true;
|
|
||||||
++text;
|
++text;
|
||||||
}
|
}
|
||||||
text += SDL_ScanUnsignedLong(text, 0, 10, &lvalue);
|
if (*text == '-' || *text == '+') {
|
||||||
value += lvalue;
|
negative = *text == '-';
|
||||||
if (*text == '.') {
|
|
||||||
int mult = 10;
|
|
||||||
++text;
|
++text;
|
||||||
while (SDL_isdigit((unsigned char)*text)) {
|
}
|
||||||
lvalue = *text - '0';
|
number_start = text;
|
||||||
value += (double)lvalue / mult;
|
if (SDL_isdigit(*text)) {
|
||||||
mult *= 10;
|
value += SDL_strtoull(text, (char **)(&text), 10);
|
||||||
|
if (*text == '.') {
|
||||||
|
double denom = 10;
|
||||||
++text;
|
++text;
|
||||||
|
while (SDL_isdigit(*text)) {
|
||||||
|
value += (double)(*text - '0') / denom;
|
||||||
|
denom *= 10;
|
||||||
|
++text;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (valuep && text > textstart) {
|
if (text == number_start) {
|
||||||
if (negative && value != 0.0) {
|
// no number was parsed, and thus no characters were consumed
|
||||||
*valuep = -value;
|
text = text_start;
|
||||||
} else {
|
|
||||||
*valuep = value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return text - textstart;
|
if (negative) {
|
||||||
|
value = -value;
|
||||||
|
}
|
||||||
|
*valuep = value;
|
||||||
|
return text - text_start;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -1302,10 +1307,8 @@ double SDL_strtod(const char *string, char **endp)
|
|||||||
#ifdef HAVE_STRTOD
|
#ifdef HAVE_STRTOD
|
||||||
return strtod(string, endp);
|
return strtod(string, endp);
|
||||||
#else
|
#else
|
||||||
size_t len;
|
double value;
|
||||||
double value = 0.0;
|
size_t len = SDL_ScanFloat(string, &value);
|
||||||
|
|
||||||
len = SDL_ScanFloat(string, &value);
|
|
||||||
if (endp) {
|
if (endp) {
|
||||||
*endp = (char *)string + len;
|
*endp = (char *)string + len;
|
||||||
}
|
}
|
||||||
@@ -1977,7 +1980,7 @@ static size_t SDL_PrintFloat(char *text, size_t maxlen, SDL_FormatInfo *info, do
|
|||||||
// This isn't especially accurate, but hey, it's easy. :)
|
// This isn't especially accurate, but hey, it's easy. :)
|
||||||
unsigned long long value;
|
unsigned long long value;
|
||||||
|
|
||||||
if (arg < 0) {
|
if (arg < 0.0 || (arg == 0.0 && 1.0 / arg < 0.0)) { // additional check for signed zero
|
||||||
num[length++] = '-';
|
num[length++] = '-';
|
||||||
arg = -arg;
|
arg = -arg;
|
||||||
} else if (info->force_sign) {
|
} else if (info->force_sign) {
|
||||||
|
Reference in New Issue
Block a user