Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 2 commits into from
Sep 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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