U_CAPI void U_EXPORT2 udata_setCommonData(const void *data, UErrorCode *pErrorCode) { UDataMemory dataMemory; if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) { return; } if(data==NULL) { *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; return; } /* do we already have common ICU data set? */ if(gCommonICUData != NULL) { *pErrorCode=U_USING_DEFAULT_WARNING; return; } /* set the data pointer and test for validity */ UDataMemory_init(&dataMemory); UDataMemory_setData(&dataMemory, data); udata_checkCommonData(&dataMemory, pErrorCode); if (U_FAILURE(*pErrorCode)) {return;} /* we have good data */ /* Set it up as the ICU Common Data. */ setCommonICUData(&dataMemory, NULL, TRUE, pErrorCode); }
UBool uprv_mapFile( UDataMemory *pData, /* Fill in with info on the result doing the mapping. */ /* Output only; any original contents are cleared. */ const char *path /* File path to be opened/mapped */ ) { HANDLE map; HANDLE file; SECURITY_ATTRIBUTES mappingAttributes; SECURITY_ATTRIBUTES *mappingAttributesPtr = NULL; SECURITY_DESCRIPTOR securityDesc; UDataMemory_init(pData); /* Clear the output struct. */ /* open the input file */ file=CreateFile(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_RANDOM_ACCESS, NULL); if(file==INVALID_HANDLE_VALUE) { return FALSE; } /* Declare and initialize a security descriptor. This is required for multiuser systems on Windows 2000 SP4 and beyond */ if (InitializeSecurityDescriptor(&securityDesc, SECURITY_DESCRIPTOR_REVISION)) { /* give the security descriptor a Null Dacl done using the "TRUE, (PACL)NULL" here */ if (SetSecurityDescriptorDacl(&securityDesc, TRUE, (PACL)NULL, FALSE)) { /* Make the security attributes point to the security descriptor */ uprv_memset(&mappingAttributes, 0, sizeof(mappingAttributes)); mappingAttributes.nLength = sizeof(mappingAttributes); mappingAttributes.lpSecurityDescriptor = &securityDesc; mappingAttributes.bInheritHandle = FALSE; /* object uninheritable */ mappingAttributesPtr = &mappingAttributes; } } /* else creating security descriptors can fail when we are on Windows 98, and mappingAttributesPtr == NULL for that case. */ /* create an unnamed Windows file-mapping object for the specified file */ map=CreateFileMapping(file, mappingAttributesPtr, PAGE_READONLY, 0, 0, NULL); CloseHandle(file); if(map==NULL) { return FALSE; } /* map a view of the file into our address space */ pData->pHeader=(const DataHeader *)MapViewOfFile(map, FILE_MAP_READ, 0, 0, 0); if(pData->pHeader==NULL) { CloseHandle(map); return FALSE; } pData->map=map; return TRUE; }
U_CAPI void U_EXPORT2 udata_close(UDataMemory *pData) { if(pData!=NULL) { uprv_unmapFile(pData); if(pData->heapAllocated ) { uprv_free(pData); } else { UDataMemory_init(pData); } } }
UDataMemory *UDataMemory_createNewInstance(UErrorCode *pErr) { UDataMemory *This; if (U_FAILURE(*pErr)) { return NULL; } This = uprv_malloc(sizeof(UDataMemory)); if (This == NULL) { *pErr = U_MEMORY_ALLOCATION_ERROR; } else { UDataMemory_init(This); This->heapAllocated = TRUE; } return This; }
static UBool extendICUData(UDataMemory *failedData, UErrorCode *pErr) { /* If the data library that we are running with turns out to be the * stub library (or, on the 390, the subset library), we will try to * load a .dat file instead. The stub library has no entries in its * TOC, which is how we identify it here. */ UDataMemory *pData; UDataMemory copyPData; if (failedData->vFuncs->NumEntries(failedData) > MAX_STUB_ENTRIES) { /* Not the stub. We can't extend. */ return FALSE; } /* See if we can explicitly open a .dat file for the ICUData. */ pData = openCommonData( U_ICUDATA_NAME, /* "icudt20l" , for example. */ FALSE, /* Pretend we're not opening ICUData */ pErr); /* How about if there is no pData, eh... */ UDataMemory_init(©PData); if(pData != NULL) { UDatamemory_assign(©PData, pData); copyPData.map = 0; /* The mapping for this data is owned by the hash table */ copyPData.mapAddr = 0; /* which will unmap it when ICU is shut down. */ /* CommonICUData is also unmapped when ICU is shut down.*/ /* To avoid unmapping the data twice, zero out the map */ /* fields in the UDataMemory that we're assigning */ /* to CommonICUData. */ setCommonICUData(©PData, /* The new common data. */ failedData, /* Old ICUData ptr. Overwrite of this value is ok, */ FALSE, /* No warnings if write didn't happen */ pErr); /* setCommonICUData honors errors; NOP if error set */ } return gCommonICUData != failedData; /* Return true if ICUData pointer was updated. */ /* (Could potentialy have been done by another thread racing */ /* us through here, but that's fine, we still return true */ /* so that current thread will also examine extended data. */ }
U_CAPI void U_EXPORT2 udata_setAppData(const char *path, const void *data, UErrorCode *err) { UDataMemory udm; if(err==NULL || U_FAILURE(*err)) { return; } if(data==NULL) { *err=U_ILLEGAL_ARGUMENT_ERROR; return; } UDataMemory_init(&udm); UDataMemory_setData(&udm, data); udata_checkCommonData(&udm, err); udata_cacheDataItem(path, &udm, err); }
UBool uprv_mapFile(UDataMemory *pData, const char *path) { FILE *file; int32_t fileLength; void *p; UDataMemory_init(pData); /* Clear the output struct. */ /* open the input file */ file=fopen(path, "rb"); if(file==NULL) { return FALSE; } /* get the file length */ fileLength=umap_fsize(file); if(ferror(file) || fileLength<=20) { fclose(file); return FALSE; } /* allocate the memory to hold the file data */ p=uprv_malloc(fileLength); if(p==NULL) { fclose(file); return FALSE; } /* read the file */ if(fileLength!=fread(p, 1, fileLength, file)) { uprv_free(p); fclose(file); return FALSE; } fclose(file); pData->map=p; pData->pHeader=(const DataHeader *)p; pData->mapAddr=p; return TRUE; }
U_CFUNC UBool uprv_mapFile(UDataMemory *pData, const char *path) { int fd; int length; struct stat mystat; void *data; UDataMemory_init(pData); /* Clear the output struct. */ /* determine the length of the file */ if(stat(path, &mystat)!=0 || mystat.st_size<=0) { return FALSE; } length=mystat.st_size; /* open the file */ fd=open(path, O_RDONLY); if(fd==-1) { return FALSE; } /* get a view of the mapping */ #if U_PLATFORM != U_PF_HPUX data=mmap(0, length, PROT_READ, MAP_SHARED, fd, 0); #else data=mmap(0, length, PROT_READ, MAP_PRIVATE, fd, 0); #endif close(fd); /* no longer needed */ if(data==MAP_FAILED) { return FALSE; } pData->map = (char *)data + length; pData->pHeader=(const DataHeader *)data; pData->mapAddr = data; #if U_PLATFORM == U_PF_IPHONE posix_madvise(data, length, POSIX_MADV_RANDOM); #endif return TRUE; }
static UDataMemory * openCommonData(const char *path, /* Path from OpenChoice? */ UBool isICUData, /* ICU Data true if path == NULL */ UErrorCode *pErrorCode) { UDataMemory tData; UDataPathIterator iter; const char *pathBuffer; const char *inBasename; if (U_FAILURE(*pErrorCode)) { return NULL; } UDataMemory_init(&tData); /* ??????? TODO revisit this */ if (isICUData) { /* "mini-cache" for common ICU data */ if(gCommonICUData != NULL) { return gCommonICUData; } tData.pHeader = &U_ICUDATA_ENTRY_POINT.hdr; udata_checkCommonData(&tData, pErrorCode); setCommonICUData(&tData, NULL, FALSE, pErrorCode); return gCommonICUData; } /* request is NOT for ICU Data. */ /* Find the base name portion of the supplied path. */ /* inBasename will be left pointing somewhere within the original path string. */ inBasename = findBasename(path); #ifdef UDATA_DEBUG fprintf(stderr, "inBasename = %s\n", inBasename); #endif if(*inBasename==0) { /* no basename. This will happen if the original path was a directory name, */ /* like "a/b/c/". (Fallback to separate files will still work.) */ #ifdef UDATA_DEBUG fprintf(stderr, "ocd: no basename in %s, bailing.\n", path); #endif *pErrorCode=U_FILE_ACCESS_ERROR; return NULL; } /* Is the requested common data file already open and cached? */ /* Note that the cache is keyed by the base name only. The rest of the path, */ /* if any, is not considered. */ { UDataMemory *dataToReturn = udata_findCachedData(inBasename); if (dataToReturn != NULL) { return dataToReturn; } } /* Requested item is not in the cache. * Hunt it down, trying all the path locations */ udata_pathiter_init(&iter, u_getDataDirectory(), inBasename, path, ".dat", TRUE); while((UDataMemory_isLoaded(&tData)==FALSE) && (pathBuffer = udata_pathiter_next(&iter)) != NULL) { #ifdef UDATA_DEBUG fprintf(stderr, "ocd: trying path %s - ", pathBuffer); #endif uprv_mapFile(&tData, pathBuffer); #ifdef UDATA_DEBUG fprintf(stderr, "%s\n", UDataMemory_isLoaded(&tData)?"LOADED":"not loaded"); #endif } udata_pathiter_dt(&iter); /* Note: this call may invalidate "pathBuffer" */ #if defined(OS390_STUBDATA) && defined(OS390BATCH) if (!UDataMemory_isLoaded(&tData)) { char ourPathBuffer[1024]; /* One more chance, for extendCommonData() */ uprv_strncpy(ourPathBuffer, path, 1019); ourPathBuffer[1019]=0; uprv_strcat(ourPathBuffer, ".dat"); uprv_mapFile(&tData, ourPathBuffer); } #endif if (!UDataMemory_isLoaded(&tData)) { /* no common data */ *pErrorCode=U_FILE_ACCESS_ERROR; return NULL; } /* we have mapped a file, check its header */ udata_checkCommonData(&tData, pErrorCode); /* Cache the UDataMemory struct for this .dat file, * so we won't need to hunt it down and map it again next time * something is needed from it. */ return udata_cacheDataItem(inBasename, &tData, pErrorCode); }
UBool uprv_mapFile(UDataMemory *pData, const char *path) { const char *inBasename; char *basename; char pathBuffer[1024]; const DataHeader *pHeader; dllhandle *handle; void *val=0; inBasename=uprv_strrchr(path, U_FILE_SEP_CHAR); if(inBasename==NULL) { inBasename = path; } else { inBasename++; } basename=uprv_computeDirPath(path, pathBuffer); if(uprv_strcmp(inBasename, U_ICUDATA_NAME".dat") != 0) { /* must mmap file... for build */ int fd; int length; struct stat mystat; void *data; UDataMemory_init(pData); /* Clear the output struct. */ /* determine the length of the file */ if(stat(path, &mystat)!=0 || mystat.st_size<=0) { return FALSE; } length=mystat.st_size; /* open the file */ fd=open(path, O_RDONLY); if(fd==-1) { return FALSE; } /* get a view of the mapping */ data=mmap(0, length, PROT_READ, MAP_PRIVATE, fd, 0); close(fd); /* no longer needed */ if(data==MAP_FAILED) { return FALSE; } pData->map = (char *)data + length; pData->pHeader=(const DataHeader *)data; pData->mapAddr = data; return TRUE; } # ifdef OS390BATCH /* ### hack: we still need to get u_getDataDirectory() fixed for OS/390 (batch mode - always return "//"? ) and this here straightened out with LIB_PREFIX and LIB_SUFFIX (both empty?!) This is probably due to the strange file system on OS/390. It's more like a database with short contentEntry names than a typical file system. */ /* U_ICUDATA_NAME should always have the correct name */ /* BUT FOR BATCH MODE IT IS AN EXCEPTION BECAUSE */ /* THE FIRST THREE LETTERS ARE PREASSIGNED TO THE */ /* PROJECT!!!!! */ uprv_strcpy(pathBuffer, "IXMI" U_ICU_VERSION_SHORT "DA"); # else /* set up the library name */ uprv_strcpy(basename, LIB_PREFIX U_LIBICUDATA_NAME U_ICU_VERSION_SHORT LIB_SUFFIX); # endif # ifdef UDATA_DEBUG fprintf(stderr, "dllload: %s ", pathBuffer); # endif handle=dllload(pathBuffer); # ifdef UDATA_DEBUG fprintf(stderr, " -> %08X\n", handle ); # endif if(handle != NULL) { /* we have a data DLL - what kind of lookup do we need here? */ /* try to find the Table of Contents */ UDataMemory_init(pData); /* Clear the output struct. */ val=dllqueryvar((dllhandle*)handle, U_ICUDATA_ENTRY_NAME); if(val == 0) { /* failed... so keep looking */ return FALSE; } # ifdef UDATA_DEBUG fprintf(stderr, "dllqueryvar(%08X, %s) -> %08X\n", handle, U_ICUDATA_ENTRY_NAME, val); # endif pData->pHeader=(const DataHeader *)val; return TRUE; } else { return FALSE; /* no handle */ } }
UBool uprv_mapFile(UDataMemory *pData, const char *path) { UDataMemory_init(pData); /* Clear the output struct. */ return FALSE; /* no file access */ }