ICU-1075 Yet more data loading changes
X-SVN-Rev: 5523
This commit is contained in:
parent
a84135e73e
commit
fc61c83aa2
@ -863,475 +863,33 @@ uprv_tzname(int n)
|
||||
static UBool
|
||||
gHaveDataDirectory=FALSE;
|
||||
|
||||
static char
|
||||
gDataDirectory[1024];
|
||||
static const char *gDataDirectory = "";
|
||||
|
||||
/*
|
||||
* Here, we use a mutex to make sure that setting the data directory
|
||||
* is thread-safe; however, reading it after calling u_getDataDirectory()
|
||||
* may still occur while it is (re)set and is therefore not thread-safe.
|
||||
* The best is to not call it after the initialization.
|
||||
* Set the data directory.
|
||||
* Make a copy of the passed string, and set the global data dir to point to it.
|
||||
* Deliberately leak any previously set string, on the chance that some code
|
||||
* may have called getDataDirectory() and still be using the old string.
|
||||
*/
|
||||
U_CAPI void U_EXPORT2
|
||||
u_setDataDirectory(const char *directory) {
|
||||
if(directory!=NULL) {
|
||||
char *newDataDir;
|
||||
|
||||
if(directory!=NULL && *directory != 0) {
|
||||
int length=uprv_strlen(directory);
|
||||
|
||||
if(length<sizeof(gDataDirectory)-1) {
|
||||
umtx_lock(NULL);
|
||||
if(length==0) {
|
||||
*gDataDirectory=0;
|
||||
} else {
|
||||
uprv_memcpy(gDataDirectory, directory, length);
|
||||
|
||||
/* terminate the directory with a separator (/ or \) */
|
||||
if(gDataDirectory[length-1]!=U_FILE_SEP_CHAR) {
|
||||
gDataDirectory[length++]=U_FILE_SEP_CHAR;
|
||||
}
|
||||
|
||||
/* zero-terminate it */
|
||||
gDataDirectory[length]=0;
|
||||
}
|
||||
gHaveDataDirectory=TRUE;
|
||||
umtx_unlock(NULL);
|
||||
newDataDir = (char *)uprv_malloc(length + 2);
|
||||
uprv_strcpy(newDataDir, directory);
|
||||
if(newDataDir[length-1]!=U_FILE_SEP_CHAR) {
|
||||
newDataDir[length++]=U_FILE_SEP_CHAR;
|
||||
newDataDir[length] = 0;
|
||||
}
|
||||
|
||||
gDataDirectory = newDataDir;
|
||||
gHaveDataDirectory=TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifndef ICU_DATA_DIR
|
||||
|
||||
# if defined(XP_MAC)
|
||||
|
||||
/* Kouichi added the following internal functions for MAC porting */
|
||||
|
||||
pascal OSErr FSMakeFSSpecCompat(short vRefNum,
|
||||
long dirID,
|
||||
ConstStr255Param fileName,
|
||||
FSSpec *spec)
|
||||
{
|
||||
OSErr result;
|
||||
|
||||
/* Let the file system create the FSSpec if it can since it does the job */
|
||||
/* much more efficiently than I can. */
|
||||
result = FSMakeFSSpec(vRefNum, dirID, fileName, spec);
|
||||
|
||||
/* Fix a bug in Macintosh PC Exchange's MakeFSSpec code where 0 is */
|
||||
/* returned in the parID field when making an FSSpec to the volume's */
|
||||
/* root directory by passing a full pathname in MakeFSSpec's */
|
||||
/* fileName parameter. Fixed in Mac OS 8.1 */
|
||||
if ( (result == noErr) && (spec->parID == 0) )
|
||||
spec->parID = fsRtParID;
|
||||
|
||||
return ( result );
|
||||
}
|
||||
|
||||
|
||||
/* FSpGetFullPath */
|
||||
pascal OSErr FSpGetFullPath(const FSSpec *spec,
|
||||
short *fullPathLength,
|
||||
Handle *fullPath)
|
||||
{
|
||||
OSErr result;
|
||||
OSErr realResult;
|
||||
FSSpec tempSpec;
|
||||
CInfoPBRec pb;
|
||||
|
||||
*fullPathLength = 0;
|
||||
*fullPath = NULL;
|
||||
|
||||
/* Default to noErr */
|
||||
realResult = result = noErr;
|
||||
|
||||
/* work around Nav Services "bug" (it returns invalid FSSpecs with empty names) */
|
||||
if ( spec->name[0] == 0 )
|
||||
{
|
||||
result = FSMakeFSSpecCompat(spec->vRefNum, spec->parID, spec->name, &tempSpec);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Make a copy of the input FSSpec that can be modified */
|
||||
BlockMoveData(spec, &tempSpec, sizeof(FSSpec));
|
||||
}
|
||||
|
||||
if ( result == noErr )
|
||||
{
|
||||
if ( tempSpec.parID == fsRtParID )
|
||||
{
|
||||
/* The object is a volume */
|
||||
|
||||
/* Add a colon to make it a full pathname */
|
||||
++tempSpec.name[0];
|
||||
tempSpec.name[tempSpec.name[0]] = ':';
|
||||
|
||||
/* We're done */
|
||||
result = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The object isn't a volume */
|
||||
|
||||
/* Is the object a file or a directory? */
|
||||
pb.dirInfo.ioNamePtr = tempSpec.name;
|
||||
pb.dirInfo.ioVRefNum = tempSpec.vRefNum;
|
||||
pb.dirInfo.ioDrDirID = tempSpec.parID;
|
||||
pb.dirInfo.ioFDirIndex = 0;
|
||||
result = PBGetCatInfoSync(&pb);
|
||||
/* Allow file/directory name at end of path to not exist. */
|
||||
realResult = result;
|
||||
if ( (result == noErr) || (result == fnfErr) )
|
||||
{
|
||||
/* if the object is a directory, append a colon so full pathname ends with colon */
|
||||
if ( (result == noErr) && (pb.hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0 )
|
||||
{
|
||||
++tempSpec.name[0];
|
||||
tempSpec.name[tempSpec.name[0]] = ':';
|
||||
}
|
||||
|
||||
/* Put the object name in first */
|
||||
result = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]);
|
||||
if ( result == noErr )
|
||||
{
|
||||
/* Get the ancestor directory names */
|
||||
pb.dirInfo.ioNamePtr = tempSpec.name;
|
||||
pb.dirInfo.ioVRefNum = tempSpec.vRefNum;
|
||||
pb.dirInfo.ioDrParID = tempSpec.parID;
|
||||
do /* loop until we have an error or find the root directory */
|
||||
{
|
||||
pb.dirInfo.ioFDirIndex = -1;
|
||||
pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrParID;
|
||||
result = PBGetCatInfoSync(&pb);
|
||||
if ( result == noErr )
|
||||
{
|
||||
/* Append colon to directory name */
|
||||
++tempSpec.name[0];
|
||||
tempSpec.name[tempSpec.name[0]] = ':';
|
||||
|
||||
/* Add directory name to beginning of fullPath */
|
||||
(void) Munger(*fullPath, 0, NULL, 0, &tempSpec.name[1], tempSpec.name[0]);
|
||||
result = MemError();
|
||||
}
|
||||
} while ( (result == noErr) && (pb.dirInfo.ioDrDirID != fsRtDirID) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( result == noErr )
|
||||
{
|
||||
/* Return the length */
|
||||
*fullPathLength = GetHandleSize(*fullPath);
|
||||
result = realResult; /* return realResult in case it was fnfErr */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Dispose of the handle and return NULL and zero length */
|
||||
if ( *fullPath != NULL )
|
||||
{
|
||||
DisposeHandle(*fullPath);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
# endif /* XP_MAC */
|
||||
|
||||
/*
|
||||
* get the system drive or volume path
|
||||
* (Windows: e.g. "C:" or "D:")
|
||||
* do not terminate with a U_FILE_SEP_CHAR separator
|
||||
* return the length of the path, or 0 if none
|
||||
*/
|
||||
static int
|
||||
getSystemPath(char *path, int size) {
|
||||
#if defined(XP_MAC)
|
||||
int32_t dirID;
|
||||
OSErr err;
|
||||
int16_t volNum;
|
||||
|
||||
path[0]=0;
|
||||
err=HGetVol((unsigned char*)path, &volNum, &dirID);
|
||||
if(err==noErr) {
|
||||
int length=(uint8_t)path[0];
|
||||
if(length>0) {
|
||||
/* convert the Pascal string to a C string */
|
||||
uprv_memmove(path, path+1, length);
|
||||
path[length]=0;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
#elif defined(WIN32)
|
||||
if(GetSystemDirectory(path, size)>=2 && path[1]==':') {
|
||||
/* remove the rest of the path - "\\winnt\\system32" or similar */
|
||||
path[2]=0;
|
||||
return 2;
|
||||
}
|
||||
|
||||
#elif defined(OS2)
|
||||
APIRET rc;
|
||||
ULONG bootDrive=0; /* 1=A, 2=B, 3=C, ... */
|
||||
|
||||
rc=DosQuerySysInfo(QSV_BOOT_DRIVE, QSV_BOOT_DRIVE, (PVOID)&bootDrive, sizeof(ULONG));
|
||||
if(rc==NO_ERROR) {
|
||||
/* convert the numeric boot drive to a string */
|
||||
path[0]='A'+bootDrive-1;
|
||||
path[1]=':';
|
||||
path[2]=0;
|
||||
return 2;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* ICU_DATA_DIR not defined */
|
||||
|
||||
/*
|
||||
* get the path to the ICU dynamic library
|
||||
* do not terminate with a U_FILE_SEP_CHAR separator
|
||||
* return the length of the path, or 0 if none
|
||||
*/
|
||||
static int
|
||||
getLibraryPath(char *path, int size) {
|
||||
#ifdef WIN32
|
||||
HINSTANCE mod=GetModuleHandle("icuuc.dll");
|
||||
if(mod!=NULL) {
|
||||
if(GetModuleFileName(mod, path, size)>0) {
|
||||
/* remove the basename and the last file separator */
|
||||
char *lastSep=uprv_strrchr(path, U_FILE_SEP_CHAR);
|
||||
if(lastSep!=NULL) {
|
||||
*lastSep=0;
|
||||
return lastSep-path;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(OS2)
|
||||
HMODULE mod=NULLHANDLE;
|
||||
APIRET rc=DosQueryModuleHandle("icuuc.dll", &mod);
|
||||
if(rc==NO_ERROR) {
|
||||
rc=DosQueryModuleName(mod, (LONG)size, path);
|
||||
if(rc==NO_ERROR) {
|
||||
/* remove the basename and the last file separator */
|
||||
char *lastSep=uprv_strrchr(path, U_FILE_SEP_CHAR);
|
||||
if(lastSep!=NULL) {
|
||||
*lastSep=0;
|
||||
return lastSep-path;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(U_SOLARIS)
|
||||
void *handle=dlopen(U_COMMON_LIBNAME, RTLD_LAZY); /* "libicu-uc.so" */
|
||||
if(handle!=NULL) {
|
||||
Link_map *p=NULL;
|
||||
char *s;
|
||||
int rc, length=0;
|
||||
|
||||
/* get the Link_map list */
|
||||
rc=dlinfo(handle, RTLD_DI_LINKMAP, (void *)&p);
|
||||
if(rc>=0) {
|
||||
/* search for the list item for the library itself */
|
||||
while(p!=NULL) {
|
||||
s=uprv_strstr(p->l_name, U_COMMON_LIBNAME); /* "libicu-uc.so" */
|
||||
if(s!=NULL) {
|
||||
if(s>p->l_name) {
|
||||
/* copy the path, without the basename and the last separator */
|
||||
length=(s-p->l_name)-1;
|
||||
if(0<length && length<size) {
|
||||
uprv_memcpy(path, p->l_name, length);
|
||||
path[length]=0;
|
||||
} else {
|
||||
length=0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
p=p->l_next;
|
||||
}
|
||||
}
|
||||
dlclose(handle);
|
||||
return length;
|
||||
}
|
||||
|
||||
#elif defined(AIX)
|
||||
void *handle=(void*)load(U_COMMON_LIBNAME, L_LIBPATH_EXEC, "."); /* "libicu-uc.a" */
|
||||
if(handle!=NULL) {
|
||||
uint8_t buffer[4096];
|
||||
struct ld_info *p=NULL;
|
||||
char *s;
|
||||
int rc, length=0;
|
||||
|
||||
/* copy the linked list of loaded libraries into the buffer */
|
||||
rc=loadquery(L_GETINFO, buffer, sizeof(buffer));
|
||||
if(rc>=0) {
|
||||
/* search for the list item for the library itself */
|
||||
p=(struct ld_info *)buffer;
|
||||
for(;;) {
|
||||
/* advance (ignore the first list item) */
|
||||
if(p->ldinfo_next==0) {
|
||||
break;
|
||||
}
|
||||
p=(struct ld_info *)((uint8_t *)p+p->ldinfo_next);
|
||||
|
||||
s=uprv_strstr(p->ldinfo_filename, U_COMMON_LIBNAME); /* "libicuuc.a" */
|
||||
if(s!=NULL) {
|
||||
if(s>p->ldinfo_filename) {
|
||||
/* copy the path, without the basename and the last separator */
|
||||
length=(s-p->ldinfo_filename)-1;
|
||||
if(0<length && length<size) {
|
||||
uprv_memcpy(path, p->ldinfo_filename, length);
|
||||
path[length]=0;
|
||||
} else {
|
||||
length=0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* p=p->l_next; */
|
||||
}
|
||||
}
|
||||
unload(handle);
|
||||
return length;
|
||||
}
|
||||
|
||||
#elif defined(HPUX)
|
||||
{
|
||||
struct shl_descriptor *p=NULL;
|
||||
char *s;
|
||||
int i=1, rc, length=0;
|
||||
|
||||
/* walk the list of shared libraries */
|
||||
/* search for the list item for the library itself */
|
||||
for(;;) {
|
||||
rc=shl_get(i, &p);
|
||||
if(rc<0) {
|
||||
break;
|
||||
}
|
||||
|
||||
s=uprv_strstr(p->filename, U_COMMON_LIBNAME);
|
||||
if(s!=NULL) {
|
||||
if(s>p->filename) {
|
||||
/* copy the path, without the basename and the last separator */
|
||||
length=(s-p->filename)-1;
|
||||
if(0<length && length<size) {
|
||||
uprv_memcpy(path, p->filename, length);
|
||||
path[length]=0;
|
||||
} else {
|
||||
length=0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
#elif defined(OS390)
|
||||
#elif defined(OS400)
|
||||
#elif defined(XP_MAC)
|
||||
#elif defined(U_LINUX)
|
||||
#elif defined(TANDEM)
|
||||
#elif defined(U_POSIX)
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
# define LIB_PATH_VAR "PATH"
|
||||
# define LIB_FILENAME "icuuc.dll"
|
||||
#elif defined(U_LINUX)
|
||||
# define LIB_PATH_VAR "LD_LIBRARY_PATH"
|
||||
# define LIB_FILENAME U_COMMON_LIBNAME
|
||||
#elif defined(OS2)
|
||||
# define LIB_PATH_VAR "LIBPATH"
|
||||
# define LIB_FILENAME "icuuc.dll"
|
||||
#elif defined(OS390)
|
||||
# define LIB_PATH_VAR "LIBPATH"
|
||||
# define LIB_FILENAME "libicuuc.a"
|
||||
#elif defined(TANDEM)
|
||||
# define LIB_PATH_VAR "LIBPATH"
|
||||
# define LIB_FILENAME "libicuuc.a"
|
||||
#elif defined(OS400)
|
||||
#elif defined(XP_MAC)
|
||||
#elif defined(U_SOLARIS)
|
||||
#elif defined(AIX)
|
||||
#elif defined(HPUX)
|
||||
#elif defined(U_POSIX)
|
||||
# define LIB_PATH_VAR "LIBPATH"
|
||||
# define LIB_FILENAME U_COMMON_LIBNAME
|
||||
#endif
|
||||
|
||||
/*
|
||||
* search for the ICU dynamic library and set the path
|
||||
* do not terminate with a U_FILE_SEP_CHAR separator
|
||||
* return the length of the path, or 0 if none
|
||||
*/
|
||||
static int
|
||||
findLibraryPath(char *path, int size) {
|
||||
/* common implementation for searching the library path */
|
||||
#ifdef LIB_FILENAME
|
||||
const char *libPath=getenv(LIB_PATH_VAR);
|
||||
|
||||
if(libPath!=NULL) {
|
||||
/* loop over all paths */
|
||||
FileStream *f;
|
||||
const char *end;
|
||||
int length;
|
||||
|
||||
for(;;) {
|
||||
/* find the end of the path */
|
||||
end=libPath;
|
||||
while(*end!=0 && *end!=U_PATH_SEP_CHAR) {
|
||||
++end;
|
||||
}
|
||||
|
||||
if(end!=libPath) {
|
||||
/* try this non-empty path */
|
||||
length=end-libPath;
|
||||
|
||||
/* do not terminate the path */
|
||||
if(*(end-1)==U_FILE_SEP_CHAR) {
|
||||
--length;
|
||||
}
|
||||
|
||||
/* copy the path and add the library filename */
|
||||
uprv_memcpy(path, libPath, length);
|
||||
uprv_strcpy(path+length, U_FILE_SEP_STRING LIB_FILENAME);
|
||||
|
||||
/* does this file exist in this path? */
|
||||
f=T_FileStream_open(path, "rb");
|
||||
if(f!=NULL) {
|
||||
/* yes, clean up and return */
|
||||
T_FileStream_close(f);
|
||||
path[length]=0;
|
||||
return length;
|
||||
}
|
||||
}
|
||||
|
||||
if(*end==0) {
|
||||
break; /* no more path */
|
||||
}
|
||||
|
||||
/* *end==U_PATH_SEP_CHAR, go to the next path */
|
||||
libPath=end+1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* define a path for fallbacks */
|
||||
#ifdef WIN32
|
||||
# define FALLBACK_PATH U_FILE_SEP_STRING ".." U_FILE_SEP_STRING "data"
|
||||
#elif defined(XP_MAC)
|
||||
# define FALLBACK_PATH U_FILE_SEP_STRING "ICU" U_FILE_SEP_STRING U_ICU_VERSION U_FILE_SEP_STRING
|
||||
#else
|
||||
# define FALLBACK_PATH U_FILE_SEP_STRING "lib" U_FILE_SEP_STRING "icu" U_FILE_SEP_STRING U_ICU_VERSION U_FILE_SEP_STRING
|
||||
#endif
|
||||
|
||||
/* #include <stdio.h> */
|
||||
/* #include <unistd.h> */
|
||||
@ -1344,171 +902,109 @@ findLibraryPath(char *path, int size) {
|
||||
|
||||
U_CAPI const char * U_EXPORT2
|
||||
u_getDataDirectory(void) {
|
||||
const char *path = NULL;
|
||||
char pathBuffer[1024];
|
||||
|
||||
/* if we have the directory, then return it immediately */
|
||||
if(!gHaveDataDirectory) {
|
||||
/* we need to look for it */
|
||||
char pathBuffer[1024];
|
||||
const char *path = NULL;
|
||||
int length;
|
||||
|
||||
# if !defined(XP_MAC)
|
||||
/* first try to get the environment variable */
|
||||
path=getenv("ICU_DATA");
|
||||
# else /* XP_MAC */
|
||||
{
|
||||
OSErr myErr;
|
||||
short vRef;
|
||||
long dir,newDir;
|
||||
int16_t volNum;
|
||||
Str255 xpath;
|
||||
FSSpec spec;
|
||||
short len;
|
||||
Handle full;
|
||||
|
||||
xpath[0]=0;
|
||||
|
||||
myErr = HGetVol(xpath, &volNum, &dir);
|
||||
|
||||
if(myErr == noErr) {
|
||||
myErr = FindFolder(volNum, kApplicationSupportFolderType, TRUE, &vRef, &dir);
|
||||
newDir=-1;
|
||||
if (myErr == noErr) {
|
||||
myErr = DirCreate(volNum,
|
||||
dir,
|
||||
"\pICU",
|
||||
&newDir);
|
||||
if( (myErr == noErr) || (myErr == dupFNErr) ) {
|
||||
spec.vRefNum = volNum;
|
||||
spec.parID = dir;
|
||||
uprv_memcpy(spec.name, "\pICU", 4);
|
||||
|
||||
myErr = FSpGetFullPath(&spec, &len, &full);
|
||||
if(full != NULL)
|
||||
{
|
||||
HLock(full);
|
||||
uprv_memcpy(pathBuffer, ((char*)(*full)), len);
|
||||
pathBuffer[len] = 0;
|
||||
path = pathBuffer;
|
||||
DisposeHandle(full);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
# endif
|
||||
# ifdef WIN32
|
||||
/* next, try to read the path from the registry */
|
||||
if(path==NULL || *path==0) {
|
||||
HKEY key;
|
||||
|
||||
if(ERROR_SUCCESS==RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\ICU\\Unicode\\Data", 0, KEY_QUERY_VALUE, &key)) {
|
||||
DWORD type=REG_EXPAND_SZ, size=sizeof(pathBuffer);
|
||||
|
||||
if(ERROR_SUCCESS==RegQueryValueEx(key, "Path", NULL, &type, (unsigned char *)pathBuffer, &size) && size>1) {
|
||||
if(type==REG_EXPAND_SZ) {
|
||||
/* replace environment variable references by their values */
|
||||
char temporaryPath[1024];
|
||||
|
||||
/* copy the path with variables to the temporary one */
|
||||
uprv_memcpy(temporaryPath, pathBuffer, size);
|
||||
|
||||
/* do the replacement and store it in the pathBuffer */
|
||||
size=ExpandEnvironmentStrings(temporaryPath, pathBuffer, sizeof(pathBuffer));
|
||||
if(size>0 && size<sizeof(pathBuffer)) {
|
||||
path=pathBuffer;
|
||||
}
|
||||
} else if(type==REG_SZ) {
|
||||
path=pathBuffer;
|
||||
}
|
||||
}
|
||||
RegCloseKey(key);
|
||||
}
|
||||
}
|
||||
# endif
|
||||
|
||||
/* before being fancy, check if we can find the right kind of
|
||||
data in the hardcoded path */
|
||||
if(path==NULL || *path==0) {
|
||||
char fileBuffer[1024]; /* XXX sloppy, should be FILE_MAX. */
|
||||
FileStream *f;
|
||||
|
||||
/* ICU_DATA_DIR may be set as a compile option */
|
||||
# ifdef ICU_DATA_DIR
|
||||
path=ICU_DATA_DIR;
|
||||
# else
|
||||
length=getSystemPath(pathBuffer, sizeof(pathBuffer));
|
||||
if(length>0) {
|
||||
uprv_strcpy(pathBuffer+length, FALLBACK_PATH);
|
||||
path=pathBuffer;
|
||||
} else {
|
||||
path=FALLBACK_PATH;
|
||||
}
|
||||
# endif
|
||||
|
||||
length = uprv_strlen(path);
|
||||
uprv_memcpy(fileBuffer, path, length);
|
||||
|
||||
/* produce the path of a file that should be here given the way
|
||||
that ICU was compiled; if it's here in the hardcoded location,
|
||||
we should just use the hardcoded path without further
|
||||
guessing */
|
||||
# if defined(UDATA_DLL)
|
||||
uprv_strcpy(fileBuffer + length, U_FILE_SEP_STRING LIB_PREFIX U_ICUDATA_NAME UDATA_SO_SUFFIX);
|
||||
# elif defined(UDATA_MAP)
|
||||
uprv_strcpy(fileBuffer + length, U_FILE_SEP_STRING U_ICUDATA_NAME "." DATA_TYPE); /* XXX Sloppy, won't be good enough on OS390 probably. */
|
||||
# elif defined(UDATA_FILES)
|
||||
uprv_strcpy(fileBuffer + length, U_FILE_SEP_STRING "uprops.dat");
|
||||
# endif
|
||||
|
||||
f = T_FileStream_open(fileBuffer, "rb"); /* XXX Sloppy, use stat(). */
|
||||
if (f) {
|
||||
T_FileStream_close(f); /* found it, keep path */
|
||||
} else {
|
||||
path = NULL; /* not found, reset path */
|
||||
}
|
||||
}
|
||||
|
||||
/* next, try to get the path to the ICU dynamic library */
|
||||
if(path==NULL || *path==0) {
|
||||
length=getLibraryPath(pathBuffer, sizeof(pathBuffer));
|
||||
if(length>0) {
|
||||
uprv_strcpy(pathBuffer+length, U_FILE_SEP_STRING ".." FALLBACK_PATH);
|
||||
path=pathBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
/* next, search for the ICU dynamic library */
|
||||
if(path==NULL || *path==0) {
|
||||
length=findLibraryPath(pathBuffer, sizeof(pathBuffer));
|
||||
if(length>0) {
|
||||
uprv_strcpy(pathBuffer+length, U_FILE_SEP_STRING ".." FALLBACK_PATH);
|
||||
path=pathBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
/* last resort: use hardcoded path */
|
||||
if(path==NULL || *path==0) {
|
||||
/* ICU_DATA_DIR may be set as a compile option */
|
||||
# ifdef ICU_DATA_DIR
|
||||
path=ICU_DATA_DIR;
|
||||
# else
|
||||
length=getSystemPath(pathBuffer, sizeof(pathBuffer));
|
||||
if(length>0) {
|
||||
uprv_strcpy(pathBuffer+length, FALLBACK_PATH);
|
||||
path=pathBuffer;
|
||||
} else {
|
||||
path=FALLBACK_PATH;
|
||||
}
|
||||
# endif
|
||||
}
|
||||
|
||||
u_setDataDirectory(path);
|
||||
if(gHaveDataDirectory) {
|
||||
return gDataDirectory;
|
||||
}
|
||||
|
||||
/* we did set the directory if necessary */
|
||||
/* we need to look for it */
|
||||
pathBuffer[0] = 0; /* Shuts up compiler warnings about unreferenced */
|
||||
/* variables when the code using it is ifdefed out */
|
||||
# if !defined(XP_MAC)
|
||||
/* first try to get the environment variable */
|
||||
path=getenv("ICU_DATA");
|
||||
# else /* XP_MAC */
|
||||
{
|
||||
OSErr myErr;
|
||||
short vRef;
|
||||
long dir,newDir;
|
||||
int16_t volNum;
|
||||
Str255 xpath;
|
||||
FSSpec spec;
|
||||
short len;
|
||||
Handle full;
|
||||
|
||||
xpath[0]=0;
|
||||
|
||||
myErr = HGetVol(xpath, &volNum, &dir);
|
||||
|
||||
if(myErr == noErr) {
|
||||
myErr = FindFolder(volNum, kApplicationSupportFolderType, TRUE, &vRef, &dir);
|
||||
newDir=-1;
|
||||
if (myErr == noErr) {
|
||||
myErr = DirCreate(volNum,
|
||||
dir,
|
||||
"\pICU",
|
||||
&newDir);
|
||||
if( (myErr == noErr) || (myErr == dupFNErr) ) {
|
||||
spec.vRefNum = volNum;
|
||||
spec.parID = dir;
|
||||
uprv_memcpy(spec.name, "\pICU", 4);
|
||||
|
||||
myErr = FSpGetFullPath(&spec, &len, &full);
|
||||
if(full != NULL)
|
||||
{
|
||||
HLock(full);
|
||||
uprv_memcpy(pathBuffer, ((char*)(*full)), len);
|
||||
pathBuffer[len] = 0;
|
||||
path = pathBuffer;
|
||||
DisposeHandle(full);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
# endif
|
||||
|
||||
|
||||
# if defined WIN32 && defined ICU_ENABLE_DEPRECATED_WIN_REGISTRY
|
||||
/* next, try to read the path from the registry */
|
||||
if(path==NULL || *path==0) {
|
||||
HKEY key;
|
||||
|
||||
if(ERROR_SUCCESS==RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\ICU\\Unicode\\Data", 0, KEY_QUERY_VALUE, &key)) {
|
||||
DWORD type=REG_EXPAND_SZ, size=sizeof(pathBuffer);
|
||||
|
||||
if(ERROR_SUCCESS==RegQueryValueEx(key, "Path", NULL, &type, (unsigned char *)pathBuffer, &size) && size>1) {
|
||||
if(type==REG_EXPAND_SZ) {
|
||||
/* replace environment variable references by their values */
|
||||
char temporaryPath[1024];
|
||||
|
||||
/* copy the path with variables to the temporary one */
|
||||
uprv_memcpy(temporaryPath, pathBuffer, size);
|
||||
|
||||
/* do the replacement and store it in the pathBuffer */
|
||||
size=ExpandEnvironmentStrings(temporaryPath, pathBuffer, sizeof(pathBuffer));
|
||||
if(size>0 && size<sizeof(pathBuffer)) {
|
||||
path=pathBuffer;
|
||||
}
|
||||
} else if(type==REG_SZ) {
|
||||
path=pathBuffer;
|
||||
}
|
||||
}
|
||||
RegCloseKey(key);
|
||||
}
|
||||
}
|
||||
# endif
|
||||
|
||||
/* ICU_DATA_DIR may be set as a compile option */
|
||||
# ifdef ICU_DATA_DIR
|
||||
if(path==NULL || *path==0) {
|
||||
path=ICU_DATA_DIR;
|
||||
}
|
||||
# endif
|
||||
|
||||
u_setDataDirectory(path);
|
||||
return gDataDirectory;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Macintosh-specific locale information ------------------------------------ */
|
||||
#ifdef XP_MAC
|
||||
|
||||
|
@ -141,13 +141,40 @@ U_CAPI char* U_EXPORT2 uprv_tzname(int n);
|
||||
U_CAPI int32_t U_EXPORT2 uprv_getUTCtime(void);
|
||||
|
||||
/**
|
||||
* Return the data directory for this platform.
|
||||
* Return the ICU data directory.
|
||||
* The data directory is where common format ICU data files (.dat files)
|
||||
* are loaded from. Note that normal use of the built-in ICU
|
||||
* facilities does not require loading of an external data file;
|
||||
* unless you are adding custom data to ICU, the data directory
|
||||
* does not need to be set.
|
||||
*
|
||||
* The data directory is determined as follows:
|
||||
* If u_setDataDirectory() has been called, that is it, otherwise
|
||||
* if the ICU_DATA environment variable is set, use that, otherwise
|
||||
* On Windows, if the SOFTWARE\ICU\Unicode\Data registry entry exists, use that
|
||||
* (use of the registry in this way is not recommended.) otherwise
|
||||
* If a data directory was specifed at ICU build time, use that
|
||||
* otherwise no data directory is available.
|
||||
*
|
||||
*@return the data directory, or an empty string ("") if no data directory has
|
||||
* been specified.
|
||||
*
|
||||
* @draft
|
||||
*/
|
||||
U_CAPI const char* U_EXPORT2 u_getDataDirectory(void);
|
||||
|
||||
/**
|
||||
* Set the data directory.
|
||||
* Set the ICU data directory.
|
||||
* The data directory is where common format ICU data files (.dat files)
|
||||
* are loaded from. Note that normal use of the built-in ICU
|
||||
* facilities does not require loading of an external data file;
|
||||
* unless you are adding custom data to ICU, the data directory
|
||||
* does not need to be set.
|
||||
*
|
||||
* This function should be called at most once in a process, before the
|
||||
* first ICU operation that will require the loading of an ICU data file.
|
||||
*
|
||||
|
||||
* @draft
|
||||
*/
|
||||
U_CAPI void U_EXPORT2 u_setDataDirectory(const char *directory);
|
||||
|
Loading…
Reference in New Issue
Block a user