From 7d97abd6099fe3b572ff1f5923655852c0e04b76 Mon Sep 17 00:00:00 2001 From: kasper3 <33230602+kasper3@users.noreply.github.com> Date: Fri, 22 Jun 2018 15:45:26 +0000 Subject: [PATCH 01/14] Rename files --- .../{calendarData.cpp => pal_calendarData.c} | 0 .../System.Globalization.Native/{casing.cpp => pal_casing.c} | 0 .../{collation.cpp => pal_collation.c} | 0 src/corefx/System.Globalization.Native/{errors.h => pal_errors.h} | 0 .../System.Globalization.Native/{icushim.cpp => pal_icushim.c} | 0 .../System.Globalization.Native/{icushim.h => pal_icushim.h} | 0 src/corefx/System.Globalization.Native/{idna.cpp => pal_idna.c} | 0 .../System.Globalization.Native/{locale.cpp => pal_locale.c} | 0 .../System.Globalization.Native/{locale.hpp => pal_locale.h} | 0 .../{localeNumberData.cpp => pal_localeNumberData.c} | 0 .../{localeStringData.cpp => pal_localeStringData.c} | 0 .../{normalization.cpp => pal_normalization.c} | 0 .../{timeZoneInfo.cpp => pal_timeZoneInfo.c} | 0 13 files changed, 0 insertions(+), 0 deletions(-) rename src/corefx/System.Globalization.Native/{calendarData.cpp => pal_calendarData.c} (100%) rename src/corefx/System.Globalization.Native/{casing.cpp => pal_casing.c} (100%) rename src/corefx/System.Globalization.Native/{collation.cpp => pal_collation.c} (100%) rename src/corefx/System.Globalization.Native/{errors.h => pal_errors.h} (100%) rename src/corefx/System.Globalization.Native/{icushim.cpp => pal_icushim.c} (100%) rename src/corefx/System.Globalization.Native/{icushim.h => pal_icushim.h} (100%) rename src/corefx/System.Globalization.Native/{idna.cpp => pal_idna.c} (100%) rename src/corefx/System.Globalization.Native/{locale.cpp => pal_locale.c} (100%) rename src/corefx/System.Globalization.Native/{locale.hpp => pal_locale.h} (100%) rename src/corefx/System.Globalization.Native/{localeNumberData.cpp => pal_localeNumberData.c} (100%) rename src/corefx/System.Globalization.Native/{localeStringData.cpp => pal_localeStringData.c} (100%) rename src/corefx/System.Globalization.Native/{normalization.cpp => pal_normalization.c} (100%) rename src/corefx/System.Globalization.Native/{timeZoneInfo.cpp => pal_timeZoneInfo.c} (100%) diff --git a/src/corefx/System.Globalization.Native/calendarData.cpp b/src/corefx/System.Globalization.Native/pal_calendarData.c similarity index 100% rename from src/corefx/System.Globalization.Native/calendarData.cpp rename to src/corefx/System.Globalization.Native/pal_calendarData.c diff --git a/src/corefx/System.Globalization.Native/casing.cpp b/src/corefx/System.Globalization.Native/pal_casing.c similarity index 100% rename from src/corefx/System.Globalization.Native/casing.cpp rename to src/corefx/System.Globalization.Native/pal_casing.c diff --git a/src/corefx/System.Globalization.Native/collation.cpp b/src/corefx/System.Globalization.Native/pal_collation.c similarity index 100% rename from src/corefx/System.Globalization.Native/collation.cpp rename to src/corefx/System.Globalization.Native/pal_collation.c diff --git a/src/corefx/System.Globalization.Native/errors.h b/src/corefx/System.Globalization.Native/pal_errors.h similarity index 100% rename from src/corefx/System.Globalization.Native/errors.h rename to src/corefx/System.Globalization.Native/pal_errors.h diff --git a/src/corefx/System.Globalization.Native/icushim.cpp b/src/corefx/System.Globalization.Native/pal_icushim.c similarity index 100% rename from src/corefx/System.Globalization.Native/icushim.cpp rename to src/corefx/System.Globalization.Native/pal_icushim.c diff --git a/src/corefx/System.Globalization.Native/icushim.h b/src/corefx/System.Globalization.Native/pal_icushim.h similarity index 100% rename from src/corefx/System.Globalization.Native/icushim.h rename to src/corefx/System.Globalization.Native/pal_icushim.h diff --git a/src/corefx/System.Globalization.Native/idna.cpp b/src/corefx/System.Globalization.Native/pal_idna.c similarity index 100% rename from src/corefx/System.Globalization.Native/idna.cpp rename to src/corefx/System.Globalization.Native/pal_idna.c diff --git a/src/corefx/System.Globalization.Native/locale.cpp b/src/corefx/System.Globalization.Native/pal_locale.c similarity index 100% rename from src/corefx/System.Globalization.Native/locale.cpp rename to src/corefx/System.Globalization.Native/pal_locale.c diff --git a/src/corefx/System.Globalization.Native/locale.hpp b/src/corefx/System.Globalization.Native/pal_locale.h similarity index 100% rename from src/corefx/System.Globalization.Native/locale.hpp rename to src/corefx/System.Globalization.Native/pal_locale.h diff --git a/src/corefx/System.Globalization.Native/localeNumberData.cpp b/src/corefx/System.Globalization.Native/pal_localeNumberData.c similarity index 100% rename from src/corefx/System.Globalization.Native/localeNumberData.cpp rename to src/corefx/System.Globalization.Native/pal_localeNumberData.c diff --git a/src/corefx/System.Globalization.Native/localeStringData.cpp b/src/corefx/System.Globalization.Native/pal_localeStringData.c similarity index 100% rename from src/corefx/System.Globalization.Native/localeStringData.cpp rename to src/corefx/System.Globalization.Native/pal_localeStringData.c diff --git a/src/corefx/System.Globalization.Native/normalization.cpp b/src/corefx/System.Globalization.Native/pal_normalization.c similarity index 100% rename from src/corefx/System.Globalization.Native/normalization.cpp rename to src/corefx/System.Globalization.Native/pal_normalization.c diff --git a/src/corefx/System.Globalization.Native/timeZoneInfo.cpp b/src/corefx/System.Globalization.Native/pal_timeZoneInfo.c similarity index 100% rename from src/corefx/System.Globalization.Native/timeZoneInfo.cpp rename to src/corefx/System.Globalization.Native/pal_timeZoneInfo.c From 63d5bab7d06056d36e7f474666954ea2b86abf10 Mon Sep 17 00:00:00 2001 From: kasper3 <33230602+kasper3@users.noreply.github.com> Date: Fri, 22 Jun 2018 15:54:55 +0000 Subject: [PATCH 02/14] Convert System.Globalization.Native to C --- .../CMakeLists.txt | 34 ++- .../configure.cmake | 10 +- .../System.Globalization.Native/holders.h | 94 ------- .../pal_calendarData.c | 243 +++++++++-------- .../pal_calendarData.h | 91 +++++++ .../System.Globalization.Native/pal_casing.c | 18 +- .../System.Globalization.Native/pal_casing.h | 24 ++ .../pal_collation.c | 256 ++++++++++-------- .../pal_collation.h | 82 ++++++ .../pal_compiler.h | 19 ++ .../System.Globalization.Native/pal_errors.h | 10 +- .../System.Globalization.Native/pal_icushim.c | 59 ++-- .../System.Globalization.Native/pal_icushim.h | 10 +- .../System.Globalization.Native/pal_idna.c | 8 +- .../System.Globalization.Native/pal_idna.h | 19 ++ .../System.Globalization.Native/pal_locale.c | 17 +- .../System.Globalization.Native/pal_locale.h | 10 + .../pal_localeNumberData.c | 169 ++++++------ .../pal_localeNumberData.h | 44 +++ .../pal_localeStringData.c | 97 +++---- .../pal_localeStringData.h | 54 ++++ .../pal_normalization.c | 27 +- .../pal_normalization.h | 28 ++ .../pal_timeZoneInfo.c | 19 +- .../pal_timeZoneInfo.h | 24 ++ 25 files changed, 902 insertions(+), 564 deletions(-) delete mode 100644 src/corefx/System.Globalization.Native/holders.h create mode 100644 src/corefx/System.Globalization.Native/pal_calendarData.h create mode 100644 src/corefx/System.Globalization.Native/pal_casing.h create mode 100644 src/corefx/System.Globalization.Native/pal_collation.h create mode 100644 src/corefx/System.Globalization.Native/pal_compiler.h create mode 100644 src/corefx/System.Globalization.Native/pal_idna.h create mode 100644 src/corefx/System.Globalization.Native/pal_localeNumberData.h create mode 100644 src/corefx/System.Globalization.Native/pal_localeStringData.h create mode 100644 src/corefx/System.Globalization.Native/pal_normalization.h create mode 100644 src/corefx/System.Globalization.Native/pal_timeZoneInfo.h diff --git a/src/corefx/System.Globalization.Native/CMakeLists.txt b/src/corefx/System.Globalization.Native/CMakeLists.txt index d3280db8ba90..c44498fecef8 100644 --- a/src/corefx/System.Globalization.Native/CMakeLists.txt +++ b/src/corefx/System.Globalization.Native/CMakeLists.txt @@ -1,5 +1,4 @@ - -project(System.Globalization.Native) +project(System.Globalization.Native C) set(CMAKE_INCLUDE_CURRENT_DIR ON) @@ -8,6 +7,9 @@ add_definitions(-DBIT64=1) set(ICU_HOMEBREW_INC_PATH "/usr/local/opt/icu4c/include") +# We mark the function which needs exporting with DLLEXPORT +add_compile_options(-fvisibility=hidden) + find_path(UTYPES_H "unicode/utypes.h" PATHS ${ICU_HOMEBREW_INC_PATH}) if(UTYPES_H STREQUAL UTYPES_H-NOTFOUND) message(FATAL_ERROR "Cannot find utypes.h, try installing libicu-dev (or the appropriate package for your platform)") @@ -39,18 +41,19 @@ endif() include(configure.cmake) add_compile_options(-fPIC) +add_compile_options(-Wno-incompatible-pointer-types-discards-qualifiers) set(NATIVEGLOBALIZATION_SOURCES - calendarData.cpp - casing.cpp - collation.cpp - idna.cpp - locale.cpp - localeNumberData.cpp - localeStringData.cpp - normalization.cpp - timeZoneInfo.cpp - icushim.cpp + pal_calendarData.c + pal_casing.c + pal_collation.c + pal_idna.c + pal_locale.c + pal_localeNumberData.c + pal_localeStringData.c + pal_normalization.c + pal_timeZoneInfo.c + pal_icushim.c ) include_directories(${UTYPES_H}) @@ -68,6 +71,12 @@ _add_library(System.Globalization.Native_Static # Disable the "lib" prefix. set_target_properties(System.Globalization.Native PROPERTIES PREFIX "") +# Force CMake to not link against libstdc++ +# http://cmake.3232098.n2.nabble.com/setting-LINKER-LANGUAGE-still-adds-lstdc-td7581940.html +set_target_properties(System.Globalization.Native PROPERTIES LINKER_LANGUAGE "C") +set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "") +set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "") + # Disable the "lib" prefix and override default name set_target_properties(System.Globalization.Native_Static PROPERTIES PREFIX "") set_target_properties(System.Globalization.Native_Static PROPERTIES OUTPUT_NAME System.Globalization.Native) @@ -97,4 +106,3 @@ verify_dependencies( # add the install targets install_clr(System.Globalization.Native) install(TARGETS System.Globalization.Native_Static DESTINATION .) - diff --git a/src/corefx/System.Globalization.Native/configure.cmake b/src/corefx/System.Globalization.Native/configure.cmake index 87992509a696..6fd506dbe25a 100644 --- a/src/corefx/System.Globalization.Native/configure.cmake +++ b/src/corefx/System.Globalization.Native/configure.cmake @@ -1,11 +1,11 @@ -include(CheckCXXSourceCompiles) -include(CheckCXXSymbolExists) +include(CheckCSourceCompiles) +include(CheckSymbolExists) set(CMAKE_REQUIRED_INCLUDES ${UTYPES_H} ${ICU_HOMEBREW_INC_PATH}) -CHECK_CXX_SOURCE_COMPILES(" +CHECK_C_SOURCE_COMPILES(" #include - int main() { UDateFormatSymbolType e = UDAT_STANDALONE_SHORTER_WEEKDAYS; } + int main(void) { enum UDateFormatSymbolType e = UDAT_STANDALONE_SHORTER_WEEKDAYS; } " HAVE_UDAT_STANDALONE_SHORTER_WEEKDAYS) if(NOT CLR_CMAKE_PLATFORM_DARWIN) @@ -14,7 +14,7 @@ else() set(CMAKE_REQUIRED_LIBRARIES ${ICUCORE}) endif() -check_cxx_symbol_exists( +check_symbol_exists( ucol_setMaxVariable "unicode/ucol.h" HAVE_SET_MAX_VARIABLE) diff --git a/src/corefx/System.Globalization.Native/holders.h b/src/corefx/System.Globalization.Native/holders.h deleted file mode 100644 index 83e253d29768..000000000000 --- a/src/corefx/System.Globalization.Native/holders.h +++ /dev/null @@ -1,94 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -// IcuHolder is a template that can manage the lifetime of a raw pointer to ensure that it is cleaned up at the correct -// time. The general usage pattern is to aquire some ICU resource via an _open call, then construct a holder using the -// pointer and UErrorCode to manage the lifetime. When the holder goes out of scope, the coresponding close method is -// called on the pointer. -template -class IcuHolder -{ - public: - IcuHolder(T* p, UErrorCode err) - { - m_p = U_SUCCESS(err) ? p : nullptr; - } - - ~IcuHolder() - { - if (m_p != nullptr) - { - Closer()(m_p); - } - } - - private: - T* m_p; - IcuHolder(const IcuHolder&) = delete; - IcuHolder operator=(const IcuHolder&) = delete; -}; - -struct UCalendarCloser -{ - void operator()(UCalendar* pCal) const - { - ucal_close(pCal); - } -}; - -struct UEnumerationCloser -{ - void operator()(UEnumeration* pEnum) const - { - uenum_close(pEnum); - } -}; - -struct UDateTimePatternGeneratorCloser -{ - void operator()(UDateTimePatternGenerator* pGenerator) const - { - udatpg_close(pGenerator); - } -}; - -struct UDateFormatCloser -{ - void operator()(UDateFormat* pDateFormat) const - { - udat_close(pDateFormat); - } -}; - -struct UNumberFormatCloser -{ - void operator()(UNumberFormat* pNumberFormat) const - { - unum_close(pNumberFormat); - } -}; - -struct ULocaleDisplayNamesCloser -{ - void operator()(ULocaleDisplayNames* pLocaleDisplayNames) const - { - uldn_close(pLocaleDisplayNames); - } -}; - -struct UResourceBundleCloser -{ - void operator()(UResourceBundle* pResourceBundle) const - { - ures_close(pResourceBundle); - } -}; - -typedef IcuHolder UCalendarHolder; -typedef IcuHolder UEnumerationHolder; -typedef IcuHolder UDateTimePatternGeneratorHolder; -typedef IcuHolder UDateFormatHolder; -typedef IcuHolder UNumberFormatHolder; -typedef IcuHolder ULocaleDisplayNamesHolder; -typedef IcuHolder UResourceBundleHolder; diff --git a/src/corefx/System.Globalization.Native/pal_calendarData.c b/src/corefx/System.Globalization.Native/pal_calendarData.c index 5a834e7cb113..c65da8f41834 100644 --- a/src/corefx/System.Globalization.Native/pal_calendarData.c +++ b/src/corefx/System.Globalization.Native/pal_calendarData.c @@ -3,13 +3,11 @@ // See the LICENSE file in the project root for more information. #include +#include #include -#include +#include -#include "icushim.h" -#include "locale.hpp" -#include "holders.h" -#include "errors.h" +#include "pal_calendarData.h" #define GREGORIAN_NAME "gregorian" #define JAPANESE_NAME "japanese" @@ -27,65 +25,6 @@ const UChar UDAT_MONTH_DAY_UCHAR[] = {'M', 'M', 'M', 'M', 'd', '\0'}; const UChar UDAT_YEAR_NUM_MONTH_DAY_UCHAR[] = {'y', 'M', 'd', '\0'}; const UChar UDAT_YEAR_MONTH_UCHAR[] = {'y', 'M', 'M', 'M', 'M', '\0'}; -/* -* These values should be kept in sync with System.Globalization.CalendarId -*/ -enum CalendarId : int16_t -{ - UNINITIALIZED_VALUE = 0, - GREGORIAN = 1, // Gregorian (localized) calendar - GREGORIAN_US = 2, // Gregorian (U.S.) calendar - JAPAN = 3, // Japanese Emperor Era calendar - /* SSS_WARNINGS_OFF */ - TAIWAN = 4, // Taiwan Era calendar /* SSS_WARNINGS_ON */ - KOREA = 5, // Korean Tangun Era calendar - HIJRI = 6, // Hijri (Arabic Lunar) calendar - THAI = 7, // Thai calendar - HEBREW = 8, // Hebrew (Lunar) calendar - GREGORIAN_ME_FRENCH = 9, // Gregorian Middle East French calendar - GREGORIAN_ARABIC = 10, // Gregorian Arabic calendar - GREGORIAN_XLIT_ENGLISH = 11, // Gregorian Transliterated English calendar - GREGORIAN_XLIT_FRENCH = 12, - // Note that all calendars after this point are MANAGED ONLY for now. - JULIAN = 13, - JAPANESELUNISOLAR = 14, - CHINESELUNISOLAR = 15, - SAKA = 16, // reserved to match Office but not implemented in our code - LUNAR_ETO_CHN = 17, // reserved to match Office but not implemented in our code - LUNAR_ETO_KOR = 18, // reserved to match Office but not implemented in our code - LUNAR_ETO_ROKUYOU = 19, // reserved to match Office but not implemented in our code - KOREANLUNISOLAR = 20, - TAIWANLUNISOLAR = 21, - PERSIAN = 22, - UMALQURA = 23, - LAST_CALENDAR = 23 // Last calendar ID -}; - -/* -* These values should be kept in sync with System.Globalization.CalendarDataType -*/ -enum CalendarDataType : int32_t -{ - Uninitialized = 0, - NativeName = 1, - MonthDay = 2, - ShortDates = 3, - LongDates = 4, - YearMonths = 5, - DayNames = 6, - AbbrevDayNames = 7, - MonthNames = 8, - AbbrevMonthNames = 9, - SuperShortDayNames = 10, - MonthGenitiveNames = 11, - AbbrevMonthGenitiveNames = 12, - EraNames = 13, - AbbrevEraNames = 14, -}; - -// the function pointer definition for the callback used in EnumCalendarInfo -typedef void (*EnumCalendarInfoCallback)(const UChar*, const void*); - /* Function: GetCalendarName @@ -171,7 +110,7 @@ GetCalendars Returns the list of CalendarIds that are available for the specified locale. */ -extern "C" int32_t GlobalizationNative_GetCalendars( +int32_t GlobalizationNative_GetCalendars( const UChar* localeName, CalendarId* calendars, int32_t calendarsCapacity) { UErrorCode err = U_ZERO_ERROR; @@ -182,14 +121,19 @@ extern "C" int32_t GlobalizationNative_GetCalendars( return 0; UEnumeration* pEnum = ucal_getKeywordValuesForLocale("calendar", locale, TRUE, &err); - UEnumerationHolder enumHolder(pEnum, err); if (U_FAILURE(err)) + { + uenum_close(pEnum); return 0; + } int stringEnumeratorCount = uenum_count(pEnum, &err); if (U_FAILURE(err)) + { + uenum_close(pEnum); return 0; + } int calendarsReturned = 0; for (int i = 0; i < stringEnumeratorCount && calendarsReturned < calendarsCapacity; i++) @@ -207,6 +151,7 @@ extern "C" int32_t GlobalizationNative_GetCalendars( } } + uenum_close(pEnum); return calendarsReturned; } @@ -220,13 +165,16 @@ ResultCode GetMonthDayPattern(const char* locale, UChar* sMonthDay, int32_t stri { UErrorCode err = U_ZERO_ERROR; UDateTimePatternGenerator* pGenerator = udatpg_open(locale, &err); - UDateTimePatternGeneratorHolder generatorHolder(pGenerator, err); if (U_FAILURE(err)) + { + udatpg_close(pGenerator); return GetResultCode(err); + } udatpg_getBestPattern(pGenerator, UDAT_MONTH_DAY_UCHAR, -1, sMonthDay, stringCapacity, &err); + udatpg_close(pGenerator); return GetResultCode(err); } @@ -240,10 +188,10 @@ ResultCode GetNativeCalendarName(const char* locale, CalendarId calendarId, UCha { UErrorCode err = U_ZERO_ERROR; ULocaleDisplayNames* pDisplayNames = uldn_open(locale, ULDN_STANDARD_NAMES, &err); - ULocaleDisplayNamesHolder displayNamesHolder(pDisplayNames, err); uldn_keyValueDisplayName(pDisplayNames, "calendar", GetCalendarName(calendarId), nativeName, stringCapacity, &err); + uldn_close(pDisplayNames); return GetResultCode(err); } @@ -254,7 +202,7 @@ GetCalendarInfo Gets a single string of calendar information by filling the result parameter with the requested value. */ -extern "C" ResultCode GlobalizationNative_GetCalendarInfo( +ResultCode GlobalizationNative_GetCalendarInfo( const UChar* localeName, CalendarId calendarId, CalendarDataType dataType, UChar* result, int32_t resultCapacity) { UErrorCode err = U_ZERO_ERROR; @@ -289,24 +237,33 @@ bool InvokeCallbackForDatePattern(const char* locale, const void* context) { UErrorCode err = U_ZERO_ERROR; - UDateFormat* pFormat = udat_open(UDAT_NONE, style, locale, nullptr, 0, nullptr, 0, &err); - UDateFormatHolder formatHolder(pFormat, err); + UDateFormat* pFormat = udat_open(UDAT_NONE, style, locale, NULL, 0, NULL, 0, &err); if (U_FAILURE(err)) + { + unum_close(pFormat); return false; + } UErrorCode ignore = U_ZERO_ERROR; - int32_t patternLen = udat_toPattern(pFormat, false, nullptr, 0, &ignore); + int32_t patternLen = udat_toPattern(pFormat, false, NULL, 0, &ignore) + 1; + + UChar* pattern = calloc(patternLen, sizeof(UChar)); + if (pattern == NULL) + { + return false; + } - std::vector pattern(patternLen + 1, '\0'); + udat_toPattern(pFormat, false, pattern, patternLen, &err); - udat_toPattern(pFormat, false, pattern.data(), patternLen + 1, &err); + udat_close(pFormat); if (U_SUCCESS(err)) { - callback(pattern.data(), context); + callback(pattern, context); } + free(pattern); return U_SUCCESS(err); } @@ -324,23 +281,31 @@ bool InvokeCallbackForDateTimePattern(const char* locale, { UErrorCode err = U_ZERO_ERROR; UDateTimePatternGenerator* pGenerator = udatpg_open(locale, &err); - UDateTimePatternGeneratorHolder generatorHolder(pGenerator, err); if (U_FAILURE(err)) + { + udatpg_close(pGenerator); return false; + } UErrorCode ignore = U_ZERO_ERROR; - int32_t patternLen = udatpg_getBestPattern(pGenerator, patternSkeleton, -1, nullptr, 0, &ignore); + int32_t patternLen = udatpg_getBestPattern(pGenerator, patternSkeleton, -1, NULL, 0, &ignore) + 1; - std::vector bestPattern(patternLen + 1, '\0'); + UChar* bestPattern = calloc(patternLen, sizeof(UChar)); + if (bestPattern == NULL) + { + return false; + } - udatpg_getBestPattern(pGenerator, patternSkeleton, -1, bestPattern.data(), patternLen + 1, &err); + udatpg_getBestPattern(pGenerator, patternSkeleton, -1, bestPattern, patternLen, &err); + udatpg_close(pGenerator); if (U_SUCCESS(err)) { - callback(bestPattern.data(), context); + callback(bestPattern, context); } + free(bestPattern); return U_SUCCESS(err); } @@ -359,24 +324,31 @@ bool EnumSymbols(const char* locale, const void* context) { UErrorCode err = U_ZERO_ERROR; - UDateFormat* pFormat = udat_open(UDAT_DEFAULT, UDAT_DEFAULT, locale, nullptr, 0, nullptr, 0, &err); - UDateFormatHolder formatHolder(pFormat, err); + UDateFormat* pFormat = udat_open(UDAT_DEFAULT, UDAT_DEFAULT, locale, NULL, 0, NULL, 0, &err); if (U_FAILURE(err)) + { + udat_close(pFormat); return false; + } char localeWithCalendarName[ULOC_FULLNAME_CAPACITY]; strncpy(localeWithCalendarName, locale, ULOC_FULLNAME_CAPACITY); uloc_setKeywordValue("calendar", GetCalendarName(calendarId), localeWithCalendarName, ULOC_FULLNAME_CAPACITY, &err); if (U_FAILURE(err)) + { + udat_close(pFormat); return false; + } - UCalendar* pCalendar = ucal_open(nullptr, 0, localeWithCalendarName, UCAL_DEFAULT, &err); - UCalendarHolder calendarHolder(pCalendar, err); + UCalendar* pCalendar = ucal_open(NULL, 0, localeWithCalendarName, UCAL_DEFAULT, &err); if (U_FAILURE(err)) + { + udat_close(pFormat); return false; + } udat_setCalendar(pFormat, pCalendar); @@ -385,20 +357,32 @@ bool EnumSymbols(const char* locale, for (int32_t i = startIndex; i < symbolCount; i++) { UErrorCode ignore = U_ZERO_ERROR; - int symbolLen = udat_getSymbols(pFormat, type, i, nullptr, 0, &ignore); + int symbolLen = udat_getSymbols(pFormat, type, i, NULL, 0, &ignore) + 1; - std::vector symbolBuf(symbolLen + 1, '\0'); + UChar* symbolBuf = calloc(symbolLen, sizeof(UChar)); + if (symbolBuf == NULL) + { + udat_close(pFormat); + free(symbolBuf); + return false; + } - udat_getSymbols(pFormat, type, i, symbolBuf.data(), symbolBuf.size(), &err); + udat_getSymbols(pFormat, type, i, symbolBuf, symbolLen, &err); assert(U_SUCCESS(err)); if (U_FAILURE(err)) + { + udat_close(pFormat); + free(symbolBuf); return false; + } - callback(symbolBuf.data(), context); + callback(symbolBuf, context); + free(symbolBuf); } + udat_close(pFormat); return true; } @@ -421,6 +405,19 @@ bool EnumUResourceBundle(const UResourceBundle* bundle, EnumCalendarInfoCallback return true; } +void CloseResBundle(const UResourceBundle* rootResBundle, + const UResourceBundle* calResBundle, + const UResourceBundle* targetCalResBundle, + const UResourceBundle* erasColResBundle, + const UResourceBundle* erasResBundle) +{ + ures_close(rootResBundle); + ures_close(calResBundle); + ures_close(targetCalResBundle); + ures_close(erasColResBundle); + ures_close(erasResBundle); +} + /* Function: EnumAbbrevEraNames @@ -447,32 +444,25 @@ bool EnumAbbrevEraNames(const char* locale, while (true) { UErrorCode status = U_ZERO_ERROR; + char* name = GetCalendarName(calendarId); - UResourceBundle* rootResBundle = ures_open(nullptr, localeNamePtr, &status); - UResourceBundleHolder rootResBundleHolder(rootResBundle, status); - - UResourceBundle* calResBundle = ures_getByKey(rootResBundle, "calendar", nullptr, &status); - UResourceBundleHolder calResBundleHolder(calResBundle, status); - - UResourceBundle* targetCalResBundle = - ures_getByKey(calResBundle, GetCalendarName(calendarId), nullptr, &status); - UResourceBundleHolder targetCalResBundleHolder(targetCalResBundle, status); - - UResourceBundle* erasColResBundle = ures_getByKey(targetCalResBundle, "eras", nullptr, &status); - UResourceBundleHolder erasColResBundleHolder(erasColResBundle, status); - - UResourceBundle* erasResBundle = ures_getByKey(erasColResBundle, "narrow", nullptr, &status); - UResourceBundleHolder erasResBundleHolder(erasResBundle, status); + UResourceBundle* rootResBundle = ures_open(NULL, localeNamePtr, &status); + UResourceBundle* calResBundle = ures_getByKey(rootResBundle, "calendar", NULL, &status); + UResourceBundle* targetCalResBundle = ures_getByKey(calResBundle, name, NULL, &status); + UResourceBundle* erasColResBundle = ures_getByKey(targetCalResBundle, "eras", NULL, &status); + UResourceBundle* erasResBundle = ures_getByKey(erasColResBundle, "narrow", NULL, &status); if (U_SUCCESS(status)) { EnumUResourceBundle(erasResBundle, callback, context); + CloseResBundle(rootResBundle, calResBundle, targetCalResBundle, erasColResBundle, erasResBundle); return true; } // Couldn't find the data we need for this locale, we should fallback. if (localeNameBuf[0] == 0x0) { + CloseResBundle(rootResBundle, calResBundle, targetCalResBundle, erasColResBundle, erasResBundle); // We are already at the root locale so there is nothing to fall back to, just use the regular eras. break; } @@ -481,6 +471,7 @@ bool EnumAbbrevEraNames(const char* locale, if (U_FAILURE(status)) { + CloseResBundle(rootResBundle, calResBundle, targetCalResBundle, erasColResBundle, erasResBundle); // Something bad happened getting the parent name, bail out. break; } @@ -492,6 +483,8 @@ bool EnumAbbrevEraNames(const char* locale, char* temp = localeNamePtr; localeNamePtr = parentNamePtr; parentNamePtr = temp; + + CloseResBundle(rootResBundle, calResBundle, targetCalResBundle, erasColResBundle, erasResBundle); } // Walking the resource bundles didn't work, just use the regular eras. @@ -508,8 +501,8 @@ Allows for a collection of calendar string data to be retrieved by invoking the callback for each value in the collection. The context parameter is passed through to the callback along with each string. */ -extern "C" int32_t GlobalizationNative_EnumCalendarInfo( - EnumCalendarInfoCallback callback, +int32_t GlobalizationNative_EnumCalendarInfo( + EnumCalendarInfoCallback callback, const UChar* localeName, CalendarId calendarId, CalendarDataType dataType, @@ -572,18 +565,21 @@ GetLatestJapaneseEra Gets the latest era in the Japanese calendar. */ -extern "C" int32_t GlobalizationNative_GetLatestJapaneseEra() +int32_t GlobalizationNative_GetLatestJapaneseEra() { UErrorCode err = U_ZERO_ERROR; - UCalendar* pCal = ucal_open(nullptr, 0, JAPANESE_LOCALE_AND_CALENDAR, UCAL_TRADITIONAL, &err); - UCalendarHolder calHolder(pCal, err); + UCalendar* pCal = ucal_open(NULL, 0, JAPANESE_LOCALE_AND_CALENDAR, UCAL_TRADITIONAL, &err); if (U_FAILURE(err)) + { + ucal_close(pCal); return 0; + } ucal_set(pCal, UCAL_EXTENDED_YEAR, 9999); int32_t ret = ucal_get(pCal, UCAL_ERA, &err); + ucal_close(pCal); return U_SUCCESS(err) ? ret : 0; } @@ -593,7 +589,7 @@ GetJapaneseEraInfo Gets the starting Gregorian date of the specified Japanese Era. */ -extern "C" int32_t GlobalizationNative_GetJapaneseEraStartDate( +int32_t GlobalizationNative_GetJapaneseEraStartDate( int32_t era, int32_t* startYear, int32_t* startMonth, int32_t* startDay) { *startYear = -1; @@ -601,11 +597,13 @@ extern "C" int32_t GlobalizationNative_GetJapaneseEraStartDate( *startDay = -1; UErrorCode err = U_ZERO_ERROR; - UCalendar* pCal = ucal_open(nullptr, 0, JAPANESE_LOCALE_AND_CALENDAR, UCAL_TRADITIONAL, &err); - UCalendarHolder calHolder(pCal, err); + UCalendar* pCal = ucal_open(NULL, 0, JAPANESE_LOCALE_AND_CALENDAR, UCAL_TRADITIONAL, &err); if (U_FAILURE(err)) + { + ucal_close(pCal); return false; + } ucal_set(pCal, UCAL_ERA, era); ucal_set(pCal, UCAL_YEAR, 1); @@ -613,7 +611,10 @@ extern "C" int32_t GlobalizationNative_GetJapaneseEraStartDate( // UCAL_EXTENDED_YEAR is the gregorian year for the JapaneseCalendar *startYear = ucal_get(pCal, UCAL_EXTENDED_YEAR, &err); if (U_FAILURE(err)) + { + ucal_close(pCal); return false; + } // set the date to Jan 1 ucal_set(pCal, UCAL_MONTH, 0); @@ -624,7 +625,10 @@ extern "C" int32_t GlobalizationNative_GetJapaneseEraStartDate( { currentEra = ucal_get(pCal, UCAL_ERA, &err); if (U_FAILURE(err)) + { + ucal_close(pCal); return false; + } if (currentEra == era) { @@ -633,25 +637,38 @@ extern "C" int32_t GlobalizationNative_GetJapaneseEraStartDate( // subtract 1 day at a time until we get out of the specified Era ucal_add(pCal, UCAL_DATE, -1, &err); if (U_FAILURE(err)) + { + ucal_close(pCal); return false; + } currentEra = ucal_get(pCal, UCAL_ERA, &err); if (U_FAILURE(err)) + { + ucal_close(pCal); return false; + } if (currentEra != era) { // add back 1 day to get back into the specified Era ucal_add(pCal, UCAL_DATE, 1, &err); if (U_FAILURE(err)) + { + ucal_close(pCal); return false; + } *startMonth = ucal_get(pCal, UCAL_MONTH, &err) + 1; // ICU Calendar months are 0-based, but .NET is 1-based if (U_FAILURE(err)) + { + ucal_close(pCal); return false; + } *startDay = ucal_get(pCal, UCAL_DATE, &err); + ucal_close(pCal); if (U_FAILURE(err)) return false; @@ -663,8 +680,12 @@ extern "C" int32_t GlobalizationNative_GetJapaneseEraStartDate( // add 1 month at a time until we get into the specified Era ucal_add(pCal, UCAL_MONTH, 1, &err); if (U_FAILURE(err)) + { + ucal_close(pCal); return false; + } } + ucal_close(pCal); return false; } diff --git a/src/corefx/System.Globalization.Native/pal_calendarData.h b/src/corefx/System.Globalization.Native/pal_calendarData.h new file mode 100644 index 000000000000..53b1b5e90cd4 --- /dev/null +++ b/src/corefx/System.Globalization.Native/pal_calendarData.h @@ -0,0 +1,91 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#include + +#include "pal_compiler.h" +#include "pal_locale.h" +#include "pal_errors.h" + +/* +* These values should be kept in sync with System.Globalization.CalendarId +*/ +typedef enum +{ + UNINITIALIZED_VALUE = 0, + GREGORIAN = 1, // Gregorian (localized) calendar + GREGORIAN_US = 2, // Gregorian (U.S.) calendar + JAPAN = 3, // Japanese Emperor Era calendar + /* SSS_WARNINGS_OFF */ + TAIWAN = 4, // Taiwan Era calendar /* SSS_WARNINGS_ON */ + KOREA = 5, // Korean Tangun Era calendar + HIJRI = 6, // Hijri (Arabic Lunar) calendar + THAI = 7, // Thai calendar + HEBREW = 8, // Hebrew (Lunar) calendar + GREGORIAN_ME_FRENCH = 9, // Gregorian Middle East French calendar + GREGORIAN_ARABIC = 10, // Gregorian Arabic calendar + GREGORIAN_XLIT_ENGLISH = 11, // Gregorian Transliterated English calendar + GREGORIAN_XLIT_FRENCH = 12, + // Note that all calendars after this point are MANAGED ONLY for now. + JULIAN = 13, + JAPANESELUNISOLAR = 14, + CHINESELUNISOLAR = 15, + SAKA = 16, // reserved to match Office but not implemented in our code + LUNAR_ETO_CHN = 17, // reserved to match Office but not implemented in our code + LUNAR_ETO_KOR = 18, // reserved to match Office but not implemented in our code + LUNAR_ETO_ROKUYOU = 19, // reserved to match Office but not implemented in our code + KOREANLUNISOLAR = 20, + TAIWANLUNISOLAR = 21, + PERSIAN = 22, + UMALQURA = 23, + LAST_CALENDAR = 23 // Last calendar ID +} CalendarId; + +/* +* These values should be kept in sync with System.Globalization.CalendarDataType +*/ +typedef enum +{ + Uninitialized = 0, + NativeName = 1, + MonthDay = 2, + ShortDates = 3, + LongDates = 4, + YearMonths = 5, + DayNames = 6, + AbbrevDayNames = 7, + MonthNames = 8, + AbbrevMonthNames = 9, + SuperShortDayNames = 10, + MonthGenitiveNames = 11, + AbbrevMonthGenitiveNames = 12, + EraNames = 13, + AbbrevEraNames = 14, +} CalendarDataType; + +// the function pointer definition for the callback used in EnumCalendarInfo +typedef void (*EnumCalendarInfoCallback)(const UChar*, const void*); + +DLLEXPORT int32_t GlobalizationNative_GetCalendars(const UChar* localeName, + CalendarId* calendars, + int32_t calendarsCapacity); + +DLLEXPORT ResultCode GlobalizationNative_GetCalendarInfo(const UChar* localeName, + CalendarId calendarId, + CalendarDataType dataType, + UChar* result, + int32_t resultCapacity); + +DLLEXPORT int32_t GlobalizationNative_EnumCalendarInfo(EnumCalendarInfoCallback callback, + const UChar* localeName, + CalendarId calendarId, + CalendarDataType dataType, + const void* context); + +DLLEXPORT int32_t GlobalizationNative_GetLatestJapaneseEra(void); + +DLLEXPORT int32_t GlobalizationNative_GetJapaneseEraStartDate(int32_t era, + int32_t* startYear, + int32_t* startMonth, + int32_t* startDay); diff --git a/src/corefx/System.Globalization.Native/pal_casing.c b/src/corefx/System.Globalization.Native/pal_casing.c index 918b8fe6ed2b..e6b27d3eb8a1 100644 --- a/src/corefx/System.Globalization.Native/pal_casing.c +++ b/src/corefx/System.Globalization.Native/pal_casing.c @@ -5,7 +5,9 @@ #include #include -#include "icushim.h" + +#include "pal_casing.h" +#include "pal_icushim.h" /* Function: @@ -14,16 +16,16 @@ ChangeCase Performs upper or lower casing of a string into a new buffer. No special casing is performed beyond that provided by ICU. */ -extern "C" void GlobalizationNative_ChangeCase( +void GlobalizationNative_ChangeCase( const UChar* lpSrc, int32_t cwSrcLength, UChar* lpDst, int32_t cwDstLength, int32_t bToUpper) { // Iterate through the string, decoding the next one or two UTF-16 code units - // into a codepoint and updating srcIdx to point to the next UTF-16 code unit - // to decode. Then upper or lower case it, write dstCodepoint into lpDst at + // into a codepoint and updating srcIdx to point to the next UTF-16 code unit + // to decode. Then upper or lower case it, write dstCodepoint into lpDst at // offset dstIdx, and update dstIdx. // (The loop here has been manually cloned for each of the four cases, rather - // than having a single loop that internally branched based on bToUpper as the + // than having a single loop that internally branched based on bToUpper as the // compiler wasn't doing that optimization, and it results in an ~15-20% perf // improvement on longer strings.) @@ -58,10 +60,10 @@ extern "C" void GlobalizationNative_ChangeCase( ChangeCaseInvariant Performs upper or lower casing of a string into a new buffer. -Special casing is performed to ensure that invariant casing +Special casing is performed to ensure that invariant casing matches that of Windows in certain situations, e.g. Turkish i's. */ -extern "C" void GlobalizationNative_ChangeCaseInvariant( +void GlobalizationNative_ChangeCaseInvariant( const UChar* lpSrc, int32_t cwSrcLength, UChar* lpDst, int32_t cwDstLength, int32_t bToUpper) { // See algorithmic comment in ChangeCase. @@ -105,7 +107,7 @@ ChangeCaseTurkish Performs upper or lower casing of a string into a new buffer, performing special casing for Turkish. */ -extern "C" void GlobalizationNative_ChangeCaseTurkish( +void GlobalizationNative_ChangeCaseTurkish( const UChar* lpSrc, int32_t cwSrcLength, UChar* lpDst, int32_t cwDstLength, int32_t bToUpper) { // See algorithmic comment in ChangeCase. diff --git a/src/corefx/System.Globalization.Native/pal_casing.h b/src/corefx/System.Globalization.Native/pal_casing.h new file mode 100644 index 000000000000..3ea29dd73b4e --- /dev/null +++ b/src/corefx/System.Globalization.Native/pal_casing.h @@ -0,0 +1,24 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#include "pal_compiler.h" +#include "pal_locale.h" + +DLLEXPORT void GlobalizationNative_ChangeCase(const UChar* lpSrc, + int32_t cwSrcLength, + UChar* lpDst, + int32_t cwDstLength, + int32_t bToUpper); + +DLLEXPORT void GlobalizationNative_ChangeCaseInvariant(const UChar* lpSrc, + int32_t cwSrcLength, + UChar* lpDst, + int32_t cwDstLength, + int32_t bToUpper); + +DLLEXPORT void GlobalizationNative_ChangeCaseTurkish(const UChar* lpSrc, + int32_t cwSrcLength, + UChar* lpDst, + int32_t cwDstLength, + int32_t bToUpper); diff --git a/src/corefx/System.Globalization.Native/pal_collation.c b/src/corefx/System.Globalization.Native/pal_collation.c index 3aefae2a6aa3..8440e48faa5b 100644 --- a/src/corefx/System.Globalization.Native/pal_collation.c +++ b/src/corefx/System.Globalization.Native/pal_collation.c @@ -5,13 +5,13 @@ #include #include +#include +#include #include -#include -#include +#include +#include -#include "icushim.h" -#include "locale.hpp" -#include "errors.h" +#include "pal_collation.h" const int32_t CompareOptionsIgnoreCase = 0x1; const int32_t CompareOptionsIgnoreNonSpace = 0x2; @@ -24,34 +24,18 @@ const int32_t CompareOptionsIgnoreWidth = 0x10; // Windows and Unix platforms. The nonalphanumeric symbols will come after alphanumeric // characters on Windows, but before on Unix. // Since locale - specific string sort order can change from one version of Windows to the next, -// there is no reason to guarantee string sort order between Windows and ICU. Thus trying to +// there is no reason to guarantee string sort order between Windows and ICU. Thus trying to // change ICU's default behavior here isn't really justified unless someone has a strong reason // for !StringSort to behave differently. -typedef std::map TCollatorMap; -typedef std::pair TCollatorMapPair; +typedef struct { UChar* items; size_t size; } UCharList; -/* - * For increased performance, we cache the UCollator objects for a locale and - * share them across threads. This is safe (and supported in ICU) if we ensure - * multiple threads are only ever dealing with const UCollators. - */ -typedef struct _sort_handle +int TreeComparer(const void* left, const void* right) { - UCollator* regular; - TCollatorMap collatorsPerOption; - pthread_mutex_t collatorsLockObject; - - _sort_handle() : regular(nullptr) - { - int result = pthread_mutex_init(&collatorsLockObject, NULL); - if (result != 0) - { - assert(false && "Unexpected pthread_mutex_init return value."); - } - } - -} SortHandle; + const TCollatorMap* leftMap = left; + const TCollatorMap* rightMap = right; + return leftMap->key - rightMap->key; +} // Hiragana character range const UChar hiraganaStart = 0x3041; @@ -133,13 +117,31 @@ bool IsHalfFullHigherSymbol(UChar character) || (0xff61 <= character && character <= 0xff65); } +static bool AddItem(UCharList* list, size_t* currentCapacity, const UChar item) +{ + size_t size = list->size++; + if(size >= *currentCapacity) + { + *currentCapacity *= 2; + UChar* ptr = (UChar*)realloc(list->items, *currentCapacity * sizeof(UChar*)); + if(ptr == NULL) + { + return false; + } + list->items = ptr; + } + + list->items[size] = item; + return true; +} + /* Gets a string of custom collation rules, if necessary. Since the CompareOptions flags don't map 1:1 with ICU default functionality, we need to fall back to using custom rules in order to support IgnoreKanaType and IgnoreWidth CompareOptions correctly. */ -std::vector GetCustomRules(int32_t options, UColAttributeValue strength, bool isIgnoreSymbols) +UCharList* GetCustomRules(int32_t options, UColAttributeValue strength, bool isIgnoreSymbols) { bool isIgnoreKanaType = (options & CompareOptionsIgnoreKanaType) == CompareOptionsIgnoreKanaType; bool isIgnoreWidth = (options & CompareOptionsIgnoreWidth) == CompareOptionsIgnoreWidth; @@ -152,60 +154,78 @@ std::vector GetCustomRules(int32_t options, UColAttributeValue strength, bool needsIgnoreWidthCustomRule = isIgnoreWidth && strength >= UCOL_TERTIARY; bool needsNotIgnoreWidthCustomRule = !isIgnoreWidth && strength < UCOL_TERTIARY; - std::vector customRules; - if (needsIgnoreKanaTypeCustomRule || needsNotIgnoreKanaTypeCustomRule || needsIgnoreWidthCustomRule || needsNotIgnoreWidthCustomRule) + if (!(needsIgnoreKanaTypeCustomRule || needsNotIgnoreKanaTypeCustomRule || needsIgnoreWidthCustomRule || needsNotIgnoreWidthCustomRule)) + return NULL; + + // If we need to create customRules, the KanaType custom rule will be 88 kana characters * 4 = 352 chars long + // and the Width custom rule will be at least 215 halfwidth characters * 4 = 860 chars long. + // Use 512 as the starting size, so the customRules won't have to grow if we are just + // doing the KanaType custom rule. + size_t capacity = 512; + UCharList* customRules = (UCharList*)malloc(sizeof(UCharList)); + if (customRules == NULL) { - // If we need to create customRules, the KanaType custom rule will be 88 kana characters * 4 = 352 chars long - // and the Width custom rule will be at least 215 halfwidth characters * 4 = 860 chars long. - // Use 512 as the starting size, so the customRules won't have to grow if we are just - // doing the KanaType custom rule. - customRules.reserve(512); + return NULL; + } - if (needsIgnoreKanaTypeCustomRule || needsNotIgnoreKanaTypeCustomRule) - { - UChar compareChar = needsIgnoreKanaTypeCustomRule ? '=' : '<'; + customRules->items = calloc(capacity, sizeof(UChar)); + if (customRules->items == NULL) + { + free(customRules); + return NULL; + } - for (UChar hiraganaChar = hiraganaStart; hiraganaChar <= hiraganaEnd; hiraganaChar++) + customRules->size = 0; + + if (needsIgnoreKanaTypeCustomRule || needsNotIgnoreKanaTypeCustomRule) + { + UChar compareChar = needsIgnoreKanaTypeCustomRule ? '=' : '<'; + + for (UChar hiraganaChar = hiraganaStart; hiraganaChar <= hiraganaEnd; hiraganaChar++) + { + // Hiragana is the range 3041 to 3096 & 309D & 309E + if (hiraganaChar <= 0x3096 || hiraganaChar >= 0x309D) // characters between 3096 and 309D are not mapped to katakana { - // Hiragana is the range 3041 to 3096 & 309D & 309E - if (hiraganaChar <= 0x3096 || hiraganaChar >= 0x309D) // characters between 3096 and 309D are not mapped to katakana + if(!(AddItem(customRules, &capacity, '&') && + AddItem(customRules, &capacity, hiraganaChar) && + AddItem(customRules, &capacity, compareChar) && + AddItem(customRules, &capacity, hiraganaChar + hiraganaToKatakanaOffset))) { - customRules.push_back('&'); - customRules.push_back(hiraganaChar); - customRules.push_back(compareChar); - customRules.push_back(hiraganaChar + hiraganaToKatakanaOffset); + free(customRules->items); + free(customRules); + return NULL; } } } + } - if (needsIgnoreWidthCustomRule || needsNotIgnoreWidthCustomRule) - { - UChar compareChar = needsIgnoreWidthCustomRule ? '=' : '<'; + if (needsIgnoreWidthCustomRule || needsNotIgnoreWidthCustomRule) + { + UChar compareChar = needsIgnoreWidthCustomRule ? '=' : '<'; - UChar lowerChar; - UChar higherChar; - bool needsEscape; - for (int i = 0; i < g_HalfFullCharsLength; i++) + UChar lowerChar; + UChar higherChar; + bool needsEscape; + for (int i = 0; i < g_HalfFullCharsLength; i++) + { + lowerChar = g_HalfFullLowerChars[i]; + higherChar = g_HalfFullHigherChars[i]; + // the lower chars need to be checked for escaping since they contain ASCII punctuation + needsEscape = NeedsEscape(lowerChar); + + // when isIgnoreSymbols is true and we are not ignoring width, check to see if + // this character is a symbol, and if so skip it + if (!(isIgnoreSymbols && needsNotIgnoreWidthCustomRule && (needsEscape || IsHalfFullHigherSymbol(higherChar)))) { - lowerChar = g_HalfFullLowerChars[i]; - higherChar = g_HalfFullHigherChars[i]; - // the lower chars need to be checked for escaping since they contain ASCII punctuation - needsEscape = NeedsEscape(lowerChar); - - // when isIgnoreSymbols is true and we are not ignoring width, check to see if - // this character is a symbol, and if so skip it - if (!(isIgnoreSymbols && needsNotIgnoreWidthCustomRule && (needsEscape || IsHalfFullHigherSymbol(higherChar)))) + if(!(AddItem(customRules, &capacity, '&') && + (!needsEscape || AddItem(customRules, &capacity, '\\')) && + AddItem(customRules, &capacity, lowerChar) && + AddItem(customRules, &capacity, compareChar) && + AddItem(customRules, &capacity, higherChar))) { - customRules.push_back('&'); - - if (needsEscape) - { - customRules.push_back('\\'); - } - customRules.push_back(lowerChar); - - customRules.push_back(compareChar); - customRules.push_back(higherChar); + free(customRules->items); + free(customRules); + return NULL; } } } @@ -239,29 +259,31 @@ UCollator* CloneCollatorWithOptions(const UCollator* pCollator, int32_t options, } UCollator* pClonedCollator; - std::vector customRules = GetCustomRules(options, strength, isIgnoreSymbols); - if (customRules.empty()) + UCharList* customRules = GetCustomRules(options, strength, isIgnoreSymbols); + if (customRules == NULL) { - pClonedCollator = ucol_safeClone(pCollator, nullptr, nullptr, pErr); + pClonedCollator = ucol_safeClone(pCollator, NULL, NULL, pErr); } else { - int32_t customRuleLength = customRules.size(); + int32_t customRuleLength = customRules->size; int32_t localeRulesLength; const UChar* localeRules = ucol_getRules(pCollator, &localeRulesLength); + int32_t completeRulesLength = localeRulesLength + customRuleLength + 1; + + UChar* completeRules = calloc(completeRulesLength, sizeof(UChar)); - std::vector completeRules(localeRulesLength + customRuleLength + 1, '\0'); for (int i = 0; i < localeRulesLength; i++) { completeRules[i] = localeRules[i]; } for (int i = 0; i < customRuleLength; i++) { - completeRules[localeRulesLength + i] = customRules[i]; + completeRules[localeRulesLength + i] = customRules->items[i]; } - pClonedCollator = ucol_openRules(completeRules.data(), completeRules.size(), UCOL_DEFAULT, strength, NULL, pErr); + pClonedCollator = ucol_openRules(completeRules, completeRulesLength, UCOL_DEFAULT, strength, NULL, pErr); } if (isIgnoreSymbols) @@ -327,46 +349,55 @@ bool CanIgnoreAllCollationElements(const UCollator* pColl, const UChar* lpStr, i } -extern "C" ResultCode GlobalizationNative_GetSortHandle(const char* lpLocaleName, SortHandle** ppSortHandle) +ResultCode GlobalizationNative_GetSortHandle(const char* lpLocaleName, SortHandle** ppSortHandle) { - assert(ppSortHandle != nullptr); - - *ppSortHandle = new (std::nothrow) SortHandle(); - if ((*ppSortHandle) == nullptr) + assert(ppSortHandle != NULL); + + *ppSortHandle = (SortHandle*)malloc(sizeof(SortHandle)); + if ((*ppSortHandle) == NULL) { return GetResultCode(U_MEMORY_ALLOCATION_ERROR); } + (*ppSortHandle)->pRoot = NULL; + int result = pthread_mutex_init(&(*ppSortHandle)->collatorsLockObject, NULL); + if (result != 0) + { + assert(false && "Unexpected pthread_mutex_init return value."); + } + UErrorCode err = U_ZERO_ERROR; (*ppSortHandle)->regular = ucol_open(lpLocaleName, &err); if (U_FAILURE(err)) { - if ((*ppSortHandle)->regular != nullptr) + if ((*ppSortHandle)->regular != NULL) ucol_close((*ppSortHandle)->regular); - delete (*ppSortHandle); - (*ppSortHandle) = nullptr; + free(*ppSortHandle); + (*ppSortHandle) = NULL; } return GetResultCode(err); } -extern "C" void GlobalizationNative_CloseSortHandle(SortHandle* pSortHandle) +void GlobalizationNative_CloseSortHandle(SortHandle* pSortHandle) { ucol_close(pSortHandle->regular); - pSortHandle->regular = nullptr; + pSortHandle->regular = NULL; - TCollatorMap::iterator it; - for (it = pSortHandle->collatorsPerOption.begin(); it != pSortHandle->collatorsPerOption.end(); it++) + while (pSortHandle->pRoot != NULL) { - ucol_close(it->second); + TCollatorMap* data = *(TCollatorMap **)pSortHandle->pRoot; + tdelete(data, &pSortHandle->pRoot, TreeComparer); + ucol_close(data->UCollator); + free(data); } pthread_mutex_destroy(&pSortHandle->collatorsLockObject); - delete pSortHandle; + free(pSortHandle); } const UCollator* GetCollatorFromSortHandle(SortHandle* pSortHandle, int32_t options, UErrorCode* pErr) @@ -384,15 +415,18 @@ const UCollator* GetCollatorFromSortHandle(SortHandle* pSortHandle, int32_t opti assert(false && "Unexpected pthread_mutex_lock return value."); } - TCollatorMap::iterator entry = pSortHandle->collatorsPerOption.find(options); - if (entry == pSortHandle->collatorsPerOption.end()) + TCollatorMap* map = (TCollatorMap*)malloc(sizeof(TCollatorMap)); + map->key = options; + void* entry = tfind(map, &pSortHandle->pRoot, TreeComparer); + if (entry == NULL) { pCollator = CloneCollatorWithOptions(pSortHandle->regular, options, pErr); - pSortHandle->collatorsPerOption[options] = pCollator; + map->UCollator = pCollator; + tsearch(map, &pSortHandle->pRoot, TreeComparer); } else { - pCollator = entry->second; + pCollator = (*(TCollatorMap**)entry)->UCollator; } pthread_mutex_unlock(&pSortHandle->collatorsLockObject); @@ -401,7 +435,7 @@ const UCollator* GetCollatorFromSortHandle(SortHandle* pSortHandle, int32_t opti return pCollator; } -extern "C" int32_t GlobalizationNative_GetSortVersion(SortHandle* pSortHandle) +int32_t GlobalizationNative_GetSortVersion(SortHandle* pSortHandle) { UErrorCode err = U_ZERO_ERROR; const UCollator* pColl = GetCollatorFromSortHandle(pSortHandle, 0, &err); @@ -425,7 +459,7 @@ extern "C" int32_t GlobalizationNative_GetSortVersion(SortHandle* pSortHandle) Function: CompareString */ -extern "C" int32_t GlobalizationNative_CompareString( +int32_t GlobalizationNative_CompareString( SortHandle* pSortHandle, const UChar* lpStr1, int32_t cwStr1Length, const UChar* lpStr2, int32_t cwStr2Length, int32_t options) { static_assert(UCOL_EQUAL == 0, "managed side requires 0 for equal strings"); @@ -448,7 +482,7 @@ extern "C" int32_t GlobalizationNative_CompareString( Function: IndexOf */ -extern "C" int32_t GlobalizationNative_IndexOf( +int32_t GlobalizationNative_IndexOf( SortHandle* pSortHandle, const UChar* lpTarget, int32_t cwTargetLength, @@ -465,7 +499,7 @@ extern "C" int32_t GlobalizationNative_IndexOf( if (U_SUCCESS(err)) { - UStringSearch* pSearch = usearch_openFromCollator(lpTarget, cwTargetLength, lpSource, cwSourceLength, pColl, nullptr, &err); + UStringSearch* pSearch = usearch_openFromCollator(lpTarget, cwTargetLength, lpSource, cwSourceLength, pColl, NULL, &err); if (U_SUCCESS(err)) { @@ -488,7 +522,7 @@ extern "C" int32_t GlobalizationNative_IndexOf( Function: LastIndexOf */ -extern "C" int32_t GlobalizationNative_LastIndexOf( +int32_t GlobalizationNative_LastIndexOf( SortHandle* pSortHandle, const UChar* lpTarget, int32_t cwTargetLength, @@ -504,7 +538,7 @@ extern "C" int32_t GlobalizationNative_LastIndexOf( if (U_SUCCESS(err)) { - UStringSearch* pSearch = usearch_openFromCollator(lpTarget, cwTargetLength, lpSource, cwSourceLength, pColl, nullptr, &err); + UStringSearch* pSearch = usearch_openFromCollator(lpTarget, cwTargetLength, lpSource, cwSourceLength, pColl, NULL, &err); if (U_SUCCESS(err)) { @@ -544,7 +578,7 @@ static bool AreEqualOrdinalIgnoreCase(UChar32 one, UChar32 two) Function: IndexOfOrdinalIgnoreCase */ -extern "C" int32_t GlobalizationNative_IndexOfOrdinalIgnoreCase( +int32_t GlobalizationNative_IndexOfOrdinalIgnoreCase( const UChar* lpTarget, int32_t cwTargetLength, const UChar* lpSource, int32_t cwSourceLength, int32_t findLast) { int32_t result = -1; @@ -589,7 +623,7 @@ extern "C" int32_t GlobalizationNative_IndexOfOrdinalIgnoreCase( /* Return value is a "Win32 BOOL" (1 = true, 0 = false) */ -extern "C" int32_t GlobalizationNative_StartsWith( +int32_t GlobalizationNative_StartsWith( SortHandle* pSortHandle, const UChar* lpTarget, int32_t cwTargetLength, @@ -603,7 +637,7 @@ extern "C" int32_t GlobalizationNative_StartsWith( if (U_SUCCESS(err)) { - UStringSearch* pSearch = usearch_openFromCollator(lpTarget, cwTargetLength, lpSource, cwSourceLength, pColl, nullptr, &err); + UStringSearch* pSearch = usearch_openFromCollator(lpTarget, cwTargetLength, lpSource, cwSourceLength, pColl, NULL, &err); int32_t idx = USEARCH_DONE; if (U_SUCCESS(err)) @@ -631,7 +665,7 @@ extern "C" int32_t GlobalizationNative_StartsWith( /* Return value is a "Win32 BOOL" (1 = true, 0 = false) */ -extern "C" int32_t GlobalizationNative_EndsWith( +int32_t GlobalizationNative_EndsWith( SortHandle* pSortHandle, const UChar* lpTarget, int32_t cwTargetLength, @@ -645,7 +679,7 @@ extern "C" int32_t GlobalizationNative_EndsWith( if (U_SUCCESS(err)) { - UStringSearch* pSearch = usearch_openFromCollator(lpTarget, cwTargetLength, lpSource, cwSourceLength, pColl, nullptr, &err); + UStringSearch* pSearch = usearch_openFromCollator(lpTarget, cwTargetLength, lpSource, cwSourceLength, pColl, NULL, &err); int32_t idx = USEARCH_DONE; if (U_SUCCESS(err)) @@ -674,7 +708,7 @@ extern "C" int32_t GlobalizationNative_EndsWith( return result; } -extern "C" int32_t GlobalizationNative_GetSortKey( +int32_t GlobalizationNative_GetSortKey( SortHandle* pSortHandle, const UChar* lpStr, int32_t cwStrLength, @@ -694,12 +728,12 @@ extern "C" int32_t GlobalizationNative_GetSortKey( return result; } -extern "C" int32_t GlobalizationNative_CompareStringOrdinalIgnoreCase( +int32_t GlobalizationNative_CompareStringOrdinalIgnoreCase( const UChar* lpStr1, int32_t cwStr1Length, const UChar* lpStr2, int32_t cwStr2Length) { - assert(lpStr1 != nullptr); + assert(lpStr1 != NULL); assert(cwStr1Length >= 0); - assert(lpStr2 != nullptr); + assert(lpStr2 != NULL); assert(cwStr2Length >= 0); int32_t str1Idx = 0; diff --git a/src/corefx/System.Globalization.Native/pal_collation.h b/src/corefx/System.Globalization.Native/pal_collation.h new file mode 100644 index 000000000000..9c3b4c2a59ba --- /dev/null +++ b/src/corefx/System.Globalization.Native/pal_collation.h @@ -0,0 +1,82 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#include "pal_compiler.h" +#include "pal_locale.h" +#include "pal_errors.h" + +typedef struct { int32_t key; UCollator* UCollator; } TCollatorMap; + +/* + * For increased performance, we cache the UCollator objects for a locale and + * share them across threads. This is safe (and supported in ICU) if we ensure + * multiple threads are only ever dealing with const UCollators. + */ +typedef struct +{ + UCollator* regular; + TCollatorMap* collatorsPerOption; + pthread_mutex_t collatorsLockObject; + void* pRoot; +} SortHandle; + +DLLEXPORT ResultCode GlobalizationNative_GetSortHandle(const char* lpLocaleName, SortHandle** ppSortHandle); + +DLLEXPORT void GlobalizationNative_CloseSortHandle(SortHandle* pSortHandle); + +DLLEXPORT int32_t GlobalizationNative_GetSortVersion(SortHandle* pSortHandle); + +DLLEXPORT int32_t GlobalizationNative_CompareString(SortHandle* pSortHandle, + const UChar* lpStr1, + int32_t cwStr1Length, + const UChar* lpStr2, + int32_t cwStr2Length, + int32_t options); + +DLLEXPORT int32_t GlobalizationNative_IndexOf(SortHandle* pSortHandle, + const UChar* lpTarget, + int32_t cwTargetLength, + const UChar* lpSource, + int32_t cwSourceLength, + int32_t options, + int32_t* pMatchedLength); + +DLLEXPORT int32_t GlobalizationNative_LastIndexOf(SortHandle* pSortHandle, + const UChar* lpTarget, + int32_t cwTargetLength, + const UChar* lpSource, + int32_t cwSourceLength, + int32_t options); + +DLLEXPORT int32_t GlobalizationNative_IndexOfOrdinalIgnoreCase(const UChar* lpTarget, + int32_t cwTargetLength, + const UChar* lpSource, + int32_t cwSourceLength, + int32_t findLast); + +DLLEXPORT int32_t GlobalizationNative_StartsWith(SortHandle* pSortHandle, + const UChar* lpTarget, + int32_t cwTargetLength, + const UChar* lpSource, + int32_t cwSourceLength, + int32_t options); + +DLLEXPORT int32_t GlobalizationNative_EndsWith(SortHandle* pSortHandle, + const UChar* lpTarget, + int32_t cwTargetLength, + const UChar* lpSource, + int32_t cwSourceLength, + int32_t options); + +DLLEXPORT int32_t GlobalizationNative_GetSortKey(SortHandle* pSortHandle, + const UChar* lpStr, + int32_t cwStrLength, + uint8_t* sortKey, + int32_t cbSortKeyLength, + int32_t options); + +DLLEXPORT int32_t GlobalizationNative_CompareStringOrdinalIgnoreCase(const UChar* lpStr1, + int32_t cwStr1Length, + const UChar* lpStr2, + int32_t cwStr2Length); diff --git a/src/corefx/System.Globalization.Native/pal_compiler.h b/src/corefx/System.Globalization.Native/pal_compiler.h new file mode 100644 index 000000000000..b87de64b82e8 --- /dev/null +++ b/src/corefx/System.Globalization.Native/pal_compiler.h @@ -0,0 +1,19 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#pragma once + +#ifndef __has_extension +#define __has_extension(...) 0 +#endif + +#ifdef static_assert +#define c_static_assert(e) static_assert((e),"") +#elif __has_extension(c_static_assert) +#define c_static_assert(e) _Static_assert((e), "") +#else +#define c_static_assert(e) typedef char __c_static_assert__[(e)?1:-1] +#endif + +#define DLLEXPORT __attribute__ ((__visibility__ ("default"))) diff --git a/src/corefx/System.Globalization.Native/pal_errors.h b/src/corefx/System.Globalization.Native/pal_errors.h index b23a0dacd518..bed61668c5da 100644 --- a/src/corefx/System.Globalization.Native/pal_errors.h +++ b/src/corefx/System.Globalization.Native/pal_errors.h @@ -4,28 +4,30 @@ #pragma once +#include "pal_compiler.h" + /* * These values should be kept in sync with * Interop.GlobalizationInterop.ResultCode */ -enum ResultCode : int32_t +typedef enum { Success = 0, UnknownError = 1, InsufficentBuffer = 2, OutOfMemory = 3 -}; +} ResultCode; /* Converts a UErrorCode to a ResultCode. */ -static ResultCode GetResultCode(UErrorCode err) +DLLEXPORT static ResultCode GetResultCode(UErrorCode err) { if (err == U_BUFFER_OVERFLOW_ERROR || err == U_STRING_NOT_TERMINATED_WARNING) { return InsufficentBuffer; } - + if (err == U_MEMORY_ALLOCATION_ERROR) { return OutOfMemory; diff --git a/src/corefx/System.Globalization.Native/pal_icushim.c b/src/corefx/System.Globalization.Native/pal_icushim.c index e250238fe9c3..4c540abbac45 100644 --- a/src/corefx/System.Globalization.Native/pal_icushim.c +++ b/src/corefx/System.Globalization.Native/pal_icushim.c @@ -5,25 +5,26 @@ #include #include +#include #include #include #include -#include "icushim.h" +#include "pal_icushim.h" // Define pointers to all the used ICU functions -#define PER_FUNCTION_BLOCK(fn, lib) decltype(fn)* fn##_ptr; +#define PER_FUNCTION_BLOCK(fn, lib) __typeof(fn)* fn##_ptr; FOR_ALL_ICU_FUNCTIONS #undef PER_FUNCTION_BLOCK -static void* libicuuc = nullptr; -static void* libicui18n = nullptr; +static void* libicuuc = NULL; +static void* libicui18n = NULL; #define VERSION_PREFIX_NONE "" #define VERSION_PREFIX_SUSE "suse" // .[suse]x.x.x, considering the max number of decimal digits for each component -static const int MaxICUVersionStringLength = sizeof(VERSION_PREFIX_SUSE) + 33; +#define MaxICUVersionStringLength (sizeof(VERSION_PREFIX_SUSE) + 33) #ifdef __APPLE__ @@ -35,13 +36,13 @@ bool FindICULibs(const char* versionPrefix, char* symbolName, char* symbolVersio // Usually OSX_ICU_LIBRARY_PATH is "/usr/lib/libicucore.dylib" libicuuc = dlopen(OSX_ICU_LIBRARY_PATH, RTLD_LAZY); - - if (libicuuc == nullptr) + + if (libicuuc == NULL) { return false; } - // in OSX all ICU APIs exist in the same library libicucore.A.dylib + // in OSX all ICU APIs exist in the same library libicucore.A.dylib libicui18n = libicuuc; return true; @@ -78,7 +79,7 @@ void GetVersionedLibFileName(const char* baseFileName, int majorVer, int minorVe if (subVer != -1) { sprintf(result + nameLen, ".%d", subVer); - } + } } } @@ -86,22 +87,22 @@ bool FindSymbolVersion(int majorVer, int minorVer, int subVer, char* symbolName, { // Find out the format of the version string added to each symbol // First try just the unversioned symbol - if (dlsym(libicuuc, "u_strlen") == nullptr) + if (dlsym(libicuuc, "u_strlen") == NULL) { // Now try just the _majorVer added sprintf(symbolVersion, "_%d", majorVer); sprintf(symbolName, "u_strlen%s", symbolVersion); - if ((dlsym(libicuuc, symbolName) == nullptr) && (minorVer != -1)) + if ((dlsym(libicuuc, symbolName) == NULL) && (minorVer != -1)) { // Now try the _majorVer_minorVer added sprintf(symbolVersion, "_%d_%d", majorVer, minorVer); sprintf(symbolName, "u_strlen%s", symbolVersion); - if ((dlsym(libicuuc, symbolName) == nullptr) && (subVer != -1)) + if ((dlsym(libicuuc, symbolName) == NULL) && (subVer != -1)) { // Finally, try the _majorVer_minorVer_subVer added sprintf(symbolVersion, "_%d_%d_%d", majorVer, minorVer, subVer); sprintf(symbolName, "u_strlen%s", symbolVersion); - if (dlsym(libicuuc, symbolName) == nullptr) + if (dlsym(libicuuc, symbolName) == NULL) { return false; } @@ -125,20 +126,20 @@ bool OpenICULibraries(int majorVer, int minorVer, int subVer, const char* versio GetVersionedLibFileName("libicui18n.so", majorVer, minorVer, subVer, versionPrefix, libicui18nName); libicuuc = dlopen(libicuucName, RTLD_LAZY); - if (libicuuc != nullptr) + if (libicuuc != NULL) { if (FindSymbolVersion(majorVer, minorVer, subVer, symbolName, symbolVersion)) { libicui18n = dlopen(libicui18nName, RTLD_LAZY); } - if (libicui18n == nullptr) + if (libicui18n == NULL) { dlclose(libicuuc); - libicuuc = nullptr; + libicuuc = NULL; } } - return libicuuc != nullptr; + return libicuuc != NULL; } // Select libraries using the version override specified by the CLR_ICU_VERSION_OVERRIDE @@ -148,7 +149,7 @@ bool OpenICULibraries(int majorVer, int minorVer, int subVer, const char* versio bool FindLibUsingOverride(const char* versionPrefix, char* symbolName, char* symbolVersion) { char* versionOverride = getenv("CLR_ICU_VERSION_OVERRIDE"); - if (versionOverride != nullptr) + if (versionOverride != NULL) { int first = -1; int second = -1; @@ -242,10 +243,10 @@ bool FindICULibs(const char* versionPrefix, char* symbolName, char* symbolVersio #endif // __APPLE__ // GlobalizationNative_LoadICU -// This method get called from the managed side during the globalization initialization. +// This method get called from the managed side during the globalization initialization. // This method shouldn't get called at all if we are running in globalization invariant mode // return 0 if failed to load ICU and 1 otherwise -extern "C" int32_t GlobalizationNative_LoadICU() +int32_t GlobalizationNative_LoadICU() { char symbolName[128]; char symbolVersion[MaxICUVersionStringLength + 1] = ""; @@ -264,15 +265,15 @@ extern "C" int32_t GlobalizationNative_LoadICU() #define PER_FUNCTION_BLOCK(fn, lib) \ static_assert((sizeof(#fn) + MaxICUVersionStringLength + 1) <= sizeof(symbolName), "The symbolName is too small for symbol " #fn); \ sprintf(symbolName, #fn "%s", symbolVersion); \ - fn##_ptr = (decltype(fn)*)dlsym(lib, symbolName); \ + fn##_ptr = (__typeof(fn)*)dlsym(lib, symbolName); \ if (fn##_ptr == NULL) { fprintf(stderr, "Cannot get symbol %s from " #lib "\nError: %s\n", symbolName, dlerror()); abort(); } FOR_ALL_ICU_FUNCTIONS #undef PER_FUNCTION_BLOCK #ifdef __APPLE__ - // libicui18n initialized with libicuuc so we null it to avoid double closing same handle - libicui18n = nullptr; + // libicui18n initialized with libicuuc so we null it to avoid double closing same handle + libicui18n = NULL; #endif // __APPLE__ return 1; @@ -280,25 +281,25 @@ extern "C" int32_t GlobalizationNative_LoadICU() // GlobalizationNative_GetICUVersion // return the current loaded ICU version -extern "C" int32_t GlobalizationNative_GetICUVersion() +int32_t GlobalizationNative_GetICUVersion() { int32_t version; u_getVersion((uint8_t *) &version); - return version; + return version; } __attribute__((destructor)) void ShutdownICUShim() { - if (libicuuc != nullptr) + if (libicuuc != NULL) { dlclose(libicuuc); - libicuuc = nullptr; + libicuuc = NULL; } - if (libicui18n != nullptr) + if (libicui18n != NULL) { dlclose(libicui18n); - libicui18n = nullptr; + libicui18n = NULL; } } diff --git a/src/corefx/System.Globalization.Native/pal_icushim.h b/src/corefx/System.Globalization.Native/pal_icushim.h index d7ec2fb05ccd..4ada6b97f517 100644 --- a/src/corefx/System.Globalization.Native/pal_icushim.h +++ b/src/corefx/System.Globalization.Native/pal_icushim.h @@ -3,19 +3,19 @@ // See the LICENSE file in the project root for more information. // -// Enable calling ICU functions through shims to enable support for +// Enable calling ICU functions through shims to enable support for // multiple versions of ICU. #ifndef __ICUSHIM_H__ #define __ICUSHIM_H__ #include "config.h" +#include "pal_compiler.h" #define U_DISABLE_RENAMING 1 // All ICU headers need to be included here so that all function prototypes are // available before the function pointers are declared below. -#include #include #include #include @@ -138,7 +138,7 @@ #endif // Declare pointers to all the used ICU functions -#define PER_FUNCTION_BLOCK(fn, lib) extern decltype(fn)* fn##_ptr; +#define PER_FUNCTION_BLOCK(fn, lib) extern __typeof(fn)* fn##_ptr; FOR_ALL_ICU_FUNCTIONS #undef PER_FUNCTION_BLOCK @@ -240,3 +240,7 @@ FOR_ALL_ICU_FUNCTIONS #define usearch_openFromCollator(...) usearch_openFromCollator_ptr(__VA_ARGS__) #endif // __ICUSHIM_H__ + +DLLEXPORT int32_t GlobalizationNative_LoadICU(void); + +DLLEXPORT int32_t GlobalizationNative_GetICUVersion(void); diff --git a/src/corefx/System.Globalization.Native/pal_idna.c b/src/corefx/System.Globalization.Native/pal_idna.c index 23942b3a6849..1d8786cca0eb 100644 --- a/src/corefx/System.Globalization.Native/pal_idna.c +++ b/src/corefx/System.Globalization.Native/pal_idna.c @@ -4,7 +4,9 @@ // #include -#include "icushim.h" + +#include "pal_icushim.h" +#include "pal_idna.h" const uint32_t AllowUnassigned = 0x1; const uint32_t UseStd3AsciiRules = 0x2; @@ -38,7 +40,7 @@ Return values: 0: internal error during conversion. >0: the length of the converted string (not including the null terminator). */ -extern "C" int32_t GlobalizationNative_ToAscii( +int32_t GlobalizationNative_ToAscii( uint32_t flags, const UChar* lpSrc, int32_t cwSrcLength, UChar* lpDst, int32_t cwDstLength) { UErrorCode err = U_ZERO_ERROR; @@ -64,7 +66,7 @@ Return values: 0: internal error during conversion. >0: the length of the converted string (not including the null terminator). */ -extern "C" int32_t GlobalizationNative_ToUnicode( +int32_t GlobalizationNative_ToUnicode( int32_t flags, const UChar* lpSrc, int32_t cwSrcLength, UChar* lpDst, int32_t cwDstLength) { UErrorCode err = U_ZERO_ERROR; diff --git a/src/corefx/System.Globalization.Native/pal_idna.h b/src/corefx/System.Globalization.Native/pal_idna.h new file mode 100644 index 000000000000..f9ff5e477088 --- /dev/null +++ b/src/corefx/System.Globalization.Native/pal_idna.h @@ -0,0 +1,19 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +#include "pal_compiler.h" +#include "pal_locale.h" + +DLLEXPORT int32_t GlobalizationNative_ToAscii(uint32_t flags, + const UChar* lpSrc, + int32_t cwSrcLength, + UChar* lpDst, + int32_t cwDstLength); + +DLLEXPORT int32_t GlobalizationNative_ToUnicode(int32_t flags, + const UChar* lpSrc, + int32_t cwSrcLength, + UChar* lpDst, + int32_t cwDstLength); diff --git a/src/corefx/System.Globalization.Native/pal_locale.c b/src/corefx/System.Globalization.Native/pal_locale.c index 951179d32159..6b9561122c6e 100644 --- a/src/corefx/System.Globalization.Native/pal_locale.c +++ b/src/corefx/System.Globalization.Native/pal_locale.c @@ -9,8 +9,7 @@ #include #include -#include "icushim.h" -#include "locale.hpp" +#include "pal_locale.h" int32_t UErrorCodeToBool(UErrorCode status) { @@ -117,7 +116,7 @@ bool IsEnvVarSet(const char* name) { const char* value = getenv(name); - return (value != nullptr) && (strcmp("", value) != 0); + return (value != NULL) && (strcmp("", value) != 0); } // The behavior of uloc_getDefault() on POSIX systems is to query @@ -135,9 +134,9 @@ bool IsEnvVarSet(const char* name) // normalization it would do. const char* DetectDefaultLocaleName() { - char* loc = setlocale(LC_MESSAGES, nullptr); + char* loc = setlocale(LC_MESSAGES, NULL); - if (loc != nullptr && (strcmp("C", loc) == 0 || strcmp("POSIX", loc) == 0)) + if (loc != NULL && (strcmp("C", loc) == 0 || strcmp("POSIX", loc) == 0)) { if (!IsEnvVarSet("LC_ALL") && !IsEnvVarSet("LC_MESSAGES") && !IsEnvVarSet("LANG")) { @@ -155,7 +154,7 @@ const char* DetectDefaultLocaleName() // locale names list. // if the value is not null, it fills the value with locale names separated by the length // of each name. -extern "C" int32_t GlobalizationNative_GetLocales(UChar *value, int32_t valueLength) +int32_t GlobalizationNative_GetLocales(UChar *value, int32_t valueLength) { int32_t totalLength = 0; int32_t index = 0; @@ -174,7 +173,7 @@ extern "C" int32_t GlobalizationNative_GetLocales(UChar *value, int32_t valueLen totalLength += localeNameLength + 1; // add 1 for the name length - if (value != nullptr) + if (value != NULL) { if (totalLength > valueLength) return -3; @@ -198,7 +197,7 @@ extern "C" int32_t GlobalizationNative_GetLocales(UChar *value, int32_t valueLen return totalLength; } -extern "C" int32_t GlobalizationNative_GetLocaleName(const UChar* localeName, UChar* value, int32_t valueLength) +int32_t GlobalizationNative_GetLocaleName(const UChar* localeName, UChar* value, int32_t valueLength) { UErrorCode status = U_ZERO_ERROR; @@ -218,7 +217,7 @@ extern "C" int32_t GlobalizationNative_GetLocaleName(const UChar* localeName, UC return UErrorCodeToBool(status); } -extern "C" int32_t GlobalizationNative_GetDefaultLocaleName(UChar* value, int32_t valueLength) +int32_t GlobalizationNative_GetDefaultLocaleName(UChar* value, int32_t valueLength) { char localeNameBuffer[ULOC_FULLNAME_CAPACITY]; UErrorCode status = U_ZERO_ERROR; diff --git a/src/corefx/System.Globalization.Native/pal_locale.h b/src/corefx/System.Globalization.Native/pal_locale.h index 79328f3b19b7..ebd64468be34 100644 --- a/src/corefx/System.Globalization.Native/pal_locale.h +++ b/src/corefx/System.Globalization.Native/pal_locale.h @@ -2,6 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#include + +#include "pal_icushim.h" + /* Function: UErrorCodeToBool @@ -48,3 +52,9 @@ Detect the default locale for the machine, defaulting to Invaraint if we can't compute one (different from uloc_getDefault()) would do. */ const char* DetectDefaultLocaleName(); + +DLLEXPORT int32_t GlobalizationNative_GetLocales(UChar *value, int32_t valueLength); + +DLLEXPORT int32_t GlobalizationNative_GetLocaleName(const UChar* localeName, UChar* value, int32_t valueLength); + +DLLEXPORT int32_t GlobalizationNative_GetDefaultLocaleName(UChar* value, int32_t valueLength); diff --git a/src/corefx/System.Globalization.Native/pal_localeNumberData.c b/src/corefx/System.Globalization.Native/pal_localeNumberData.c index a3586b568fc3..1a13b92f6b93 100644 --- a/src/corefx/System.Globalization.Native/pal_localeNumberData.c +++ b/src/corefx/System.Globalization.Native/pal_localeNumberData.c @@ -4,12 +4,11 @@ // #include +#include +#include #include -#include -#include "icushim.h" -#include "locale.hpp" -#include "holders.h" +#include "pal_localeNumberData.h" // invariant character definitions used by ICU #define UCHAR_CURRENCY ((UChar)0x00A4) // international currency @@ -24,34 +23,6 @@ #define ARRAY_LENGTH(array) (sizeof(array) / sizeof(array[0])) -// Enum that corresponds to managed enum CultureData.LocaleNumberData. -// The numeric values of the enum members match their Win32 counterparts. -enum LocaleNumberData : int32_t -{ - LanguageId = 0x00000001, - MeasurementSystem = 0x0000000D, - FractionalDigitsCount = 0x00000011, - NegativeNumberFormat = 0x00001010, - MonetaryFractionalDigitsCount = 0x00000019, - PositiveMonetaryNumberFormat = 0x0000001B, - NegativeMonetaryNumberFormat = 0x0000001C, - FirstDayofWeek = 0x0000100C, - FirstWeekOfYear = 0x0000100D, - ReadingLayout = 0x00000070, - NegativePercentFormat = 0x00000074, - PositivePercentFormat = 0x00000075, - Digit = 0x00000010, - Monetary = 0x00000018 -}; - -// Enum that corresponds to managed enum System.Globalization.CalendarWeekRule -enum CalendarWeekRule : int32_t -{ - FirstDay = 0, - FirstFullWeek = 1, - FirstFourDayWeek = 2 -}; - /* Function: NormalizeNumericPattern @@ -59,16 +30,8 @@ NormalizeNumericPattern Returns a numeric string pattern in a format that we can match against the appropriate managed pattern. */ -std::string NormalizeNumericPattern(const UChar* srcPattern, bool isNegative) +char* NormalizeNumericPattern(const UChar* srcPattern, bool isNegative) { - // A srcPattern example: "#,##0.00 C;(#,##0.00 C)" but where C is the - // international currency symbol (UCHAR_CURRENCY) - // The positive pattern comes first, then an optional negative pattern - // separated by a semicolon - // A destPattern example: "(C n)" where C represents the currency symbol, and - // n is the number - std::string destPattern; - int iStart = 0; int iEnd = u_strlen(srcPattern); int32_t iNegativePatternStart = -1; @@ -93,11 +56,46 @@ std::string NormalizeNumericPattern(const UChar* srcPattern, bool isNegative) } } + int index = 0; bool minusAdded = false; bool digitAdded = false; bool currencyAdded = false; bool spaceAdded = false; + for (int i = iStart; i <= iEnd; i++) + { + UChar ch = srcPattern[i]; + switch (ch) + { + case UCHAR_MINUS: + case UCHAR_OPENPAREN: + case UCHAR_CLOSEPAREN: + minusAdded = true; + break; + } + } + + // international currency symbol (UCHAR_CURRENCY) + // The positive pattern comes first, then an optional negative pattern + // separated by a semicolon + // A destPattern example: "(C n)" where C represents the currency symbol, and + // n is the number + char* destPattern; + + // if there is no negative subpattern, the ICU convention is to prefix the + // minus sign + if (isNegative && !minusAdded) + { + size_t length = (iEnd - iStart) + 2; + destPattern = calloc(length, sizeof(char)); + destPattern[index++] = '-'; + } + else + { + size_t length = (iEnd - iStart) + 1; + destPattern = calloc(length, sizeof(char)); + } + for (int i = iStart; i <= iEnd; i++) { UChar ch = srcPattern[i]; @@ -107,7 +105,7 @@ std::string NormalizeNumericPattern(const UChar* srcPattern, bool isNegative) if (!digitAdded) { digitAdded = true; - destPattern.push_back('n'); + destPattern[index++] = 'n'; } break; @@ -115,7 +113,7 @@ std::string NormalizeNumericPattern(const UChar* srcPattern, bool isNegative) if (!currencyAdded) { currencyAdded = true; - destPattern.push_back('C'); + destPattern[index++] = 'C'; } break; @@ -124,7 +122,7 @@ std::string NormalizeNumericPattern(const UChar* srcPattern, bool isNegative) if (!spaceAdded) { spaceAdded = true; - destPattern.push_back(' '); + destPattern[index++] = ' '; } else { @@ -136,22 +134,15 @@ std::string NormalizeNumericPattern(const UChar* srcPattern, bool isNegative) case UCHAR_OPENPAREN: case UCHAR_CLOSEPAREN: minusAdded = true; - destPattern.push_back(static_cast(ch)); + destPattern[index++] = (char)ch; break; case UCHAR_PERCENT: - destPattern.push_back('%'); + destPattern[index++] = '%'; break; } } - // if there is no negative subpattern, the ICU convention is to prefix the - // minus sign - if (isNegative && !minusAdded) - { - destPattern.insert(destPattern.begin(), '-'); - } - return destPattern; } @@ -169,35 +160,46 @@ int GetNumericPattern(const UNumberFormat* pNumberFormat, const char* patterns[] const int MAX_DOTNET_NUMERIC_PATTERN_LENGTH = 6; // example: "(C n)" plus terminator UErrorCode ignore = U_ZERO_ERROR; - int32_t icuPatternLength = unum_toPattern(pNumberFormat, false, nullptr, 0, &ignore); + int32_t icuPatternLength = unum_toPattern(pNumberFormat, false, NULL, 0, &ignore) + 1; - std::vector icuPattern(icuPatternLength + 1, '\0'); + UChar* icuPattern = calloc(icuPatternLength, sizeof(UChar)); + if (icuPattern == NULL) + { + return U_MEMORY_ALLOCATION_ERROR; + } UErrorCode err = U_ZERO_ERROR; - unum_toPattern(pNumberFormat, false, icuPattern.data(), icuPattern.size(), &err); + unum_toPattern(pNumberFormat, false, icuPattern, icuPatternLength, &err); assert(U_SUCCESS(err)); - std::string normalizedPattern = NormalizeNumericPattern(icuPattern.data(), isNegative); + char* normalizedPattern = NormalizeNumericPattern(icuPattern, isNegative); + + free(icuPattern); + + size_t normalizedPatternLength = strlen(normalizedPattern); - assert(normalizedPattern.length() > 0); - assert(normalizedPattern.length() < MAX_DOTNET_NUMERIC_PATTERN_LENGTH); + assert(normalizedPatternLength > 0); + assert(normalizedPatternLength < MAX_DOTNET_NUMERIC_PATTERN_LENGTH); - if (normalizedPattern.length() == 0 || normalizedPattern.length() >= MAX_DOTNET_NUMERIC_PATTERN_LENGTH) + if (normalizedPatternLength == 0 || normalizedPatternLength >= MAX_DOTNET_NUMERIC_PATTERN_LENGTH) { + free(normalizedPattern); return INVALID_FORMAT; } for (int i = 0; i < patternsCount; i++) { - if (strcmp(normalizedPattern.c_str(), patterns[i]) == 0) + if (strcmp(normalizedPattern, patterns[i]) == 0) { + free(normalizedPattern); return i; } }; assert(false); // should have found a valid pattern + free(normalizedPattern); return INVALID_FORMAT; } @@ -229,8 +231,7 @@ int GetCurrencyNegativePattern(const char* locale) "(n C)"}; UErrorCode status = U_ZERO_ERROR; - UNumberFormat* pFormat = unum_open(UNUM_CURRENCY, nullptr, 0, locale, nullptr, &status); - UNumberFormatHolder formatHolder(pFormat, status); + UNumberFormat* pFormat = unum_open(UNUM_CURRENCY, NULL, 0, locale, NULL, &status); assert(U_SUCCESS(status)); @@ -239,10 +240,12 @@ int GetCurrencyNegativePattern(const char* locale) int value = GetNumericPattern(pFormat, Patterns, ARRAY_LENGTH(Patterns), true); if (value >= 0) { + unum_close(pFormat); return value; } } + unum_close(pFormat); return DEFAULT_VALUE; } @@ -259,8 +262,7 @@ int GetCurrencyPositivePattern(const char* locale) static const char* Patterns[] = {"Cn", "nC", "C n", "n C"}; UErrorCode status = U_ZERO_ERROR; - UNumberFormat* pFormat = unum_open(UNUM_CURRENCY, nullptr, 0, locale, nullptr, &status); - UNumberFormatHolder formatHolder(pFormat, status); + UNumberFormat* pFormat = unum_open(UNUM_CURRENCY, NULL, 0, locale, NULL, &status); assert(U_SUCCESS(status)); @@ -269,10 +271,12 @@ int GetCurrencyPositivePattern(const char* locale) int value = GetNumericPattern(pFormat, Patterns, ARRAY_LENGTH(Patterns), false); if (value >= 0) { + unum_close(pFormat); return value; } } + unum_close(pFormat); return DEFAULT_VALUE; } @@ -289,8 +293,7 @@ int GetNumberNegativePattern(const char* locale) static const char* Patterns[] = {"(n)", "-n", "- n", "n-", "n -"}; UErrorCode status = U_ZERO_ERROR; - UNumberFormat* pFormat = unum_open(UNUM_DECIMAL, nullptr, 0, locale, nullptr, &status); - UNumberFormatHolder formatHolder(pFormat, status); + UNumberFormat* pFormat = unum_open(UNUM_DECIMAL, NULL, 0, locale, NULL, &status); assert(U_SUCCESS(status)); @@ -299,10 +302,12 @@ int GetNumberNegativePattern(const char* locale) int value = GetNumericPattern(pFormat, Patterns, ARRAY_LENGTH(Patterns), true); if (value >= 0) { + unum_close(pFormat); return value; } } + unum_close(pFormat); return DEFAULT_VALUE; } @@ -320,8 +325,7 @@ int GetPercentNegativePattern(const char* locale) "-n %", "-n%", "-%n", "%-n", "%n-", "n-%", "n%-", "-% n", "n %-", "% n-", "% -n", "n- %"}; UErrorCode status = U_ZERO_ERROR; - UNumberFormat* pFormat = unum_open(UNUM_PERCENT, nullptr, 0, locale, nullptr, &status); - UNumberFormatHolder formatHolder(pFormat, status); + UNumberFormat* pFormat = unum_open(UNUM_PERCENT, NULL, 0, locale, NULL, &status); assert(U_SUCCESS(status)); @@ -330,10 +334,12 @@ int GetPercentNegativePattern(const char* locale) int value = GetNumericPattern(pFormat, Patterns, ARRAY_LENGTH(Patterns), true); if (value >= 0) { + unum_close(pFormat); return value; } } + unum_close(pFormat); return DEFAULT_VALUE; } @@ -350,8 +356,7 @@ int GetPercentPositivePattern(const char* locale) static const char* Patterns[] = {"n %", "n%", "%n", "% n"}; UErrorCode status = U_ZERO_ERROR; - UNumberFormat* pFormat = unum_open(UNUM_PERCENT, nullptr, 0, locale, nullptr, &status); - UNumberFormatHolder formatHolder(pFormat, status); + UNumberFormat* pFormat = unum_open(UNUM_PERCENT, NULL, 0, locale, NULL, &status); assert(U_SUCCESS(status)); @@ -360,10 +365,12 @@ int GetPercentPositivePattern(const char* locale) int value = GetNumericPattern(pFormat, Patterns, ARRAY_LENGTH(Patterns), false); if (value >= 0) { + unum_close(pFormat); return value; } } + unum_close(pFormat); return DEFAULT_VALUE; } @@ -381,7 +388,7 @@ UErrorCode GetMeasurementSystem(const char* locale, int32_t* value) UMeasurementSystem measurementSystem = ulocdata_getMeasurementSystem(locale, &status); if (U_SUCCESS(status)) { - *value = (measurementSystem == UMeasurementSystem::UMS_US) ? 1 : 0; + *value = (measurementSystem == UMS_US) ? 1 : 0; } return status; @@ -394,7 +401,7 @@ GetLocaleInfoInt Obtains integer locale information Returns 1 for success, 0 otherwise */ -extern "C" int32_t GlobalizationNative_GetLocaleInfoInt( +int32_t GlobalizationNative_GetLocaleInfoInt( const UChar* localeName, LocaleNumberData localeNumberData, int32_t* value) { UErrorCode status = U_ZERO_ERROR; @@ -446,8 +453,7 @@ extern "C" int32_t GlobalizationNative_GetLocaleInfoInt( case FirstWeekOfYear: { // corresponds to DateTimeFormat.CalendarWeekRule - UCalendar* pCal = ucal_open(nullptr, 0, locale, UCAL_TRADITIONAL, &status); - UCalendarHolder calHolder(pCal, status); + UCalendar* pCal = ucal_open(NULL, 0, locale, UCAL_TRADITIONAL, &status); if (U_SUCCESS(status)) { @@ -455,21 +461,22 @@ extern "C" int32_t GlobalizationNative_GetLocaleInfoInt( int minDaysInWeek = ucal_getAttribute(pCal, UCAL_MINIMAL_DAYS_IN_FIRST_WEEK); if (minDaysInWeek == 1) { - *value = CalendarWeekRule::FirstDay; + *value = FirstDay; } else if (minDaysInWeek == 7) { - *value = CalendarWeekRule::FirstFullWeek; + *value = FirstFullWeek; } else if (minDaysInWeek >= 4) { - *value = CalendarWeekRule::FirstFourDayWeek; + *value = FirstFourDayWeek; } else { status = U_UNSUPPORTED_ERROR; } } + ucal_close(pCal); break; } case ReadingLayout: @@ -489,13 +496,13 @@ extern "C" int32_t GlobalizationNative_GetLocaleInfoInt( } case FirstDayofWeek: { - UCalendar* pCal = ucal_open(nullptr, 0, locale, UCAL_TRADITIONAL, &status); - UCalendarHolder calHolder(pCal, status); + UCalendar* pCal = ucal_open(NULL, 0, locale, UCAL_TRADITIONAL, &status); if (U_SUCCESS(status)) { *value = ucal_getAttribute(pCal, UCAL_FIRST_DAY_OF_WEEK) - 1; // .NET is 0-based and ICU is 1-based } + ucal_close(pCal); break; } case NegativePercentFormat: @@ -520,7 +527,7 @@ GetLocaleInfoGroupingSizes Obtains grouping sizes for decimal and currency Returns 1 for success, 0 otherwise */ -extern "C" int32_t GlobalizationNative_GetLocaleInfoGroupingSizes( +int32_t GlobalizationNative_GetLocaleInfoGroupingSizes( const UChar* localeName, LocaleNumberData localeGroupingData, int32_t* primaryGroupSize, int32_t* secondaryGroupSize) { UErrorCode status = U_ZERO_ERROR; diff --git a/src/corefx/System.Globalization.Native/pal_localeNumberData.h b/src/corefx/System.Globalization.Native/pal_localeNumberData.h new file mode 100644 index 000000000000..670c4245551c --- /dev/null +++ b/src/corefx/System.Globalization.Native/pal_localeNumberData.h @@ -0,0 +1,44 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +#include "pal_compiler.h" +#include "pal_locale.h" + +// Enum that corresponds to managed enum CultureData.LocaleNumberData. +// The numeric values of the enum members match their Win32 counterparts. +typedef enum +{ + LanguageId = 0x01, + MeasurementSystem = 0x0D, + FractionalDigitsCount = 0x00000011, + NegativeNumberFormat = 0x00001010, + MonetaryFractionalDigitsCount = 0x00000019, + PositiveMonetaryNumberFormat = 0x0000001B, + NegativeMonetaryNumberFormat = 0x0000001C, + FirstDayofWeek = 0x0000100C, + FirstWeekOfYear = 0x0000100D, + ReadingLayout = 0x00000070, + NegativePercentFormat = 0x00000074, + PositivePercentFormat = 0x00000075, + Digit = 0x00000010, + Monetary = 0x00000018 +} LocaleNumberData; + +// Enum that corresponds to managed enum System.Globalization.CalendarWeekRule +typedef enum +{ + FirstDay = 0, + FirstFullWeek = 1, + FirstFourDayWeek = 2 +} CalendarWeekRule; + +DLLEXPORT int32_t GlobalizationNative_GetLocaleInfoInt(const UChar* localeName, + LocaleNumberData localeNumberData, + int32_t* value); + +DLLEXPORT int32_t GlobalizationNative_GetLocaleInfoGroupingSizes(const UChar* localeName, + LocaleNumberData localeGroupingData, + int32_t* primaryGroupSize, + int32_t* secondaryGroupSize); diff --git a/src/corefx/System.Globalization.Native/pal_localeStringData.c b/src/corefx/System.Globalization.Native/pal_localeStringData.c index b8eaa307c735..a7256e665b1d 100644 --- a/src/corefx/System.Globalization.Native/pal_localeStringData.c +++ b/src/corefx/System.Globalization.Native/pal_localeStringData.c @@ -4,49 +4,10 @@ // #include +#include #include -#include -#include "icushim.h" -#include "locale.hpp" -#include "holders.h" - -// Enum that corresponds to managed enum CultureData.LocaleStringData. -// The numeric values of the enum members match their Win32 counterparts. -enum LocaleStringData : int32_t -{ - LocalizedDisplayName = 0x00000002, - EnglishDisplayName = 0x00000072, - NativeDisplayName = 0x00000073, - LocalizedLanguageName = 0x0000006f, - EnglishLanguageName = 0x00001001, - NativeLanguageName = 0x00000004, - EnglishCountryName = 0x00001002, - NativeCountryName = 0x00000008, - ListSeparator = 0x0000000C, - DecimalSeparator = 0x0000000E, - ThousandSeparator = 0x0000000F, - Digits = 0x00000013, - MonetarySymbol = 0x00000014, - CurrencyEnglishName = 0x00001007, - CurrencyNativeName = 0x00001008, - Iso4217MonetarySymbol = 0x00000015, - MonetaryDecimalSeparator = 0x00000016, - MonetaryThousandSeparator = 0x00000017, - AMDesignator = 0x00000028, - PMDesignator = 0x00000029, - PositiveSign = 0x00000050, - NegativeSign = 0x00000051, - Iso639LanguageTwoLetterName = 0x00000059, - Iso639LanguageThreeLetterName = 0x00000067, - Iso3166CountryName = 0x0000005A, - Iso3166CountryName2= 0x00000068, - NaNSymbol = 0x00000069, - PositiveInfinitySymbol = 0x0000006a, - ParentName = 0x0000006d, - PercentSymbol = 0x00000076, - PerMilleSymbol = 0x00000077 -}; +#include "pal_localeStringData.h" /* Function: @@ -58,16 +19,17 @@ UErrorCode GetLocaleInfoDecimalFormatSymbol(const char* locale, UNumberFormatSymbol symbol, UChar* value, int32_t valueLength) { UErrorCode status = U_ZERO_ERROR; - UNumberFormat* pFormat = unum_open(UNUM_DECIMAL, nullptr, 0, locale, nullptr, &status); - UNumberFormatHolder formatHolder(pFormat, status); + UNumberFormat* pFormat = unum_open(UNUM_DECIMAL, NULL, 0, locale, NULL, &status); if (U_FAILURE(status)) { + unum_close(pFormat); return status; } unum_getSymbol(pFormat, symbol, value, valueLength, &status); + unum_close(pFormat); return status; } @@ -101,16 +63,17 @@ Obtains the value of the AM or PM string for a locale. UErrorCode GetLocaleInfoAmPm(const char* locale, bool am, UChar* value, int32_t valueLength) { UErrorCode status = U_ZERO_ERROR; - UDateFormat* pFormat = udat_open(UDAT_DEFAULT, UDAT_DEFAULT, locale, nullptr, 0, nullptr, 0, &status); - UDateFormatHolder formatHolder(pFormat, status); + UDateFormat* pFormat = udat_open(UDAT_DEFAULT, UDAT_DEFAULT, locale, NULL, 0, NULL, 0, &status); if (U_FAILURE(status)) { + udat_close(pFormat); return status; } udat_getSymbols(pFormat, UDAT_AM_PMS, am ? 0 : 1, value, valueLength, &status); + udat_close(pFormat); return status; } @@ -123,18 +86,24 @@ Gets the language name for a locale (via uloc_getLanguage) and converts the resu UErrorCode GetLocaleIso639LanguageTwoLetterName(const char* locale, UChar* value, int32_t valueLength) { UErrorCode status = U_ZERO_ERROR; - int32_t length = uloc_getLanguage(locale, nullptr, 0, &status); + int32_t length = uloc_getLanguage(locale, NULL, 0, &status) + 1; + + char* buf = calloc(length, sizeof(char)); + if (buf == NULL) + { + return U_MEMORY_ALLOCATION_ERROR; + } - std::vector buf(length + 1, '\0'); status = U_ZERO_ERROR; - uloc_getLanguage(locale, buf.data(), length + 1, &status); + uloc_getLanguage(locale, buf, length, &status); if (U_SUCCESS(status)) { - status = u_charsToUChars_safe(buf.data(), value, valueLength); + status = u_charsToUChars_safe(buf, value, valueLength); } + free(buf); return status; } @@ -151,7 +120,7 @@ UErrorCode GetLocaleIso639LanguageThreeLetterName(const char* locale, UChar* val { return U_ILLEGAL_ARGUMENT_ERROR; } - + return u_charsToUChars_safe(isoLanguage, value, valueLength); } @@ -164,18 +133,25 @@ Gets the country name for a locale (via uloc_getCountry) and converts the result UErrorCode GetLocaleIso3166CountryName(const char* locale, UChar* value, int32_t valueLength) { UErrorCode status = U_ZERO_ERROR; - int32_t length = uloc_getCountry(locale, nullptr, 0, &status); + int32_t length = uloc_getCountry(locale, NULL, 0, &status) + 1; + + char* buf = calloc(length, sizeof(char)); + if (buf == NULL) + { + return U_MEMORY_ALLOCATION_ERROR; + } - std::vector buf(length + 1, '\0'); status = U_ZERO_ERROR; - uloc_getCountry(locale, buf.data(), length + 1, &status); + uloc_getCountry(locale, buf, length, &status); if (U_SUCCESS(status)) { - status = u_charsToUChars_safe(buf.data(), value, valueLength); + status = u_charsToUChars_safe(buf, value, valueLength); } + free(buf); + return status; } @@ -246,7 +222,7 @@ GetLocaleInfoString Obtains string locale information. Returns 1 for success, 0 otherwise */ -extern "C" int32_t GlobalizationNative_GetLocaleInfoString( +int32_t GlobalizationNative_GetLocaleInfoString( const UChar* localeName, LocaleStringData localeStringData, UChar* value, int32_t valueLength) { UErrorCode status = U_ZERO_ERROR; @@ -299,7 +275,7 @@ extern "C" int32_t GlobalizationNative_GetLocaleInfoString( { int charIndex = symbol - UNUM_ONE_DIGIT_SYMBOL + 1; status = GetDigitSymbol( - locale, status, static_cast(symbol), charIndex, value, valueLength); + locale, status, (UNumberFormatSymbol)symbol, charIndex, value, valueLength); } break; case MonetarySymbol: @@ -389,7 +365,7 @@ GetLocaleTimeFormat Obtains time format information (in ICU format, it needs to be coverted to .NET Format). Returns 1 for success, 0 otherwise */ -extern "C" int32_t GlobalizationNative_GetLocaleTimeFormat( +int32_t GlobalizationNative_GetLocaleTimeFormat( const UChar* localeName, int shortFormat, UChar* value, int32_t valueLength) { UErrorCode err = U_ZERO_ERROR; @@ -402,13 +378,16 @@ extern "C" int32_t GlobalizationNative_GetLocaleTimeFormat( } UDateFormatStyle style = (shortFormat != 0) ? UDAT_SHORT : UDAT_MEDIUM; - UDateFormat* pFormat = udat_open(style, UDAT_NONE, locale, nullptr, 0, nullptr, 0, &err); - UDateFormatHolder formatHolder(pFormat, err); + UDateFormat* pFormat = udat_open(style, UDAT_NONE, locale, NULL, 0, NULL, 0, &err); if (U_FAILURE(err)) + { + udat_close(pFormat); return UErrorCodeToBool(err); + } udat_toPattern(pFormat, false, value, valueLength, &err); + udat_close(pFormat); return UErrorCodeToBool(err); } diff --git a/src/corefx/System.Globalization.Native/pal_localeStringData.h b/src/corefx/System.Globalization.Native/pal_localeStringData.h new file mode 100644 index 000000000000..cb6a7b3af58a --- /dev/null +++ b/src/corefx/System.Globalization.Native/pal_localeStringData.h @@ -0,0 +1,54 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +#include "pal_compiler.h" +#include "pal_locale.h" + +// Enum that corresponds to managed enum CultureData.LocaleStringData. +// The numeric values of the enum members match their Win32 counterparts. +typedef enum +{ + LocalizedDisplayName = 0x02, + EnglishDisplayName = 0x00000072, + NativeDisplayName = 0x00000073, + LocalizedLanguageName = 0x0000006f, + EnglishLanguageName = 0x00001001, + NativeLanguageName = 0x04, + EnglishCountryName = 0x00001002, + NativeCountryName = 0x08, + ListSeparator = 0x0C, + DecimalSeparator = 0x0E, + ThousandSeparator = 0x0F, + Digits = 0x00000013, + MonetarySymbol = 0x00000014, + CurrencyEnglishName = 0x00001007, + CurrencyNativeName = 0x00001008, + Iso4217MonetarySymbol = 0x00000015, + MonetaryDecimalSeparator = 0x00000016, + MonetaryThousandSeparator = 0x00000017, + AMDesignator = 0x00000028, + PMDesignator = 0x00000029, + PositiveSign = 0x00000050, + NegativeSign = 0x00000051, + Iso639LanguageTwoLetterName = 0x00000059, + Iso639LanguageThreeLetterName = 0x00000067, + Iso3166CountryName = 0x0000005A, + Iso3166CountryName2= 0x00000068, + NaNSymbol = 0x00000069, + PositiveInfinitySymbol = 0x0000006a, + ParentName = 0x0000006d, + PercentSymbol = 0x00000076, + PerMilleSymbol = 0x00000077 +} LocaleStringData; + +DLLEXPORT int32_t GlobalizationNative_GetLocaleInfoString(const UChar* localeName, + LocaleStringData localeStringData, + UChar* value, + int32_t valueLength); + +DLLEXPORT int32_t GlobalizationNative_GetLocaleTimeFormat(const UChar* localeName, + int shortFormat, UChar* value, + int32_t valueLength); + diff --git a/src/corefx/System.Globalization.Native/pal_normalization.c b/src/corefx/System.Globalization.Native/pal_normalization.c index 014894a5edc5..9c0847b9497a 100644 --- a/src/corefx/System.Globalization.Native/pal_normalization.c +++ b/src/corefx/System.Globalization.Native/pal_normalization.c @@ -4,35 +4,26 @@ // #include -#include "icushim.h" -/* - * These values should be kept in sync with System.Text.NormalizationForm - */ -enum class NormalizationForm : int32_t -{ - C = 0x1, - D = 0x2, - KC = 0x5, - KD = 0x6 -}; +#include "pal_icushim.h" +#include "pal_normalization.h" const UNormalizer2* GetNormalizerForForm(NormalizationForm normalizationForm, UErrorCode* pErrorCode) { switch (normalizationForm) { - case NormalizationForm::C: + case C: return unorm2_getNFCInstance(pErrorCode); - case NormalizationForm::D: + case D: return unorm2_getNFDInstance(pErrorCode); - case NormalizationForm::KC: + case KC: return unorm2_getNFKCInstance(pErrorCode); - case NormalizationForm::KD: + case KD: return unorm2_getNFKDInstance(pErrorCode); } *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR; - return nullptr; + return NULL; } /* @@ -48,7 +39,7 @@ Return values: 1: lpStr is normalized. -1: internal error during normalization. */ -extern "C" int32_t GlobalizationNative_IsNormalized( +int32_t GlobalizationNative_IsNormalized( NormalizationForm normalizationForm, const UChar* lpStr, int32_t cwStrLength) { UErrorCode err = U_ZERO_ERROR; @@ -77,7 +68,7 @@ Return values: 0: internal error during normalization. >0: the length of the normalized string (not counting the null terminator). */ -extern "C" int32_t GlobalizationNative_NormalizeString( +int32_t GlobalizationNative_NormalizeString( NormalizationForm normalizationForm, const UChar* lpSrc, int32_t cwSrcLength, UChar* lpDst, int32_t cwDstLength) { UErrorCode err = U_ZERO_ERROR; diff --git a/src/corefx/System.Globalization.Native/pal_normalization.h b/src/corefx/System.Globalization.Native/pal_normalization.h new file mode 100644 index 000000000000..7478d5b9434c --- /dev/null +++ b/src/corefx/System.Globalization.Native/pal_normalization.h @@ -0,0 +1,28 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +#include "pal_compiler.h" +#include "pal_locale.h" + +/* + * These values should be kept in sync with System.Text.NormalizationForm + */ +typedef enum +{ + C = 0x1, + D = 0x2, + KC = 0x5, + KD = 0x6 +} NormalizationForm; + +DLLEXPORT int32_t GlobalizationNative_IsNormalized(NormalizationForm normalizationForm, + const UChar* lpStr, + int32_t cwStrLength); + +DLLEXPORT int32_t GlobalizationNative_NormalizeString(NormalizationForm normalizationForm, + const UChar* lpSrc, + int32_t cwSrcLength, + UChar* lpDst, + int32_t cwDstLength); diff --git a/src/corefx/System.Globalization.Native/pal_timeZoneInfo.c b/src/corefx/System.Globalization.Native/pal_timeZoneInfo.c index d5ab7e094d60..1ea378b835dd 100644 --- a/src/corefx/System.Globalization.Native/pal_timeZoneInfo.c +++ b/src/corefx/System.Globalization.Native/pal_timeZoneInfo.c @@ -6,25 +6,12 @@ #include #include -#include "icushim.h" -#include "locale.hpp" -#include "holders.h" -#include "errors.h" - -/* -These values should be kept in sync with the managed Interop.GlobalizationInterop.TimeZoneDisplayNameType enum. -*/ -enum TimeZoneDisplayNameType : int32_t -{ - Generic = 0, - Standard = 1, - DaylightSavings = 2, -}; +#include "pal_timeZoneInfo.h" /* Gets the localized display name for the specified time zone. */ -extern "C" ResultCode GlobalizationNative_GetTimeZoneDisplayName( +ResultCode GlobalizationNative_GetTimeZoneDisplayName( const UChar* localeName, const UChar* timeZoneId, TimeZoneDisplayNameType type, UChar* result, int32_t resultLength) { UErrorCode err = U_ZERO_ERROR; @@ -33,7 +20,6 @@ extern "C" ResultCode GlobalizationNative_GetTimeZoneDisplayName( int32_t timeZoneIdLength = -1; // timeZoneId is NULL-terminated UCalendar* calendar = ucal_open(timeZoneId, timeZoneIdLength, locale, UCAL_DEFAULT, &err); - UCalendarHolder calendarHolder(calendar, err); // TODO (https://github.com/dotnet/corefx/issues/5741): need to support Generic names, but ICU "C" api // has no public option for this. For now, just use the ICU standard name for both Standard and Generic @@ -41,5 +27,6 @@ extern "C" ResultCode GlobalizationNative_GetTimeZoneDisplayName( ucal_getTimeZoneDisplayName( calendar, type == DaylightSavings ? UCAL_DST : UCAL_STANDARD, locale, result, resultLength, &err); + ucal_close(calendar); return GetResultCode(err); } diff --git a/src/corefx/System.Globalization.Native/pal_timeZoneInfo.h b/src/corefx/System.Globalization.Native/pal_timeZoneInfo.h new file mode 100644 index 000000000000..bee24eb72882 --- /dev/null +++ b/src/corefx/System.Globalization.Native/pal_timeZoneInfo.h @@ -0,0 +1,24 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +#include "pal_compiler.h" +#include "pal_locale.h" +#include "pal_errors.h" + +/* +These values should be kept in sync with the managed Interop.GlobalizationInterop.TimeZoneDisplayNameType enum. +*/ +typedef enum +{ + Generic = 0, + Standard = 1, + DaylightSavings = 2, +} TimeZoneDisplayNameType; + +DLLEXPORT ResultCode GlobalizationNative_GetTimeZoneDisplayName(const UChar* localeName, + const UChar* timeZoneId, + TimeZoneDisplayNameType type, + UChar* result, + int32_t resultLength); From 35326c66500cb6f5a54000c26f31f145eb09780e Mon Sep 17 00:00:00 2001 From: kasper3 <33230602+kasper3@users.noreply.github.com> Date: Mon, 25 Jun 2018 14:39:57 +0000 Subject: [PATCH 03/14] Address feedback --- .../pal_calendarData.c | 30 ++----- .../pal_collation.c | 85 +++++++++++-------- .../pal_localeStringData.c | 9 -- 3 files changed, 54 insertions(+), 70 deletions(-) diff --git a/src/corefx/System.Globalization.Native/pal_calendarData.c b/src/corefx/System.Globalization.Native/pal_calendarData.c index c65da8f41834..404c0df22093 100644 --- a/src/corefx/System.Globalization.Native/pal_calendarData.c +++ b/src/corefx/System.Globalization.Native/pal_calendarData.c @@ -123,10 +123,7 @@ int32_t GlobalizationNative_GetCalendars( UEnumeration* pEnum = ucal_getKeywordValuesForLocale("calendar", locale, TRUE, &err); if (U_FAILURE(err)) - { - uenum_close(pEnum); return 0; - } int stringEnumeratorCount = uenum_count(pEnum, &err); if (U_FAILURE(err)) @@ -167,10 +164,7 @@ ResultCode GetMonthDayPattern(const char* locale, UChar* sMonthDay, int32_t stri UDateTimePatternGenerator* pGenerator = udatpg_open(locale, &err); if (U_FAILURE(err)) - { - udatpg_close(pGenerator); return GetResultCode(err); - } udatpg_getBestPattern(pGenerator, UDAT_MONTH_DAY_UCHAR, -1, sMonthDay, stringCapacity, &err); @@ -240,10 +234,7 @@ bool InvokeCallbackForDatePattern(const char* locale, UDateFormat* pFormat = udat_open(UDAT_NONE, style, locale, NULL, 0, NULL, 0, &err); if (U_FAILURE(err)) - { - unum_close(pFormat); return false; - } UErrorCode ignore = U_ZERO_ERROR; int32_t patternLen = udat_toPattern(pFormat, false, NULL, 0, &ignore) + 1; @@ -251,11 +242,11 @@ bool InvokeCallbackForDatePattern(const char* locale, UChar* pattern = calloc(patternLen, sizeof(UChar)); if (pattern == NULL) { + udat_close(pFormat); return false; } udat_toPattern(pFormat, false, pattern, patternLen, &err); - udat_close(pFormat); if (U_SUCCESS(err)) @@ -283,10 +274,7 @@ bool InvokeCallbackForDateTimePattern(const char* locale, UDateTimePatternGenerator* pGenerator = udatpg_open(locale, &err); if (U_FAILURE(err)) - { - udatpg_close(pGenerator); return false; - } UErrorCode ignore = U_ZERO_ERROR; int32_t patternLen = udatpg_getBestPattern(pGenerator, patternSkeleton, -1, NULL, 0, &ignore) + 1; @@ -294,12 +282,13 @@ bool InvokeCallbackForDateTimePattern(const char* locale, UChar* bestPattern = calloc(patternLen, sizeof(UChar)); if (bestPattern == NULL) { + udatpg_close(pGenerator); return false; } udatpg_getBestPattern(pGenerator, patternSkeleton, -1, bestPattern, patternLen, &err); - udatpg_close(pGenerator); + if (U_SUCCESS(err)) { callback(bestPattern, context); @@ -327,10 +316,7 @@ bool EnumSymbols(const char* locale, UDateFormat* pFormat = udat_open(UDAT_DEFAULT, UDAT_DEFAULT, locale, NULL, 0, NULL, 0, &err); if (U_FAILURE(err)) - { - udat_close(pFormat); return false; - } char localeWithCalendarName[ULOC_FULLNAME_CAPACITY]; strncpy(localeWithCalendarName, locale, ULOC_FULLNAME_CAPACITY); @@ -363,7 +349,7 @@ bool EnumSymbols(const char* locale, if (symbolBuf == NULL) { udat_close(pFormat); - free(symbolBuf); + ucal_close(pCalendar); return false; } @@ -374,6 +360,7 @@ bool EnumSymbols(const char* locale, if (U_FAILURE(err)) { udat_close(pFormat); + ucal_close(pCalendar); free(symbolBuf); return false; } @@ -383,6 +370,7 @@ bool EnumSymbols(const char* locale, } udat_close(pFormat); + ucal_close(pCalendar); return true; } @@ -571,10 +559,7 @@ int32_t GlobalizationNative_GetLatestJapaneseEra() UCalendar* pCal = ucal_open(NULL, 0, JAPANESE_LOCALE_AND_CALENDAR, UCAL_TRADITIONAL, &err); if (U_FAILURE(err)) - { - ucal_close(pCal); return 0; - } ucal_set(pCal, UCAL_EXTENDED_YEAR, 9999); int32_t ret = ucal_get(pCal, UCAL_ERA, &err); @@ -600,10 +585,7 @@ int32_t GlobalizationNative_GetJapaneseEraStartDate( UCalendar* pCal = ucal_open(NULL, 0, JAPANESE_LOCALE_AND_CALENDAR, UCAL_TRADITIONAL, &err); if (U_FAILURE(err)) - { - ucal_close(pCal); return false; - } ucal_set(pCal, UCAL_ERA, era); ucal_set(pCal, UCAL_YEAR, 1); diff --git a/src/corefx/System.Globalization.Native/pal_collation.c b/src/corefx/System.Globalization.Native/pal_collation.c index 8440e48faa5b..f642680b004e 100644 --- a/src/corefx/System.Globalization.Native/pal_collation.c +++ b/src/corefx/System.Globalization.Native/pal_collation.c @@ -34,7 +34,9 @@ int TreeComparer(const void* left, const void* right) { const TCollatorMap* leftMap = left; const TCollatorMap* rightMap = right; - return leftMap->key - rightMap->key; + if (leftMap->key < rightMap->key) return -1; + if (leftMap->key > rightMap->key) return 1; + return 0; } // Hiragana character range @@ -120,11 +122,11 @@ bool IsHalfFullHigherSymbol(UChar character) static bool AddItem(UCharList* list, size_t* currentCapacity, const UChar item) { size_t size = list->size++; - if(size >= *currentCapacity) + if (size >= *currentCapacity) { *currentCapacity *= 2; UChar* ptr = (UChar*)realloc(list->items, *currentCapacity * sizeof(UChar*)); - if(ptr == NULL) + if (ptr == NULL) { return false; } @@ -284,6 +286,7 @@ UCollator* CloneCollatorWithOptions(const UCollator* pCollator, int32_t options, } pClonedCollator = ucol_openRules(completeRules, completeRulesLength, UCOL_DEFAULT, strength, NULL, pErr); + free(customRules); } if (isIgnoreSymbols) @@ -349,22 +352,32 @@ bool CanIgnoreAllCollationElements(const UCollator* pColl, const UChar* lpStr, i } -ResultCode GlobalizationNative_GetSortHandle(const char* lpLocaleName, SortHandle** ppSortHandle) +void CreateSortHandle(SortHandle** ppSortHandle) { - assert(ppSortHandle != NULL); - *ppSortHandle = (SortHandle*)malloc(sizeof(SortHandle)); if ((*ppSortHandle) == NULL) { - return GetResultCode(U_MEMORY_ALLOCATION_ERROR); + return; } (*ppSortHandle)->pRoot = NULL; int result = pthread_mutex_init(&(*ppSortHandle)->collatorsLockObject, NULL); + if (result != 0) { assert(false && "Unexpected pthread_mutex_init return value."); } +} + +ResultCode GlobalizationNative_GetSortHandle(const char* lpLocaleName, SortHandle** ppSortHandle) +{ + assert(ppSortHandle != NULL); + + CreateSortHandle(ppSortHandle); + if ((*ppSortHandle) == NULL) + { + return GetResultCode(U_MEMORY_ALLOCATION_ERROR); + } UErrorCode err = U_ZERO_ERROR; @@ -372,9 +385,6 @@ ResultCode GlobalizationNative_GetSortHandle(const char* lpLocaleName, SortHandl if (U_FAILURE(err)) { - if ((*ppSortHandle)->regular != NULL) - ucol_close((*ppSortHandle)->regular); - free(*ppSortHandle); (*ppSortHandle) = NULL; } @@ -426,6 +436,7 @@ const UCollator* GetCollatorFromSortHandle(SortHandle* pSortHandle, int32_t opti } else { + free(map); pCollator = (*(TCollatorMap**)entry)->UCollator; } @@ -483,11 +494,11 @@ int32_t GlobalizationNative_CompareString( IndexOf */ int32_t GlobalizationNative_IndexOf( - SortHandle* pSortHandle, - const UChar* lpTarget, - int32_t cwTargetLength, - const UChar* lpSource, - int32_t cwSourceLength, + SortHandle* pSortHandle, + const UChar* lpTarget, + int32_t cwTargetLength, + const UChar* lpSource, + int32_t cwSourceLength, int32_t options, int32_t* pMatchedLength) { @@ -508,8 +519,8 @@ int32_t GlobalizationNative_IndexOf( // if the search was successful, // we'll try to get the matched string length. if(result != USEARCH_DONE && pMatchedLength != NULL) - { - *pMatchedLength = usearch_getMatchedLength(pSearch); + { + *pMatchedLength = usearch_getMatchedLength(pSearch); } usearch_close(pSearch); } @@ -523,11 +534,11 @@ int32_t GlobalizationNative_IndexOf( LastIndexOf */ int32_t GlobalizationNative_LastIndexOf( - SortHandle* pSortHandle, - const UChar* lpTarget, - int32_t cwTargetLength, - const UChar* lpSource, - int32_t cwSourceLength, + SortHandle* pSortHandle, + const UChar* lpTarget, + int32_t cwTargetLength, + const UChar* lpSource, + int32_t cwSourceLength, int32_t options) { static_assert(USEARCH_DONE == -1, "managed side requires -1 for not found"); @@ -624,11 +635,11 @@ int32_t GlobalizationNative_IndexOfOrdinalIgnoreCase( Return value is a "Win32 BOOL" (1 = true, 0 = false) */ int32_t GlobalizationNative_StartsWith( - SortHandle* pSortHandle, - const UChar* lpTarget, - int32_t cwTargetLength, - const UChar* lpSource, - int32_t cwSourceLength, + SortHandle* pSortHandle, + const UChar* lpTarget, + int32_t cwTargetLength, + const UChar* lpSource, + int32_t cwSourceLength, int32_t options) { int32_t result = FALSE; @@ -666,11 +677,11 @@ int32_t GlobalizationNative_StartsWith( Return value is a "Win32 BOOL" (1 = true, 0 = false) */ int32_t GlobalizationNative_EndsWith( - SortHandle* pSortHandle, - const UChar* lpTarget, - int32_t cwTargetLength, - const UChar* lpSource, - int32_t cwSourceLength, + SortHandle* pSortHandle, + const UChar* lpTarget, + int32_t cwTargetLength, + const UChar* lpSource, + int32_t cwSourceLength, int32_t options) { int32_t result = FALSE; @@ -709,11 +720,11 @@ int32_t GlobalizationNative_EndsWith( } int32_t GlobalizationNative_GetSortKey( - SortHandle* pSortHandle, - const UChar* lpStr, - int32_t cwStrLength, - uint8_t* sortKey, - int32_t cbSortKeyLength, + SortHandle* pSortHandle, + const UChar* lpStr, + int32_t cwStrLength, + uint8_t* sortKey, + int32_t cbSortKeyLength, int32_t options) { UErrorCode err = U_ZERO_ERROR; diff --git a/src/corefx/System.Globalization.Native/pal_localeStringData.c b/src/corefx/System.Globalization.Native/pal_localeStringData.c index a7256e665b1d..5f97792eaa6a 100644 --- a/src/corefx/System.Globalization.Native/pal_localeStringData.c +++ b/src/corefx/System.Globalization.Native/pal_localeStringData.c @@ -22,10 +22,7 @@ GetLocaleInfoDecimalFormatSymbol(const char* locale, UNumberFormatSymbol symbol, UNumberFormat* pFormat = unum_open(UNUM_DECIMAL, NULL, 0, locale, NULL, &status); if (U_FAILURE(status)) - { - unum_close(pFormat); return status; - } unum_getSymbol(pFormat, symbol, value, valueLength, &status); @@ -66,10 +63,7 @@ UErrorCode GetLocaleInfoAmPm(const char* locale, bool am, UChar* value, int32_t UDateFormat* pFormat = udat_open(UDAT_DEFAULT, UDAT_DEFAULT, locale, NULL, 0, NULL, 0, &status); if (U_FAILURE(status)) - { - udat_close(pFormat); return status; - } udat_getSymbols(pFormat, UDAT_AM_PMS, am ? 0 : 1, value, valueLength, &status); @@ -381,10 +375,7 @@ int32_t GlobalizationNative_GetLocaleTimeFormat( UDateFormat* pFormat = udat_open(style, UDAT_NONE, locale, NULL, 0, NULL, 0, &err); if (U_FAILURE(err)) - { - udat_close(pFormat); return UErrorCodeToBool(err); - } udat_toPattern(pFormat, false, value, valueLength, &err); From db8dbe8a005beec124eaac1adcfa30d4715338bd Mon Sep 17 00:00:00 2001 From: kasper3 <33230602+kasper3@users.noreply.github.com> Date: Mon, 25 Jun 2018 20:05:58 +0000 Subject: [PATCH 04/14] Convert version.cpp to C --- CMakeLists.txt | 2 +- build.sh | 6 +++--- src/corefx/System.Globalization.Native/CMakeLists.txt | 6 ------ 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 31b814f118d8..a9649e642dd3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,7 +24,7 @@ set(CLR_DIR ${CMAKE_CURRENT_SOURCE_DIR}) set(VM_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src/vm) set(GENERATED_INCLUDE_DIR ${CMAKE_CURRENT_BINARY_DIR}/src/inc) set(GENERATED_EVENTING_DIR ${CMAKE_CURRENT_BINARY_DIR}/eventing) -set(VERSION_FILE_PATH "${CMAKE_BINARY_DIR}/version.cpp") +set(VERSION_FILE_PATH "${CMAKE_BINARY_DIR}/version.c") set(PAL_REDEFINES_FILE ${CMAKE_CURRENT_SOURCE_DIR}/src/dlls/mscordac/palredefines.S) set(CORECLR_SET_RPATH ON) diff --git a/build.sh b/build.sh index 72d0456db2d3..536dbe8f5bb3 100755 --- a/build.sh +++ b/build.sh @@ -293,8 +293,8 @@ build_native() if [ $__SkipConfigure == 0 ]; then # if msbuild is not supported, then set __SkipGenerateVersion to 1 if [ $__isMSBuildOnNETCoreSupported == 0 ]; then __SkipGenerateVersion=1; fi - # Drop version.cpp file - __versionSourceFile="$intermediatesForBuild/version.cpp" + # Drop version.c file + __versionSourceFile="$intermediatesForBuild/version.c" if [ $__SkipGenerateVersion == 0 ]; then pwd "$__ProjectRoot/dotnet.sh" msbuild /nologo /verbosity:minimal /clp:Summary \ @@ -304,7 +304,7 @@ build_native() "$__ProjectDir/build.proj" /p:GenerateVersionSourceFile=true /t:GenerateVersionSourceFile /p:NativeVersionSourceFile=$__versionSourceFile \ $__CommonMSBuildArgs $__UnprocessedBuildArgs else - # Generate the dummy version.cpp, but only if it didn't exist to make sure we don't trigger unnecessary rebuild + # Generate the dummy version.c, but only if it didn't exist to make sure we don't trigger unnecessary rebuild __versionSourceLine="static char sccsid[] __attribute__((used)) = \"@(#)No version information produced\";" if [ -e $__versionSourceFile ]; then read existingVersionSourceLine < $__versionSourceFile diff --git a/src/corefx/System.Globalization.Native/CMakeLists.txt b/src/corefx/System.Globalization.Native/CMakeLists.txt index c44498fecef8..026e5bb1e291 100644 --- a/src/corefx/System.Globalization.Native/CMakeLists.txt +++ b/src/corefx/System.Globalization.Native/CMakeLists.txt @@ -71,12 +71,6 @@ _add_library(System.Globalization.Native_Static # Disable the "lib" prefix. set_target_properties(System.Globalization.Native PROPERTIES PREFIX "") -# Force CMake to not link against libstdc++ -# http://cmake.3232098.n2.nabble.com/setting-LINKER-LANGUAGE-still-adds-lstdc-td7581940.html -set_target_properties(System.Globalization.Native PROPERTIES LINKER_LANGUAGE "C") -set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "") -set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "") - # Disable the "lib" prefix and override default name set_target_properties(System.Globalization.Native_Static PROPERTIES PREFIX "") set_target_properties(System.Globalization.Native_Static PROPERTIES OUTPUT_NAME System.Globalization.Native) From 6cd0d928a55d8eae12d7eeaf77d02440d3443deb Mon Sep 17 00:00:00 2001 From: kasper3 <33230602+kasper3@users.noreply.github.com> Date: Fri, 29 Jun 2018 15:15:56 +0000 Subject: [PATCH 05/14] Address feedback --- .../pal_collation.c | 42 ++++++++++--------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/src/corefx/System.Globalization.Native/pal_collation.c b/src/corefx/System.Globalization.Native/pal_collation.c index f642680b004e..3541802b6dd3 100644 --- a/src/corefx/System.Globalization.Native/pal_collation.c +++ b/src/corefx/System.Globalization.Native/pal_collation.c @@ -28,7 +28,7 @@ const int32_t CompareOptionsIgnoreWidth = 0x10; // change ICU's default behavior here isn't really justified unless someone has a strong reason // for !StringSort to behave differently. -typedef struct { UChar* items; size_t size; } UCharList; +typedef struct { UChar* items; size_t capacity; size_t size; } UCharList; int TreeComparer(const void* left, const void* right) { @@ -119,13 +119,13 @@ bool IsHalfFullHigherSymbol(UChar character) || (0xff61 <= character && character <= 0xff65); } -static bool AddItem(UCharList* list, size_t* currentCapacity, const UChar item) +static bool AddItem(UCharList* list, const UChar item) { size_t size = list->size++; - if (size >= *currentCapacity) + if (size >= list->capacity) { - *currentCapacity *= 2; - UChar* ptr = (UChar*)realloc(list->items, *currentCapacity * sizeof(UChar*)); + list->capacity *= 2; + UChar* ptr = (UChar*)realloc(list->items, list->capacity * sizeof(UChar*)); if (ptr == NULL) { return false; @@ -159,18 +159,18 @@ UCharList* GetCustomRules(int32_t options, UColAttributeValue strength, bool isI if (!(needsIgnoreKanaTypeCustomRule || needsNotIgnoreKanaTypeCustomRule || needsIgnoreWidthCustomRule || needsNotIgnoreWidthCustomRule)) return NULL; - // If we need to create customRules, the KanaType custom rule will be 88 kana characters * 4 = 352 chars long - // and the Width custom rule will be at least 215 halfwidth characters * 4 = 860 chars long. - // Use 512 as the starting size, so the customRules won't have to grow if we are just - // doing the KanaType custom rule. - size_t capacity = 512; UCharList* customRules = (UCharList*)malloc(sizeof(UCharList)); if (customRules == NULL) { return NULL; } - customRules->items = calloc(capacity, sizeof(UChar)); + // If we need to create customRules, the KanaType custom rule will be 88 kana characters * 4 = 352 chars long + // and the Width custom rule will be at least 215 halfwidth characters * 4 = 860 chars long. + // Use 512 as the starting size, so the customRules won't have to grow if we are just + // doing the KanaType custom rule. + customRules->capacity = 512; + customRules->items = calloc(customRules->capacity, sizeof(UChar)); if (customRules->items == NULL) { free(customRules); @@ -188,10 +188,10 @@ UCharList* GetCustomRules(int32_t options, UColAttributeValue strength, bool isI // Hiragana is the range 3041 to 3096 & 309D & 309E if (hiraganaChar <= 0x3096 || hiraganaChar >= 0x309D) // characters between 3096 and 309D are not mapped to katakana { - if(!(AddItem(customRules, &capacity, '&') && - AddItem(customRules, &capacity, hiraganaChar) && - AddItem(customRules, &capacity, compareChar) && - AddItem(customRules, &capacity, hiraganaChar + hiraganaToKatakanaOffset))) + if(!(AddItem(customRules, '&') && + AddItem(customRules, hiraganaChar) && + AddItem(customRules, compareChar) && + AddItem(customRules, hiraganaChar + hiraganaToKatakanaOffset))) { free(customRules->items); free(customRules); @@ -219,11 +219,11 @@ UCharList* GetCustomRules(int32_t options, UColAttributeValue strength, bool isI // this character is a symbol, and if so skip it if (!(isIgnoreSymbols && needsNotIgnoreWidthCustomRule && (needsEscape || IsHalfFullHigherSymbol(higherChar)))) { - if(!(AddItem(customRules, &capacity, '&') && - (!needsEscape || AddItem(customRules, &capacity, '\\')) && - AddItem(customRules, &capacity, lowerChar) && - AddItem(customRules, &capacity, compareChar) && - AddItem(customRules, &capacity, higherChar))) + if(!(AddItem(customRules, '&') && + (!needsEscape || AddItem(customRules, '\\')) && + AddItem(customRules, lowerChar) && + AddItem(customRules, compareChar) && + AddItem(customRules, higherChar))) { free(customRules->items); free(customRules); @@ -286,6 +286,7 @@ UCollator* CloneCollatorWithOptions(const UCollator* pCollator, int32_t options, } pClonedCollator = ucol_openRules(completeRules, completeRulesLength, UCOL_DEFAULT, strength, NULL, pErr); + free(completeRules); free(customRules); } @@ -385,6 +386,7 @@ ResultCode GlobalizationNative_GetSortHandle(const char* lpLocaleName, SortHandl if (U_FAILURE(err)) { + pthread_mutex_destroy(&(*ppSortHandle)->collatorsLockObject); free(*ppSortHandle); (*ppSortHandle) = NULL; } From 08bc2bf9b7de78ae8f80fdb08b7e1bf0cb8c1615 Mon Sep 17 00:00:00 2001 From: kasper3 <33230602+kasper3@users.noreply.github.com> Date: Sun, 1 Jul 2018 09:51:09 +0000 Subject: [PATCH 06/14] Fix enum alignment --- src/corefx/System.Globalization.Native/pal_calendarData.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/corefx/System.Globalization.Native/pal_calendarData.h b/src/corefx/System.Globalization.Native/pal_calendarData.h index 53b1b5e90cd4..394c6129f8d7 100644 --- a/src/corefx/System.Globalization.Native/pal_calendarData.h +++ b/src/corefx/System.Globalization.Native/pal_calendarData.h @@ -11,7 +11,7 @@ /* * These values should be kept in sync with System.Globalization.CalendarId */ -typedef enum +enum { UNINITIALIZED_VALUE = 0, GREGORIAN = 1, // Gregorian (localized) calendar @@ -40,7 +40,8 @@ typedef enum PERSIAN = 22, UMALQURA = 23, LAST_CALENDAR = 23 // Last calendar ID -} CalendarId; +}; +typedef uint16_t CalendarId; /* * These values should be kept in sync with System.Globalization.CalendarDataType From 39c5ffdbe835acb0208a7c24e76886ce423e4b97 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Sun, 3 Feb 2019 01:19:29 +0100 Subject: [PATCH 07/14] Change NormalizationForm to address feedback. --- .../System.Globalization.Native/pal_normalization.c | 8 ++++---- .../System.Globalization.Native/pal_normalization.h | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/corefx/System.Globalization.Native/pal_normalization.c b/src/corefx/System.Globalization.Native/pal_normalization.c index 9c0847b9497a..1fc880b6d0d0 100644 --- a/src/corefx/System.Globalization.Native/pal_normalization.c +++ b/src/corefx/System.Globalization.Native/pal_normalization.c @@ -12,13 +12,13 @@ const UNormalizer2* GetNormalizerForForm(NormalizationForm normalizationForm, UE { switch (normalizationForm) { - case C: + case FormC: return unorm2_getNFCInstance(pErrorCode); - case D: + case FormD: return unorm2_getNFDInstance(pErrorCode); - case KC: + case FormKC: return unorm2_getNFKCInstance(pErrorCode); - case KD: + case FormKD: return unorm2_getNFKDInstance(pErrorCode); } diff --git a/src/corefx/System.Globalization.Native/pal_normalization.h b/src/corefx/System.Globalization.Native/pal_normalization.h index 7478d5b9434c..993d95678d3d 100644 --- a/src/corefx/System.Globalization.Native/pal_normalization.h +++ b/src/corefx/System.Globalization.Native/pal_normalization.h @@ -11,10 +11,10 @@ */ typedef enum { - C = 0x1, - D = 0x2, - KC = 0x5, - KD = 0x6 + FormC = 0x1, + FormD = 0x2, + FormKC = 0x5, + FormKD = 0x6 } NormalizationForm; DLLEXPORT int32_t GlobalizationNative_IsNormalized(NormalizationForm normalizationForm, From a7f13657cf6bdb27fb51f6ad57835378857a5059 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Sun, 3 Feb 2019 01:50:56 +0100 Subject: [PATCH 08/14] Simplify and fix error handling --- .../pal_calendarData.c | 65 ++----------------- .../pal_localeStringData.c | 23 ------- 2 files changed, 4 insertions(+), 84 deletions(-) diff --git a/src/corefx/System.Globalization.Native/pal_calendarData.c b/src/corefx/System.Globalization.Native/pal_calendarData.c index 404c0df22093..8e14d8b5564b 100644 --- a/src/corefx/System.Globalization.Native/pal_calendarData.c +++ b/src/corefx/System.Globalization.Native/pal_calendarData.c @@ -116,22 +116,8 @@ int32_t GlobalizationNative_GetCalendars( UErrorCode err = U_ZERO_ERROR; char locale[ULOC_FULLNAME_CAPACITY]; GetLocale(localeName, locale, ULOC_FULLNAME_CAPACITY, false, &err); - - if (U_FAILURE(err)) - return 0; - UEnumeration* pEnum = ucal_getKeywordValuesForLocale("calendar", locale, TRUE, &err); - - if (U_FAILURE(err)) - return 0; - int stringEnumeratorCount = uenum_count(pEnum, &err); - if (U_FAILURE(err)) - { - uenum_close(pEnum); - return 0; - } - int calendarsReturned = 0; for (int i = 0; i < stringEnumeratorCount && calendarsReturned < calendarsCapacity; i++) { @@ -147,7 +133,6 @@ int32_t GlobalizationNative_GetCalendars( } } } - uenum_close(pEnum); return calendarsReturned; } @@ -162,12 +147,7 @@ ResultCode GetMonthDayPattern(const char* locale, UChar* sMonthDay, int32_t stri { UErrorCode err = U_ZERO_ERROR; UDateTimePatternGenerator* pGenerator = udatpg_open(locale, &err); - - if (U_FAILURE(err)) - return GetResultCode(err); - udatpg_getBestPattern(pGenerator, UDAT_MONTH_DAY_UCHAR, -1, sMonthDay, stringCapacity, &err); - udatpg_close(pGenerator); return GetResultCode(err); } @@ -603,69 +583,32 @@ int32_t GlobalizationNative_GetJapaneseEraStartDate( ucal_set(pCal, UCAL_DATE, 1); int32_t currentEra; - for (int i = 0; i <= 12; i++) + for (int i = 0; U_SUCCESS(err) && i <= 12; i++) { currentEra = ucal_get(pCal, UCAL_ERA, &err); - if (U_FAILURE(err)) - { - ucal_close(pCal); - return false; - } - if (currentEra == era) { - for (int i = 0; i < 31; i++) + for (int i = 0; U_SUCCESS(err) && i < 31; i++) { // subtract 1 day at a time until we get out of the specified Era ucal_add(pCal, UCAL_DATE, -1, &err); - if (U_FAILURE(err)) - { - ucal_close(pCal); - return false; - } - currentEra = ucal_get(pCal, UCAL_ERA, &err); - if (U_FAILURE(err)) - { - ucal_close(pCal); - return false; - } - - if (currentEra != era) + if (U_SUCCESS(err) && currentEra != era) { // add back 1 day to get back into the specified Era ucal_add(pCal, UCAL_DATE, 1, &err); - if (U_FAILURE(err)) - { - ucal_close(pCal); - return false; - } - *startMonth = ucal_get(pCal, UCAL_MONTH, &err) + 1; // ICU Calendar months are 0-based, but .NET is 1-based - if (U_FAILURE(err)) - { - ucal_close(pCal); - return false; - } - *startDay = ucal_get(pCal, UCAL_DATE, &err); ucal_close(pCal); - if (U_FAILURE(err)) - return false; - return true; + return U_SUCCESS(err); } } } // add 1 month at a time until we get into the specified Era ucal_add(pCal, UCAL_MONTH, 1, &err); - if (U_FAILURE(err)) - { - ucal_close(pCal); - return false; - } } ucal_close(pCal); diff --git a/src/corefx/System.Globalization.Native/pal_localeStringData.c b/src/corefx/System.Globalization.Native/pal_localeStringData.c index 5f97792eaa6a..d17e66700c95 100644 --- a/src/corefx/System.Globalization.Native/pal_localeStringData.c +++ b/src/corefx/System.Globalization.Native/pal_localeStringData.c @@ -20,12 +20,7 @@ GetLocaleInfoDecimalFormatSymbol(const char* locale, UNumberFormatSymbol symbol, { UErrorCode status = U_ZERO_ERROR; UNumberFormat* pFormat = unum_open(UNUM_DECIMAL, NULL, 0, locale, NULL, &status); - - if (U_FAILURE(status)) - return status; - unum_getSymbol(pFormat, symbol, value, valueLength, &status); - unum_close(pFormat); return status; } @@ -61,12 +56,7 @@ UErrorCode GetLocaleInfoAmPm(const char* locale, bool am, UChar* value, int32_t { UErrorCode status = U_ZERO_ERROR; UDateFormat* pFormat = udat_open(UDAT_DEFAULT, UDAT_DEFAULT, locale, NULL, 0, NULL, 0, &status); - - if (U_FAILURE(status)) - return status; - udat_getSymbols(pFormat, UDAT_AM_PMS, am ? 0 : 1, value, valueLength, &status); - udat_close(pFormat); return status; } @@ -88,8 +78,6 @@ UErrorCode GetLocaleIso639LanguageTwoLetterName(const char* locale, UChar* value return U_MEMORY_ALLOCATION_ERROR; } - status = U_ZERO_ERROR; - uloc_getLanguage(locale, buf, length, &status); if (U_SUCCESS(status)) @@ -365,20 +353,9 @@ int32_t GlobalizationNative_GetLocaleTimeFormat( UErrorCode err = U_ZERO_ERROR; char locale[ULOC_FULLNAME_CAPACITY]; GetLocale(localeName, locale, ULOC_FULLNAME_CAPACITY, false, &err); - - if (U_FAILURE(err)) - { - return UErrorCodeToBool(U_ILLEGAL_ARGUMENT_ERROR); - } - UDateFormatStyle style = (shortFormat != 0) ? UDAT_SHORT : UDAT_MEDIUM; UDateFormat* pFormat = udat_open(style, UDAT_NONE, locale, NULL, 0, NULL, 0, &err); - - if (U_FAILURE(err)) - return UErrorCodeToBool(err); - udat_toPattern(pFormat, false, value, valueLength, &err); - udat_close(pFormat); return UErrorCodeToBool(err); } From bea81cdfa6b0aaeb26f28780b72c04b1838c43d1 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Sun, 3 Feb 2019 02:02:24 +0100 Subject: [PATCH 09/14] Update one more place to use version.c instead of version.cpp --- build-test.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build-test.sh b/build-test.sh index a0ba5da53ca0..86472d1d7376 100755 --- a/build-test.sh +++ b/build-test.sh @@ -472,8 +472,8 @@ build_native_projects() if [ $__SkipConfigure == 0 ]; then # if msbuild is not supported, then set __SkipGenerateVersion to 1 if [ $__isMSBuildOnNETCoreSupported == 0 ]; then __SkipGenerateVersion=1; fi - # Drop version.cpp file - __versionSourceFile="$intermediatesForBuild/version.cpp" + # Drop version.c file + __versionSourceFile="$intermediatesForBuild/version.c" if [ $__SkipGenerateVersion == 0 ]; then pwd $__ProjectRoot/dotnet.sh msbuild /nologo /verbosity:minimal /clp:Summary \ @@ -484,7 +484,7 @@ build_native_projects() /l:BinClashLogger,Tools/Microsoft.DotNet.Build.Tasks.dll\;LogFile=binclash.log \ $__CommonMSBuildArgs $__UnprocessedBuildArgs else - # Generate the dummy version.cpp, but only if it didn't exist to make sure we don't trigger unnecessary rebuild + # Generate the dummy version.c, but only if it didn't exist to make sure we don't trigger unnecessary rebuild __versionSourceLine="static char sccsid[] __attribute__((used)) = \"@(#)No version information produced\";" if [ -e $__versionSourceFile ]; then read existingVersionSourceLine < $__versionSourceFile From 1edbceb16f7f54c535d4a8416cf2c34691e484bc Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Sun, 3 Feb 2019 03:20:45 +0100 Subject: [PATCH 10/14] Fix error handling in GetLocaleIso639LanguageTwoLetterName --- src/corefx/System.Globalization.Native/pal_localeStringData.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/corefx/System.Globalization.Native/pal_localeStringData.c b/src/corefx/System.Globalization.Native/pal_localeStringData.c index d17e66700c95..f8c9e8793797 100644 --- a/src/corefx/System.Globalization.Native/pal_localeStringData.c +++ b/src/corefx/System.Globalization.Native/pal_localeStringData.c @@ -72,12 +72,14 @@ UErrorCode GetLocaleIso639LanguageTwoLetterName(const char* locale, UChar* value UErrorCode status = U_ZERO_ERROR; int32_t length = uloc_getLanguage(locale, NULL, 0, &status) + 1; + assert(status == U_BUFFER_OVERFLOW_ERROR); char* buf = calloc(length, sizeof(char)); if (buf == NULL) { return U_MEMORY_ALLOCATION_ERROR; } + status = U_ZERO_ERROR; uloc_getLanguage(locale, buf, length, &status); if (U_SUCCESS(status)) From 91df8d26a01cc50672ac4f7f71359cd19e8e2db2 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Sun, 3 Feb 2019 03:37:19 +0100 Subject: [PATCH 11/14] Avoid memory allocation in EnumSymbols for small buffers --- .../pal_calendarData.c | 35 +++++++++++-------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/src/corefx/System.Globalization.Native/pal_calendarData.c b/src/corefx/System.Globalization.Native/pal_calendarData.c index 8e14d8b5564b..12b735d1b234 100644 --- a/src/corefx/System.Globalization.Native/pal_calendarData.c +++ b/src/corefx/System.Globalization.Native/pal_calendarData.c @@ -319,39 +319,44 @@ bool EnumSymbols(const char* locale, udat_setCalendar(pFormat, pCalendar); int32_t symbolCount = udat_countSymbols(pFormat, type); + UChar stackSymbolBuf[100]; + UChar* symbolBuf; - for (int32_t i = startIndex; i < symbolCount; i++) + for (int32_t i = startIndex; U_SUCCESS(err) && i < symbolCount; i++) { UErrorCode ignore = U_ZERO_ERROR; int symbolLen = udat_getSymbols(pFormat, type, i, NULL, 0, &ignore) + 1; - UChar* symbolBuf = calloc(symbolLen, sizeof(UChar)); - if (symbolBuf == NULL) + if (symbolLen <= sizeof(stackSymbolBuf) / sizeof(stackSymbolBuf[0])) { - udat_close(pFormat); - ucal_close(pCalendar); - return false; + symbolBuf = stackSymbolBuf; + } + else + { + symbolBuf = calloc(symbolLen, sizeof(UChar)); + if (symbolBuf == NULL) + { + err = U_MEMORY_ALLOCATION_ERROR; + break; + } } udat_getSymbols(pFormat, type, i, symbolBuf, symbolLen, &err); - assert(U_SUCCESS(err)); + if (U_SUCCESS(err)) + { + callback(symbolBuf, context); + } - if (U_FAILURE(err)) + if (symbolBuf != stackSymbolBuf) { - udat_close(pFormat); - ucal_close(pCalendar); free(symbolBuf); - return false; } - - callback(symbolBuf, context); - free(symbolBuf); } udat_close(pFormat); ucal_close(pCalendar); - return true; + return U_SUCCESS(err); } bool EnumUResourceBundle(const UResourceBundle* bundle, EnumCalendarInfoCallback callback, const void* context) From 5875f89361938c51cc1943901007aa362e828fae Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Sun, 3 Feb 2019 08:46:33 +0100 Subject: [PATCH 12/14] Update static_assert usage to c_static_assert_msg --- .../System.Globalization.Native/pal_collation.c | 13 +++++-------- .../System.Globalization.Native/pal_compiler.h | 6 +++--- .../System.Globalization.Native/pal_icushim.c | 8 ++++---- 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/src/corefx/System.Globalization.Native/pal_collation.c b/src/corefx/System.Globalization.Native/pal_collation.c index 3541802b6dd3..74f7bb3068ea 100644 --- a/src/corefx/System.Globalization.Native/pal_collation.c +++ b/src/corefx/System.Globalization.Native/pal_collation.c @@ -13,6 +13,11 @@ #include "pal_collation.h" +c_static_assert_msg(UCOL_EQUAL == 0, "managed side requires 0 for equal strings"); +c_static_assert_msg(UCOL_LESS < 0, "managed side requires less than zero for a < b"); +c_static_assert_msg(UCOL_GREATER > 0, "managed side requires greater than zero for a > b"); +c_static_assert_msg(USEARCH_DONE == -1, "managed side requires -1 for not found"); + const int32_t CompareOptionsIgnoreCase = 0x1; const int32_t CompareOptionsIgnoreNonSpace = 0x2; const int32_t CompareOptionsIgnoreSymbols = 0x4; @@ -475,10 +480,6 @@ CompareString int32_t GlobalizationNative_CompareString( SortHandle* pSortHandle, const UChar* lpStr1, int32_t cwStr1Length, const UChar* lpStr2, int32_t cwStr2Length, int32_t options) { - static_assert(UCOL_EQUAL == 0, "managed side requires 0 for equal strings"); - static_assert(UCOL_LESS < 0, "managed side requires less than zero for a < b"); - static_assert(UCOL_GREATER > 0, "managed side requires greater than zero for a > b"); - UCollationResult result = UCOL_EQUAL; UErrorCode err = U_ZERO_ERROR; const UCollator* pColl = GetCollatorFromSortHandle(pSortHandle, options, &err); @@ -504,8 +505,6 @@ int32_t GlobalizationNative_IndexOf( int32_t options, int32_t* pMatchedLength) { - static_assert(USEARCH_DONE == -1, "managed side requires -1 for not found"); - int32_t result = USEARCH_DONE; UErrorCode err = U_ZERO_ERROR; const UCollator* pColl = GetCollatorFromSortHandle(pSortHandle, options, &err); @@ -543,8 +542,6 @@ int32_t GlobalizationNative_LastIndexOf( int32_t cwSourceLength, int32_t options) { - static_assert(USEARCH_DONE == -1, "managed side requires -1 for not found"); - int32_t result = USEARCH_DONE; UErrorCode err = U_ZERO_ERROR; const UCollator* pColl = GetCollatorFromSortHandle(pSortHandle, options, &err); diff --git a/src/corefx/System.Globalization.Native/pal_compiler.h b/src/corefx/System.Globalization.Native/pal_compiler.h index b87de64b82e8..01ba72ad9771 100644 --- a/src/corefx/System.Globalization.Native/pal_compiler.h +++ b/src/corefx/System.Globalization.Native/pal_compiler.h @@ -9,11 +9,11 @@ #endif #ifdef static_assert -#define c_static_assert(e) static_assert((e),"") +#define c_static_assert_msg(e, msg) static_assert((e), msg) #elif __has_extension(c_static_assert) -#define c_static_assert(e) _Static_assert((e), "") +#define c_static_assert_msg(e, msg) _Static_assert((e), msg) #else -#define c_static_assert(e) typedef char __c_static_assert__[(e)?1:-1] +#define c_static_assert_msg(e, msg) typedef char __c_static_assert__[(e)?1:-1] #endif #define DLLEXPORT __attribute__ ((__visibility__ ("default"))) diff --git a/src/corefx/System.Globalization.Native/pal_icushim.c b/src/corefx/System.Globalization.Native/pal_icushim.c index 4c540abbac45..df92dec8b6cd 100644 --- a/src/corefx/System.Globalization.Native/pal_icushim.c +++ b/src/corefx/System.Globalization.Native/pal_icushim.c @@ -31,7 +31,7 @@ static void* libicui18n = NULL; bool FindICULibs(const char* versionPrefix, char* symbolName, char* symbolVersion) { #ifndef OSX_ICU_LIBRARY_PATH - static_assert(false, "The ICU Library path is not defined"); + c_static_assert_msg(false, "The ICU Library path is not defined"); #endif // OSX_ICU_LIBRARY_PATH // Usually OSX_ICU_LIBRARY_PATH is "/usr/lib/libicucore.dylib" @@ -119,10 +119,10 @@ bool OpenICULibraries(int majorVer, int minorVer, int subVer, const char* versio char libicuucName[64]; char libicui18nName[64]; - static_assert(sizeof("libicuuc.so") + MaxICUVersionStringLength <= sizeof(libicuucName), "The libicuucName is too small"); + c_static_assert_msg(sizeof("libicuuc.so") + MaxICUVersionStringLength <= sizeof(libicuucName), "The libicuucName is too small"); GetVersionedLibFileName("libicuuc.so", majorVer, minorVer, subVer, versionPrefix, libicuucName); - static_assert(sizeof("libicui18n.so") + MaxICUVersionStringLength <= sizeof(libicui18nName), "The libicui18nName is too small"); + c_static_assert_msg(sizeof("libicui18n.so") + MaxICUVersionStringLength <= sizeof(libicui18nName), "The libicui18nName is too small"); GetVersionedLibFileName("libicui18n.so", majorVer, minorVer, subVer, versionPrefix, libicui18nName); libicuuc = dlopen(libicuucName, RTLD_LAZY); @@ -263,7 +263,7 @@ int32_t GlobalizationNative_LoadICU() // Get pointers to all the ICU functions that are needed #define PER_FUNCTION_BLOCK(fn, lib) \ - static_assert((sizeof(#fn) + MaxICUVersionStringLength + 1) <= sizeof(symbolName), "The symbolName is too small for symbol " #fn); \ + c_static_assert_msg((sizeof(#fn) + MaxICUVersionStringLength + 1) <= sizeof(symbolName), "The symbolName is too small for symbol " #fn); \ sprintf(symbolName, #fn "%s", symbolVersion); \ fn##_ptr = (__typeof(fn)*)dlsym(lib, symbolName); \ if (fn##_ptr == NULL) { fprintf(stderr, "Cannot get symbol %s from " #lib "\nError: %s\n", symbolName, dlerror()); abort(); } From c152ba92901a3345a58a42f2a4c5ac5634cfbd3e Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Sun, 3 Feb 2019 10:26:27 +0100 Subject: [PATCH 13/14] Fix inconsistent usage of various bool types Convert u_charsToUChars_safe to ICU style error handling Unify error handling code across functions to use the same patterns Add static modifier to functions that are used only from single C file --- .../pal_calendarData.c | 136 +++++++++--------- .../pal_collation.c | 65 ++++----- .../System.Globalization.Native/pal_icushim.c | 49 ++++--- .../System.Globalization.Native/pal_locale.c | 70 ++++----- .../System.Globalization.Native/pal_locale.h | 8 +- .../pal_localeNumberData.c | 66 ++++----- .../pal_localeStringData.c | 104 +++++++------- .../pal_timeZoneInfo.c | 9 +- 8 files changed, 249 insertions(+), 258 deletions(-) diff --git a/src/corefx/System.Globalization.Native/pal_calendarData.c b/src/corefx/System.Globalization.Native/pal_calendarData.c index 12b735d1b234..307d0780f814 100644 --- a/src/corefx/System.Globalization.Native/pal_calendarData.c +++ b/src/corefx/System.Globalization.Native/pal_calendarData.c @@ -31,7 +31,7 @@ GetCalendarName Gets the associated ICU calendar name for the CalendarId. */ -const char* GetCalendarName(CalendarId calendarId) +static const char* GetCalendarName(CalendarId calendarId) { switch (calendarId) { @@ -79,7 +79,7 @@ GetCalendarId Gets the associated CalendarId for the ICU calendar name. */ -CalendarId GetCalendarId(const char* calendarName) +static CalendarId GetCalendarId(const char* calendarName) { if (strcasecmp(calendarName, GREGORIAN_NAME) == 0) // TODO: what about the other gregorian types? @@ -115,7 +115,7 @@ int32_t GlobalizationNative_GetCalendars( { UErrorCode err = U_ZERO_ERROR; char locale[ULOC_FULLNAME_CAPACITY]; - GetLocale(localeName, locale, ULOC_FULLNAME_CAPACITY, false, &err); + GetLocale(localeName, locale, ULOC_FULLNAME_CAPACITY, FALSE, &err); UEnumeration* pEnum = ucal_getKeywordValuesForLocale("calendar", locale, TRUE, &err); int stringEnumeratorCount = uenum_count(pEnum, &err); int calendarsReturned = 0; @@ -143,7 +143,9 @@ GetMonthDayPattern Gets the Month-Day DateTime pattern for the specified locale. */ -ResultCode GetMonthDayPattern(const char* locale, UChar* sMonthDay, int32_t stringCapacity) +static ResultCode GetMonthDayPattern(const char* locale, + UChar* sMonthDay, + int32_t stringCapacity) { UErrorCode err = U_ZERO_ERROR; UDateTimePatternGenerator* pGenerator = udatpg_open(locale, &err); @@ -158,7 +160,10 @@ GetNativeCalendarName Gets the native calendar name. */ -ResultCode GetNativeCalendarName(const char* locale, CalendarId calendarId, UChar* nativeName, int32_t stringCapacity) +static ResultCode GetNativeCalendarName(const char* locale, + CalendarId calendarId, + UChar* nativeName, + int32_t stringCapacity) { UErrorCode err = U_ZERO_ERROR; ULocaleDisplayNames* pDisplayNames = uldn_open(locale, ULDN_STANDARD_NAMES, &err); @@ -181,7 +186,7 @@ ResultCode GlobalizationNative_GetCalendarInfo( { UErrorCode err = U_ZERO_ERROR; char locale[ULOC_FULLNAME_CAPACITY]; - GetLocale(localeName, locale, ULOC_FULLNAME_CAPACITY, false, &err); + GetLocale(localeName, locale, ULOC_FULLNAME_CAPACITY, FALSE, &err); if (U_FAILURE(err)) return UnknownError; @@ -193,7 +198,7 @@ ResultCode GlobalizationNative_GetCalendarInfo( case MonthDay: return GetMonthDayPattern(locale, result, resultCapacity); default: - assert(false); + assert(FALSE); return UnknownError; } } @@ -205,28 +210,28 @@ InvokeCallbackForDatePattern Gets the ICU date pattern for the specified locale and EStyle and invokes the callback with the result. */ -bool InvokeCallbackForDatePattern(const char* locale, - UDateFormatStyle style, - EnumCalendarInfoCallback callback, - const void* context) +static int InvokeCallbackForDatePattern(const char* locale, + UDateFormatStyle style, + EnumCalendarInfoCallback callback, + const void* context) { UErrorCode err = U_ZERO_ERROR; UDateFormat* pFormat = udat_open(UDAT_NONE, style, locale, NULL, 0, NULL, 0, &err); if (U_FAILURE(err)) - return false; + return FALSE; UErrorCode ignore = U_ZERO_ERROR; - int32_t patternLen = udat_toPattern(pFormat, false, NULL, 0, &ignore) + 1; + int32_t patternLen = udat_toPattern(pFormat, FALSE, NULL, 0, &ignore) + 1; UChar* pattern = calloc(patternLen, sizeof(UChar)); if (pattern == NULL) { udat_close(pFormat); - return false; + return FALSE; } - udat_toPattern(pFormat, false, pattern, patternLen, &err); + udat_toPattern(pFormat, FALSE, pattern, patternLen, &err); udat_close(pFormat); if (U_SUCCESS(err)) @@ -235,7 +240,7 @@ bool InvokeCallbackForDatePattern(const char* locale, } free(pattern); - return U_SUCCESS(err); + return UErrorCodeToBool(err); } /* @@ -245,16 +250,16 @@ InvokeCallbackForDateTimePattern Gets the DateTime pattern for the specified skeleton and invokes the callback with the retrieved value. */ -bool InvokeCallbackForDateTimePattern(const char* locale, - const UChar* patternSkeleton, - EnumCalendarInfoCallback callback, - const void* context) +static int InvokeCallbackForDateTimePattern(const char* locale, + const UChar* patternSkeleton, + EnumCalendarInfoCallback callback, + const void* context) { UErrorCode err = U_ZERO_ERROR; UDateTimePatternGenerator* pGenerator = udatpg_open(locale, &err); if (U_FAILURE(err)) - return false; + return FALSE; UErrorCode ignore = U_ZERO_ERROR; int32_t patternLen = udatpg_getBestPattern(pGenerator, patternSkeleton, -1, NULL, 0, &ignore) + 1; @@ -263,7 +268,7 @@ bool InvokeCallbackForDateTimePattern(const char* locale, if (bestPattern == NULL) { udatpg_close(pGenerator); - return false; + return FALSE; } udatpg_getBestPattern(pGenerator, patternSkeleton, -1, bestPattern, patternLen, &err); @@ -275,7 +280,7 @@ bool InvokeCallbackForDateTimePattern(const char* locale, } free(bestPattern); - return U_SUCCESS(err); + return UErrorCodeToBool(err); } /* @@ -285,35 +290,29 @@ EnumSymbols Enumerates all of the symbols of a type for a locale and calendar and invokes a callback for each value. */ -bool EnumSymbols(const char* locale, - CalendarId calendarId, - UDateFormatSymbolType type, - int32_t startIndex, - EnumCalendarInfoCallback callback, - const void* context) +static int32_t EnumSymbols(const char* locale, + CalendarId calendarId, + UDateFormatSymbolType type, + int32_t startIndex, + EnumCalendarInfoCallback callback, + const void* context) { UErrorCode err = U_ZERO_ERROR; UDateFormat* pFormat = udat_open(UDAT_DEFAULT, UDAT_DEFAULT, locale, NULL, 0, NULL, 0, &err); if (U_FAILURE(err)) - return false; + return FALSE; char localeWithCalendarName[ULOC_FULLNAME_CAPACITY]; strncpy(localeWithCalendarName, locale, ULOC_FULLNAME_CAPACITY); uloc_setKeywordValue("calendar", GetCalendarName(calendarId), localeWithCalendarName, ULOC_FULLNAME_CAPACITY, &err); - if (U_FAILURE(err)) - { - udat_close(pFormat); - return false; - } - UCalendar* pCalendar = ucal_open(NULL, 0, localeWithCalendarName, UCAL_DEFAULT, &err); if (U_FAILURE(err)) { udat_close(pFormat); - return false; + return FALSE; } udat_setCalendar(pFormat, pCalendar); @@ -356,10 +355,12 @@ bool EnumSymbols(const char* locale, udat_close(pFormat); ucal_close(pCalendar); - return U_SUCCESS(err); + return UErrorCodeToBool(err); } -bool EnumUResourceBundle(const UResourceBundle* bundle, EnumCalendarInfoCallback callback, const void* context) +static void EnumUResourceBundle(const UResourceBundle* bundle, + EnumCalendarInfoCallback callback, + const void* context) { int32_t eraNameCount = ures_getSize(bundle); @@ -374,15 +375,13 @@ bool EnumUResourceBundle(const UResourceBundle* bundle, EnumCalendarInfoCallback callback(eraName, context); } } - - return true; } -void CloseResBundle(const UResourceBundle* rootResBundle, - const UResourceBundle* calResBundle, - const UResourceBundle* targetCalResBundle, - const UResourceBundle* erasColResBundle, - const UResourceBundle* erasResBundle) +static void CloseResBundle(const UResourceBundle* rootResBundle, + const UResourceBundle* calResBundle, + const UResourceBundle* targetCalResBundle, + const UResourceBundle* erasColResBundle, + const UResourceBundle* erasResBundle) { ures_close(rootResBundle); ures_close(calResBundle); @@ -398,10 +397,10 @@ EnumAbbrevEraNames Enumerates all the abbreviated era names of the specified locale and calendar, invoking the callback function for each era name. */ -bool EnumAbbrevEraNames(const char* locale, - CalendarId calendarId, - EnumCalendarInfoCallback callback, - const void* context) +static int32_t EnumAbbrevEraNames(const char* locale, + CalendarId calendarId, + EnumCalendarInfoCallback callback, + const void* context) { // The C-API for ICU provides no way to get at the abbreviated era names for a calendar (so we can't use EnumSymbols // here). Instead we will try to walk the ICU resource tables directly and fall back to regular era names if can't @@ -414,7 +413,7 @@ bool EnumAbbrevEraNames(const char* locale, strncpy(localeNamePtr, locale, ULOC_FULLNAME_CAPACITY); - while (true) + while (TRUE) { UErrorCode status = U_ZERO_ERROR; char* name = GetCalendarName(calendarId); @@ -429,7 +428,7 @@ bool EnumAbbrevEraNames(const char* locale, { EnumUResourceBundle(erasResBundle, callback, context); CloseResBundle(rootResBundle, calResBundle, targetCalResBundle, erasColResBundle, erasResBundle); - return true; + return TRUE; } // Couldn't find the data we need for this locale, we should fallback. @@ -474,19 +473,18 @@ Allows for a collection of calendar string data to be retrieved by invoking the callback for each value in the collection. The context parameter is passed through to the callback along with each string. */ -int32_t GlobalizationNative_EnumCalendarInfo( - EnumCalendarInfoCallback callback, - const UChar* localeName, - CalendarId calendarId, - CalendarDataType dataType, - const void* context) +int32_t GlobalizationNative_EnumCalendarInfo(EnumCalendarInfoCallback callback, + const UChar* localeName, + CalendarId calendarId, + CalendarDataType dataType, + const void* context) { UErrorCode err = U_ZERO_ERROR; char locale[ULOC_FULLNAME_CAPACITY]; - GetLocale(localeName, locale, ULOC_FULLNAME_CAPACITY, false, &err); + GetLocale(localeName, locale, ULOC_FULLNAME_CAPACITY, FALSE, &err); if (U_FAILURE(err)) - return false; + return FALSE; switch (dataType) { @@ -527,8 +525,8 @@ int32_t GlobalizationNative_EnumCalendarInfo( case AbbrevEraNames: return EnumAbbrevEraNames(locale, calendarId, callback, context); default: - assert(false); - return false; + assert(FALSE); + return FALSE; } } @@ -559,8 +557,10 @@ GetJapaneseEraInfo Gets the starting Gregorian date of the specified Japanese Era. */ -int32_t GlobalizationNative_GetJapaneseEraStartDate( - int32_t era, int32_t* startYear, int32_t* startMonth, int32_t* startDay) +int32_t GlobalizationNative_GetJapaneseEraStartDate(int32_t era, + int32_t* startYear, + int32_t* startMonth, + int32_t* startDay) { *startYear = -1; *startMonth = -1; @@ -570,7 +570,7 @@ int32_t GlobalizationNative_GetJapaneseEraStartDate( UCalendar* pCal = ucal_open(NULL, 0, JAPANESE_LOCALE_AND_CALENDAR, UCAL_TRADITIONAL, &err); if (U_FAILURE(err)) - return false; + return FALSE; ucal_set(pCal, UCAL_ERA, era); ucal_set(pCal, UCAL_YEAR, 1); @@ -580,7 +580,7 @@ int32_t GlobalizationNative_GetJapaneseEraStartDate( if (U_FAILURE(err)) { ucal_close(pCal); - return false; + return FALSE; } // set the date to Jan 1 @@ -607,7 +607,7 @@ int32_t GlobalizationNative_GetJapaneseEraStartDate( *startDay = ucal_get(pCal, UCAL_DATE, &err); ucal_close(pCal); - return U_SUCCESS(err); + return UErrorCodeToBool(err); } } } @@ -617,5 +617,5 @@ int32_t GlobalizationNative_GetJapaneseEraStartDate( } ucal_close(pCal); - return false; + return FALSE; } diff --git a/src/corefx/System.Globalization.Native/pal_collation.c b/src/corefx/System.Globalization.Native/pal_collation.c index 74f7bb3068ea..a56aa09cc557 100644 --- a/src/corefx/System.Globalization.Native/pal_collation.c +++ b/src/corefx/System.Globalization.Native/pal_collation.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include @@ -100,7 +99,7 @@ Thus, to use these characters in a rule, they need to be escaped. This rule was taken from http://www.unicode.org/reports/tr35/tr35-collation.html#Rules. */ -bool NeedsEscape(UChar character) +static int NeedsEscape(UChar character) { return ((0x21 <= character && character <= 0x2f) || (0x3a <= character && character <= 0x40) @@ -118,13 +117,13 @@ This is done so we can use range checks instead of comparing individual characte These ranges were obtained by running the above characters through .NET CompareInfo.Compare with CompareOptions.IgnoreSymbols on Windows. */ -bool IsHalfFullHigherSymbol(UChar character) +static int IsHalfFullHigherSymbol(UChar character) { return (0xffe0 <= character && character <= 0xffe6) || (0xff61 <= character && character <= 0xff65); } -static bool AddItem(UCharList* list, const UChar item) +static int AddItem(UCharList* list, const UChar item) { size_t size = list->size++; if (size >= list->capacity) @@ -133,13 +132,13 @@ static bool AddItem(UCharList* list, const UChar item) UChar* ptr = (UChar*)realloc(list->items, list->capacity * sizeof(UChar*)); if (ptr == NULL) { - return false; + return FALSE; } list->items = ptr; } list->items[size] = item; - return true; + return TRUE; } /* @@ -148,18 +147,18 @@ Gets a string of custom collation rules, if necessary. Since the CompareOptions flags don't map 1:1 with ICU default functionality, we need to fall back to using custom rules in order to support IgnoreKanaType and IgnoreWidth CompareOptions correctly. */ -UCharList* GetCustomRules(int32_t options, UColAttributeValue strength, bool isIgnoreSymbols) +static UCharList* GetCustomRules(int32_t options, UColAttributeValue strength, int isIgnoreSymbols) { - bool isIgnoreKanaType = (options & CompareOptionsIgnoreKanaType) == CompareOptionsIgnoreKanaType; - bool isIgnoreWidth = (options & CompareOptionsIgnoreWidth) == CompareOptionsIgnoreWidth; + int isIgnoreKanaType = (options & CompareOptionsIgnoreKanaType) == CompareOptionsIgnoreKanaType; + int isIgnoreWidth = (options & CompareOptionsIgnoreWidth) == CompareOptionsIgnoreWidth; // kana differs at the tertiary level - bool needsIgnoreKanaTypeCustomRule = isIgnoreKanaType && strength >= UCOL_TERTIARY; - bool needsNotIgnoreKanaTypeCustomRule = !isIgnoreKanaType && strength < UCOL_TERTIARY; + int needsIgnoreKanaTypeCustomRule = isIgnoreKanaType && strength >= UCOL_TERTIARY; + int needsNotIgnoreKanaTypeCustomRule = !isIgnoreKanaType && strength < UCOL_TERTIARY; // character width differs at the tertiary level - bool needsIgnoreWidthCustomRule = isIgnoreWidth && strength >= UCOL_TERTIARY; - bool needsNotIgnoreWidthCustomRule = !isIgnoreWidth && strength < UCOL_TERTIARY; + int needsIgnoreWidthCustomRule = isIgnoreWidth && strength >= UCOL_TERTIARY; + int needsNotIgnoreWidthCustomRule = !isIgnoreWidth && strength < UCOL_TERTIARY; if (!(needsIgnoreKanaTypeCustomRule || needsNotIgnoreKanaTypeCustomRule || needsIgnoreWidthCustomRule || needsNotIgnoreWidthCustomRule)) return NULL; @@ -212,7 +211,7 @@ UCharList* GetCustomRules(int32_t options, UColAttributeValue strength, bool isI UChar lowerChar; UChar higherChar; - bool needsEscape; + int needsEscape; for (int i = 0; i < g_HalfFullCharsLength; i++) { lowerChar = g_HalfFullLowerChars[i]; @@ -251,9 +250,9 @@ UCollator* CloneCollatorWithOptions(const UCollator* pCollator, int32_t options, { UColAttributeValue strength = ucol_getStrength(pCollator); - bool isIgnoreCase = (options & CompareOptionsIgnoreCase) == CompareOptionsIgnoreCase; - bool isIgnoreNonSpace = (options & CompareOptionsIgnoreNonSpace) == CompareOptionsIgnoreNonSpace; - bool isIgnoreSymbols = (options & CompareOptionsIgnoreSymbols) == CompareOptionsIgnoreSymbols; + int isIgnoreCase = (options & CompareOptionsIgnoreCase) == CompareOptionsIgnoreCase; + int isIgnoreNonSpace = (options & CompareOptionsIgnoreNonSpace) == CompareOptionsIgnoreNonSpace; + int isIgnoreSymbols = (options & CompareOptionsIgnoreSymbols) == CompareOptionsIgnoreSymbols; if (isIgnoreCase) { @@ -325,36 +324,28 @@ UCollator* CloneCollatorWithOptions(const UCollator* pCollator, int32_t options, } // Returns TRUE if all the collation elements in str are completely ignorable -bool CanIgnoreAllCollationElements(const UCollator* pColl, const UChar* lpStr, int32_t length) +static int CanIgnoreAllCollationElements(const UCollator* pColl, const UChar* lpStr, int32_t length) { - bool result = false; + int result = TRUE; UErrorCode err = U_ZERO_ERROR; UCollationElements* pCollElem = ucol_openElements(pColl, lpStr, length, &err); if (U_SUCCESS(err)) { int32_t curCollElem = UCOL_NULLORDER; - - result = true; - while ((curCollElem = ucol_next(pCollElem, &err)) != UCOL_NULLORDER) { if (curCollElem != 0) { - result = false; + result = FALSE; break; } } - if (U_FAILURE(err)) - { - result = false; - } - ucol_closeElements(pCollElem); } - return result; + return U_SUCCESS(err) ? result : FALSE; } @@ -371,7 +362,7 @@ void CreateSortHandle(SortHandle** ppSortHandle) if (result != 0) { - assert(false && "Unexpected pthread_mutex_init return value."); + assert(FALSE && "Unexpected pthread_mutex_init return value."); } } @@ -429,7 +420,7 @@ const UCollator* GetCollatorFromSortHandle(SortHandle* pSortHandle, int32_t opti int lockResult = pthread_mutex_lock(&pSortHandle->collatorsLockObject); if (lockResult != 0) { - assert(false && "Unexpected pthread_mutex_lock return value."); + assert(FALSE && "Unexpected pthread_mutex_lock return value."); } TCollatorMap* map = (TCollatorMap*)malloc(sizeof(TCollatorMap)); @@ -465,7 +456,7 @@ int32_t GlobalizationNative_GetSortVersion(SortHandle* pSortHandle) } else { - assert(false && "Unexpected ucol_getVersion to fail."); + assert(FALSE && "Unexpected ucol_getVersion to fail."); // we didn't use UCOL_TAILORINGS_VERSION because it is deprecated in ICU v5 result = UCOL_RUNTIME_VERSION << 16 | UCOL_BUILDER_VERSION; @@ -564,13 +555,13 @@ int32_t GlobalizationNative_LastIndexOf( Static Function: AreEqualOrdinalIgnoreCase */ -static bool AreEqualOrdinalIgnoreCase(UChar32 one, UChar32 two) +static int AreEqualOrdinalIgnoreCase(UChar32 one, UChar32 two) { // Return whether the two characters are identical or would be identical if they were upper-cased. if (one == two) { - return true; + return TRUE; } if (one == 0x0131 || two == 0x0131) @@ -578,7 +569,7 @@ static bool AreEqualOrdinalIgnoreCase(UChar32 one, UChar32 two) // On Windows with InvariantCulture, the LATIN SMALL LETTER DOTLESS I (U+0131) // capitalizes to itself, whereas with ICU it capitalizes to LATIN CAPITAL LETTER I (U+0049). // We special case it to match the Windows invariant behavior. - return false; + return FALSE; } return u_toupper(one) == u_toupper(two); @@ -603,14 +594,14 @@ int32_t GlobalizationNative_IndexOfOrdinalIgnoreCase( const UChar *src = lpSource, *trg = lpTarget; UChar32 srcCodepoint, trgCodepoint; - bool match = true; + int32_t match = TRUE; while (trgIdx < cwTargetLength) { U16_NEXT(src, srcIdx, cwSourceLength, srcCodepoint); U16_NEXT(trg, trgIdx, cwTargetLength, trgCodepoint); if (!AreEqualOrdinalIgnoreCase(srcCodepoint, trgCodepoint)) { - match = false; + match = FALSE; break; } } diff --git a/src/corefx/System.Globalization.Native/pal_icushim.c b/src/corefx/System.Globalization.Native/pal_icushim.c index df92dec8b6cd..ce42af642fcd 100644 --- a/src/corefx/System.Globalization.Native/pal_icushim.c +++ b/src/corefx/System.Globalization.Native/pal_icushim.c @@ -5,7 +5,6 @@ #include #include -#include #include #include #include @@ -28,7 +27,7 @@ static void* libicui18n = NULL; #ifdef __APPLE__ -bool FindICULibs(const char* versionPrefix, char* symbolName, char* symbolVersion) +static int FindICULibs(const char* versionPrefix, char* symbolName, char* symbolVersion) { #ifndef OSX_ICU_LIBRARY_PATH c_static_assert_msg(false, "The ICU Library path is not defined"); @@ -39,13 +38,13 @@ bool FindICULibs(const char* versionPrefix, char* symbolName, char* symbolVersio if (libicuuc == NULL) { - return false; + return FALSE; } // in OSX all ICU APIs exist in the same library libicucore.A.dylib libicui18n = libicuuc; - return true; + return TRUE; } #else // __APPLE__ @@ -67,7 +66,7 @@ static const int MaxSubICUVersion = 5; // 1. Only majorVer is not equal to -1 => result is baseFileName.majorver // 2. Only majorVer and minorVer are not equal to -1 => result is baseFileName.majorver.minorVer // 3. All components are not equal to -1 => result is baseFileName.majorver.minorVer.subver -void GetVersionedLibFileName(const char* baseFileName, int majorVer, int minorVer, int subVer, const char* versionPrefix, char* result) +static void GetVersionedLibFileName(const char* baseFileName, int majorVer, int minorVer, int subVer, const char* versionPrefix, char* result) { assert(majorVer != -1); @@ -83,7 +82,7 @@ void GetVersionedLibFileName(const char* baseFileName, int majorVer, int minorVe } } -bool FindSymbolVersion(int majorVer, int minorVer, int subVer, char* symbolName, char* symbolVersion) +static int FindSymbolVersion(int majorVer, int minorVer, int subVer, char* symbolName, char* symbolVersion) { // Find out the format of the version string added to each symbol // First try just the unversioned symbol @@ -104,17 +103,17 @@ bool FindSymbolVersion(int majorVer, int minorVer, int subVer, char* symbolName, sprintf(symbolName, "u_strlen%s", symbolVersion); if (dlsym(libicuuc, symbolName) == NULL) { - return false; + return FALSE; } } } } - return true; + return TRUE; } // Try to open the necessary ICU libraries -bool OpenICULibraries(int majorVer, int minorVer, int subVer, const char* versionPrefix, char* symbolName, char* symbolVersion) +static int OpenICULibraries(int majorVer, int minorVer, int subVer, const char* versionPrefix, char* symbolName, char* symbolVersion) { char libicuucName[64]; char libicui18nName[64]; @@ -146,7 +145,7 @@ bool OpenICULibraries(int majorVer, int minorVer, int subVer, const char* versio // environment variable. // The format of the string in this variable is majorVer[.minorVer[.subVer]] (the brackets // indicate optional parts). -bool FindLibUsingOverride(const char* versionPrefix, char* symbolName, char* symbolVersion) +static int FindLibUsingOverride(const char* versionPrefix, char* symbolName, char* symbolVersion) { char* versionOverride = getenv("CLR_ICU_VERSION_OVERRIDE"); if (versionOverride != NULL) @@ -160,16 +159,16 @@ bool FindLibUsingOverride(const char* versionPrefix, char* symbolName, char* sym { if (OpenICULibraries(first, second, third, versionPrefix, symbolName, symbolVersion)) { - return true; + return TRUE; } } } - return false; + return FALSE; } // Search for library files with names including the major version. -bool FindLibWithMajorVersion(const char* versionPrefix, char* symbolName, char* symbolVersion) +static int FindLibWithMajorVersion(const char* versionPrefix, char* symbolName, char* symbolVersion) { // ICU packaging documentation (http://userguide.icu-project.org/packaging) // describes applications link against the major (e.g. libicuuc.so.54). @@ -177,7 +176,7 @@ bool FindLibWithMajorVersion(const char* versionPrefix, char* symbolName, char* // Select the version of ICU present at build time. if (OpenICULibraries(MinICUVersion, -1, -1, versionPrefix, symbolName, symbolVersion)) { - return true; + return TRUE; } // Select the highest supported version of ICU present on the local machine @@ -185,16 +184,16 @@ bool FindLibWithMajorVersion(const char* versionPrefix, char* symbolName, char* { if (OpenICULibraries(i, -1, -1, versionPrefix, symbolName, symbolVersion)) { - return true; + return TRUE; } } - return false; + return FALSE; } // Select the highest supported version of ICU present on the local machine // Search for library files with names including the major and minor version. -bool FindLibWithMajorMinorVersion(const char* versionPrefix, char* symbolName, char* symbolVersion) +static int FindLibWithMajorMinorVersion(const char* versionPrefix, char* symbolName, char* symbolVersion) { for (int i = MaxICUVersion; i >= MinICUVersion; i--) { @@ -202,17 +201,17 @@ bool FindLibWithMajorMinorVersion(const char* versionPrefix, char* symbolName, c { if (OpenICULibraries(i, j, -1, versionPrefix, symbolName, symbolVersion)) { - return true; + return TRUE; } } } - return false; + return FALSE; } // Select the highest supported version of ICU present on the local machine // Search for library files with names including the major, minor and sub version. -bool FindLibWithMajorMinorSubVersion(const char* versionPrefix, char* symbolName, char* symbolVersion) +static int FindLibWithMajorMinorSubVersion(const char* versionPrefix, char* symbolName, char* symbolVersion) { for (int i = MaxICUVersion; i >= MinICUVersion; i--) { @@ -222,17 +221,17 @@ bool FindLibWithMajorMinorSubVersion(const char* versionPrefix, char* symbolName { if (OpenICULibraries(i, j, k, versionPrefix, symbolName, symbolVersion)) { - return true; + return TRUE; } } } } - return false; + return FALSE; } -bool FindICULibs(const char* versionPrefix, char* symbolName, char* symbolVersion) +static int FindICULibs(const char* versionPrefix, char* symbolName, char* symbolVersion) { return FindLibUsingOverride(versionPrefix, symbolName, symbolVersion) || FindLibWithMajorVersion(versionPrefix, symbolName, symbolVersion) || @@ -257,7 +256,7 @@ int32_t GlobalizationNative_LoadICU() if (!FindICULibs(VERSION_PREFIX_SUSE, symbolName, symbolVersion)) #endif { - return 0; + return FALSE; } } @@ -276,7 +275,7 @@ int32_t GlobalizationNative_LoadICU() libicui18n = NULL; #endif // __APPLE__ - return 1; + return TRUE; } // GlobalizationNative_GetICUVersion diff --git a/src/corefx/System.Globalization.Native/pal_locale.c b/src/corefx/System.Globalization.Native/pal_locale.c index 6b9561122c6e..b7465df2768b 100644 --- a/src/corefx/System.Globalization.Native/pal_locale.c +++ b/src/corefx/System.Globalization.Native/pal_locale.c @@ -15,7 +15,7 @@ int32_t UErrorCodeToBool(UErrorCode status) { if (U_SUCCESS(status)) { - return 1; + return TRUE; } // assert errors that should never occur @@ -24,15 +24,23 @@ int32_t UErrorCodeToBool(UErrorCode status) // add possible SetLastError support here - return 0; + return FALSE; } -int32_t GetLocale( - const UChar* localeName, char* localeNameResult, int32_t localeNameResultLength, bool canonicalize, UErrorCode* err) +int32_t GetLocale(const UChar* localeName, + char* localeNameResult, + int32_t localeNameResultLength, + UBool canonicalize, + UErrorCode* err) { char localeNameTemp[ULOC_FULLNAME_CAPACITY] = {0}; int32_t localeLength; + if (U_FAILURE(*err)) + { + return 0; + } + // Convert ourselves instead of doing u_UCharsToChars as that function considers '@' a variant and stops. for (int i = 0; i < ULOC_FULLNAME_CAPACITY - 1; i++) { @@ -81,17 +89,21 @@ int32_t GetLocale( return localeLength; } -UErrorCode u_charsToUChars_safe(const char* str, UChar* value, int32_t valueLength) +void u_charsToUChars_safe(const char* str, UChar* value, int32_t valueLength, UErrorCode* err) { - int len = strlen(str); + if (U_FAILURE(*err)) + { + return; + } + int len = strlen(str); if (len >= valueLength) { - return U_BUFFER_OVERFLOW_ERROR; + *err = U_BUFFER_OVERFLOW_ERROR; + return; } u_charsToUChars(str, value, len + 1); - return U_ZERO_ERROR; } int32_t FixupLocaleName(UChar* value, int32_t valueLength) @@ -112,7 +124,7 @@ int32_t FixupLocaleName(UChar* value, int32_t valueLength) return i; } -bool IsEnvVarSet(const char* name) +static int IsEnvVarSet(const char* name) { const char* value = getenv(name); @@ -202,16 +214,12 @@ int32_t GlobalizationNative_GetLocaleName(const UChar* localeName, UChar* value, UErrorCode status = U_ZERO_ERROR; char localeNameBuffer[ULOC_FULLNAME_CAPACITY]; - GetLocale(localeName, localeNameBuffer, ULOC_FULLNAME_CAPACITY, true, &status); + GetLocale(localeName, localeNameBuffer, ULOC_FULLNAME_CAPACITY, TRUE, &status); + u_charsToUChars_safe(localeNameBuffer, value, valueLength, &status); if (U_SUCCESS(status)) { - status = u_charsToUChars_safe(localeNameBuffer, value, valueLength); - - if (U_SUCCESS(status)) - { - FixupLocaleName(value, valueLength); - } + FixupLocaleName(value, valueLength); } return UErrorCodeToBool(status); @@ -225,30 +233,22 @@ int32_t GlobalizationNative_GetDefaultLocaleName(UChar* value, int32_t valueLeng const char* defaultLocale = DetectDefaultLocaleName(); uloc_getBaseName(defaultLocale, localeNameBuffer, ULOC_FULLNAME_CAPACITY, &status); + u_charsToUChars_safe(localeNameBuffer, value, valueLength, &status); if (U_SUCCESS(status)) { - status = u_charsToUChars_safe(localeNameBuffer, value, valueLength); - - if (U_SUCCESS(status)) - { - int localeNameLen = FixupLocaleName(value, valueLength); + int localeNameLen = FixupLocaleName(value, valueLength); - char collationValueTemp[ULOC_KEYWORDS_CAPACITY]; - int32_t collationLen = - uloc_getKeywordValue(defaultLocale, "collation", collationValueTemp, ULOC_KEYWORDS_CAPACITY, &status); + char collationValueTemp[ULOC_KEYWORDS_CAPACITY]; + int32_t collationLen = + uloc_getKeywordValue(defaultLocale, "collation", collationValueTemp, ULOC_KEYWORDS_CAPACITY, &status); - if (U_SUCCESS(status) && collationLen > 0) - { - // copy the collation; managed uses a "_" to represent collation (not - // "@collation=") - status = u_charsToUChars_safe("_", &value[localeNameLen], valueLength - localeNameLen); - if (U_SUCCESS(status)) - { - status = u_charsToUChars_safe( - collationValueTemp, &value[localeNameLen + 1], valueLength - localeNameLen - 1); - } - } + if (U_SUCCESS(status) && collationLen > 0) + { + // copy the collation; managed uses a "_" to represent collation (not + // "@collation=") + u_charsToUChars_safe("_", &value[localeNameLen], valueLength - localeNameLen, &status); + u_charsToUChars_safe(collationValueTemp, &value[localeNameLen + 1], valueLength - localeNameLen - 1, &status); } } diff --git a/src/corefx/System.Globalization.Native/pal_locale.h b/src/corefx/System.Globalization.Native/pal_locale.h index ebd64468be34..134291e4d457 100644 --- a/src/corefx/System.Globalization.Native/pal_locale.h +++ b/src/corefx/System.Globalization.Native/pal_locale.h @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#include - #include "pal_icushim.h" /* @@ -24,7 +22,7 @@ Converts a managed localeName into something ICU understands and can use as a lo int32_t GetLocale(const UChar* localeName, char* localeNameResult, int32_t localeNameResultLength, - bool canonicalize, + UBool canonicalize, UErrorCode* err); /* @@ -33,7 +31,7 @@ u_charsToUChars_safe Copies the given null terminated char* to UChar with error checking. Replacement for ICU u_charsToUChars */ -UErrorCode u_charsToUChars_safe(const char* str, UChar* value, int32_t valueLength); +void u_charsToUChars_safe(const char* str, UChar* value, int32_t valueLength, UErrorCode* err); /* Function: @@ -42,7 +40,7 @@ FixupLocaleName Replace underscores with hyphens to interop with existing .NET code. Returns the length of the string. */ -int FixupLocaleName(UChar* value, int32_t valueLength); +int32_t FixupLocaleName(UChar* value, int32_t valueLength); /* Function: diff --git a/src/corefx/System.Globalization.Native/pal_localeNumberData.c b/src/corefx/System.Globalization.Native/pal_localeNumberData.c index 1a13b92f6b93..84af3ba49691 100644 --- a/src/corefx/System.Globalization.Native/pal_localeNumberData.c +++ b/src/corefx/System.Globalization.Native/pal_localeNumberData.c @@ -5,7 +5,6 @@ #include #include -#include #include #include "pal_localeNumberData.h" @@ -30,7 +29,7 @@ NormalizeNumericPattern Returns a numeric string pattern in a format that we can match against the appropriate managed pattern. */ -char* NormalizeNumericPattern(const UChar* srcPattern, bool isNegative) +static char* NormalizeNumericPattern(const UChar* srcPattern, int isNegative) { int iStart = 0; int iEnd = u_strlen(srcPattern); @@ -57,10 +56,10 @@ char* NormalizeNumericPattern(const UChar* srcPattern, bool isNegative) } int index = 0; - bool minusAdded = false; - bool digitAdded = false; - bool currencyAdded = false; - bool spaceAdded = false; + int minusAdded = FALSE; + int digitAdded = FALSE; + int currencyAdded = FALSE; + int spaceAdded = FALSE; for (int i = iStart; i <= iEnd; i++) { @@ -70,7 +69,7 @@ char* NormalizeNumericPattern(const UChar* srcPattern, bool isNegative) case UCHAR_MINUS: case UCHAR_OPENPAREN: case UCHAR_CLOSEPAREN: - minusAdded = true; + minusAdded = TRUE; break; } } @@ -104,7 +103,7 @@ char* NormalizeNumericPattern(const UChar* srcPattern, bool isNegative) case UCHAR_DIGIT: if (!digitAdded) { - digitAdded = true; + digitAdded = TRUE; destPattern[index++] = 'n'; } break; @@ -112,7 +111,7 @@ char* NormalizeNumericPattern(const UChar* srcPattern, bool isNegative) case UCHAR_CURRENCY: if (!currencyAdded) { - currencyAdded = true; + currencyAdded = TRUE; destPattern[index++] = 'C'; } break; @@ -121,19 +120,19 @@ char* NormalizeNumericPattern(const UChar* srcPattern, bool isNegative) case UCHAR_NBSPACE: if (!spaceAdded) { - spaceAdded = true; + spaceAdded = TRUE; destPattern[index++] = ' '; } else { - assert(false); + assert(FALSE); } break; case UCHAR_MINUS: case UCHAR_OPENPAREN: case UCHAR_CLOSEPAREN: - minusAdded = true; + minusAdded = TRUE; destPattern[index++] = (char)ch; break; @@ -154,13 +153,16 @@ Determines the pattern from the decimalFormat and returns the matching pattern's index from patterns[]. Returns index -1 if no pattern is found. */ -int GetNumericPattern(const UNumberFormat* pNumberFormat, const char* patterns[], int patternsCount, bool isNegative) +static int GetNumericPattern(const UNumberFormat* pNumberFormat, + const char* patterns[], + int patternsCount, + int isNegative) { const int INVALID_FORMAT = -1; const int MAX_DOTNET_NUMERIC_PATTERN_LENGTH = 6; // example: "(C n)" plus terminator UErrorCode ignore = U_ZERO_ERROR; - int32_t icuPatternLength = unum_toPattern(pNumberFormat, false, NULL, 0, &ignore) + 1; + int32_t icuPatternLength = unum_toPattern(pNumberFormat, FALSE, NULL, 0, &ignore) + 1; UChar* icuPattern = calloc(icuPatternLength, sizeof(UChar)); if (icuPattern == NULL) @@ -170,7 +172,7 @@ int GetNumericPattern(const UNumberFormat* pNumberFormat, const char* patterns[] UErrorCode err = U_ZERO_ERROR; - unum_toPattern(pNumberFormat, false, icuPattern, icuPatternLength, &err); + unum_toPattern(pNumberFormat, FALSE, icuPattern, icuPatternLength, &err); assert(U_SUCCESS(err)); @@ -196,9 +198,9 @@ int GetNumericPattern(const UNumberFormat* pNumberFormat, const char* patterns[] free(normalizedPattern); return i; } - }; + } - assert(false); // should have found a valid pattern + assert(FALSE); // should have found a valid pattern free(normalizedPattern); return INVALID_FORMAT; } @@ -210,7 +212,7 @@ GetCurrencyNegativePattern Implementation of NumberFormatInfo.CurrencyNegativePattern. Returns the pattern index. */ -int GetCurrencyNegativePattern(const char* locale) +static int GetCurrencyNegativePattern(const char* locale) { const int DEFAULT_VALUE = 0; static const char* Patterns[] = {"(Cn)", @@ -237,7 +239,7 @@ int GetCurrencyNegativePattern(const char* locale) if (U_SUCCESS(status)) { - int value = GetNumericPattern(pFormat, Patterns, ARRAY_LENGTH(Patterns), true); + int value = GetNumericPattern(pFormat, Patterns, ARRAY_LENGTH(Patterns), TRUE); if (value >= 0) { unum_close(pFormat); @@ -256,7 +258,7 @@ GetCurrencyPositivePattern Implementation of NumberFormatInfo.CurrencyPositivePattern. Returns the pattern index. */ -int GetCurrencyPositivePattern(const char* locale) +static int GetCurrencyPositivePattern(const char* locale) { const int DEFAULT_VALUE = 0; static const char* Patterns[] = {"Cn", "nC", "C n", "n C"}; @@ -268,7 +270,7 @@ int GetCurrencyPositivePattern(const char* locale) if (U_SUCCESS(status)) { - int value = GetNumericPattern(pFormat, Patterns, ARRAY_LENGTH(Patterns), false); + int value = GetNumericPattern(pFormat, Patterns, ARRAY_LENGTH(Patterns), FALSE); if (value >= 0) { unum_close(pFormat); @@ -287,7 +289,7 @@ GetNumberNegativePattern Implementation of NumberFormatInfo.NumberNegativePattern. Returns the pattern index. */ -int GetNumberNegativePattern(const char* locale) +static int GetNumberNegativePattern(const char* locale) { const int DEFAULT_VALUE = 1; static const char* Patterns[] = {"(n)", "-n", "- n", "n-", "n -"}; @@ -299,7 +301,7 @@ int GetNumberNegativePattern(const char* locale) if (U_SUCCESS(status)) { - int value = GetNumericPattern(pFormat, Patterns, ARRAY_LENGTH(Patterns), true); + int value = GetNumericPattern(pFormat, Patterns, ARRAY_LENGTH(Patterns), TRUE); if (value >= 0) { unum_close(pFormat); @@ -318,7 +320,7 @@ GetPercentNegativePattern Implementation of NumberFormatInfo.PercentNegativePattern. Returns the pattern index. */ -int GetPercentNegativePattern(const char* locale) +static int GetPercentNegativePattern(const char* locale) { const int DEFAULT_VALUE = 0; static const char* Patterns[] = { @@ -331,7 +333,7 @@ int GetPercentNegativePattern(const char* locale) if (U_SUCCESS(status)) { - int value = GetNumericPattern(pFormat, Patterns, ARRAY_LENGTH(Patterns), true); + int value = GetNumericPattern(pFormat, Patterns, ARRAY_LENGTH(Patterns), TRUE); if (value >= 0) { unum_close(pFormat); @@ -350,7 +352,7 @@ GetPercentPositivePattern Implementation of NumberFormatInfo.PercentPositivePattern. Returns the pattern index. */ -int GetPercentPositivePattern(const char* locale) +static int GetPercentPositivePattern(const char* locale) { const int DEFAULT_VALUE = 0; static const char* Patterns[] = {"n %", "n%", "%n", "% n"}; @@ -362,7 +364,7 @@ int GetPercentPositivePattern(const char* locale) if (U_SUCCESS(status)) { - int value = GetNumericPattern(pFormat, Patterns, ARRAY_LENGTH(Patterns), false); + int value = GetNumericPattern(pFormat, Patterns, ARRAY_LENGTH(Patterns), FALSE); if (value >= 0) { unum_close(pFormat); @@ -381,7 +383,7 @@ GetMeasurementSystem Obtains the measurement system for the local, determining if US or metric. Returns 1 for US, 0 otherwise. */ -UErrorCode GetMeasurementSystem(const char* locale, int32_t* value) +static UErrorCode GetMeasurementSystem(const char* locale, int32_t* value) { UErrorCode status = U_ZERO_ERROR; @@ -406,11 +408,11 @@ int32_t GlobalizationNative_GetLocaleInfoInt( { UErrorCode status = U_ZERO_ERROR; char locale[ULOC_FULLNAME_CAPACITY]; - GetLocale(localeName, locale, ULOC_FULLNAME_CAPACITY, false, &status); + GetLocale(localeName, locale, ULOC_FULLNAME_CAPACITY, FALSE, &status); if (U_FAILURE(status)) { - return UErrorCodeToBool(U_ILLEGAL_ARGUMENT_ERROR); + return FALSE; } switch (localeNumberData) @@ -513,7 +515,7 @@ int32_t GlobalizationNative_GetLocaleInfoInt( break; default: status = U_UNSUPPORTED_ERROR; - assert(false); + assert(FALSE); break; } @@ -532,7 +534,7 @@ int32_t GlobalizationNative_GetLocaleInfoGroupingSizes( { UErrorCode status = U_ZERO_ERROR; char locale[ULOC_FULLNAME_CAPACITY]; - GetLocale(localeName, locale, ULOC_FULLNAME_CAPACITY, false, &status); + GetLocale(localeName, locale, ULOC_FULLNAME_CAPACITY, FALSE, &status); if (U_FAILURE(status)) { diff --git a/src/corefx/System.Globalization.Native/pal_localeStringData.c b/src/corefx/System.Globalization.Native/pal_localeStringData.c index f8c9e8793797..97cc42acac25 100644 --- a/src/corefx/System.Globalization.Native/pal_localeStringData.c +++ b/src/corefx/System.Globalization.Native/pal_localeStringData.c @@ -15,8 +15,10 @@ GetLocaleInfoDecimalFormatSymbol Obtains the value of a DecimalFormatSymbols */ -UErrorCode -GetLocaleInfoDecimalFormatSymbol(const char* locale, UNumberFormatSymbol symbol, UChar* value, int32_t valueLength) +static UErrorCode GetLocaleInfoDecimalFormatSymbol(const char* locale, + UNumberFormatSymbol symbol, + UChar* value, + int32_t valueLength) { UErrorCode status = U_ZERO_ERROR; UNumberFormat* pFormat = unum_open(UNUM_DECIMAL, NULL, 0, locale, NULL, &status); @@ -31,12 +33,12 @@ GetDigitSymbol Obtains the value of a Digit DecimalFormatSymbols */ -UErrorCode GetDigitSymbol(const char* locale, - UErrorCode previousStatus, - UNumberFormatSymbol symbol, - int digit, - UChar* value, - int32_t valueLength) +static UErrorCode GetDigitSymbol(const char* locale, + UErrorCode previousStatus, + UNumberFormatSymbol symbol, + int digit, + UChar* value, + int32_t valueLength) { if (U_FAILURE(previousStatus)) { @@ -52,7 +54,10 @@ GetLocaleInfoAmPm Obtains the value of the AM or PM string for a locale. */ -UErrorCode GetLocaleInfoAmPm(const char* locale, bool am, UChar* value, int32_t valueLength) +static UErrorCode GetLocaleInfoAmPm(const char* locale, + int am, + UChar* value, + int32_t valueLength) { UErrorCode status = U_ZERO_ERROR; UDateFormat* pFormat = udat_open(UDAT_DEFAULT, UDAT_DEFAULT, locale, NULL, 0, NULL, 0, &status); @@ -67,27 +72,21 @@ GetLocaleIso639LanguageTwoLetterName Gets the language name for a locale (via uloc_getLanguage) and converts the result to UChars */ -UErrorCode GetLocaleIso639LanguageTwoLetterName(const char* locale, UChar* value, int32_t valueLength) +static UErrorCode GetLocaleIso639LanguageTwoLetterName(const char* locale, UChar* value, int32_t valueLength) { - UErrorCode status = U_ZERO_ERROR; - int32_t length = uloc_getLanguage(locale, NULL, 0, &status) + 1; + UErrorCode status = U_ZERO_ERROR, ignore = U_ZERO_ERROR; + int32_t length = uloc_getLanguage(locale, NULL, 0, &ignore) + 1; - assert(status == U_BUFFER_OVERFLOW_ERROR); char* buf = calloc(length, sizeof(char)); if (buf == NULL) { return U_MEMORY_ALLOCATION_ERROR; } - status = U_ZERO_ERROR; uloc_getLanguage(locale, buf, length, &status); - - if (U_SUCCESS(status)) - { - status = u_charsToUChars_safe(buf, value, valueLength); - } - + u_charsToUChars_safe(buf, value, valueLength, &status); free(buf); + return status; } @@ -97,15 +96,17 @@ GetLocaleIso639LanguageThreeLetterName Gets the language name for a locale (via uloc_getISO3Language) and converts the result to UChars */ -UErrorCode GetLocaleIso639LanguageThreeLetterName(const char* locale, UChar* value, int32_t valueLength) +static UErrorCode GetLocaleIso639LanguageThreeLetterName(const char* locale, UChar* value, int32_t valueLength) { + UErrorCode status = U_ZERO_ERROR; const char *isoLanguage = uloc_getISO3Language(locale); if (isoLanguage[0] == 0) { return U_ILLEGAL_ARGUMENT_ERROR; } - return u_charsToUChars_safe(isoLanguage, value, valueLength); + u_charsToUChars_safe(isoLanguage, value, valueLength, &status); + return status; } /* @@ -114,10 +115,10 @@ GetLocaleIso3166CountryName Gets the country name for a locale (via uloc_getCountry) and converts the result to UChars */ -UErrorCode GetLocaleIso3166CountryName(const char* locale, UChar* value, int32_t valueLength) +static UErrorCode GetLocaleIso3166CountryName(const char* locale, UChar* value, int32_t valueLength) { - UErrorCode status = U_ZERO_ERROR; - int32_t length = uloc_getCountry(locale, NULL, 0, &status) + 1; + UErrorCode status = U_ZERO_ERROR, ignore = U_ZERO_ERROR; + int32_t length = uloc_getCountry(locale, NULL, 0, &ignore) + 1; char* buf = calloc(length, sizeof(char)); if (buf == NULL) @@ -125,15 +126,8 @@ UErrorCode GetLocaleIso3166CountryName(const char* locale, UChar* value, int32_t return U_MEMORY_ALLOCATION_ERROR; } - status = U_ZERO_ERROR; - uloc_getCountry(locale, buf, length, &status); - - if (U_SUCCESS(status)) - { - status = u_charsToUChars_safe(buf, value, valueLength); - } - + u_charsToUChars_safe(buf, value, valueLength, &status); free(buf); return status; @@ -145,8 +139,9 @@ GetLocaleIso3166CountryCode Gets the 3 letter country code for a locale (via uloc_getISO3Country) and converts the result to UChars */ -UErrorCode GetLocaleIso3166CountryCode(const char* locale, UChar* value, int32_t valueLength) +static UErrorCode GetLocaleIso3166CountryCode(const char* locale, UChar* value, int32_t valueLength) { + UErrorCode status = U_ZERO_ERROR; const char *pIsoCountryName = uloc_getISO3Country(locale); int len = strlen(pIsoCountryName); @@ -155,7 +150,8 @@ UErrorCode GetLocaleIso3166CountryCode(const char* locale, UChar* value, int32_t return U_ILLEGAL_ARGUMENT_ERROR; } - return u_charsToUChars_safe(pIsoCountryName, value, valueLength); + u_charsToUChars_safe(pIsoCountryName, value, valueLength, &status); + return status; } /* @@ -164,7 +160,7 @@ GetLocaleCurrencyName Gets the locale currency English or native name and convert the result to UChars */ -UErrorCode GetLocaleCurrencyName(const char* locale, bool nativeName, UChar* value, int32_t valueLength) +static UErrorCode GetLocaleCurrencyName(const char* locale, UBool nativeName, UChar* value, int32_t valueLength) { UErrorCode status = U_ZERO_ERROR; @@ -193,9 +189,10 @@ UErrorCode GetLocaleCurrencyName(const char* locale, bool nativeName, UChar* val { return U_BUFFER_OVERFLOW_ERROR; } + u_strncpy(value, pCurrencyLongName, len); value[len] = 0; - + return status; } @@ -206,12 +203,14 @@ GetLocaleInfoString Obtains string locale information. Returns 1 for success, 0 otherwise */ -int32_t GlobalizationNative_GetLocaleInfoString( - const UChar* localeName, LocaleStringData localeStringData, UChar* value, int32_t valueLength) +int32_t GlobalizationNative_GetLocaleInfoString(const UChar* localeName, + LocaleStringData localeStringData, + UChar* value, + int32_t valueLength) { UErrorCode status = U_ZERO_ERROR; char locale[ULOC_FULLNAME_CAPACITY]; - GetLocale(localeName, locale, ULOC_FULLNAME_CAPACITY, false, &status); + GetLocale(localeName, locale, ULOC_FULLNAME_CAPACITY, FALSE, &status); if (U_FAILURE(status)) { @@ -269,10 +268,10 @@ int32_t GlobalizationNative_GetLocaleInfoString( status = GetLocaleInfoDecimalFormatSymbol(locale, UNUM_INTL_CURRENCY_SYMBOL, value, valueLength); break; case CurrencyEnglishName: - status = GetLocaleCurrencyName(locale, false, value, valueLength); + status = GetLocaleCurrencyName(locale, FALSE, value, valueLength); break; case CurrencyNativeName: - status = GetLocaleCurrencyName(locale, true, value, valueLength); + status = GetLocaleCurrencyName(locale, TRUE, value, valueLength); break; case MonetaryDecimalSeparator: status = GetLocaleInfoDecimalFormatSymbol(locale, UNUM_MONETARY_SEPARATOR_SYMBOL, value, valueLength); @@ -282,10 +281,10 @@ int32_t GlobalizationNative_GetLocaleInfoString( GetLocaleInfoDecimalFormatSymbol(locale, UNUM_MONETARY_GROUPING_SEPARATOR_SYMBOL, value, valueLength); break; case AMDesignator: - status = GetLocaleInfoAmPm(locale, true, value, valueLength); + status = GetLocaleInfoAmPm(locale, TRUE, value, valueLength); break; case PMDesignator: - status = GetLocaleInfoAmPm(locale, false, value, valueLength); + status = GetLocaleInfoAmPm(locale, FALSE, value, valueLength); break; case PositiveSign: status = GetLocaleInfoDecimalFormatSymbol(locale, UNUM_PLUS_SIGN_SYMBOL, value, valueLength); @@ -318,13 +317,10 @@ int32_t GlobalizationNative_GetLocaleInfoString( char localeNameTemp[ULOC_FULLNAME_CAPACITY]; uloc_getParent(locale, localeNameTemp, ULOC_FULLNAME_CAPACITY, &status); + u_charsToUChars_safe(localeNameTemp, value, valueLength, &status); if (U_SUCCESS(status)) { - status = u_charsToUChars_safe(localeNameTemp, value, valueLength); - if (U_SUCCESS(status)) - { - FixupLocaleName(value, valueLength); - } + FixupLocaleName(value, valueLength); } break; } @@ -349,15 +345,17 @@ GetLocaleTimeFormat Obtains time format information (in ICU format, it needs to be coverted to .NET Format). Returns 1 for success, 0 otherwise */ -int32_t GlobalizationNative_GetLocaleTimeFormat( - const UChar* localeName, int shortFormat, UChar* value, int32_t valueLength) +int32_t GlobalizationNative_GetLocaleTimeFormat(const UChar* localeName, + int shortFormat, + UChar* value, + int32_t valueLength) { UErrorCode err = U_ZERO_ERROR; char locale[ULOC_FULLNAME_CAPACITY]; - GetLocale(localeName, locale, ULOC_FULLNAME_CAPACITY, false, &err); + GetLocale(localeName, locale, ULOC_FULLNAME_CAPACITY, FALSE, &err); UDateFormatStyle style = (shortFormat != 0) ? UDAT_SHORT : UDAT_MEDIUM; UDateFormat* pFormat = udat_open(style, UDAT_NONE, locale, NULL, 0, NULL, 0, &err); - udat_toPattern(pFormat, false, value, valueLength, &err); + udat_toPattern(pFormat, FALSE, value, valueLength, &err); udat_close(pFormat); return UErrorCodeToBool(err); } diff --git a/src/corefx/System.Globalization.Native/pal_timeZoneInfo.c b/src/corefx/System.Globalization.Native/pal_timeZoneInfo.c index 1ea378b835dd..7ed2a2c3c369 100644 --- a/src/corefx/System.Globalization.Native/pal_timeZoneInfo.c +++ b/src/corefx/System.Globalization.Native/pal_timeZoneInfo.c @@ -11,12 +11,15 @@ /* Gets the localized display name for the specified time zone. */ -ResultCode GlobalizationNative_GetTimeZoneDisplayName( - const UChar* localeName, const UChar* timeZoneId, TimeZoneDisplayNameType type, UChar* result, int32_t resultLength) +ResultCode GlobalizationNative_GetTimeZoneDisplayName(const UChar* localeName, + const UChar* timeZoneId, + TimeZoneDisplayNameType type, + UChar* result, + int32_t resultLength) { UErrorCode err = U_ZERO_ERROR; char locale[ULOC_FULLNAME_CAPACITY]; - GetLocale(localeName, locale, ULOC_FULLNAME_CAPACITY, false, &err); + GetLocale(localeName, locale, ULOC_FULLNAME_CAPACITY, FALSE, &err); int32_t timeZoneIdLength = -1; // timeZoneId is NULL-terminated UCalendar* calendar = ucal_open(timeZoneId, timeZoneIdLength, locale, UCAL_DEFAULT, &err); From 772b2da3a105a08e133e3b50342b47fe1b4ba047 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Sun, 3 Feb 2019 10:59:55 +0100 Subject: [PATCH 14/14] Prefix enums, remove DLLEXPORT from GetResultCode Move SortHandle out of public API header, it is opaque structure --- .../pal_calendarData.c | 28 ++++----- .../pal_calendarData.h | 30 ++++----- .../pal_collation.c | 17 ++++- .../pal_collation.h | 15 +---- .../System.Globalization.Native/pal_errors.h | 2 +- .../pal_localeNumberData.c | 34 +++++----- .../pal_localeNumberData.h | 34 +++++----- .../pal_localeStringData.c | 62 +++++++++---------- .../pal_localeStringData.h | 62 +++++++++---------- .../pal_timeZoneInfo.c | 7 ++- .../pal_timeZoneInfo.h | 6 +- 11 files changed, 152 insertions(+), 145 deletions(-) diff --git a/src/corefx/System.Globalization.Native/pal_calendarData.c b/src/corefx/System.Globalization.Native/pal_calendarData.c index 307d0780f814..be0cc9b6b8b7 100644 --- a/src/corefx/System.Globalization.Native/pal_calendarData.c +++ b/src/corefx/System.Globalization.Native/pal_calendarData.c @@ -193,9 +193,9 @@ ResultCode GlobalizationNative_GetCalendarInfo( switch (dataType) { - case NativeName: + case CalendarData_NativeName: return GetNativeCalendarName(locale, calendarId, result, resultCapacity); - case MonthDay: + case CalendarData_MonthDay: return GetMonthDayPattern(locale, result, resultCapacity); default: assert(FALSE); @@ -488,27 +488,27 @@ int32_t GlobalizationNative_EnumCalendarInfo(EnumCalendarInfoCallback callback, switch (dataType) { - case ShortDates: + case CalendarData_ShortDates: // ShortDates to map kShort and kMedium in ICU, but also adding the "yMd" // skeleton as well, as this closely matches what is used on Windows return InvokeCallbackForDatePattern(locale, UDAT_SHORT, callback, context) && InvokeCallbackForDatePattern(locale, UDAT_MEDIUM, callback, context) && InvokeCallbackForDateTimePattern(locale, UDAT_YEAR_NUM_MONTH_DAY_UCHAR, callback, context); - case LongDates: + case CalendarData_LongDates: // LongDates map to kFull and kLong in ICU. return InvokeCallbackForDatePattern(locale, UDAT_FULL, callback, context) && InvokeCallbackForDatePattern(locale, UDAT_LONG, callback, context); - case YearMonths: + case CalendarData_YearMonths: return InvokeCallbackForDateTimePattern(locale, UDAT_YEAR_MONTH_UCHAR, callback, context); - case DayNames: + case CalendarData_DayNames: return EnumSymbols(locale, calendarId, UDAT_STANDALONE_WEEKDAYS, 1, callback, context); - case AbbrevDayNames: + case CalendarData_AbbrevDayNames: return EnumSymbols(locale, calendarId, UDAT_STANDALONE_SHORT_WEEKDAYS, 1, callback, context); - case MonthNames: + case CalendarData_MonthNames: return EnumSymbols(locale, calendarId, UDAT_STANDALONE_MONTHS, 0, callback, context); - case AbbrevMonthNames: + case CalendarData_AbbrevMonthNames: return EnumSymbols(locale, calendarId, UDAT_STANDALONE_SHORT_MONTHS, 0, callback, context); - case SuperShortDayNames: + case CalendarData_SuperShortDayNames: // UDAT_STANDALONE_SHORTER_WEEKDAYS was added in ICU 51, and CentOS 7 currently uses ICU 50. // fallback to UDAT_STANDALONE_NARROW_WEEKDAYS in that case. #if HAVE_UDAT_STANDALONE_SHORTER_WEEKDAYS @@ -516,13 +516,13 @@ int32_t GlobalizationNative_EnumCalendarInfo(EnumCalendarInfoCallback callback, #else return EnumSymbols(locale, calendarId, UDAT_STANDALONE_NARROW_WEEKDAYS, 1, callback, context); #endif - case MonthGenitiveNames: + case CalendarData_MonthGenitiveNames: return EnumSymbols(locale, calendarId, UDAT_MONTHS, 0, callback, context); - case AbbrevMonthGenitiveNames: + case CalendarData_AbbrevMonthGenitiveNames: return EnumSymbols(locale, calendarId, UDAT_SHORT_MONTHS, 0, callback, context); - case EraNames: + case CalendarData_EraNames: return EnumSymbols(locale, calendarId, UDAT_ERAS, 0, callback, context); - case AbbrevEraNames: + case CalendarData_AbbrevEraNames: return EnumAbbrevEraNames(locale, calendarId, callback, context); default: assert(FALSE); diff --git a/src/corefx/System.Globalization.Native/pal_calendarData.h b/src/corefx/System.Globalization.Native/pal_calendarData.h index 394c6129f8d7..e0d5ac5f4672 100644 --- a/src/corefx/System.Globalization.Native/pal_calendarData.h +++ b/src/corefx/System.Globalization.Native/pal_calendarData.h @@ -48,21 +48,21 @@ typedef uint16_t CalendarId; */ typedef enum { - Uninitialized = 0, - NativeName = 1, - MonthDay = 2, - ShortDates = 3, - LongDates = 4, - YearMonths = 5, - DayNames = 6, - AbbrevDayNames = 7, - MonthNames = 8, - AbbrevMonthNames = 9, - SuperShortDayNames = 10, - MonthGenitiveNames = 11, - AbbrevMonthGenitiveNames = 12, - EraNames = 13, - AbbrevEraNames = 14, + CalendarData_Uninitialized = 0, + CalendarData_NativeName = 1, + CalendarData_MonthDay = 2, + CalendarData_ShortDates = 3, + CalendarData_LongDates = 4, + CalendarData_YearMonths = 5, + CalendarData_DayNames = 6, + CalendarData_AbbrevDayNames = 7, + CalendarData_MonthNames = 8, + CalendarData_AbbrevMonthNames = 9, + CalendarData_SuperShortDayNames = 10, + CalendarData_MonthGenitiveNames = 11, + CalendarData_AbbrevMonthGenitiveNames = 12, + CalendarData_EraNames = 13, + CalendarData_AbbrevEraNames = 14, } CalendarDataType; // the function pointer definition for the callback used in EnumCalendarInfo diff --git a/src/corefx/System.Globalization.Native/pal_collation.c b/src/corefx/System.Globalization.Native/pal_collation.c index a56aa09cc557..a0ce96d1fd4b 100644 --- a/src/corefx/System.Globalization.Native/pal_collation.c +++ b/src/corefx/System.Globalization.Native/pal_collation.c @@ -32,9 +32,24 @@ const int32_t CompareOptionsIgnoreWidth = 0x10; // change ICU's default behavior here isn't really justified unless someone has a strong reason // for !StringSort to behave differently. +typedef struct { int32_t key; UCollator* UCollator; } TCollatorMap; + +/* + * For increased performance, we cache the UCollator objects for a locale and + * share them across threads. This is safe (and supported in ICU) if we ensure + * multiple threads are only ever dealing with const UCollators. + */ +struct SortHandle +{ + UCollator* regular; + TCollatorMap* collatorsPerOption; + pthread_mutex_t collatorsLockObject; + void* pRoot; +}; + typedef struct { UChar* items; size_t capacity; size_t size; } UCharList; -int TreeComparer(const void* left, const void* right) +static int TreeComparer(const void* left, const void* right) { const TCollatorMap* leftMap = left; const TCollatorMap* rightMap = right; diff --git a/src/corefx/System.Globalization.Native/pal_collation.h b/src/corefx/System.Globalization.Native/pal_collation.h index 9c3b4c2a59ba..482a59a7eca2 100644 --- a/src/corefx/System.Globalization.Native/pal_collation.h +++ b/src/corefx/System.Globalization.Native/pal_collation.h @@ -6,20 +6,7 @@ #include "pal_locale.h" #include "pal_errors.h" -typedef struct { int32_t key; UCollator* UCollator; } TCollatorMap; - -/* - * For increased performance, we cache the UCollator objects for a locale and - * share them across threads. This is safe (and supported in ICU) if we ensure - * multiple threads are only ever dealing with const UCollators. - */ -typedef struct -{ - UCollator* regular; - TCollatorMap* collatorsPerOption; - pthread_mutex_t collatorsLockObject; - void* pRoot; -} SortHandle; +typedef struct SortHandle SortHandle; DLLEXPORT ResultCode GlobalizationNative_GetSortHandle(const char* lpLocaleName, SortHandle** ppSortHandle); diff --git a/src/corefx/System.Globalization.Native/pal_errors.h b/src/corefx/System.Globalization.Native/pal_errors.h index bed61668c5da..55d9ca026b94 100644 --- a/src/corefx/System.Globalization.Native/pal_errors.h +++ b/src/corefx/System.Globalization.Native/pal_errors.h @@ -21,7 +21,7 @@ typedef enum /* Converts a UErrorCode to a ResultCode. */ -DLLEXPORT static ResultCode GetResultCode(UErrorCode err) +static ResultCode GetResultCode(UErrorCode err) { if (err == U_BUFFER_OVERFLOW_ERROR || err == U_STRING_NOT_TERMINATED_WARNING) { diff --git a/src/corefx/System.Globalization.Native/pal_localeNumberData.c b/src/corefx/System.Globalization.Native/pal_localeNumberData.c index 84af3ba49691..5663c63d8251 100644 --- a/src/corefx/System.Globalization.Native/pal_localeNumberData.c +++ b/src/corefx/System.Globalization.Native/pal_localeNumberData.c @@ -417,13 +417,13 @@ int32_t GlobalizationNative_GetLocaleInfoInt( switch (localeNumberData) { - case LanguageId: + case LocaleNumber_LanguageId: *value = uloc_getLCID(locale); break; - case MeasurementSystem: + case LocaleNumber_MeasurementSystem: status = GetMeasurementSystem(locale, value); break; - case FractionalDigitsCount: + case LocaleNumber_FractionalDigitsCount: { UNumberFormat* numformat = unum_open(UNUM_DECIMAL, NULL, 0, locale, NULL, &status); if (U_SUCCESS(status)) @@ -433,10 +433,10 @@ int32_t GlobalizationNative_GetLocaleInfoInt( } break; } - case NegativeNumberFormat: + case LocaleNumber_NegativeNumberFormat: *value = GetNumberNegativePattern(locale); break; - case MonetaryFractionalDigitsCount: + case LocaleNumber_MonetaryFractionalDigitsCount: { UNumberFormat* numformat = unum_open(UNUM_CURRENCY, NULL, 0, locale, NULL, &status); if (U_SUCCESS(status)) @@ -446,13 +446,13 @@ int32_t GlobalizationNative_GetLocaleInfoInt( } break; } - case PositiveMonetaryNumberFormat: + case LocaleNumber_PositiveMonetaryNumberFormat: *value = GetCurrencyPositivePattern(locale); break; - case NegativeMonetaryNumberFormat: + case LocaleNumber_NegativeMonetaryNumberFormat: *value = GetCurrencyNegativePattern(locale); break; - case FirstWeekOfYear: + case LocaleNumber_FirstWeekOfYear: { // corresponds to DateTimeFormat.CalendarWeekRule UCalendar* pCal = ucal_open(NULL, 0, locale, UCAL_TRADITIONAL, &status); @@ -463,15 +463,15 @@ int32_t GlobalizationNative_GetLocaleInfoInt( int minDaysInWeek = ucal_getAttribute(pCal, UCAL_MINIMAL_DAYS_IN_FIRST_WEEK); if (minDaysInWeek == 1) { - *value = FirstDay; + *value = WeekRule_FirstDay; } else if (minDaysInWeek == 7) { - *value = FirstFullWeek; + *value = WeekRule_FirstFullWeek; } else if (minDaysInWeek >= 4) { - *value = FirstFourDayWeek; + *value = WeekRule_FirstFourDayWeek; } else { @@ -481,7 +481,7 @@ int32_t GlobalizationNative_GetLocaleInfoInt( ucal_close(pCal); break; } - case ReadingLayout: + case LocaleNumber_ReadingLayout: { // coresponds to values 0 and 1 in LOCALE_IREADINGLAYOUT (values 2 and 3 not // used in coreclr) @@ -496,7 +496,7 @@ int32_t GlobalizationNative_GetLocaleInfoInt( } break; } - case FirstDayofWeek: + case LocaleNumber_FirstDayofWeek: { UCalendar* pCal = ucal_open(NULL, 0, locale, UCAL_TRADITIONAL, &status); @@ -507,10 +507,10 @@ int32_t GlobalizationNative_GetLocaleInfoInt( ucal_close(pCal); break; } - case NegativePercentFormat: + case LocaleNumber_NegativePercentFormat: *value = GetPercentNegativePattern(locale); break; - case PositivePercentFormat: + case LocaleNumber_PositivePercentFormat: *value = GetPercentPositivePattern(locale); break; default: @@ -544,10 +544,10 @@ int32_t GlobalizationNative_GetLocaleInfoGroupingSizes( UNumberFormatStyle style; switch (localeGroupingData) { - case Digit: + case LocaleNumber_Digit: style = UNUM_DECIMAL; break; - case Monetary: + case LocaleNumber_Monetary: style = UNUM_CURRENCY; break; default: diff --git a/src/corefx/System.Globalization.Native/pal_localeNumberData.h b/src/corefx/System.Globalization.Native/pal_localeNumberData.h index 670c4245551c..32eb3fd8a079 100644 --- a/src/corefx/System.Globalization.Native/pal_localeNumberData.h +++ b/src/corefx/System.Globalization.Native/pal_localeNumberData.h @@ -10,28 +10,28 @@ // The numeric values of the enum members match their Win32 counterparts. typedef enum { - LanguageId = 0x01, - MeasurementSystem = 0x0D, - FractionalDigitsCount = 0x00000011, - NegativeNumberFormat = 0x00001010, - MonetaryFractionalDigitsCount = 0x00000019, - PositiveMonetaryNumberFormat = 0x0000001B, - NegativeMonetaryNumberFormat = 0x0000001C, - FirstDayofWeek = 0x0000100C, - FirstWeekOfYear = 0x0000100D, - ReadingLayout = 0x00000070, - NegativePercentFormat = 0x00000074, - PositivePercentFormat = 0x00000075, - Digit = 0x00000010, - Monetary = 0x00000018 + LocaleNumber_LanguageId = 0x01, + LocaleNumber_MeasurementSystem = 0x0D, + LocaleNumber_FractionalDigitsCount = 0x00000011, + LocaleNumber_NegativeNumberFormat = 0x00001010, + LocaleNumber_MonetaryFractionalDigitsCount = 0x00000019, + LocaleNumber_PositiveMonetaryNumberFormat = 0x0000001B, + LocaleNumber_NegativeMonetaryNumberFormat = 0x0000001C, + LocaleNumber_FirstDayofWeek = 0x0000100C, + LocaleNumber_FirstWeekOfYear = 0x0000100D, + LocaleNumber_ReadingLayout = 0x00000070, + LocaleNumber_NegativePercentFormat = 0x00000074, + LocaleNumber_PositivePercentFormat = 0x00000075, + LocaleNumber_Digit = 0x00000010, + LocaleNumber_Monetary = 0x00000018 } LocaleNumberData; // Enum that corresponds to managed enum System.Globalization.CalendarWeekRule typedef enum { - FirstDay = 0, - FirstFullWeek = 1, - FirstFourDayWeek = 2 + WeekRule_FirstDay = 0, + WeekRule_FirstFullWeek = 1, + WeekRule_FirstFourDayWeek = 2 } CalendarWeekRule; DLLEXPORT int32_t GlobalizationNative_GetLocaleInfoInt(const UChar* localeName, diff --git a/src/corefx/System.Globalization.Native/pal_localeStringData.c b/src/corefx/System.Globalization.Native/pal_localeStringData.c index 97cc42acac25..a989b57f7946 100644 --- a/src/corefx/System.Globalization.Native/pal_localeStringData.c +++ b/src/corefx/System.Globalization.Native/pal_localeStringData.c @@ -219,39 +219,39 @@ int32_t GlobalizationNative_GetLocaleInfoString(const UChar* localeName, switch (localeStringData) { - case LocalizedDisplayName: + case LocaleString_LocalizedDisplayName: uloc_getDisplayName(locale, DetectDefaultLocaleName(), value, valueLength, &status); break; - case EnglishDisplayName: + case LocaleString_EnglishDisplayName: uloc_getDisplayName(locale, ULOC_ENGLISH, value, valueLength, &status); break; - case NativeDisplayName: + case LocaleString_NativeDisplayName: uloc_getDisplayName(locale, locale, value, valueLength, &status); break; - case LocalizedLanguageName: + case LocaleString_LocalizedLanguageName: uloc_getDisplayLanguage(locale, DetectDefaultLocaleName(), value, valueLength, &status); break; - case EnglishLanguageName: + case LocaleString_EnglishLanguageName: uloc_getDisplayLanguage(locale, ULOC_ENGLISH, value, valueLength, &status); break; - case NativeLanguageName: + case LocaleString_NativeLanguageName: uloc_getDisplayLanguage(locale, locale, value, valueLength, &status); break; - case EnglishCountryName: + case LocaleString_EnglishCountryName: uloc_getDisplayCountry(locale, ULOC_ENGLISH, value, valueLength, &status); break; - case NativeCountryName: + case LocaleString_NativeCountryName: uloc_getDisplayCountry(locale, locale, value, valueLength, &status); break; - case ListSeparator: + case LocaleString_ListSeparator: // fall through - case ThousandSeparator: + case LocaleString_ThousandSeparator: status = GetLocaleInfoDecimalFormatSymbol(locale, UNUM_GROUPING_SEPARATOR_SYMBOL, value, valueLength); break; - case DecimalSeparator: + case LocaleString_DecimalSeparator: status = GetLocaleInfoDecimalFormatSymbol(locale, UNUM_DECIMAL_SEPARATOR_SYMBOL, value, valueLength); break; - case Digits: + case LocaleString_Digits: status = GetDigitSymbol(locale, status, UNUM_ZERO_DIGIT_SYMBOL, 0, value, valueLength); // symbols UNUM_ONE_DIGIT to UNUM_NINE_DIGIT are contiguous for (int32_t symbol = UNUM_ONE_DIGIT_SYMBOL; symbol <= UNUM_NINE_DIGIT_SYMBOL; symbol++) @@ -261,56 +261,56 @@ int32_t GlobalizationNative_GetLocaleInfoString(const UChar* localeName, locale, status, (UNumberFormatSymbol)symbol, charIndex, value, valueLength); } break; - case MonetarySymbol: + case LocaleString_MonetarySymbol: status = GetLocaleInfoDecimalFormatSymbol(locale, UNUM_CURRENCY_SYMBOL, value, valueLength); break; - case Iso4217MonetarySymbol: + case LocaleString_Iso4217MonetarySymbol: status = GetLocaleInfoDecimalFormatSymbol(locale, UNUM_INTL_CURRENCY_SYMBOL, value, valueLength); break; - case CurrencyEnglishName: + case LocaleString_CurrencyEnglishName: status = GetLocaleCurrencyName(locale, FALSE, value, valueLength); break; - case CurrencyNativeName: + case LocaleString_CurrencyNativeName: status = GetLocaleCurrencyName(locale, TRUE, value, valueLength); break; - case MonetaryDecimalSeparator: + case LocaleString_MonetaryDecimalSeparator: status = GetLocaleInfoDecimalFormatSymbol(locale, UNUM_MONETARY_SEPARATOR_SYMBOL, value, valueLength); break; - case MonetaryThousandSeparator: + case LocaleString_MonetaryThousandSeparator: status = GetLocaleInfoDecimalFormatSymbol(locale, UNUM_MONETARY_GROUPING_SEPARATOR_SYMBOL, value, valueLength); break; - case AMDesignator: + case LocaleString_AMDesignator: status = GetLocaleInfoAmPm(locale, TRUE, value, valueLength); break; - case PMDesignator: + case LocaleString_PMDesignator: status = GetLocaleInfoAmPm(locale, FALSE, value, valueLength); break; - case PositiveSign: + case LocaleString_PositiveSign: status = GetLocaleInfoDecimalFormatSymbol(locale, UNUM_PLUS_SIGN_SYMBOL, value, valueLength); break; - case NegativeSign: + case LocaleString_NegativeSign: status = GetLocaleInfoDecimalFormatSymbol(locale, UNUM_MINUS_SIGN_SYMBOL, value, valueLength); break; - case Iso639LanguageTwoLetterName: + case LocaleString_Iso639LanguageTwoLetterName: status = GetLocaleIso639LanguageTwoLetterName(locale, value, valueLength); break; - case Iso639LanguageThreeLetterName: + case LocaleString_Iso639LanguageThreeLetterName: status = GetLocaleIso639LanguageThreeLetterName(locale, value, valueLength); break; - case Iso3166CountryName: + case LocaleString_Iso3166CountryName: status = GetLocaleIso3166CountryName(locale, value, valueLength); break; - case Iso3166CountryName2: + case LocaleString_Iso3166CountryName2: status = GetLocaleIso3166CountryCode(locale, value, valueLength); break; - case NaNSymbol: + case LocaleString_NaNSymbol: status = GetLocaleInfoDecimalFormatSymbol(locale, UNUM_NAN_SYMBOL, value, valueLength); break; - case PositiveInfinitySymbol: + case LocaleString_PositiveInfinitySymbol: status = GetLocaleInfoDecimalFormatSymbol(locale, UNUM_INFINITY_SYMBOL, value, valueLength); break; - case ParentName: + case LocaleString_ParentName: { // ICU supports lang[-script][-region][-variant] so up to 4 parents // including invariant locale @@ -324,10 +324,10 @@ int32_t GlobalizationNative_GetLocaleInfoString(const UChar* localeName, } break; } - case PercentSymbol: + case LocaleString_PercentSymbol: status = GetLocaleInfoDecimalFormatSymbol(locale, UNUM_PERCENT_SYMBOL, value, valueLength); break; - case PerMilleSymbol: + case LocaleString_PerMilleSymbol: status = GetLocaleInfoDecimalFormatSymbol(locale, UNUM_PERMILL_SYMBOL, value, valueLength); break; default: diff --git a/src/corefx/System.Globalization.Native/pal_localeStringData.h b/src/corefx/System.Globalization.Native/pal_localeStringData.h index cb6a7b3af58a..58894284f1ec 100644 --- a/src/corefx/System.Globalization.Native/pal_localeStringData.h +++ b/src/corefx/System.Globalization.Native/pal_localeStringData.h @@ -10,37 +10,37 @@ // The numeric values of the enum members match their Win32 counterparts. typedef enum { - LocalizedDisplayName = 0x02, - EnglishDisplayName = 0x00000072, - NativeDisplayName = 0x00000073, - LocalizedLanguageName = 0x0000006f, - EnglishLanguageName = 0x00001001, - NativeLanguageName = 0x04, - EnglishCountryName = 0x00001002, - NativeCountryName = 0x08, - ListSeparator = 0x0C, - DecimalSeparator = 0x0E, - ThousandSeparator = 0x0F, - Digits = 0x00000013, - MonetarySymbol = 0x00000014, - CurrencyEnglishName = 0x00001007, - CurrencyNativeName = 0x00001008, - Iso4217MonetarySymbol = 0x00000015, - MonetaryDecimalSeparator = 0x00000016, - MonetaryThousandSeparator = 0x00000017, - AMDesignator = 0x00000028, - PMDesignator = 0x00000029, - PositiveSign = 0x00000050, - NegativeSign = 0x00000051, - Iso639LanguageTwoLetterName = 0x00000059, - Iso639LanguageThreeLetterName = 0x00000067, - Iso3166CountryName = 0x0000005A, - Iso3166CountryName2= 0x00000068, - NaNSymbol = 0x00000069, - PositiveInfinitySymbol = 0x0000006a, - ParentName = 0x0000006d, - PercentSymbol = 0x00000076, - PerMilleSymbol = 0x00000077 + LocaleString_LocalizedDisplayName = 0x02, + LocaleString_EnglishDisplayName = 0x00000072, + LocaleString_NativeDisplayName = 0x00000073, + LocaleString_LocalizedLanguageName = 0x0000006f, + LocaleString_EnglishLanguageName = 0x00001001, + LocaleString_NativeLanguageName = 0x04, + LocaleString_EnglishCountryName = 0x00001002, + LocaleString_NativeCountryName = 0x08, + LocaleString_ListSeparator = 0x0C, + LocaleString_DecimalSeparator = 0x0E, + LocaleString_ThousandSeparator = 0x0F, + LocaleString_Digits = 0x00000013, + LocaleString_MonetarySymbol = 0x00000014, + LocaleString_CurrencyEnglishName = 0x00001007, + LocaleString_CurrencyNativeName = 0x00001008, + LocaleString_Iso4217MonetarySymbol = 0x00000015, + LocaleString_MonetaryDecimalSeparator = 0x00000016, + LocaleString_MonetaryThousandSeparator = 0x00000017, + LocaleString_AMDesignator = 0x00000028, + LocaleString_PMDesignator = 0x00000029, + LocaleString_PositiveSign = 0x00000050, + LocaleString_NegativeSign = 0x00000051, + LocaleString_Iso639LanguageTwoLetterName = 0x00000059, + LocaleString_Iso639LanguageThreeLetterName = 0x00000067, + LocaleString_Iso3166CountryName = 0x0000005A, + LocaleString_Iso3166CountryName2= 0x00000068, + LocaleString_NaNSymbol = 0x00000069, + LocaleString_PositiveInfinitySymbol = 0x0000006a, + LocaleString_ParentName = 0x0000006d, + LocaleString_PercentSymbol = 0x00000076, + LocaleString_PerMilleSymbol = 0x00000077 } LocaleStringData; DLLEXPORT int32_t GlobalizationNative_GetLocaleInfoString(const UChar* localeName, diff --git a/src/corefx/System.Globalization.Native/pal_timeZoneInfo.c b/src/corefx/System.Globalization.Native/pal_timeZoneInfo.c index 7ed2a2c3c369..bf2a9dca0f2c 100644 --- a/src/corefx/System.Globalization.Native/pal_timeZoneInfo.c +++ b/src/corefx/System.Globalization.Native/pal_timeZoneInfo.c @@ -28,7 +28,12 @@ ResultCode GlobalizationNative_GetTimeZoneDisplayName(const UChar* localeName, // has no public option for this. For now, just use the ICU standard name for both Standard and Generic // (which is the same behavior on Windows with the mincore TIME_ZONE_INFORMATION APIs). ucal_getTimeZoneDisplayName( - calendar, type == DaylightSavings ? UCAL_DST : UCAL_STANDARD, locale, result, resultLength, &err); + calendar, + type == TimeZoneDisplayName_DaylightSavings ? UCAL_DST : UCAL_STANDARD, + locale, + result, + resultLength, + &err); ucal_close(calendar); return GetResultCode(err); diff --git a/src/corefx/System.Globalization.Native/pal_timeZoneInfo.h b/src/corefx/System.Globalization.Native/pal_timeZoneInfo.h index bee24eb72882..1c030ca0c3cb 100644 --- a/src/corefx/System.Globalization.Native/pal_timeZoneInfo.h +++ b/src/corefx/System.Globalization.Native/pal_timeZoneInfo.h @@ -12,9 +12,9 @@ These values should be kept in sync with the managed Interop.GlobalizationIntero */ typedef enum { - Generic = 0, - Standard = 1, - DaylightSavings = 2, + TimeZoneDisplayName_Generic = 0, + TimeZoneDisplayName_Standard = 1, + TimeZoneDisplayName_DaylightSavings = 2, } TimeZoneDisplayNameType; DLLEXPORT ResultCode GlobalizationNative_GetTimeZoneDisplayName(const UChar* localeName,