Skip to content

Commit

Permalink
Change compile time dependency of ICU API ucol_setMaxVariable to be r…
Browse files Browse the repository at this point in the history
…untime instead. (#58485)

* Change compile time dependency of ICU API ucol_setMaxVariable to be runtime instead.

* Fix Android Build Break
  • Loading branch information
tarekgh authored Sep 2, 2021
1 parent 1dd8a59 commit af4bb8b
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,25 @@ static UCollator* CloneCollatorWithOptions(const UCollator* pCollator, int32_t o
{
ucol_setAttribute(pClonedCollator, UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED, pErr);

#if !defined(STATIC_ICU)
if (ucol_setMaxVariable_ptr != NULL)
{
// by default, ICU alternate shifted handling only ignores punctuation, but
// IgnoreSymbols needs symbols and currency as well, so change the "variable top"
// to include all symbols and currency
ucol_setMaxVariable(pClonedCollator, UCOL_REORDER_CODE_CURRENCY, pErr);
}
else
{
assert(ucol_setVariableTop_ptr != NULL);
// 0xfdfc is the last currency character before the first digit character
// in http://source.icu-project.org/repos/icu/icu/tags/release-52-1/source/data/unidata/FractionalUCA.txt
const UChar ignoreSymbolsVariableTop[] = { 0xfdfc };
ucol_setVariableTop_ptr(pClonedCollator, ignoreSymbolsVariableTop, 1, pErr);
}

#else // !defined(STATIC_ICU)

// by default, ICU alternate shifted handling only ignores punctuation, but
// IgnoreSymbols needs symbols and currency as well, so change the "variable top"
// to include all symbols and currency
Expand All @@ -376,6 +395,8 @@ static UCollator* CloneCollatorWithOptions(const UCollator* pCollator, int32_t o
const UChar ignoreSymbolsVariableTop[] = { 0xfdfc };
ucol_setVariableTop(pClonedCollator, ignoreSymbolsVariableTop, 1, pErr);
#endif

#endif //!defined(STATIC_ICU)
}

ucol_setAttribute(pClonedCollator, UCOL_STRENGTH, strength, pErr);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ FOR_ALL_ICU_FUNCTIONS

static void* libicuuc = NULL;
static void* libicui18n = NULL;
ucol_setVariableTop_func ucol_setVariableTop_ptr = NULL;

#if defined (TARGET_UNIX)

Expand Down Expand Up @@ -380,6 +381,34 @@ static void ValidateICUDataCanLoad()
}
}

static void InitializeVariableMaxAndTopPointers(char* symbolVersion)
{
if (ucol_setMaxVariable_ptr != NULL)
{
return;
}

#if defined(TARGET_OSX) || defined(TARGET_ANDROID)
// OSX and Android always run against ICU version which has ucol_setMaxVariable.
// We shouldn't come here.
assert(false);
#elif defined(TARGET_WINDOWS)
char symbolName[SYMBOL_NAME_SIZE];
sprintf_s(symbolName, SYMBOL_NAME_SIZE, "ucol_setVariableTop%s", symbolVersion);
ucol_setVariableTop_ptr = (ucol_setVariableTop_func)GetProcAddress((HMODULE)libicui18n, symbolName);
#else
char symbolName[SYMBOL_NAME_SIZE];
sprintf(symbolName, "ucol_setVariableTop%s", symbolVersion);
ucol_setVariableTop_ptr = (ucol_setVariableTop_func)dlsym(libicui18n, symbolName);
#endif // defined(TARGET_OSX) || defined(TARGET_ANDROID)

if (ucol_setVariableTop_ptr == NULL)
{
fprintf(stderr, "Cannot get the symbols of ICU APIs ucol_setMaxVariable or ucol_setVariableTop.\n");
abort();
}
}

// GlobalizationNative_LoadICU
// 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
Expand Down Expand Up @@ -413,6 +442,9 @@ int32_t GlobalizationNative_LoadICU()

FOR_ALL_ICU_FUNCTIONS
ValidateICUDataCanLoad();

InitializeVariableMaxAndTopPointers(symbolVersion);

return true;
}

Expand Down Expand Up @@ -466,6 +498,8 @@ void GlobalizationNative_InitICUFunctions(void* icuuc, void* icuin, const char*

FOR_ALL_ICU_FUNCTIONS
ValidateICUDataCanLoad();

InitializeVariableMaxAndTopPointers(symbolVersion);
}

#undef PER_FUNCTION_BLOCK
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,17 @@
#include "pal_compiler.h"

#if !defined(STATIC_ICU)
// ucol_setVariableTop is a deprecated function on the newer ICU versions and ucol_setMaxVariable should be used instead.
// As can run against ICU versions which not supported ucol_setMaxVariable, we'll dynamically try to get the pointer to ucol_setVariableTop
// when we couldn't get a pointer to ucol_setMaxVariable.
typedef uint32_t (*ucol_setVariableTop_func)(UCollator* coll, const UChar* varTop, int32_t len, UErrorCode* status);
extern ucol_setVariableTop_func ucol_setVariableTop_ptr;

#if !defined(TARGET_ANDROID)
// (U_ICU_VERSION_MAJOR_NUM < 52)
// The following APIs are not supported in the ICU versions less than 52. We need to define them manually.
// We have to do runtime check before using the pointers to these APIs. That is why these are listed in the FOR_ALL_OPTIONAL_ICU_FUNCTIONS list.
U_CAPI void U_EXPORT2 ucol_setMaxVariable(UCollator* coll, UColReorderCode group, UErrorCode* pErrorCode);
U_CAPI int32_t U_EXPORT2 ucal_getTimeZoneIDForWindowsID(const UChar* winid, int32_t len, const char* region, UChar* id, int32_t idCapacity, UErrorCode* status);
U_CAPI int32_t U_EXPORT2 ucal_getWindowsTimeZoneID(const UChar* id, int32_t len, UChar* winid, int32_t winidCapacity, UErrorCode* status);
#endif
Expand Down Expand Up @@ -164,15 +170,6 @@ U_CAPI int32_t U_EXPORT2 ucal_getWindowsTimeZoneID(const UChar* id, int32_t len,
PER_FUNCTION_BLOCK(usearch_setPattern, libicui18n, true) \
PER_FUNCTION_BLOCK(usearch_setText, libicui18n, true)

#if HAVE_SET_MAX_VARIABLE
#define FOR_ALL_SET_VARIABLE_ICU_FUNCTIONS \
PER_FUNCTION_BLOCK(ucol_setMaxVariable, libicui18n, true)
#else

#define FOR_ALL_SET_VARIABLE_ICU_FUNCTIONS \
PER_FUNCTION_BLOCK(ucol_setVariableTop, libicui18n, true)
#endif

#if defined(TARGET_WINDOWS)
#define FOR_ALL_OS_CONDITIONAL_ICU_FUNCTIONS \
PER_FUNCTION_BLOCK(ucurr_forLocale, libicuuc, true) \
Expand All @@ -195,11 +192,11 @@ U_CAPI int32_t U_EXPORT2 ucal_getWindowsTimeZoneID(const UChar* id, int32_t len,
// Otherwise, we'll just not provide the functionality to users which needed these APIs.
#define FOR_ALL_OPTIONAL_ICU_FUNCTIONS \
PER_FUNCTION_BLOCK(ucal_getWindowsTimeZoneID, libicui18n, false) \
PER_FUNCTION_BLOCK(ucal_getTimeZoneIDForWindowsID, libicui18n, false)
PER_FUNCTION_BLOCK(ucal_getTimeZoneIDForWindowsID, libicui18n, false) \
PER_FUNCTION_BLOCK(ucol_setMaxVariable, libicui18n, false)

#define FOR_ALL_ICU_FUNCTIONS \
FOR_ALL_UNCONDITIONAL_ICU_FUNCTIONS \
FOR_ALL_SET_VARIABLE_ICU_FUNCTIONS \
FOR_ALL_OPTIONAL_ICU_FUNCTIONS \
FOR_ALL_OS_CONDITIONAL_ICU_FUNCTIONS

Expand Down Expand Up @@ -249,11 +246,7 @@ FOR_ALL_ICU_FUNCTIONS
#define ucol_openRules(...) ucol_openRules_ptr(__VA_ARGS__)
#define ucol_safeClone(...) ucol_safeClone_ptr(__VA_ARGS__)
#define ucol_setAttribute(...) ucol_setAttribute_ptr(__VA_ARGS__)
#if HAVE_SET_MAX_VARIABLE
#define ucol_setMaxVariable(...) ucol_setMaxVariable_ptr(__VA_ARGS__)
#else
#define ucol_setVariableTop(...) ucol_setVariableTop_ptr(__VA_ARGS__)
#endif
#define ucol_strcoll(...) ucol_strcoll_ptr(__VA_ARGS__)
#define ucurr_forLocale(...) ucurr_forLocale_ptr(__VA_ARGS__)
#define ucurr_getName(...) ucurr_getName_ptr(__VA_ARGS__)
Expand Down

0 comments on commit af4bb8b

Please sign in to comment.