123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196 |
- #include "il2cpp-config.h"
- #if IL2CPP_TARGET_POSIX && !IL2CPP_USE_PLATFORM_SPECIFIC_LOCALE
- #include <clocale>
- #include <locale.h>
- #if IL2CPP_TARGET_DARWIN
- #include <xlocale.h>
- #include <CoreFoundation/CoreFoundation.h>
- #endif
- #include "os/Locale.h"
- #include "utils/Memory.h"
- namespace il2cpp
- {
- namespace os
- {
- #if IL2CPP_TARGET_ANDROID
- std::string AndroidGetLocale();
- #endif
- #if IL2CPP_TARGET_DARWIN
- static std::string DarwinGetLocale()
- {
- char *darwin_locale = NULL;
- CFLocaleRef locale = NULL;
- CFStringRef locale_language = NULL;
- CFStringRef locale_country = NULL;
- CFStringRef locale_script = NULL;
- CFStringRef locale_cfstr = NULL;
- CFIndex bytes_converted;
- CFIndex bytes_written;
- CFIndex len;
- locale = CFLocaleCopyCurrent();
- if (locale)
- {
- locale_language = (CFStringRef)CFLocaleGetValue(locale, kCFLocaleLanguageCode);
- if (locale_language != NULL && CFStringGetBytes(locale_language, CFRangeMake(0, CFStringGetLength(locale_language)), kCFStringEncodingMacRoman, 0, FALSE, NULL, 0, &bytes_converted) > 0)
- {
- len = bytes_converted + 1;
- locale_country = (CFStringRef)CFLocaleGetValue(locale, kCFLocaleCountryCode);
- if (locale_country != NULL && CFStringGetBytes(locale_country, CFRangeMake(0, CFStringGetLength(locale_country)), kCFStringEncodingMacRoman, 0, FALSE, NULL, 0, &bytes_converted) > 0)
- {
- len += bytes_converted + 1;
- locale_script = (CFStringRef)CFLocaleGetValue(locale, kCFLocaleScriptCode);
- if (locale_script != NULL && CFStringGetBytes(locale_script, CFRangeMake(0, CFStringGetLength(locale_script)), kCFStringEncodingMacRoman, 0, FALSE, NULL, 0, &bytes_converted) > 0)
- {
- len += bytes_converted + 1;
- }
- darwin_locale = (char *)IL2CPP_MALLOC(len + 1);
- CFStringGetBytes(locale_language, CFRangeMake(0, CFStringGetLength(locale_language)), kCFStringEncodingMacRoman, 0, FALSE, (UInt8 *)darwin_locale, len, &bytes_converted);
- darwin_locale[bytes_converted] = '-';
- bytes_written = bytes_converted + 1;
- if (locale_script != NULL && CFStringGetBytes(locale_script, CFRangeMake(0, CFStringGetLength(locale_script)), kCFStringEncodingMacRoman, 0, FALSE, (UInt8 *)&darwin_locale[bytes_written], len - bytes_written, &bytes_converted) > 0)
- {
- darwin_locale[bytes_written + bytes_converted] = '-';
- bytes_written += bytes_converted + 1;
- }
- CFStringGetBytes(locale_country, CFRangeMake(0, CFStringGetLength(locale_country)), kCFStringEncodingMacRoman, 0, FALSE, (UInt8 *)&darwin_locale[bytes_written], len - bytes_written, &bytes_converted);
- darwin_locale[bytes_written + bytes_converted] = '\0';
- }
- }
- if (darwin_locale == NULL)
- {
- locale_cfstr = CFLocaleGetIdentifier(locale);
- if (locale_cfstr)
- {
- len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(locale_cfstr), kCFStringEncodingMacRoman) + 1;
- darwin_locale = (char *)IL2CPP_MALLOC(len);
- if (!CFStringGetCString(locale_cfstr, darwin_locale, len, kCFStringEncodingMacRoman))
- {
- IL2CPP_FREE(darwin_locale);
- CFRelease(locale);
- return std::string();
- }
- for (int i = 0; i < strlen(darwin_locale); i++)
- if (darwin_locale[i] == '_')
- darwin_locale[i] = '-';
- }
- }
- CFRelease(locale);
- }
- std::string result(darwin_locale);
- IL2CPP_FREE(darwin_locale);
- return result;
- }
- #endif
- /*
- * The following method is modified from the ICU source code. (http://oss.software.ibm.com/icu)
- * Copyright (c) 1995-2003 International Business Machines Corporation and others
- * All rights reserved.
- */
- static std::string PosixGetLocale()
- {
- const char* posix_locale = NULL;
- posix_locale = getenv("LC_ALL");
- if (posix_locale == 0)
- {
- posix_locale = getenv("LANG");
- if (posix_locale == 0)
- {
- posix_locale = setlocale(LC_ALL, NULL);
- }
- }
- if (posix_locale == NULL)
- return std::string();
- #if IL2CPP_TARGET_JAVASCRIPT || IL2CPP_TARGET_ANDROID
- // This code is here due to a few factors:
- // 1. Emscripten and Android give us a "C" locale (the POSIX default).
- // 2. The Mono class library code uses managed exceptions for flow control.
- // 3. We need to support Emscripten builds with exceptions disabled.
- // 4. Our localization tables don't have any entry for the "C" locale.
- // These factors mean that with Emscripten, the class library code _always_
- // throws a managed exception to due CultureInfo processing. To make this
- // work without exceptions enabled, let's map "C" -> "en-us" for Emscripten.
- if (strcmp(posix_locale, "C.UTF-8") == 0)
- posix_locale = "en-us";
- #endif
- if ((strcmp("C", posix_locale) == 0) || (strchr(posix_locale, ' ') != NULL)
- || (strchr(posix_locale, '/') != NULL))
- {
- /*
- * HPUX returns 'C C C C C C C'
- * Solaris can return /en_US/C/C/C/C/C on the second try.
- * Maybe we got some garbage.
- */
- return std::string();
- }
- return std::string(posix_locale);
- }
- std::string Locale::GetLocale()
- {
- std::string locale;
- #if IL2CPP_TARGET_DARWIN
- locale = DarwinGetLocale();
- #elif IL2CPP_TARGET_ANDROID
- locale = AndroidGetLocale();
- #endif
- if (locale.empty())
- locale = PosixGetLocale();
- return locale;
- }
- #if IL2CPP_SUPPORT_LOCALE_INDEPENDENT_PARSING
- static locale_t s_cLocale = NULL;
- #endif
- void Locale::Initialize()
- {
- #if IL2CPP_SUPPORT_LOCALE_INDEPENDENT_PARSING
- s_cLocale = newlocale(LC_ALL_MASK, "", NULL);
- #endif
- }
- void Locale::UnInitialize()
- {
- #if IL2CPP_SUPPORT_LOCALE_INDEPENDENT_PARSING
- if (s_cLocale)
- freelocale(s_cLocale);
- s_cLocale = NULL;
- #endif
- }
- #if IL2CPP_SUPPORT_LOCALE_INDEPENDENT_PARSING
- double Locale::DoubleParseLocaleIndependentImpl(char *ptr, char** endptr)
- {
- return strtod_l(ptr, endptr, s_cLocale);
- }
- #endif
- } /* namespace os */
- } /* namespace il2cpp */
- #endif
|