mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 10:08:18 +00:00
Add os_locale_str
to get user locale
This function determines the preferred user locale setting.
This commit is contained in:
parent
6e6dfc9659
commit
413227a5c1
|
@ -26,6 +26,7 @@
|
|||
|
||||
#if defined(CONF_FAMILY_UNIX)
|
||||
#include <csignal>
|
||||
#include <locale>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/utsname.h>
|
||||
|
@ -51,6 +52,7 @@
|
|||
#define _task_user_
|
||||
|
||||
#include <Carbon/Carbon.h>
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <mach-o/dyld.h>
|
||||
#include <mach/mach_time.h>
|
||||
|
||||
|
@ -4266,6 +4268,72 @@ int os_version_str(char *version, int length)
|
|||
#endif
|
||||
}
|
||||
|
||||
void os_locale_str(char *locale, size_t length)
|
||||
{
|
||||
#if defined(CONF_FAMILY_WINDOWS)
|
||||
wchar_t wide_buffer[LOCALE_NAME_MAX_LENGTH];
|
||||
dbg_assert(GetUserDefaultLocaleName(wide_buffer, std::size(wide_buffer)) > 0, "GetUserDefaultLocaleName failure");
|
||||
|
||||
// Assume maximum possible length for encoding as UTF-8.
|
||||
char buffer[UTF8_BYTE_LENGTH * LOCALE_NAME_MAX_LENGTH + 1];
|
||||
dbg_assert(WideCharToMultiByte(CP_UTF8, 0, wide_buffer, -1, buffer, sizeof(buffer), NULL, NULL) > 0, "WideCharToMultiByte failure");
|
||||
|
||||
str_copy(locale, buffer, length);
|
||||
#elif defined(CONF_PLATFORM_MACOS)
|
||||
CFLocaleRef locale_ref = CFLocaleCopyCurrent();
|
||||
CFStringRef locale_identifier_ref = static_cast<CFStringRef>(CFLocaleGetValue(locale_ref, kCFLocaleIdentifier));
|
||||
|
||||
// Count number of UTF16 codepoints, +1 for zero-termination.
|
||||
// Assume maximum possible length for encoding as UTF-8.
|
||||
CFIndex locale_identifier_size = (UTF8_BYTE_LENGTH * CFStringGetLength(locale_identifier_ref) + 1) * sizeof(char);
|
||||
char *locale_identifier = (char *)malloc(locale_identifier_size);
|
||||
dbg_assert(CFStringGetCString(locale_identifier_ref, locale_identifier, locale_identifier_size, kCFStringEncodingUTF8), "CFStringGetCString failure");
|
||||
|
||||
str_copy(locale, locale_identifier, length);
|
||||
|
||||
free(locale_identifier);
|
||||
CFRelease(locale_ref);
|
||||
#else
|
||||
static const char *ENV_VARIABLES[] = {
|
||||
"LC_ALL",
|
||||
"LC_MESSAGES",
|
||||
"LANG",
|
||||
};
|
||||
|
||||
locale[0] = '\0';
|
||||
for(const char *env_variable : ENV_VARIABLES)
|
||||
{
|
||||
const char *env_value = getenv(env_variable);
|
||||
if(env_value)
|
||||
{
|
||||
str_copy(locale, env_value, length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Ensure RFC 3066 format:
|
||||
// - use hyphens instead of underscores
|
||||
// - truncate locale string after first non-standard letter
|
||||
for(int i = 0; i < str_length(locale); ++i)
|
||||
{
|
||||
if(locale[i] == '_')
|
||||
{
|
||||
locale[i] = '-';
|
||||
}
|
||||
else if(locale[i] != '-' && !(locale[i] >= 'a' && locale[i] <= 'z') && !(locale[i] >= 'A' && locale[i] <= 'Z') && !(locale[i] >= '0' && locale[i] <= '9'))
|
||||
{
|
||||
locale[i] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Use default if we could not determine the locale,
|
||||
// i.e. if only the C or POSIX locale is available.
|
||||
if(locale[0] == '\0' || str_comp(locale, "C") == 0 || str_comp(locale, "POSIX") == 0)
|
||||
str_copy(locale, "en-US", length);
|
||||
}
|
||||
|
||||
#if defined(CONF_EXCEPTION_HANDLING)
|
||||
#if defined(CONF_FAMILY_WINDOWS)
|
||||
static HMODULE exception_handling_module = nullptr;
|
||||
|
|
|
@ -2143,6 +2143,14 @@ char str_uppercase(char c);
|
|||
int str_isallnum(const char *str);
|
||||
unsigned str_quickhash(const char *str);
|
||||
|
||||
enum
|
||||
{
|
||||
/**
|
||||
* The maximum bytes necessary to encode one Unicode codepoint with UTF-8.
|
||||
*/
|
||||
UTF8_BYTE_LENGTH = 4,
|
||||
};
|
||||
|
||||
int str_utf8_to_skeleton(const char *str, int *buf, int buf_len);
|
||||
|
||||
/*
|
||||
|
@ -2586,6 +2594,20 @@ int secure_rand_below(int below);
|
|||
*/
|
||||
int os_version_str(char *version, int length);
|
||||
|
||||
/**
|
||||
* Returns a string of the preferred locale of the user / operating system.
|
||||
* The string conforms to [RFC 3066](https://www.ietf.org/rfc/rfc3066.txt)
|
||||
* and only contains the characters `a`-`z`, `A`-`Z`, `0`-`9` and `-`.
|
||||
* If the preferred locale could not be determined this function
|
||||
* falls back to the locale `"en-US"`.
|
||||
*
|
||||
* @param locale Buffer to use for the output.
|
||||
* @param length Length of the output buffer.
|
||||
*
|
||||
* @remark The destination buffer will be zero-terminated.
|
||||
*/
|
||||
void os_locale_str(char *locale, size_t length);
|
||||
|
||||
#if defined(CONF_EXCEPTION_HANDLING)
|
||||
void init_exception_handler();
|
||||
void set_exception_handler_log_file(const char *log_file_path);
|
||||
|
|
|
@ -9,3 +9,10 @@ TEST(Os, VersionStr)
|
|||
EXPECT_FALSE(os_version_str(aVersion, sizeof(aVersion)));
|
||||
EXPECT_STRNE(aVersion, "");
|
||||
}
|
||||
|
||||
TEST(Os, LocaleStr)
|
||||
{
|
||||
char aLocale[128];
|
||||
os_locale_str(aLocale, sizeof(aLocale));
|
||||
EXPECT_STRNE(aLocale, "");
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue