Use thread-safe nl_langinfo_l(), not nl_langinfo().

This gets rid of some setlocale() calls.  The remaining call to
setlocale() in pg_get_encoding_from_locale() is a query of the name
of the current locale when none was provided (in a multi-threaded future
that would need more work).

All known non-Windows targets have nl_langinfo_l(), from POSIX 2008, and
for Windows we already do something thread-safe.

Reviewed-by: Heikki Linnakangas <hlinnaka@iki.fi>
Discussion: https://postgr.es/m/CA%2BhUKGJqVe0%2BPv9dvC9dSums_PXxGo9SWcxYAMBguWJUGbWz-A%40mail.gmail.com
This commit is contained in:
Thomas Munro 2024-08-13 22:27:16 +12:00
parent 14c648ff00
commit 35eeea6230
1 changed files with 21 additions and 50 deletions

View File

@ -306,63 +306,34 @@ pg_get_encoding_from_locale(const char *ctype, bool write_message)
char *sys;
int i;
#ifndef WIN32
locale_t loc;
#endif
/* Get the CODESET property, and also LC_CTYPE if not passed in */
if (ctype)
{
char *save;
char *name;
/* If locale is C or POSIX, we can allow all encodings */
if (pg_strcasecmp(ctype, "C") == 0 ||
pg_strcasecmp(ctype, "POSIX") == 0)
return PG_SQL_ASCII;
save = setlocale(LC_CTYPE, NULL);
if (!save)
return -1; /* setlocale() broken? */
/* must copy result, or it might change after setlocale */
save = strdup(save);
if (!save)
return -1; /* out of memory; unlikely */
name = setlocale(LC_CTYPE, ctype);
if (!name)
{
free(save);
return -1; /* bogus ctype passed in? */
}
#ifndef WIN32
sys = nl_langinfo(CODESET);
if (sys)
sys = strdup(sys);
#else
sys = win32_langinfo(name);
#endif
setlocale(LC_CTYPE, save);
free(save);
}
else
{
/* much easier... */
if (!ctype)
ctype = setlocale(LC_CTYPE, NULL);
if (!ctype)
return -1; /* setlocale() broken? */
/* If locale is C or POSIX, we can allow all encodings */
if (pg_strcasecmp(ctype, "C") == 0 ||
pg_strcasecmp(ctype, "POSIX") == 0)
return PG_SQL_ASCII;
/* If locale is C or POSIX, we can allow all encodings */
if (pg_strcasecmp(ctype, "C") == 0 ||
pg_strcasecmp(ctype, "POSIX") == 0)
return PG_SQL_ASCII;
#ifndef WIN32
sys = nl_langinfo(CODESET);
if (sys)
sys = strdup(sys);
loc = newlocale(LC_CTYPE_MASK, ctype, (locale_t) 0);
if (loc == (locale_t) 0)
return -1; /* bogus ctype passed in? */
sys = nl_langinfo_l(CODESET, loc);
if (sys)
sys = strdup(sys);
freelocale(loc);
#else
sys = win32_langinfo(ctype);
sys = win32_langinfo(ctype);
#endif
}
if (!sys)
return -1; /* out of memory; unlikely */