diff options
author | Karl Berry <karl@freefriends.org> | 2019-01-08 19:24:46 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2019-01-08 19:24:46 +0000 |
commit | 3eec52e2f37fb5ad2e6de4ec20cb26ff280777a1 (patch) | |
tree | 206a748c51d12870ca8426c9d7a59a11639d87b2 /Build/source/libs/icu/icu-src/source/common/putil.cpp | |
parent | 730f4601e0de27c5eccd405e393f80425fa6cdf2 (diff) |
icu 63.1
git-svn-id: svn://tug.org/texlive/trunk@49641 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/libs/icu/icu-src/source/common/putil.cpp')
-rw-r--r-- | Build/source/libs/icu/icu-src/source/common/putil.cpp | 209 |
1 files changed, 88 insertions, 121 deletions
diff --git a/Build/source/libs/icu/icu-src/source/common/putil.cpp b/Build/source/libs/icu/icu-src/source/common/putil.cpp index 83f08ac0705..769309b422c 100644 --- a/Build/source/libs/icu/icu-src/source/common/putil.cpp +++ b/Build/source/libs/icu/icu-src/source/common/putil.cpp @@ -102,9 +102,8 @@ # define NOMCX # include <windows.h> # include "unicode/uloc.h" -#if U_PLATFORM_HAS_WINUWP_API == 0 # include "wintz.h" -#else // U_PLATFORM_HAS_WINUWP_API +#if U_PLATFORM_HAS_WINUWP_API typedef PVOID LPMSG; // TODO: figure out how to get rid of this typedef #include <Windows.Globalization.h> #include <windows.system.userprofile.h> @@ -533,6 +532,28 @@ uprv_fmin(double x, double y) return (x > y ? y : x); } +U_CAPI UBool U_EXPORT2 +uprv_add32_overflow(int32_t a, int32_t b, int32_t* res) { + // NOTE: Some compilers (GCC, Clang) have primitives available, like __builtin_add_overflow. + // This function could be optimized by calling one of those primitives. + auto a64 = static_cast<int64_t>(a); + auto b64 = static_cast<int64_t>(b); + int64_t res64 = a64 + b64; + *res = static_cast<int32_t>(res64); + return res64 != *res; +} + +U_CAPI UBool U_EXPORT2 +uprv_mul32_overflow(int32_t a, int32_t b, int32_t* res) { + // NOTE: Some compilers (GCC, Clang) have primitives available, like __builtin_mul_overflow. + // This function could be optimized by calling one of those primitives. + auto a64 = static_cast<int64_t>(a); + auto b64 = static_cast<int64_t>(b); + int64_t res64 = a64 * b64; + *res = static_cast<int32_t>(res64); + return res64 != *res; +} + /** * Truncates the given double. * trunc(3.3) = 3.0, trunc (-3.3) = -3.0 @@ -1040,53 +1061,13 @@ uprv_tzname_clear_cache() #endif } -// With the Universal Windows Platform we can just ask Windows for the name -#if U_PLATFORM_HAS_WINUWP_API -U_CAPI const char* U_EXPORT2 -uprv_getWindowsTimeZone() -{ - // Get default Windows timezone. - ComPtr<IInspectable> calendar; - HRESULT hr = RoActivateInstance( - HStringReference(RuntimeClass_Windows_Globalization_Calendar).Get(), - &calendar); - if (SUCCEEDED(hr)) - { - ComPtr<ABI::Windows::Globalization::ITimeZoneOnCalendar> timezone; - hr = calendar.As(&timezone); - if (SUCCEEDED(hr)) - { - HString timezoneString; - hr = timezone->GetTimeZone(timezoneString.GetAddressOf()); - if (SUCCEEDED(hr)) - { - int32_t length = static_cast<int32_t>(wcslen(timezoneString.GetRawBuffer(NULL))); - char* asciiId = (char*)uprv_calloc(length + 1, sizeof(char)); - if (asciiId != nullptr) - { - u_UCharsToChars((UChar*)timezoneString.GetRawBuffer(NULL), asciiId, length); - return asciiId; - } - } - } - } - - // Failed - return nullptr; -} -#endif - U_CAPI const char* U_EXPORT2 uprv_tzname(int n) { (void)n; // Avoid unreferenced parameter warning. const char *tzid = NULL; #if U_PLATFORM_USES_ONLY_WIN32_API -#if U_PLATFORM_HAS_WINUWP_API > 0 - tzid = uprv_getWindowsTimeZone(); -#else tzid = uprv_detectWindowsTimeZone(); -#endif if (tzid != NULL) { return tzid; @@ -1344,6 +1325,43 @@ uprv_pathIsAbsolute(const char *path) # endif #endif +#if U_PLATFORM_HAS_WINUWP_API != 0 +// Helper function to get the ICU Data Directory under the Windows directory location. +static BOOL U_CALLCONV getIcuDataDirectoryUnderWindowsDirectory(char* directoryBuffer, UINT bufferLength) +{ +#if defined(ICU_DATA_DIR_WINDOWS) + wchar_t windowsPath[MAX_PATH]; + char windowsPathUtf8[MAX_PATH]; + + UINT length = GetSystemWindowsDirectoryW(windowsPath, UPRV_LENGTHOF(windowsPath)); + if ((length > 0) && (length < (UPRV_LENGTHOF(windowsPath) - 1))) { + // Convert UTF-16 to a UTF-8 string. + UErrorCode status = U_ZERO_ERROR; + int32_t windowsPathUtf8Len = 0; + u_strToUTF8(windowsPathUtf8, static_cast<int32_t>(UPRV_LENGTHOF(windowsPathUtf8)), + &windowsPathUtf8Len, reinterpret_cast<const UChar*>(windowsPath), -1, &status); + + if (U_SUCCESS(status) && (status != U_STRING_NOT_TERMINATED_WARNING) && + (windowsPathUtf8Len < (UPRV_LENGTHOF(windowsPathUtf8) - 1))) { + // Ensure it always has a separator, so we can append the ICU data path. + if (windowsPathUtf8[windowsPathUtf8Len - 1] != U_FILE_SEP_CHAR) { + windowsPathUtf8[windowsPathUtf8Len++] = U_FILE_SEP_CHAR; + windowsPathUtf8[windowsPathUtf8Len] = '\0'; + } + // Check if the concatenated string will fit. + if ((windowsPathUtf8Len + UPRV_LENGTHOF(ICU_DATA_DIR_WINDOWS)) < bufferLength) { + uprv_strcpy(directoryBuffer, windowsPathUtf8); + uprv_strcat(directoryBuffer, ICU_DATA_DIR_WINDOWS); + return TRUE; + } + } + } +#endif + + return FALSE; +} +#endif + static void U_CALLCONV dataDirectoryInitFn() { /* If we already have the directory, then return immediately. Will happen if user called * u_setDataDirectory(). @@ -1403,24 +1421,10 @@ static void U_CALLCONV dataDirectoryInitFn() { } #endif -#if defined(ICU_DATA_DIR_WINDOWS) && U_PLATFORM_HAS_WINUWP_API != 0 - // Use data from the %windir%\globalization\icu directory - // This is only available if ICU is built as a system component +#if U_PLATFORM_HAS_WINUWP_API != 0 && defined(ICU_DATA_DIR_WINDOWS) char datadir_path_buffer[MAX_PATH]; - UINT length = GetWindowsDirectoryA(datadir_path_buffer, UPRV_LENGTHOF(datadir_path_buffer)); - if (length > 0 && length < (UPRV_LENGTHOF(datadir_path_buffer) - sizeof(ICU_DATA_DIR_WINDOWS) - 1)) - { - if (datadir_path_buffer[length - 1] != '\\') - { - datadir_path_buffer[length++] = '\\'; - datadir_path_buffer[length] = '\0'; - } - - if ((length + 1 + sizeof(ICU_DATA_DIR_WINDOWS)) < UPRV_LENGTHOF(datadir_path_buffer)) - { - uprv_strcat(datadir_path_buffer, ICU_DATA_DIR_WINDOWS); - path = datadir_path_buffer; - } + if (getIcuDataDirectoryUnderWindowsDirectory(datadir_path_buffer, UPRV_LENGTHOF(datadir_path_buffer))) { + path = datadir_path_buffer; } #endif @@ -1469,20 +1473,30 @@ static void U_CALLCONV TimeZoneDataDirInitFn(UErrorCode &status) { status = U_MEMORY_ALLOCATION_ERROR; return; } -#if U_PLATFORM_HAS_WINUWP_API == 0 - const char *dir = getenv("ICU_TIMEZONE_FILES_DIR"); -#else - // TODO: UWP does not support alternate timezone data directories at this time + const char *dir = ""; + +#if U_PLATFORM_HAS_WINUWP_API != 0 + // The UWP version does not support the environment variable setting, but can possibly pick them up from the Windows directory. + char datadir_path_buffer[MAX_PATH]; + if (getIcuDataDirectoryUnderWindowsDirectory(datadir_path_buffer, UPRV_LENGTHOF(datadir_path_buffer))) { + dir = datadir_path_buffer; + } +#else + dir = getenv("ICU_TIMEZONE_FILES_DIR"); #endif // U_PLATFORM_HAS_WINUWP_API + #if defined(U_TIMEZONE_FILES_DIR) if (dir == NULL) { + // Build time configuration setting. dir = TO_STRING(U_TIMEZONE_FILES_DIR); } #endif + if (dir == NULL) { dir = ""; } + setTimeZoneFilesDir(dir, status); } @@ -1654,7 +1668,8 @@ The leftmost codepage (.xxx) wins. /* Note that we scan the *uncorrected* ID. */ if ((p = uprv_strrchr(posixID, '@')) != NULL) { if (correctedPOSIXLocale == NULL) { - correctedPOSIXLocale = static_cast<char *>(uprv_malloc(uprv_strlen(posixID)+1)); + /* new locale can be 1 char longer than old one if @ -> __ */ + correctedPOSIXLocale = static_cast<char *>(uprv_malloc(uprv_strlen(posixID)+2)); /* Exit on memory allocation error. */ if (correctedPOSIXLocale == NULL) { return NULL; @@ -1671,7 +1686,7 @@ The leftmost codepage (.xxx) wins. } if (uprv_strchr(correctedPOSIXLocale,'_') == NULL) { - uprv_strcat(correctedPOSIXLocale, "__"); /* aa@b -> aa__b */ + uprv_strcat(correctedPOSIXLocale, "__"); /* aa@b -> aa__b (note this can make the new locale 1 char longer) */ } else { uprv_strcat(correctedPOSIXLocale, "_"); /* aa_CC@b -> aa_CC_b */ @@ -1725,70 +1740,22 @@ The leftmost codepage (.xxx) wins. #elif U_PLATFORM_USES_ONLY_WIN32_API #define POSIX_LOCALE_CAPACITY 64 UErrorCode status = U_ZERO_ERROR; - char *correctedPOSIXLocale = 0; + char *correctedPOSIXLocale = nullptr; // If we have already figured this out just use the cached value - if (gCorrectedPOSIXLocale != NULL) { + if (gCorrectedPOSIXLocale != nullptr) { return gCorrectedPOSIXLocale; } // No cached value, need to determine the current value - static WCHAR windowsLocale[LOCALE_NAME_MAX_LENGTH]; -#if U_PLATFORM_HAS_WINUWP_API == 0 - // If not a Universal Windows App, we'll need user default language. - // Vista and above should use Locale Names instead of LCIDs - int length = GetUserDefaultLocaleName(windowsLocale, UPRV_LENGTHOF(windowsLocale)); -#else - // In a UWP app, we want the top language that the application and user agreed upon - ComPtr<ABI::Windows::Foundation::Collections::IVectorView<HSTRING>> languageList; - - ComPtr<ABI::Windows::Globalization::IApplicationLanguagesStatics> applicationLanguagesStatics; - HRESULT hr = GetActivationFactory( - HStringReference(RuntimeClass_Windows_Globalization_ApplicationLanguages).Get(), - &applicationLanguagesStatics); - if (SUCCEEDED(hr)) - { - hr = applicationLanguagesStatics->get_Languages(&languageList); - } - - if (FAILED(hr)) - { - // If there is no application context, then use the top language from the user language profile - ComPtr<ABI::Windows::System::UserProfile::IGlobalizationPreferencesStatics> globalizationPreferencesStatics; - hr = GetActivationFactory( - HStringReference(RuntimeClass_Windows_System_UserProfile_GlobalizationPreferences).Get(), - &globalizationPreferencesStatics); - if (SUCCEEDED(hr)) - { - hr = globalizationPreferencesStatics->get_Languages(&languageList); - } - } - - // We have a list of languages, ICU knows one, so use the top one for our locale - HString topLanguage; - if (SUCCEEDED(hr)) - { - hr = languageList->GetAt(0, topLanguage.GetAddressOf()); - } + static WCHAR windowsLocale[LOCALE_NAME_MAX_LENGTH] = {}; + int length = GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_SNAME, windowsLocale, LOCALE_NAME_MAX_LENGTH); - if (FAILED(hr)) - { - // Unexpected, use en-US by default - if (gCorrectedPOSIXLocale == NULL) { - gCorrectedPOSIXLocale = "en_US"; - } - - return gCorrectedPOSIXLocale; - } - - // ResolveLocaleName will get a likely subtags form consistent with Windows behavior. - int length = ResolveLocaleName(topLanguage.GetRawBuffer(NULL), windowsLocale, UPRV_LENGTHOF(windowsLocale)); -#endif - // Now we should have a Windows locale name that needs converted to the POSIX style, - if (length > 0) + // Now we should have a Windows locale name that needs converted to the POSIX style. + if (length > 0) // If length is 0, then the GetLocaleInfoEx failed. { // First we need to go from UTF-16 to char (and also convert from _ to - while we're at it.) - char modifiedWindowsLocale[LOCALE_NAME_MAX_LENGTH]; + char modifiedWindowsLocale[LOCALE_NAME_MAX_LENGTH] = {}; int32_t i; for (i = 0; i < UPRV_LENGTHOF(modifiedWindowsLocale); i++) @@ -1836,7 +1803,7 @@ The leftmost codepage (.xxx) wins. } // If unable to find a locale we can agree upon, use en-US by default - if (gCorrectedPOSIXLocale == NULL) { + if (gCorrectedPOSIXLocale == nullptr) { gCorrectedPOSIXLocale = "en_US"; } return gCorrectedPOSIXLocale; |