diff --git a/Sources/FoundationEssentials/JSON/JSON5Scanner.swift b/Sources/FoundationEssentials/JSON/JSON5Scanner.swift index 10d1af10b..d0f24d27b 100644 --- a/Sources/FoundationEssentials/JSON/JSON5Scanner.swift +++ b/Sources/FoundationEssentials/JSON/JSON5Scanner.swift @@ -1081,7 +1081,7 @@ extension JSON5Scanner { jsonBytes.formIndex(after: &index) } - let cmp = jsonBytes[index..) { let decodedValue = buffer.withUnsafePointer { nptr, count -> Double? in var endPtr: UnsafeMutablePointer? = nil - let decodedValue = _stringshims_strtod_l(nptr, &endPtr, nil) + let decodedValue = _stringshims_strtod_clocale(nptr, &endPtr) if let endPtr, nptr.advanced(by: count) == endPtr { return decodedValue } else { @@ -1195,7 +1195,7 @@ extension Float : PrevalidatedJSONNumberBufferConvertible { init?(prevalidatedBuffer buffer: BufferView) { let decodedValue = buffer.withUnsafePointer { nptr, count -> Float? in var endPtr: UnsafeMutablePointer? = nil - let decodedValue = _stringshims_strtof_l(nptr, &endPtr, nil) + let decodedValue = _stringshims_strtof_clocale(nptr, &endPtr) if let endPtr, nptr.advanced(by: count) == endPtr { return decodedValue } else { diff --git a/Sources/FoundationEssentials/PropertyList/PlistDecoder.swift b/Sources/FoundationEssentials/PropertyList/PlistDecoder.swift index 79ec14087..3c620cb84 100644 --- a/Sources/FoundationEssentials/PropertyList/PlistDecoder.swift +++ b/Sources/FoundationEssentials/PropertyList/PlistDecoder.swift @@ -231,7 +231,7 @@ open class PropertyListDecoder { } return try buffer[unchecked: baseIdx..? let res : T if MemoryLayout.size == MemoryLayout.size { - res = T(_stringshims_strtof_l(ptr, &parseEndPtr, nil)) + res = T(_stringshims_strtof_clocale(ptr, &parseEndPtr)) } else if MemoryLayout.size == MemoryLayout.size { - res = T(_stringshims_strtod_l(ptr, &parseEndPtr, nil)) + res = T(_stringshims_strtod_clocale(ptr, &parseEndPtr)) } else { preconditionFailure("Only Float and Double are currently supported by PropertyListDecoder, not \(type))") } diff --git a/Sources/_FoundationCShims/include/string_shims.h b/Sources/_FoundationCShims/include/string_shims.h index f6d7ce81a..9d7b586e3 100644 --- a/Sources/_FoundationCShims/include/string_shims.h +++ b/Sources/_FoundationCShims/include/string_shims.h @@ -37,11 +37,11 @@ extern "C" { #define locale_t void * #endif -INTERNAL int _stringshims_strncasecmp_l(const char * _Nullable s1, const char * _Nullable s2, size_t n, locale_t _Nullable loc); +INTERNAL int _stringshims_strncasecmp_clocale(const char * _Nullable s1, const char * _Nullable s2, size_t n); -INTERNAL double _stringshims_strtod_l(const char * _Nullable __restrict nptr, char * _Nullable * _Nullable __restrict endptr, locale_t _Nullable loc); +INTERNAL double _stringshims_strtod_clocale(const char * _Nullable __restrict nptr, char * _Nullable * _Nullable __restrict endptr); -INTERNAL float _stringshims_strtof_l(const char * _Nullable __restrict nptr, char * _Nullable * _Nullable __restrict endptr, locale_t _Nullable loc); +INTERNAL float _stringshims_strtof_clocale(const char * _Nullable __restrict nptr, char * _Nullable * _Nullable __restrict endptr); #define _STRINGSHIMS_MACROMAN_MAP_SIZE 129 INTERNAL const uint8_t _stringshims_macroman_mapping[_STRINGSHIMS_MACROMAN_MAP_SIZE][3]; diff --git a/Sources/_FoundationCShims/string_shims.c b/Sources/_FoundationCShims/string_shims.c index 2a744ab20..877c325be 100644 --- a/Sources/_FoundationCShims/string_shims.c +++ b/Sources/_FoundationCShims/string_shims.c @@ -23,57 +23,57 @@ #include #endif -int _stringshims_strncasecmp_l(const char * _Nullable s1, - const char * _Nullable s2, - size_t n, - locale_t _Nullable loc) -{ #if TARGET_OS_WINDOWS - static _locale_t storage; - static _locale_t *cloc = NULL; - if (cloc == NULL) { - storage = _create_locale(LC_ALL, "C"); - cloc = &storage; - } - return _strnicmp_l(s1, s2, n, loc ? loc : *cloc); -#else - if (loc != NULL) { -#if (defined(TARGET_OS_EXCLAVEKIT) && TARGET_OS_EXCLAVEKIT) || \ - (defined(TARGET_OS_ANDROID) && TARGET_OS_ANDROID && __ANDROID_API__ < 23) - abort(); +#define FOUNDATION_C_LOCALE (_clocale()) +static _locale_t _clocale() { + static _locale_t storage; + static bool once = false; + if (!once) { + storage = _create_locale(LC_ALL, "C"); + once = true; + } + return storage; +} +#elif TARGET_OS_MAC +#define FOUNDATION_C_LOCALE LC_C_LOCALE #else - return strncasecmp_l(s1, s2, n, loc); -#endif +#define FOUNDATION_C_LOCALE (_clocale()) +static locale_t _clocale() { + static locale_t storage; + static bool once = false; + if (!once) { + storage = newlocale(LC_ALL_MASK, "C", (locale_t)0); + once = true; } - // On Darwin, NULL loc means unlocalized compare. - // Uses the standard C locale for Linux in this case -#if (defined(TARGET_OS_EXCLAVEKIT) && TARGET_OS_EXCLAVEKIT) || \ + return storage; +} +#endif + + +int _stringshims_strncasecmp_clocale(const char * _Nullable s1, + const char * _Nullable s2, + size_t n) +{ +#if TARGET_OS_WINDOWS + return _strnicmp_l(s1, s2, n, FOUNDATION_C_LOCALE); +#elif (defined(TARGET_OS_EXCLAVEKIT) && TARGET_OS_EXCLAVEKIT) || \ (defined(TARGET_OS_ANDROID) && TARGET_OS_ANDROID && __ANDROID_API__ < 23) return strncasecmp(s1, s2, n); -#elif TARGET_OS_MAC - return strncasecmp_l(s1, s2, n, NULL); #else - locale_t clocale = newlocale(LC_ALL_MASK, "C", (locale_t)0); - return strncasecmp_l(s1, s2, n, clocale); -#endif // TARGET_OS_MAC -#endif // TARGET_OS_WINDOWS + return strncasecmp_l(s1, s2, n, FOUNDATION_C_LOCALE); +#endif } -double _stringshims_strtod_l(const char * _Nullable restrict nptr, - char * _Nullable * _Nullable restrict endptr, - locale_t _Nullable loc) +double _stringshims_strtod_clocale(const char * _Nullable restrict nptr, + char * _Nullable * _Nullable restrict endptr) { -#if defined(TARGET_OS_EXCLAVEKIT) && TARGET_OS_EXCLAVEKIT - assert(loc == NULL); - return strtod_l(nptr, endptr, NULL); -#elif TARGET_OS_MAC - return strtod_l(nptr, endptr, loc); +#if TARGET_OS_MAC + return strtod_l(nptr, endptr, FOUNDATION_C_LOCALE); #elif TARGET_OS_WINDOWS - return _strtod_l(nptr, endptr, loc); + return _strtod_l(nptr, endptr, FOUNDATION_C_LOCALE); #else // Use the C locale - locale_t clocale = newlocale(LC_ALL_MASK, "C", (locale_t)0); - locale_t oldLocale = uselocale(clocale); + locale_t oldLocale = uselocale(FOUNDATION_C_LOCALE); double result = strtod(nptr, endptr); // Restore locale uselocale(oldLocale); @@ -81,22 +81,17 @@ double _stringshims_strtod_l(const char * _Nullable restrict nptr, #endif } -float _stringshims_strtof_l(const char * _Nullable restrict nptr, - char * _Nullable * _Nullable restrict endptr, - locale_t _Nullable loc) +float _stringshims_strtof_clocale(const char * _Nullable restrict nptr, + char * _Nullable * _Nullable restrict endptr) { -#if defined(TARGET_OS_EXCLAVEKIT) && TARGET_OS_EXCLAVEKIT - assert(loc == NULL); - return strtof_l(nptr, endptr, NULL); -#elif TARGET_OS_MAC - return strtof_l(nptr, endptr, loc); +#if TARGET_OS_MAC + return strtof_l(nptr, endptr, FOUNDATION_C_LOCALE); #elif TARGET_OS_WINDOWS - return _strtof_l(nptr, endptr, loc); + return _strtof_l(nptr, endptr, FOUNDATION_C_LOCALE); #else // Use the C locale - locale_t clocale = newlocale(LC_ALL_MASK, "C", (locale_t)0); - locale_t oldLocale = uselocale(clocale); - float result = strtof(nptr, endptr); + locale_t oldLocale = uselocale(FOUNDATION_C_LOCALE); + double result = strtof(nptr, endptr); // Restore locale uselocale(oldLocale); return result;