patch android + gcc locale issue
SFINAE workaround for missing lconv support in Android (gcc + libstdc++)
See: 2fd6c0b245
Discussion: https://github.com/nlohmann/json/issues/638#issuecomment-314079985
Note: Clang + libc++ should work (where available)
Returns the thousands separator for the current locale. On android (gcc/libstdc++) the lconv structure is stubbed using an empty structure. The test is for the size only, not for the presense of thousands_sep in std::lconv, because if one would add thousands_sep at some point, the size of structure would be at least sizeof(char*)
Ditto for decimal_point.
This commit is contained in:
parent
850d856aae
commit
cb8716ef43
47
src/json.hpp
47
src/json.hpp
@ -108,6 +108,44 @@ SOFTWARE.
|
|||||||
#define JSON_UNLIKELY(x) x
|
#define JSON_UNLIKELY(x) x
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
namespace nlohmann
|
||||||
|
{
|
||||||
|
namespace internal
|
||||||
|
{
|
||||||
|
// SFINAE workaround for missing lconv support in Android (gcc + libstdc++)
|
||||||
|
// See: https://github.com/fmtlib/fmt/commit/2fd6c0b24524f7ef107090d08cd86cdeb98fdac0
|
||||||
|
//
|
||||||
|
// Discussion: https://github.com/nlohmann/json/issues/638#issuecomment-314079985
|
||||||
|
// Note: Clang + libc++ should work (where available)
|
||||||
|
//
|
||||||
|
// Returns the thousands separator for the current locale.
|
||||||
|
// On android (gcc/libstdc++) the lconv structure is stubbed using an empty structure
|
||||||
|
// The test is for the size only, not for the presense of
|
||||||
|
// thousands_sep in std::lconv, because if one would add thousands_sep
|
||||||
|
// at some point, the size of structure would be at least sizeof(char*)
|
||||||
|
//
|
||||||
|
// Ditto for decimal_point.
|
||||||
|
template<typename Lconv, bool=(sizeof(Lconv) >= sizeof(char*))>
|
||||||
|
struct Locale
|
||||||
|
{
|
||||||
|
static const char * thousands_sep() { return ""; }
|
||||||
|
static const char * decimal_point() { return "."; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Lconv>
|
||||||
|
struct Locale<Lconv, true>
|
||||||
|
{
|
||||||
|
static const char * thousands_sep() { return static_cast<Lconv*>(std::localeconv())->thousands_sep; }
|
||||||
|
static const char * decimal_point() { return static_cast<Lconv*>(std::localeconv())->decimal_point; }
|
||||||
|
};
|
||||||
|
|
||||||
|
inline const char first_or_null(const char *str)
|
||||||
|
{
|
||||||
|
return str == nullptr ? '\0' : str[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief namespace for Niels Lohmann
|
@brief namespace for Niels Lohmann
|
||||||
@see https://github.com/nlohmann
|
@see https://github.com/nlohmann
|
||||||
@ -1652,9 +1690,7 @@ class lexer
|
|||||||
/// return the locale-dependent decimal point
|
/// return the locale-dependent decimal point
|
||||||
static char get_decimal_point() noexcept
|
static char get_decimal_point() noexcept
|
||||||
{
|
{
|
||||||
const auto loc = localeconv();
|
return internal::first_or_null(internal::Locale<lconv>::decimal_point());
|
||||||
assert(loc != nullptr);
|
|
||||||
return (loc->decimal_point == nullptr) ? '.' : loc->decimal_point[0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////
|
/////////////////////
|
||||||
@ -6145,10 +6181,11 @@ class serializer
|
|||||||
@param[in] s output stream to serialize to
|
@param[in] s output stream to serialize to
|
||||||
@param[in] ichar indentation character to use
|
@param[in] ichar indentation character to use
|
||||||
*/
|
*/
|
||||||
|
|
||||||
serializer(output_adapter_t<char> s, const char ichar)
|
serializer(output_adapter_t<char> s, const char ichar)
|
||||||
: o(s), loc(std::localeconv()),
|
: o(s), loc(std::localeconv()),
|
||||||
thousands_sep(loc->thousands_sep == nullptr ? '\0' : loc->thousands_sep[0]),
|
thousands_sep(internal::first_or_null(internal::Locale<lconv>::thousands_sep())),
|
||||||
decimal_point(loc->decimal_point == nullptr ? '\0' : loc->decimal_point[0]),
|
decimal_point(internal::first_or_null(internal::Locale<lconv>::decimal_point())),
|
||||||
indent_char(ichar), indent_string(512, indent_char) {}
|
indent_char(ichar), indent_string(512, indent_char) {}
|
||||||
|
|
||||||
// delete because of pointer members
|
// delete because of pointer members
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user