mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 22:43:03 +01:00
Fix ICU loading in Android.
This commit is contained in:
parent
85b84da6df
commit
c969aa0575
@ -49,7 +49,8 @@ public:
|
||||
{}
|
||||
|
||||
~DlfcnModule();
|
||||
void* findSymbol (ISC_STATUS*, const Firebird::string&);
|
||||
void* findSymbol(ISC_STATUS*, const Firebird::string&) override;
|
||||
bool getRealPath(const Firebird::string& anySymbol, Firebird::PathName& path) override;
|
||||
|
||||
private:
|
||||
void* module;
|
||||
@ -155,4 +156,30 @@ void* DlfcnModule::findSymbol(ISC_STATUS* status, const Firebird::string& symNam
|
||||
return result;
|
||||
}
|
||||
|
||||
bool DlfcnModule::getRealPath(const Firebird::string& anySymbol, Firebird::PathName& path)
|
||||
{
|
||||
#ifdef HAVE_DLADDR
|
||||
void* symbolPtr = dlsym(module, anySymbol.c_str());
|
||||
|
||||
if (!symbolPtr)
|
||||
symbolPtr = dlsym(module, ('_' + anySymbol).c_str());
|
||||
|
||||
if (symbolPtr)
|
||||
{
|
||||
Dl_info info;
|
||||
if (dladdr(symbolPtr, &info))
|
||||
{
|
||||
char buffer[PATH_MAX];
|
||||
|
||||
if (realpath(info.dli_fname, buffer))
|
||||
{
|
||||
path = buffer;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // HAVE_DLADDR
|
||||
|
||||
path.clear();
|
||||
return false;
|
||||
}
|
||||
|
@ -62,6 +62,8 @@ public:
|
||||
**/
|
||||
virtual void* findSymbol(ISC_STATUS*, const Firebird::string&) = 0;
|
||||
|
||||
virtual bool getRealPath(const Firebird::string& anySymbol, Firebird::PathName& path) = 0;
|
||||
|
||||
template <typename T> T& findSymbol(ISC_STATUS* status, const Firebird::string& symbol, T& ptr)
|
||||
{
|
||||
return (ptr = (T)(findSymbol(status, symbol)));
|
||||
@ -72,10 +74,6 @@ public:
|
||||
|
||||
const Firebird::PathName fileName;
|
||||
|
||||
#ifdef LINUX
|
||||
virtual bool getRealPath(Firebird::PathName& path) = 0;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
/// The constructor is protected so normal code can't allocate instances
|
||||
/// of the class, but the class itself is still able to be subclassed.
|
||||
|
@ -51,7 +51,7 @@ public:
|
||||
|
||||
void* findSymbol(ISC_STATUS*, const Firebird::string&) override;
|
||||
|
||||
bool getRealPath(Firebird::PathName& path) override;
|
||||
bool getRealPath(const Firebird::string& anySymbol, Firebird::PathName& path) override;
|
||||
|
||||
private:
|
||||
void* module;
|
||||
@ -157,40 +157,7 @@ DlfcnModule::DlfcnModule(MemoryPool& pool, const Firebird::PathName& aFileName,
|
||||
module(m),
|
||||
realPath(pool)
|
||||
{
|
||||
#ifdef HAVE_DLINFO
|
||||
char b[PATH_MAX];
|
||||
|
||||
#ifdef HAVE_RTLD_DI_ORIGIN
|
||||
if (dlinfo(module, RTLD_DI_ORIGIN, b) == 0)
|
||||
{
|
||||
realPath = b;
|
||||
realPath += '/';
|
||||
realPath += fileName;
|
||||
|
||||
if (realpath(realPath.c_str(), b))
|
||||
{
|
||||
realPath = b;
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_RTLD_DI_LINKMAP
|
||||
struct link_map* lm;
|
||||
if (dlinfo(module, RTLD_DI_LINKMAP, &lm) == 0)
|
||||
{
|
||||
if (realpath(lm->l_name, b))
|
||||
{
|
||||
realPath = b;
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// Error getting real path.
|
||||
realPath.clear();
|
||||
getRealPath("", realPath);
|
||||
}
|
||||
|
||||
DlfcnModule::~DlfcnModule()
|
||||
@ -202,6 +169,7 @@ DlfcnModule::~DlfcnModule()
|
||||
void* DlfcnModule::findSymbol(ISC_STATUS* status, const Firebird::string& symName)
|
||||
{
|
||||
void* result = dlsym(module, symName.c_str());
|
||||
|
||||
if (!result)
|
||||
{
|
||||
Firebird::string newSym = '_' + symName;
|
||||
@ -253,11 +221,69 @@ void* DlfcnModule::findSymbol(ISC_STATUS* status, const Firebird::string& symNam
|
||||
return result;
|
||||
}
|
||||
|
||||
bool DlfcnModule::getRealPath(Firebird::PathName& path)
|
||||
bool DlfcnModule::getRealPath(const Firebird::string& anySymbol, Firebird::PathName& path)
|
||||
{
|
||||
if (realPath.isEmpty())
|
||||
return false;
|
||||
if (realPath.hasData())
|
||||
{
|
||||
path = realPath;
|
||||
return true;
|
||||
}
|
||||
|
||||
path = realPath;
|
||||
return true;
|
||||
char buffer[PATH_MAX];
|
||||
|
||||
#ifdef HAVE_DLINFO
|
||||
#ifdef HAVE_RTLD_DI_ORIGIN
|
||||
if (dlinfo(module, RTLD_DI_ORIGIN, buffer) == 0)
|
||||
{
|
||||
path = buffer;
|
||||
path += '/';
|
||||
path += fileName;
|
||||
|
||||
if (realpath(path.c_str(), buffer))
|
||||
{
|
||||
path = buffer;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_RTLD_DI_LINKMAP
|
||||
struct link_map* lm;
|
||||
if (dlinfo(module, RTLD_DI_LINKMAP, &lm) == 0)
|
||||
{
|
||||
if (realpath(lm->l_name, buffer))
|
||||
{
|
||||
path = buffer;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DLADDR
|
||||
if (anySymbol.hasData())
|
||||
{
|
||||
void* symbolPtr = dlsym(module, anySymbol.c_str());
|
||||
|
||||
if (!symbolPtr)
|
||||
symbolPtr = dlsym(module, ('_' + anySymbol).c_str());
|
||||
|
||||
if (symbolPtr)
|
||||
{
|
||||
Dl_info info;
|
||||
if (dladdr(symbolPtr, &info))
|
||||
{
|
||||
if (realpath(info.dli_fname, buffer))
|
||||
{
|
||||
path = buffer;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // HAVE_DLADDR
|
||||
|
||||
path.clear();
|
||||
return false;
|
||||
}
|
||||
|
@ -172,7 +172,9 @@ public:
|
||||
|
||||
~Win32Module();
|
||||
|
||||
void *findSymbol(ISC_STATUS* status, const string&);
|
||||
void* findSymbol(ISC_STATUS* status, const string&) override;
|
||||
|
||||
bool getRealPath(const string& anySymbol, PathName& path) override;
|
||||
|
||||
private:
|
||||
const HMODULE module;
|
||||
@ -272,3 +274,16 @@ void* Win32Module::findSymbol(ISC_STATUS* status, const string& symName)
|
||||
|
||||
return (void*) result;
|
||||
}
|
||||
|
||||
bool Win32Module::getRealPath(const string& /*anySymbol*/, PathName& path)
|
||||
{
|
||||
char moduleFileName[MAX_PATH];
|
||||
|
||||
if (GetModuleFileName(module, moduleFileName, sizeof(moduleFileName)) != 0)
|
||||
{
|
||||
path = moduleFileName;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -70,6 +70,10 @@ const char* const inTemplate = "libicui18n.so.%s";
|
||||
const char* const ucTemplate = "libicuuc.so.%s";
|
||||
#endif
|
||||
|
||||
#ifdef ANDROID
|
||||
const char* const dataTemplate = "libicudata.so.%s";
|
||||
#endif
|
||||
|
||||
// encapsulate ICU library
|
||||
struct BaseICU
|
||||
{
|
||||
@ -80,22 +84,22 @@ private:
|
||||
public:
|
||||
BaseICU(int aMajorVersion, int aMinorVersion)
|
||||
: majorVersion(aMajorVersion),
|
||||
minorVersion(aMinorVersion)
|
||||
minorVersion(aMinorVersion),
|
||||
isSystem(aMajorVersion == 0)
|
||||
{
|
||||
}
|
||||
|
||||
ModuleLoader::Module* formatAndLoad(const char* templateName);
|
||||
void initialize(ModuleLoader::Module* module);
|
||||
|
||||
template <typename T> void getEntryPoint(const char* name, ModuleLoader::Module* module, T& ptr,
|
||||
template <typename T> string getEntryPoint(const char* name, ModuleLoader::Module* module, T& ptr,
|
||||
bool optional = false)
|
||||
{
|
||||
// System-wide ICU have no version number at entries names
|
||||
if (!majorVersion)
|
||||
{
|
||||
fb_assert(false); // ASF: I don't think this code path is correct.
|
||||
|
||||
if (module->findSymbol(NULL, name, ptr))
|
||||
return;
|
||||
return name;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -111,63 +115,132 @@ public:
|
||||
{
|
||||
symbol.printf(pattern, name, majorVersion, minorVersion);
|
||||
if (module->findSymbol(NULL, symbol, ptr))
|
||||
return;
|
||||
return symbol;
|
||||
}
|
||||
}
|
||||
|
||||
if (!optional)
|
||||
(Arg::Gds(isc_icu_entrypoint) << name).raise();
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
int majorVersion;
|
||||
int minorVersion;
|
||||
bool isSystem;
|
||||
void (U_EXPORT2* u_getVersion) (UVersionInfo versionArray) = nullptr;
|
||||
};
|
||||
|
||||
ModuleLoader::Module* BaseICU::formatAndLoad(const char* templateName)
|
||||
{
|
||||
ModuleLoader::Module* module = nullptr;
|
||||
|
||||
// System-wide ICU have no version number at file names
|
||||
if (isSystem)
|
||||
{
|
||||
PathName filename;
|
||||
filename.printf(templateName, "");
|
||||
filename.rtrim(".");
|
||||
|
||||
//gds__log("ICU: link %s", filename.c_str());
|
||||
|
||||
module = ModuleLoader::fixAndLoadModule(NULL, filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
fb_assert(majorVersion);
|
||||
|
||||
// ICU has several schemas for placing version into file name
|
||||
const char* const patterns[] =
|
||||
{
|
||||
#ifdef WIN_NT
|
||||
"%d",
|
||||
#endif
|
||||
"%d_%d",
|
||||
"%d.%d",
|
||||
"%d%d"
|
||||
};
|
||||
|
||||
PathName s, filename;
|
||||
for (auto pattern : patterns)
|
||||
{
|
||||
s.printf(pattern, majorVersion, minorVersion);
|
||||
filename.printf(templateName, s.c_str());
|
||||
|
||||
module = ModuleLoader::fixAndLoadModule(NULL, filename);
|
||||
if (module)
|
||||
break;
|
||||
}
|
||||
|
||||
#ifndef WIN_NT
|
||||
// There is no sence to try pattern "%d" for different minor versions
|
||||
// ASF: In Windows ICU 63.1 libraries use 63.dll suffix. This is handled in 'patterns' above.
|
||||
if (!module && minorVersion == 0)
|
||||
{
|
||||
s.printf("%d", majorVersion);
|
||||
filename.printf(templateName, s.c_str());
|
||||
|
||||
module = ModuleLoader::fixAndLoadModule(NULL, filename);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return module;
|
||||
}
|
||||
|
||||
void BaseICU::initialize(ModuleLoader::Module* module)
|
||||
{
|
||||
getEntryPoint("u_getVersion", module, u_getVersion);
|
||||
|
||||
UVersionInfo versionInfo;
|
||||
u_getVersion(versionInfo);
|
||||
|
||||
if (!isSystem && (versionInfo[0] != majorVersion || versionInfo[1] != minorVersion))
|
||||
{
|
||||
string err;
|
||||
err.printf(
|
||||
"Wrong version of icu module: loaded %d.%d, expected %d.%d",
|
||||
(int) versionInfo[0], (int) versionInfo[1],
|
||||
this->majorVersion, this->minorVersion);
|
||||
|
||||
(Arg::Gds(isc_random) << Arg::Str(err)).raise();
|
||||
}
|
||||
|
||||
majorVersion = versionInfo[0];
|
||||
minorVersion = versionInfo[1];
|
||||
|
||||
void (U_EXPORT2 *uInit)(UErrorCode* status);
|
||||
void (U_EXPORT2 *uSetTimeZoneFilesDirectory)(const char* path, UErrorCode* status);
|
||||
void (U_EXPORT2 *uSetDataDirectory)(const char* directory);
|
||||
|
||||
getEntryPoint("u_init", module, uInit, true);
|
||||
getEntryPoint("u_setTimeZoneFilesDirectory", module, uSetTimeZoneFilesDirectory, true);
|
||||
getEntryPoint("u_setDataDirectory", module, uSetDataDirectory, true);
|
||||
const auto uSetDataDirectorySymbolName = getEntryPoint("u_setDataDirectory", module, uSetDataDirectory, true);
|
||||
|
||||
#if defined(WIN_NT) || defined(DARWIN) || defined(ANDROID)
|
||||
if (uSetDataDirectory)
|
||||
{
|
||||
// call uSetDataDirectory only if .dat file is exists at same folder
|
||||
// as the loaded module
|
||||
// call uSetDataDirectory only if .dat file exists at same folder as the loaded module
|
||||
|
||||
PathName modulePathName;
|
||||
if (!module->getRealPath(uSetDataDirectorySymbolName.c_str(), modulePathName))
|
||||
modulePathName = module->fileName;
|
||||
|
||||
PathName path, file, fullName;
|
||||
PathUtils::splitLastComponent(path, file, module->fileName);
|
||||
PathUtils::splitLastComponent(path, file, modulePathName);
|
||||
|
||||
#ifdef WIN_NT
|
||||
// icuucXX.dll -> icudtXX.dll
|
||||
file.replace(3, 2, "dt");
|
||||
|
||||
// icudtXX.dll -> icudtXXl.dat
|
||||
const FB_SIZE_T pos = file.find_last_of('.');
|
||||
file.erase(pos);
|
||||
file.append("l.dat");
|
||||
file.printf("icudt%u%c.dat", majorVersion,
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
'b'
|
||||
#else
|
||||
// libicuuc.so.XX -> icudtXX
|
||||
const FB_SIZE_T pos = file.find_last_of('.');
|
||||
if (pos > 0 && pos != file.npos)
|
||||
{
|
||||
file.replace(0, pos + 1, "icudt");
|
||||
}
|
||||
|
||||
// icudtXX -> icudtXXl.dat
|
||||
file += "l.dat";
|
||||
'l'
|
||||
#endif
|
||||
);
|
||||
|
||||
PathUtils::concatPath(fullName, path, file);
|
||||
|
||||
if (PathUtils::canAccess(fullName, 0))
|
||||
uSetDataDirectory(path.c_str());
|
||||
}
|
||||
#endif
|
||||
|
||||
if (uInit)
|
||||
{
|
||||
@ -195,10 +268,6 @@ void BaseICU::initialize(ModuleLoader::Module* module)
|
||||
|
||||
namespace Jrd {
|
||||
|
||||
static ModuleLoader::Module* formatAndLoad(const char* templateName,
|
||||
int& majorVersion, int& minorVersion);
|
||||
|
||||
|
||||
// encapsulate ICU collations libraries
|
||||
struct UnicodeUtil::ICU : public BaseICU
|
||||
{
|
||||
@ -316,7 +385,16 @@ private:
|
||||
ImplementConversionICU(int aMajorVersion, int aMinorVersion)
|
||||
: BaseICU(aMajorVersion, aMinorVersion)
|
||||
{
|
||||
module = formatAndLoad(ucTemplate, this->majorVersion, this->minorVersion);
|
||||
#ifdef ANDROID
|
||||
auto dataModule = formatAndLoad(dataTemplate);
|
||||
#endif
|
||||
|
||||
module = formatAndLoad(ucTemplate);
|
||||
|
||||
#ifdef ANDROID
|
||||
delete dataModule;
|
||||
#endif
|
||||
|
||||
if (!module)
|
||||
return;
|
||||
|
||||
@ -325,7 +403,6 @@ private:
|
||||
getEntryPoint("ucnv_open", module, ucnv_open);
|
||||
getEntryPoint("ucnv_close", module, ucnv_close);
|
||||
getEntryPoint("ucnv_fromUChars", module, ucnv_fromUChars);
|
||||
getEntryPoint("u_getVersion", module, u_getVersion);
|
||||
getEntryPoint("u_tolower", module, u_tolower);
|
||||
getEntryPoint("u_toupper", module, u_toupper);
|
||||
getEntryPoint("u_strCompare", module, u_strCompare);
|
||||
@ -344,19 +421,10 @@ private:
|
||||
|
||||
getEntryPoint("u_strcmp", module, ustrcmp);
|
||||
|
||||
inModule = formatAndLoad(inTemplate, aMajorVersion, aMinorVersion);
|
||||
inModule = formatAndLoad(inTemplate);
|
||||
if (!inModule)
|
||||
return;
|
||||
|
||||
if (aMajorVersion != this->majorVersion || aMinorVersion != this->minorVersion)
|
||||
{
|
||||
string err;
|
||||
err.printf("Wrong version of IN icu module: loaded %d.%d, expected %d.%d",
|
||||
aMajorVersion, aMinorVersion, this->majorVersion, this->minorVersion);
|
||||
|
||||
(Arg::Gds(isc_random) << Arg::Str(err)).raise();
|
||||
}
|
||||
|
||||
getEntryPoint("ucal_getTZDataVersion", inModule, ucalGetTZDataVersion);
|
||||
getEntryPoint("ucal_getDefaultTimeZone", inModule, ucalGetDefaultTimeZone);
|
||||
getEntryPoint("ucal_open", inModule, ucalOpen);
|
||||
@ -384,11 +452,8 @@ public:
|
||||
|
||||
if (o)
|
||||
{
|
||||
UVersionInfo versionInfo;
|
||||
o->u_getVersion(versionInfo);
|
||||
|
||||
o->vMajor = versionInfo[0];
|
||||
o->vMinor = versionInfo[1];
|
||||
o->vMajor = o->majorVersion;
|
||||
o->vMinor = o->minorVersion;
|
||||
}
|
||||
|
||||
return o;
|
||||
@ -430,128 +495,6 @@ static const char* const COLL_30_VERSION = "41.128.4.4"; // ICU 3.0 collator ver
|
||||
|
||||
static GlobalPtr<UnicodeUtil::ICUModules> icuModules;
|
||||
|
||||
#ifdef LINUX
|
||||
static bool extractVersionFromPath(const PathName& realPath, int& major, int& minor)
|
||||
{
|
||||
major = 0;
|
||||
minor = 0;
|
||||
int mult = 1;
|
||||
|
||||
const FB_SIZE_T len = realPath.length();
|
||||
const char* buf = realPath.begin();
|
||||
|
||||
bool dot = false;
|
||||
for (const char* p = buf + len - 1; p >= buf; p--)
|
||||
{
|
||||
if (*p >= '0' && *p < '9')
|
||||
{
|
||||
major += (*p - '0') * mult;
|
||||
mult *= 10;
|
||||
}
|
||||
else if (*p == '.' && !dot)
|
||||
{
|
||||
dot = true;
|
||||
minor = major;
|
||||
major = 0;
|
||||
mult = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (minor && !major)
|
||||
{
|
||||
major = minor;
|
||||
minor = 0;
|
||||
}
|
||||
|
||||
return major != 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static ModuleLoader::Module* formatAndLoad(const char* templateName,
|
||||
int& majorVersion, int& minorVersion)
|
||||
{
|
||||
#ifdef ANDROID
|
||||
static ModuleLoader::Module* dat = ModuleLoader::loadModule(NULL,
|
||||
fb_utils::getPrefix(Firebird::IConfigManager::DIR_LIB, "libicudata.so"));
|
||||
|
||||
Firebird::PathName newName = fb_utils::getPrefix(Firebird::IConfigManager::DIR_LIB, templateName);
|
||||
templateName = newName.c_str();
|
||||
#endif
|
||||
|
||||
ModuleLoader::Module* module = nullptr;
|
||||
|
||||
// System-wide ICU have no version number at file names
|
||||
if (!majorVersion)
|
||||
{
|
||||
PathName filename;
|
||||
filename.printf(templateName, "");
|
||||
filename.rtrim(".");
|
||||
|
||||
//gds__log("ICU: link %s", filename.c_str());
|
||||
|
||||
module = ModuleLoader::fixAndLoadModule(NULL, filename);
|
||||
|
||||
#ifdef LINUX
|
||||
// try to resolve symlinks and extract version numbers from suffix
|
||||
PathName realPath;
|
||||
if (module && module->getRealPath(realPath))
|
||||
{
|
||||
//gds__log("ICU: module name %s, real path %s", module->fileName.c_str(), realPath.c_str());
|
||||
|
||||
int major, minor;
|
||||
if (extractVersionFromPath(realPath, major, minor))
|
||||
{
|
||||
//gds__log("ICU: extracted version %d.%d", major, minor);
|
||||
majorVersion = major;
|
||||
minorVersion = minor;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
// ICU has several schemas for placing version into file name
|
||||
const char* const patterns[] =
|
||||
{
|
||||
#ifdef WIN_NT
|
||||
"%d",
|
||||
#endif
|
||||
"%d_%d",
|
||||
"%d.%d",
|
||||
"%d%d"
|
||||
};
|
||||
|
||||
PathName s, filename;
|
||||
for (auto pattern : patterns)
|
||||
{
|
||||
s.printf(pattern, majorVersion, minorVersion);
|
||||
filename.printf(templateName, s.c_str());
|
||||
|
||||
module = ModuleLoader::fixAndLoadModule(NULL, filename);
|
||||
if (module)
|
||||
break;
|
||||
}
|
||||
|
||||
#ifndef WIN_NT
|
||||
// There is no sence to try pattern "%d" for different minor versions
|
||||
// ASF: In Windows ICU 63.1 libraries use 63.dll suffix. This is handled in 'patterns' above.
|
||||
if (!module && minorVersion == 0)
|
||||
{
|
||||
s.printf("%d", majorVersion);
|
||||
filename.printf(templateName, s.c_str());
|
||||
|
||||
module = ModuleLoader::fixAndLoadModule(NULL, filename);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return module;
|
||||
}
|
||||
|
||||
|
||||
static void getVersions(const string& configInfo, ObjectsArray<string>& versions)
|
||||
{
|
||||
@ -1220,7 +1163,16 @@ UnicodeUtil::ICU* UnicodeUtil::loadICU(const string& icuVersion, const string& c
|
||||
|
||||
icu = FB_NEW_POOL(*getDefaultMemoryPool()) ICU(majorVersion, minorVersion);
|
||||
|
||||
icu->ucModule = formatAndLoad(ucTemplate, icu->majorVersion, icu->minorVersion);
|
||||
#ifdef ANDROID
|
||||
auto dataModule = icu->formatAndLoad(dataTemplate);
|
||||
#endif
|
||||
|
||||
icu->ucModule = icu->formatAndLoad(ucTemplate);
|
||||
|
||||
#ifdef ANDROID
|
||||
delete dataModule;
|
||||
#endif
|
||||
|
||||
if (!icu->ucModule)
|
||||
{
|
||||
gds__log("failed to load UC icu module version %s", configVersion.c_str());
|
||||
@ -1228,26 +1180,18 @@ UnicodeUtil::ICU* UnicodeUtil::loadICU(const string& icuVersion, const string& c
|
||||
continue;
|
||||
}
|
||||
|
||||
icu->inModule = formatAndLoad(inTemplate, majorVersion, minorVersion);
|
||||
if (!icu->inModule)
|
||||
{
|
||||
gds__log("failed to load IN icu module version %s", configVersion.c_str());
|
||||
delete icu;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (icu->majorVersion != majorVersion || icu->minorVersion != minorVersion)
|
||||
{
|
||||
gds__log("Wrong version of IN icu module: loaded %d.%d, expected %d.%d",
|
||||
majorVersion, minorVersion, icu->majorVersion, icu->minorVersion);
|
||||
delete icu;
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
icu->initialize(icu->ucModule);
|
||||
|
||||
icu->inModule = icu->formatAndLoad(inTemplate);
|
||||
if (!icu->inModule)
|
||||
{
|
||||
gds__log("failed to load IN icu module version %s", configVersion.c_str());
|
||||
delete icu;
|
||||
continue;
|
||||
}
|
||||
|
||||
icu->getEntryPoint("u_versionToString", icu->ucModule, icu->uVersionToString);
|
||||
icu->getEntryPoint("uloc_countAvailable", icu->ucModule, icu->ulocCountAvailable);
|
||||
icu->getEntryPoint("uloc_getAvailable", icu->ucModule, icu->ulocGetAvailable);
|
||||
|
@ -58,7 +58,6 @@ public:
|
||||
const UChar *src, int32_t srcLength,
|
||||
UErrorCode *pErrorCode);
|
||||
|
||||
void (U_EXPORT2* u_getVersion) (UVersionInfo versionArray);
|
||||
UChar32 (U_EXPORT2* u_tolower) (UChar32 c);
|
||||
UChar32 (U_EXPORT2* u_toupper) (UChar32 c);
|
||||
int32_t (U_EXPORT2* u_strCompare) (const UChar* s1, int32_t length1,
|
||||
|
Loading…
Reference in New Issue
Block a user