Locale.cpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. #include "il2cpp-config.h"
  2. #if IL2CPP_TARGET_POSIX && !IL2CPP_USE_PLATFORM_SPECIFIC_LOCALE
  3. #include <clocale>
  4. #include <locale.h>
  5. #if IL2CPP_TARGET_DARWIN
  6. #include <xlocale.h>
  7. #include <CoreFoundation/CoreFoundation.h>
  8. #endif
  9. #include "os/Locale.h"
  10. #include "utils/Memory.h"
  11. namespace il2cpp
  12. {
  13. namespace os
  14. {
  15. #if IL2CPP_TARGET_ANDROID
  16. std::string AndroidGetLocale();
  17. #endif
  18. #if IL2CPP_TARGET_DARWIN
  19. static std::string DarwinGetLocale()
  20. {
  21. char *darwin_locale = NULL;
  22. CFLocaleRef locale = NULL;
  23. CFStringRef locale_language = NULL;
  24. CFStringRef locale_country = NULL;
  25. CFStringRef locale_script = NULL;
  26. CFStringRef locale_cfstr = NULL;
  27. CFIndex bytes_converted;
  28. CFIndex bytes_written;
  29. CFIndex len;
  30. locale = CFLocaleCopyCurrent();
  31. if (locale)
  32. {
  33. locale_language = (CFStringRef)CFLocaleGetValue(locale, kCFLocaleLanguageCode);
  34. if (locale_language != NULL && CFStringGetBytes(locale_language, CFRangeMake(0, CFStringGetLength(locale_language)), kCFStringEncodingMacRoman, 0, FALSE, NULL, 0, &bytes_converted) > 0)
  35. {
  36. len = bytes_converted + 1;
  37. locale_country = (CFStringRef)CFLocaleGetValue(locale, kCFLocaleCountryCode);
  38. if (locale_country != NULL && CFStringGetBytes(locale_country, CFRangeMake(0, CFStringGetLength(locale_country)), kCFStringEncodingMacRoman, 0, FALSE, NULL, 0, &bytes_converted) > 0)
  39. {
  40. len += bytes_converted + 1;
  41. locale_script = (CFStringRef)CFLocaleGetValue(locale, kCFLocaleScriptCode);
  42. if (locale_script != NULL && CFStringGetBytes(locale_script, CFRangeMake(0, CFStringGetLength(locale_script)), kCFStringEncodingMacRoman, 0, FALSE, NULL, 0, &bytes_converted) > 0)
  43. {
  44. len += bytes_converted + 1;
  45. }
  46. darwin_locale = (char *)IL2CPP_MALLOC(len + 1);
  47. CFStringGetBytes(locale_language, CFRangeMake(0, CFStringGetLength(locale_language)), kCFStringEncodingMacRoman, 0, FALSE, (UInt8 *)darwin_locale, len, &bytes_converted);
  48. darwin_locale[bytes_converted] = '-';
  49. bytes_written = bytes_converted + 1;
  50. 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)
  51. {
  52. darwin_locale[bytes_written + bytes_converted] = '-';
  53. bytes_written += bytes_converted + 1;
  54. }
  55. CFStringGetBytes(locale_country, CFRangeMake(0, CFStringGetLength(locale_country)), kCFStringEncodingMacRoman, 0, FALSE, (UInt8 *)&darwin_locale[bytes_written], len - bytes_written, &bytes_converted);
  56. darwin_locale[bytes_written + bytes_converted] = '\0';
  57. }
  58. }
  59. if (darwin_locale == NULL)
  60. {
  61. locale_cfstr = CFLocaleGetIdentifier(locale);
  62. if (locale_cfstr)
  63. {
  64. len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(locale_cfstr), kCFStringEncodingMacRoman) + 1;
  65. darwin_locale = (char *)IL2CPP_MALLOC(len);
  66. if (!CFStringGetCString(locale_cfstr, darwin_locale, len, kCFStringEncodingMacRoman))
  67. {
  68. IL2CPP_FREE(darwin_locale);
  69. CFRelease(locale);
  70. return std::string();
  71. }
  72. for (int i = 0; i < strlen(darwin_locale); i++)
  73. if (darwin_locale[i] == '_')
  74. darwin_locale[i] = '-';
  75. }
  76. }
  77. CFRelease(locale);
  78. }
  79. std::string result(darwin_locale);
  80. IL2CPP_FREE(darwin_locale);
  81. return result;
  82. }
  83. #endif
  84. /*
  85. * The following method is modified from the ICU source code. (http://oss.software.ibm.com/icu)
  86. * Copyright (c) 1995-2003 International Business Machines Corporation and others
  87. * All rights reserved.
  88. */
  89. static std::string PosixGetLocale()
  90. {
  91. const char* posix_locale = NULL;
  92. posix_locale = getenv("LC_ALL");
  93. if (posix_locale == 0)
  94. {
  95. posix_locale = getenv("LANG");
  96. if (posix_locale == 0)
  97. {
  98. posix_locale = setlocale(LC_ALL, NULL);
  99. }
  100. }
  101. if (posix_locale == NULL)
  102. return std::string();
  103. #if IL2CPP_TARGET_JAVASCRIPT || IL2CPP_TARGET_ANDROID
  104. // This code is here due to a few factors:
  105. // 1. Emscripten and Android give us a "C" locale (the POSIX default).
  106. // 2. The Mono class library code uses managed exceptions for flow control.
  107. // 3. We need to support Emscripten builds with exceptions disabled.
  108. // 4. Our localization tables don't have any entry for the "C" locale.
  109. // These factors mean that with Emscripten, the class library code _always_
  110. // throws a managed exception to due CultureInfo processing. To make this
  111. // work without exceptions enabled, let's map "C" -> "en-us" for Emscripten.
  112. if (strcmp(posix_locale, "C.UTF-8") == 0)
  113. posix_locale = "en-us";
  114. #endif
  115. if ((strcmp("C", posix_locale) == 0) || (strchr(posix_locale, ' ') != NULL)
  116. || (strchr(posix_locale, '/') != NULL))
  117. {
  118. /*
  119. * HPUX returns 'C C C C C C C'
  120. * Solaris can return /en_US/C/C/C/C/C on the second try.
  121. * Maybe we got some garbage.
  122. */
  123. return std::string();
  124. }
  125. return std::string(posix_locale);
  126. }
  127. std::string Locale::GetLocale()
  128. {
  129. std::string locale;
  130. #if IL2CPP_TARGET_DARWIN
  131. locale = DarwinGetLocale();
  132. #elif IL2CPP_TARGET_ANDROID
  133. locale = AndroidGetLocale();
  134. #endif
  135. if (locale.empty())
  136. locale = PosixGetLocale();
  137. return locale;
  138. }
  139. #if IL2CPP_SUPPORT_LOCALE_INDEPENDENT_PARSING
  140. static locale_t s_cLocale = NULL;
  141. #endif
  142. void Locale::Initialize()
  143. {
  144. #if IL2CPP_SUPPORT_LOCALE_INDEPENDENT_PARSING
  145. s_cLocale = newlocale(LC_ALL_MASK, "", NULL);
  146. #endif
  147. }
  148. void Locale::UnInitialize()
  149. {
  150. #if IL2CPP_SUPPORT_LOCALE_INDEPENDENT_PARSING
  151. if (s_cLocale)
  152. freelocale(s_cLocale);
  153. s_cLocale = NULL;
  154. #endif
  155. }
  156. #if IL2CPP_SUPPORT_LOCALE_INDEPENDENT_PARSING
  157. double Locale::DoubleParseLocaleIndependentImpl(char *ptr, char** endptr)
  158. {
  159. return strtod_l(ptr, endptr, s_cLocale);
  160. }
  161. #endif
  162. } /* namespace os */
  163. } /* namespace il2cpp */
  164. #endif