Skip to content

Commit d3a9314

Browse files
committed
[stdlib] Simplify the strto* platform stubs.
Currently, _swift_stdlib_strtoX_clocale_impl is present here twice: one general definition for most platforms that wraps the standard strto* functions, and another general definition with a slightly different implementation for Cygwin, Haiku, and Windows, using stringstreams to achieve a similar result. Furthermore, for Windows, the stringstream implementation isn't even used but specialized away. Firstly: the stringstream implementation is slightly broken, since it causes some of the unit tests to fail; secondly, there is an awful lot of repetition here that is ripe for simplification. Instead of duplicating twice and using template specialization to induce platform-specific behavior, we massage the stringstream implementation for Cygwin and Haiku into something that looks like a standard strto* function. Now we have one definition (for each type) of swift_strto*_l. By default, the _swift_stdlib_strto*_clocale stubs will refer to strto*_l, and platforms withing to make use of the swift_strto*_l stubs can make the necessary preprocessor definitions to utilize them.
1 parent 3cc9d75 commit d3a9314

File tree

1 file changed

+47
-84
lines changed

1 file changed

+47
-84
lines changed

stdlib/public/stubs/Stubs.cpp

Lines changed: 47 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,18 @@
3636
#endif
3737
#include <climits>
3838
#include <clocale>
39+
#include <cmath>
3940
#include <cstdarg>
4041
#include <cstdint>
4142
#include <cstdio>
4243
#include <cstdlib>
4344
#include <cstring>
44-
#if defined(__OpenBSD__) || defined(__ANDROID__) || defined(__linux__) || defined(__wasi__)
45-
#include <locale.h>
46-
#elif defined(__CYGWIN__) || defined(__HAIKU__) || defined(_WIN32)
4745
#include <sstream>
48-
#include <cmath>
46+
#if defined(__OpenBSD__) || defined(__ANDROID__) || defined(__linux__) || defined(__wasi__) || defined(_WIN32)
47+
#include <locale.h>
48+
#if defined(_WIN32)
49+
#define locale_t _locale_t
50+
#endif
4951
#else
5052
#include <xlocale.h>
5153
#endif
@@ -351,52 +353,61 @@ static bool swift_stringIsSignalingNaN(const char *nptr) {
351353
return strcasecmp(nptr, "snan") == 0;
352354
}
353355

354-
#if defined(__OpenBSD__)
355-
static double swift_strtod_l(const char *nptr, char **endptr, locale_t loc) {
356-
return strtod(nptr, endptr);
357-
}
358-
#elif defined(__ANDROID_API__) && __ANDROID_API__ < 26
359-
static double swift_strtod_l(const char *nptr, char **endptr, locale_t loc) {
360-
return strtod(nptr, endptr);
356+
// This implementation should only be used on platforms without the
357+
// relevant strto* functions, such as Cygwin or Haiku.
358+
// Note that using this currently causes test failures.
359+
template <typename T>
360+
T _swift_strto(const char *nptr, char **endptr) {
361+
std::istringstream ValueStream(nptr);
362+
ValueStream.imbue(std::locale::classic());
363+
T ParsedValue;
364+
ValueStream >> ParsedValue;
365+
366+
std::streamoff pos = ValueStream.tellg();
367+
if (ValueStream.eof())
368+
pos = static_cast<std::streamoff>(strlen(nptr));
369+
if (pos <= 0) {
370+
errno = ERANGE;
371+
return 0.0;
372+
}
373+
374+
return ParsedValue;
361375
}
362-
#elif defined(_WIN32)
376+
363377
static double swift_strtod_l(const char *nptr, char **endptr, locale_t loc) {
378+
#if defined(_WIN32)
364379
return _strtod_l(nptr, endptr, getCLocale());
365-
}
380+
#elif defined(__CYGWIN__) || defined(__HAIKU__)
381+
return _swift_strto<double>(nptr, endptr);
382+
#else
383+
return strtod(nptr, endptr);
366384
#endif
367-
368-
#if defined(__OpenBSD__)
369-
static float swift_strtof_l(const char *nptr, char **endptr, locale_t loc) {
370-
return strtof(nptr, endptr);
371-
}
372-
#elif defined(__ANDROID_API__) && __ANDROID_API__ < 26
373-
static float swift_strtof_l(const char *nptr, char **endptr, locale_t loc) {
374-
return strtof(nptr, endptr);
375385
}
376-
#elif defined(_WIN32)
386+
377387
static float swift_strtof_l(const char *nptr, char **endptr, locale_t loc) {
388+
#if defined(_WIN32)
378389
return _strtof_l(nptr, endptr, getCLocale());
379-
}
390+
#elif defined(__CYGWIN__) || defined(__HAIKU__)
391+
return _swift_strto<float>(nptr, endptr);
392+
#else
393+
return strtof(nptr, endptr);
380394
#endif
381-
382-
#if defined(__OpenBSD__)
383-
static long double swift_strtold_l(const char *nptr, char **endptr,
384-
locale_t loc) {
385-
return strtold(nptr, endptr);
386-
}
387-
#elif defined(__ANDROID_API__) && __ANDROID_API__ < 21
388-
static long double swift_strtold_l(const char *nptr, char **endptr,
389-
locale_t loc) {
390-
return strtod(nptr, endptr);
391395
}
392-
#elif defined(_WIN32)
396+
393397
static long double swift_strtold_l(const char *nptr, char **endptr,
394398
locale_t loc) {
399+
#if defined(_WIN32)
395400
return _strtod_l(nptr, endptr, getCLocale());
396-
}
401+
#elif defined(__ANDROID__)
402+
return strtod(nptr, endptr);
403+
#elif defined(__CYGWIN__) || defined(__HAIKU__)
404+
return _swift_strto<long double>(nptr, endptr);
405+
#else
406+
return strtold(nptr, endptr);
397407
#endif
408+
}
398409

399-
#if defined(__OpenBSD__) || defined(_WIN32)
410+
#if defined(__OpenBSD__) || defined(_WIN32) || defined(__CYGWIN__) || defined(__HAIKU__)
400411
#define strtod_l swift_strtod_l
401412
#define strtof_l swift_strtof_l
402413
#define strtold_l swift_strtold_l
@@ -409,55 +420,8 @@ static long double swift_strtold_l(const char *nptr, char **endptr,
409420
#define strtod_l swift_strtod_l
410421
#define strtof_l swift_strtof_l
411422
#endif
412-
#elif defined(_WIN32)
413-
#define strtod_l swift_strtod_l
414-
#define strtof_l swift_strtof_l
415-
#define strtold_l swift_strtold_l
416423
#endif
417424

418-
#if defined(__CYGWIN__) || defined(__HAIKU__)
419-
// Cygwin does not support uselocale(), but we can use the locale feature
420-
// in stringstream object.
421-
template <typename T>
422-
static const char *_swift_stdlib_strtoX_clocale_impl(
423-
const char *nptr, T *outResult) {
424-
if (swift_stringIsSignalingNaN(nptr)) {
425-
*outResult = std::numeric_limits<T>::signaling_NaN();
426-
return nptr + std::strlen(nptr);
427-
}
428-
429-
std::istringstream ValueStream(nptr);
430-
ValueStream.imbue(std::locale::classic());
431-
T ParsedValue;
432-
ValueStream >> ParsedValue;
433-
*outResult = ParsedValue;
434-
435-
std::streamoff pos = ValueStream.tellg();
436-
if (ValueStream.eof())
437-
pos = static_cast<std::streamoff>(strlen(nptr));
438-
if (pos <= 0)
439-
return nullptr;
440-
441-
return nptr + pos;
442-
}
443-
444-
const char *swift::_swift_stdlib_strtold_clocale(
445-
const char *nptr, void *outResult) {
446-
return _swift_stdlib_strtoX_clocale_impl(
447-
nptr, static_cast<long double*>(outResult));
448-
}
449-
450-
const char *swift::_swift_stdlib_strtod_clocale(
451-
const char * nptr, double *outResult) {
452-
return _swift_stdlib_strtoX_clocale_impl(nptr, outResult);
453-
}
454-
455-
const char *swift::_swift_stdlib_strtof_clocale(
456-
const char * nptr, float *outResult) {
457-
return _swift_stdlib_strtoX_clocale_impl(nptr, outResult);
458-
}
459-
#else
460-
461425
static inline void _swift_set_errno(int to) {
462426
#if defined(_WIN32)
463427
_set_errno(0);
@@ -508,7 +472,6 @@ const char *swift::_swift_stdlib_strtof_clocale(
508472
return _swift_stdlib_strtoX_clocale_impl(
509473
nptr, outResult, HUGE_VALF, strtof_l);
510474
}
511-
#endif
512475

513476
const char *swift::_swift_stdlib_strtof16_clocale(
514477
const char * nptr, __fp16 *outResult) {

0 commit comments

Comments
 (0)