00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "unicode/utypes.h"
00018 #include "unicode/putil.h"
00019 #include "umutex.h"
00020 #include "cmemory.h"
00021 #include "cstring.h"
00022 #include "unicode/udata.h"
00023
00024
00025
00026 #if !defined(HAVE_DLOPEN)
00027 # define HAVE_DLOPEN 0
00028 #endif
00029
00030 #if !defined(UDATA_DLL) && !defined(UDATA_MAP)
00031 # define UDATA_DLL
00032 #endif
00033
00034 #define COMMON_DATA_NAME U_ICUDATA_NAME
00035 #define COMMON_DATA_NAME_LENGTH 8
00036
00037
00038 #define DATA_TYPE "dat"
00039
00040
00041
00042
00043 #if defined(UDATA_DEBUG)
00044 # include <stdio.h>
00045 #endif
00046
00047
00048
00049 #ifdef WIN32
00050 # include <windows.h>
00051
00052 typedef HINSTANCE Library;
00053
00054 # define LIB_SUFFIX ".dll"
00055
00056 # define NO_LIBRARY NULL
00057 # define IS_LIBRARY(lib) ((lib)!=NULL)
00058 # define LOAD_LIBRARY(path, basename) LoadLibrary(path)
00059 # define UNLOAD_LIBRARY(lib) FreeLibrary(lib)
00060
00061 # define GET_LIBRARY_ENTRY(lib, entryName) GetProcAddress(lib, entryName)
00062
00063 #elif HAVE_DLOPEN
00064 # ifndef UDATA_SO_SUFFIX
00065 # error Please define UDATA_SO_SUFFIX to the shlib suffix (i.e. '.so' )
00066 # endif
00067
00068 # define LIB_PREFIX "lib"
00069 # define LIB_PREFIX_LENGTH 3
00070 # define LIB_SUFFIX UDATA_SO_SUFFIX
00071
00072 # ifdef ICU_USE_SHL_LOAD
00073
00074
00075
00076 # define RTLD_LAZY 0
00077 # define RTLD_GLOBAL 0
00078
00079 # ifdef OS390
00080 # include <dll.h>
00081
00082 # define RTLD_LAZY 0
00083 # define RTLD_GLOBAL 0
00084
00085 void *dlopen(const char *filename, int flag) {
00086 dllhandle *handle;
00087
00088 # ifdef UDATA_DEBUG
00089 fprintf(stderr, "dllload: %s ", filename);
00090 # endif
00091 handle=dllload(filename);
00092 # ifdef UDATA_DEBUG
00093 fprintf(stderr, " -> %08X\n", handle );
00094 # endif
00095 return handle;
00096 }
00097
00098 void *dlsym(void *h, const char *symbol) {
00099 void *val=0;
00100 val=dllqueryvar((dllhandle*)h,symbol);
00101 # ifdef UDATA_DEBUG
00102 fprintf(stderr, "dllqueryvar(%08X, %s) -> %08X\n", h, symbol, val);
00103 # endif
00104 return val;
00105 }
00106
00107 int dlclose(void *handle) {
00108 # ifdef UDATA_DEBUG
00109 fprintf(stderr, "dllfree: %08X\n", handle);
00110 # endif
00111 return dllfree((dllhandle*)handle);
00112 }
00113 # else
00114 # include <dl.h>
00115
00116 void *dlopen (const char *filename, int flag) {
00117 void *handle;
00118 # ifdef UDATA_DEBUG
00119 fprintf(stderr, "shl_load: %s ", filename);
00120 # endif
00121 handle=shl_load(filename, BIND_NONFATAL | BIND_DEFERRED | DYNAMIC_PATH, 0L);
00122 # ifdef UDATA_DEBUG
00123 fprintf(stderr, " -> %08X\n", handle );
00124 # endif
00125 return handle;
00126 }
00127
00128 void *dlsym(void *h, char *symbol) {
00129 void *val=0;
00130 int rv;
00131 shl_t mysh;
00132
00133 mysh=(shl_t)h;
00134
00135 rv=shl_findsym(&mysh, symbol, TYPE_DATA, (void*)&val);
00136 # ifdef UDATA_DEBUG
00137 fprintf(stderr, "shl_findsym(%08X, %s) -> %08X [%d]\n", h, symbol, val, rv);
00138 # endif
00139 return val;
00140 }
00141
00142 int dlclose (void *handle) {
00143 # ifndef HPUX
00144 # ifdef UDATA_DEBUG
00145 fprintf(stderr, "shl_unload: %08X\n", handle);
00146 # endif
00147 return shl_unload((shl_t)handle);
00148 # else
00149
00150
00151
00152
00153
00154 return 0;
00155 # endif
00156 }
00157 # endif
00158 # else
00159
00160 # include <dlfcn.h>
00161 #ifndef RTLD_GLOBAL
00162 #define RTLD_GLOBAL 0
00163 #endif
00164 # endif
00165
00166 typedef void *Library;
00167
00168 # define NO_LIBRARY NULL
00169 # define IS_LIBRARY(lib) ((lib)!=NULL)
00170
00171
00172 #ifndef UDATA_DEBUG
00173 # define LOAD_LIBRARY(path, basename) dlopen(path, RTLD_LAZY|RTLD_GLOBAL)
00174 # define UNLOAD_LIBRARY(lib) dlclose(lib)
00175 # define GET_LIBRARY_ENTRY(lib, entryName) dlsym(lib, entryName)
00176 #else
00177 void *LOAD_LIBRARY(const char *path, const char *basename)
00178 {
00179 void *rc;
00180 rc = dlopen(path, RTLD_LAZY|RTLD_GLOBAL);
00181 fprintf(stderr, "Load [%s|%s] -> %p\n", path, basename, rc);
00182 return rc;
00183 }
00184 void UNLOAD_LIBRARY(void *lib)
00185 {
00186 dlclose(lib);
00187 fprintf(stderr, "Unload [%p]\n", lib);
00188 }
00189 void * GET_LIBRARY_ENTRY(void *lib, const char *entryName)
00190 {
00191 void *rc;
00192 rc = dlsym(lib, entryName);
00193 fprintf(stderr, "Get[%p] %s->%p\n", lib, entryName, rc);
00194 return rc;
00195 }
00196 #endif
00197
00198
00199 #else
00200 # ifndef UDATA_NO_DLL
00201 # define UDATA_NO_DLL 1
00202 # endif
00203 typedef const void *Library;
00204
00205 # define NO_LIBRARY NULL
00206 # define IS_LIBRARY(lib) ((lib)!=NULL)
00207 # define LOAD_LIBRARY(path, basename) NULL
00208 # define UNLOAD_LIBRARY(lib) ;
00209
00210 # define GET_LIBRARY_ENTRY(lib, entryName) NULL
00211
00212 #endif
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222 #define MAP_WIN32 1
00223 #define MAP_POSIX 2
00224 #define MAP_FILE_STREAM 3
00225
00226 #ifdef WIN32
00227 typedef HANDLE MemoryMap;
00228
00229 # define NO_MAP NULL
00230 # define IS_MAP(map) ((map)!=NULL)
00231
00232 # define MAP_IMPLEMENTATION MAP_WIN32
00233
00234
00235 #elif HAVE_MMAP || defined(U_LINUX) || defined(POSIX) || defined(U_SOLARIS) || defined(AIX) || defined(HPUX) || defined(OS390) || defined(PTX)
00236 typedef size_t MemoryMap;
00237
00238 # define NO_MAP 0
00239 # define IS_MAP(map) ((map)!=0)
00240
00241 # include <unistd.h>
00242 # include <sys/mman.h>
00243 # include <sys/stat.h>
00244 # include <fcntl.h>
00245
00246 # ifndef MAP_FAILED
00247 # define MAP_FAILED ((void*)-1)
00248 # endif
00249
00250 # define MAP_IMPLEMENTATION MAP_POSIX
00251
00252 #else
00253
00254 # include "filestrm.h"
00255
00256 typedef void *MemoryMap;
00257
00258 # define NO_MAP NULL
00259 # define IS_MAP(map) ((map)!=NULL)
00260
00261 # define MAP_IMPLEMENTATION MAP_FILE_STREAM
00262
00263 #endif
00264
00265
00266
00267
00268 enum {
00269 NO_DATA_MEMORY,
00270 FLAT_DATA_MEMORY,
00271 DLL_DATA_MEMORY
00272 };
00273
00274
00275 enum {
00276 NO_TOC,
00277 OFFSET_TOC,
00278 POINTER_TOC,
00279 DLL_INTRINSIC_TOC
00280 };
00281
00282
00283 #define DATA_MEMORY_TYPE_MASK 0xf
00284 #define TOC_TYPE_SHIFT 4
00285 #define TOC_TYPE_MASK 0xf
00286 #define SET_DATA_POINTER_SHIFT 30
00287 #define DYNAMIC_DATA_MEMORY_SHIFT 31
00288
00289 typedef struct {
00290 uint16_t headerSize;
00291 uint8_t magic1, magic2;
00292 } MappedData;
00293
00294 typedef struct {
00295 MappedData dataHeader;
00296 UDataInfo info;
00297 } DataHeader;
00298
00299 typedef const DataHeader *
00300 LookupFn(const UDataMemory *pData,
00301 const char *tocEntryName,
00302 const char *dllEntryName,
00303 UErrorCode *pErrorCode);
00304
00305 struct UDataMemory {
00306 UDataMemory *parent;
00307 Library lib;
00308 MemoryMap map;
00309 LookupFn *lookupFn;
00310 const void *toc;
00311 const DataHeader *pHeader;
00312 uint32_t flags;
00313 int32_t refCount;
00314 };
00315
00316 #define IS_DATA_MEMORY_LOADED(pData) ((pData)->flags!=0)
00317
00318 typedef struct {
00319 const char *entryName;
00320 const DataHeader *pHeader;
00321 } PointerTOCEntry;
00322
00323
00324
00325 #if MAP_IMPLEMENTATION==MAP_WIN32
00326 static UBool
00327 uprv_mapFile(UDataMemory *pData, const char *path, const char *basename) {
00328 char buffer[200];
00329 HANDLE map;
00330 char *p;
00331
00332
00333 uprv_strcpy(buffer, "icu" U_ICU_VERSION " ");
00334 uprv_strcat(buffer, path);
00335
00336
00337 for(p=buffer; *p; p++) {
00338 if (*p == '\\') {
00339 *p = '/';
00340 }
00341 }
00342
00343
00344 map=OpenFileMapping(FILE_MAP_READ, FALSE, buffer);
00345 if(map==NULL) {
00346
00347 HANDLE file;
00348
00349
00350 file=CreateFile(path, GENERIC_READ, FILE_SHARE_READ, NULL,
00351 OPEN_EXISTING,
00352 FILE_ATTRIBUTE_NORMAL|FILE_FLAG_RANDOM_ACCESS, NULL);
00353 if(file==INVALID_HANDLE_VALUE) {
00354 return FALSE;
00355 }
00356
00357
00358 map=CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, buffer);
00359 CloseHandle(file);
00360 if(map==NULL) {
00361 return FALSE;
00362 }
00363 }
00364
00365
00366 pData->pHeader=(const DataHeader *)MapViewOfFile(map, FILE_MAP_READ, 0, 0, 0);
00367 if(pData->pHeader==NULL) {
00368 CloseHandle(map);
00369 return FALSE;
00370 }
00371 pData->map=map;
00372 pData->flags=FLAT_DATA_MEMORY;
00373 return TRUE;
00374 }
00375
00376 static void
00377 uprv_unmapFile(UDataMemory *pData) {
00378 if(pData!=NULL && pData->map!=NULL) {
00379 UnmapViewOfFile(pData->pHeader);
00380 CloseHandle(pData->map);
00381 pData->pHeader=NULL;
00382 pData->map=NULL;
00383 }
00384 }
00385
00386 #elif MAP_IMPLEMENTATION==MAP_POSIX
00387 static UBool
00388 uprv_mapFile(UDataMemory *pData, const char *path, const char *basename) {
00389 int fd;
00390 int length;
00391 const char *dataDir;
00392 struct stat mystat;
00393 const void *data;
00394
00395
00396 if(stat(path, &mystat)!=0 || mystat.st_size<=0) {
00397 return FALSE;
00398 }
00399 length=mystat.st_size;
00400
00401
00402 fd=open(path, O_RDONLY);
00403 if(fd==-1) {
00404 return FALSE;
00405 }
00406
00407
00408 #ifndef HPUX
00409 data=mmap(0, length, PROT_READ, MAP_SHARED, fd, 0);
00410 #else
00411 data=mmap(0, length, PROT_READ, MAP_PRIVATE, fd, 0);
00412 #endif
00413 close(fd);
00414 if(data==MAP_FAILED) {
00415
00416 # ifdef UDATA_DEBUG
00417 perror("mmap");
00418 # endif
00419
00420 return FALSE;
00421 }
00422
00423 # ifdef UDATA_DEBUG
00424 fprintf(stderr, "mmap of %s [%d bytes] succeeded, -> 0x%X\n", path, length, data);
00425 fflush(stderr);
00426 # endif
00427
00428 pData->map=length;
00429 pData->pHeader=(const DataHeader *)data;
00430 pData->flags=FLAT_DATA_MEMORY;
00431 return TRUE;
00432 }
00433
00434 static void
00435 uprv_unmapFile(UDataMemory *pData) {
00436 if(pData!=NULL && pData->map>0) {
00437 if(munmap((void *)pData->pHeader, pData->map)==-1) {
00438 # ifdef UDATA_DEBUG
00439 perror("munmap");
00440 # endif
00441 }
00442 pData->pHeader=NULL;
00443 pData->map=0;
00444 }
00445 }
00446
00447 #elif MAP_IMPLEMENTATION==MAP_FILE_STREAM
00448 static UBool
00449 uprv_mapFile(UDataMemory *pData, const char *path, const char *basename) {
00450 FileStream *file;
00451 int32_t fileLength;
00452 void *p;
00453
00454
00455 file=T_FileStream_open(path, "rb");
00456 if(file==NULL) {
00457 return FALSE;
00458 }
00459
00460
00461 fileLength=T_FileStream_size(file);
00462 if(T_FileStream_error(file) || fileLength<=20) {
00463 T_FileStream_close(file);
00464 return FALSE;
00465 }
00466
00467
00468 p=uprv_malloc(fileLength);
00469 if(p==NULL) {
00470 T_FileStream_close(file);
00471 return FALSE;
00472 }
00473
00474
00475 if(fileLength!=T_FileStream_read(file, p, fileLength)) {
00476 uprv_free(p);
00477 T_FileStream_close(file);
00478 return FALSE;
00479 }
00480
00481 T_FileStream_close(file);
00482 pData->map=p;
00483 pData->pHeader=(const DataHeader *)p;
00484 pData->flags=FLAT_DATA_MEMORY;
00485 return TRUE;
00486 }
00487
00488 static void
00489 uprv_unmapFile(UDataMemory *pData) {
00490 if(pData!=NULL && pData->map!=NULL) {
00491 uprv_free(pData->map);
00492 pData->map=NULL;
00493 }
00494 }
00495
00496 #else
00497 # error MAP_IMPLEMENTATION is set incorrectly
00498 #endif
00499
00500
00501
00502 static const DataHeader *
00503 normalizeDataPointer(const DataHeader *p) {
00504
00505 if(p==NULL || (p->dataHeader.magic1==0xda && p->dataHeader.magic2==0x27)) {
00506 return p;
00507 } else {
00508 return (const DataHeader *)((const double *)p+1);
00509 }
00510 }
00511
00512 static const DataHeader *
00513 offsetTOCLookupFn(const UDataMemory *pData,
00514 const char *tocEntryName,
00515 const char *dllEntryName,
00516 UErrorCode *pErrorCode) {
00517 #ifdef UDATA_DEBUG
00518 fprintf(stderr, "offsetTOC[%p] looking for %s/%s\n",
00519 pData,
00520 tocEntryName,dllEntryName);
00521 #endif
00522
00523 if(pData->toc!=NULL) {
00524 const char *base=(const char *)pData->toc;
00525 uint32_t *toc=(uint32_t *)pData->toc;
00526 uint32_t start, limit, number;
00527
00528
00529 start=0;
00530 limit=*toc++;
00531 while(start<limit-1) {
00532 number=(start+limit)/2;
00533 if(uprv_strcmp(tocEntryName, base+toc[2*number])<0) {
00534 limit=number;
00535 } else {
00536 start=number;
00537 }
00538 }
00539
00540 if(uprv_strcmp(tocEntryName, base+toc[2*start])==0) {
00541
00542 #ifdef UDATA_DEBUG
00543 fprintf(stderr, "Found: %p\n",(base+toc[2*start+1]));
00544 #endif
00545 return (const DataHeader *)(base+toc[2*start+1]);
00546 } else {
00547 #ifdef UDATA_DEBUG
00548 fprintf(stderr, "Not found.\n");
00549 #endif
00550 return NULL;
00551 }
00552 } else {
00553 #ifdef UDATA_DEBUG
00554 fprintf(stderr, "returning header\n");
00555 #endif
00556
00557 return pData->pHeader;
00558 }
00559 }
00560
00561 static const DataHeader *
00562 pointerTOCLookupFn(const UDataMemory *pData,
00563 const char *tocEntryName,
00564 const char *dllEntryName,
00565 UErrorCode *pErrorCode) {
00566 #ifdef UDATA_DEBUG
00567 fprintf(stderr, "ptrTOC[%p] looking for %s/%s\n",
00568 pData,
00569 tocEntryName,dllEntryName);
00570 #endif
00571 if(pData->toc!=NULL) {
00572 const PointerTOCEntry *toc=(const PointerTOCEntry *)((const uint32_t *)pData->toc+2);
00573 uint32_t start, limit, number;
00574
00575
00576 start=0;
00577 limit=*(const uint32_t *)pData->toc;
00578
00579 #ifdef UDATA_DEBUG
00580 fprintf(stderr, " # of ents: %d\n", limit);
00581 fflush(stderr);
00582 #endif
00583
00584 while(start<limit-1) {
00585 number=(start+limit)/2;
00586 if(uprv_strcmp(tocEntryName, toc[number].entryName)<0) {
00587 limit=number;
00588 } else {
00589 start=number;
00590 }
00591 }
00592
00593 if(uprv_strcmp(tocEntryName, toc[start].entryName)==0) {
00594
00595 #ifdef UDATA_DEBUG
00596 fprintf(stderr, "FOUND: %p\n",
00597 normalizeDataPointer(toc[start].pHeader));
00598 #endif
00599
00600 return normalizeDataPointer(toc[start].pHeader);
00601 } else {
00602 #ifdef UDATA_DEBUG
00603 fprintf(stderr, "NOT found\n");
00604 #endif
00605 return NULL;
00606 }
00607 } else {
00608 #ifdef UDATA_DEBUG
00609 fprintf(stderr, "Returning header\n");
00610 #endif
00611 return pData->pHeader;
00612 }
00613 }
00614
00615 static const DataHeader *
00616 dllTOCLookupFn(const UDataMemory *pData,
00617 const char *tocEntryName,
00618 const char *dllEntryName,
00619 UErrorCode *pErrorCode) {
00620 #ifndef UDATA_NO_DLL
00621 if(pData->lib!=NULL) {
00622 return normalizeDataPointer((const DataHeader *)GET_LIBRARY_ENTRY(pData->lib, dllEntryName));
00623 }
00624 #endif
00625 return NULL;
00626 }
00627
00628
00629
00630 static UDataMemory commonICUData={ NULL };
00631
00632 static void
00633 setCommonICUData(UDataMemory *pData) {
00634 UBool setThisLib=FALSE;
00635
00636
00637 umtx_lock(NULL);
00638 if(!IS_DATA_MEMORY_LOADED(&commonICUData)) {
00639 uprv_memcpy(&commonICUData, pData, sizeof(UDataMemory));
00640 commonICUData.flags&=~(1UL<<DYNAMIC_DATA_MEMORY_SHIFT);
00641 uprv_memset(pData, 0, sizeof(UDataMemory));
00642 setThisLib=TRUE;
00643 }
00644 umtx_unlock(NULL);
00645
00646
00647 if(!setThisLib) {
00648 udata_close(pData);
00649 }
00650 }
00651
00652 static char *
00653 strcpy_returnEnd(char *dest, const char *src) {
00654 while((*dest=*src)!=0) {
00655 ++dest;
00656 ++src;
00657 }
00658 return dest;
00659 }
00660
00661 static char *
00662 setPathGetBasename(const char *path, char *pathBuffer) {
00663
00664
00665 if(*pathBuffer!=0) {
00666
00667
00668
00669 return pathBuffer+uprv_strlen(pathBuffer);
00670 } else if(path==NULL) {
00671
00672 path=u_getDataDirectory();
00673 if(path!=NULL && *path!=0) {
00674 return strcpy_returnEnd(pathBuffer, path);
00675 } else {
00676
00677 return pathBuffer;
00678 }
00679 } else {
00680
00681 char *basename=uprv_strrchr(path, U_FILE_SEP_CHAR);
00682 if(basename==NULL) {
00683
00684 path=u_getDataDirectory();
00685 if(path!=NULL && *path!=0) {
00686 return strcpy_returnEnd(pathBuffer, path);
00687 } else {
00688
00689 return pathBuffer;
00690 }
00691 } else {
00692
00693 ++basename;
00694 uprv_memcpy(pathBuffer, path, basename-path);
00695 basename=pathBuffer+(basename-path);
00696 *basename=0;
00697 return basename;
00698 }
00699 }
00700 }
00701
00702 static const char *
00703 findBasename(const char *path) {
00704 const char *basename=uprv_strrchr(path, U_FILE_SEP_CHAR);
00705 if(basename==NULL) {
00706 return path;
00707 } else {
00708 return basename+1;
00709 }
00710 }
00711
00712 static UDataMemory *
00713 openCommonData(UDataMemory *pData,
00714 const char *path, UBool isICUData,
00715 char *pathBuffer,
00716 UErrorCode *pErrorCode) {
00717 # if !UDATA_NO_DLL
00718 Library lib;
00719 # endif
00720 const char *inBasename;
00721 char *basename, *suffix;
00722
00723
00724 if(isICUData && IS_DATA_MEMORY_LOADED(&commonICUData)) {
00725 return &commonICUData;
00726 }
00727
00728
00729
00730
00731 basename=setPathGetBasename(path, pathBuffer);
00732 if(isICUData) {
00733 inBasename=COMMON_DATA_NAME;
00734 } else {
00735 inBasename=findBasename(path);
00736 if(*inBasename==0) {
00737
00738 *pErrorCode=U_FILE_ACCESS_ERROR;
00739 return NULL;
00740 }
00741 }
00742
00743
00744 # if !UDATA_NO_DLL
00745
00746 # ifndef LIB_PREFIX
00747 suffix=strcpy_returnEnd(basename, inBasename);
00748 # else
00749 uprv_memcpy(basename, LIB_PREFIX, LIB_PREFIX_LENGTH);
00750 suffix=strcpy_returnEnd(basename+LIB_PREFIX_LENGTH, inBasename);
00751 # endif
00752 uprv_strcpy(suffix, LIB_SUFFIX);
00753
00754
00755 # ifdef OS390BATCH
00756
00757
00758
00759 lib=LOAD_LIBRARY("//" U_ICUDATA_NAME, "//" U_ICUDATA_NAME);
00760 # else
00761 lib=LOAD_LIBRARY(pathBuffer, basename);
00762 # endif
00763 if(!IS_LIBRARY(lib) && basename!=pathBuffer) {
00764
00765 lib=LOAD_LIBRARY(basename, basename);
00766 }
00767
00768 if(IS_LIBRARY(lib)) {
00769
00770 char entryName[100];
00771 const DataHeader *pHeader;
00772 *basename=0;
00773
00774
00775 uprv_strcpy(entryName, inBasename);
00776 uprv_strcat(entryName, "_" DATA_TYPE);
00777 pHeader=normalizeDataPointer((const DataHeader *)GET_LIBRARY_ENTRY(lib, entryName));
00778 if(pHeader==NULL) {
00779
00780 pData->lib=lib;
00781 pData->lookupFn=dllTOCLookupFn;
00782 pData->flags=DLL_DATA_MEMORY|DLL_INTRINSIC_TOC<<TOC_TYPE_SHIFT;
00783 } else if(!(pHeader->dataHeader.magic1==0xda && pHeader->dataHeader.magic2==0x27 &&
00784 pHeader->info.isBigEndian==U_IS_BIG_ENDIAN &&
00785 pHeader->info.charsetFamily==U_CHARSET_FAMILY)
00786 ) {
00787
00788 UNLOAD_LIBRARY(lib);
00789 *pErrorCode=U_INVALID_FORMAT_ERROR;
00790 return NULL;
00791
00792
00793 } else if(pHeader->info.dataFormat[0]==0x43 &&
00794 pHeader->info.dataFormat[1]==0x6d &&
00795 pHeader->info.dataFormat[2]==0x6e &&
00796 pHeader->info.dataFormat[3]==0x44 &&
00797 pHeader->info.formatVersion[0]==1
00798 ) {
00799
00800 pData->lib=lib;
00801 pData->lookupFn=offsetTOCLookupFn;
00802 pData->toc=(const char *)pHeader+pHeader->dataHeader.headerSize;
00803 pData->flags=DLL_DATA_MEMORY|OFFSET_TOC<<TOC_TYPE_SHIFT;
00804 } else if(pHeader->info.dataFormat[0]==0x54 &&
00805 pHeader->info.dataFormat[1]==0x6f &&
00806 pHeader->info.dataFormat[2]==0x43 &&
00807 pHeader->info.dataFormat[3]==0x50 &&
00808 pHeader->info.formatVersion[0]==1
00809 ) {
00810
00811 pData->lib=lib;
00812 pData->lookupFn=pointerTOCLookupFn;
00813 pData->toc=(const char *)pHeader+pHeader->dataHeader.headerSize;
00814 pData->flags=DLL_DATA_MEMORY|POINTER_TOC<<TOC_TYPE_SHIFT;
00815 } else {
00816
00817 UNLOAD_LIBRARY(lib);
00818 *pErrorCode=U_INVALID_FORMAT_ERROR;
00819 return NULL;
00820 }
00821
00822
00823 if(isICUData) {
00824 setCommonICUData(pData);
00825 return &commonICUData;
00826 } else {
00827 return pData;
00828 }
00829 }
00830 # endif
00831
00832
00833
00834
00835 suffix=strcpy_returnEnd(basename, inBasename);
00836 uprv_strcpy(suffix, "." DATA_TYPE);
00837
00838
00839 if( uprv_mapFile(pData, pathBuffer, basename) ||
00840 (basename!=pathBuffer && uprv_mapFile(pData, basename, basename))
00841 ) {
00842 const DataHeader *pHeader;
00843 *basename=0;
00844
00845
00846 pHeader=pData->pHeader;
00847 if(!(pHeader->dataHeader.magic1==0xda && pHeader->dataHeader.magic2==0x27 &&
00848 pHeader->info.isBigEndian==U_IS_BIG_ENDIAN &&
00849 pHeader->info.charsetFamily==U_CHARSET_FAMILY &&
00850 pHeader->info.dataFormat[0]==0x43 &&
00851 pHeader->info.dataFormat[1]==0x6d &&
00852 pHeader->info.dataFormat[2]==0x6e &&
00853 pHeader->info.dataFormat[3]==0x44 &&
00854 pHeader->info.formatVersion[0]==1)
00855 ) {
00856 uprv_unmapFile(pData);
00857 pData->flags=0;
00858 *pErrorCode=U_INVALID_FORMAT_ERROR;
00859 return NULL;
00860 }
00861
00862
00863 pData->lookupFn=offsetTOCLookupFn;
00864 pData->toc=(const char *)pHeader+pHeader->dataHeader.headerSize;
00865 pData->flags|=OFFSET_TOC<<TOC_TYPE_SHIFT;
00866 if(isICUData) {
00867 setCommonICUData(pData);
00868 return &commonICUData;
00869 } else {
00870 return pData;
00871 }
00872 }
00873
00874
00875 *basename=0;
00876
00877
00878 *pErrorCode=U_FILE_ACCESS_ERROR;
00879 return NULL;
00880 }
00881
00882 U_CAPI void U_EXPORT2
00883 udata_setCommonData(const void *data, UErrorCode *pErrorCode) {
00884 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
00885 return;
00886 }
00887
00888 if(data==NULL) {
00889 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
00890 return;
00891 }
00892
00893
00894 if(IS_DATA_MEMORY_LOADED(&commonICUData)) {
00895 *pErrorCode=U_USING_DEFAULT_ERROR;
00896 return;
00897 } else {
00898
00899 UDataMemory dataMemory={ NULL };
00900 const DataHeader *pHeader=normalizeDataPointer((const DataHeader *)data);
00901 if(!(pHeader->dataHeader.magic1==0xda && pHeader->dataHeader.magic2==0x27 &&
00902 pHeader->info.isBigEndian==U_IS_BIG_ENDIAN &&
00903 pHeader->info.charsetFamily==U_CHARSET_FAMILY)
00904 ) {
00905
00906 *pErrorCode=U_INVALID_FORMAT_ERROR;
00907 return;
00908
00909
00910 } else if(pHeader->info.dataFormat[0]==0x43 &&
00911 pHeader->info.dataFormat[1]==0x6d &&
00912 pHeader->info.dataFormat[2]==0x6e &&
00913 pHeader->info.dataFormat[3]==0x44 &&
00914 pHeader->info.formatVersion[0]==1
00915 ) {
00916
00917 dataMemory.lookupFn=offsetTOCLookupFn;
00918 dataMemory.toc=(const char *)pHeader+pHeader->dataHeader.headerSize;
00919 dataMemory.flags=DLL_DATA_MEMORY|OFFSET_TOC<<TOC_TYPE_SHIFT;
00920 } else if(pHeader->info.dataFormat[0]==0x54 &&
00921 pHeader->info.dataFormat[1]==0x6f &&
00922 pHeader->info.dataFormat[2]==0x43 &&
00923 pHeader->info.dataFormat[3]==0x50 &&
00924 pHeader->info.formatVersion[0]==1
00925 ) {
00926
00927 dataMemory.lookupFn=pointerTOCLookupFn;
00928 dataMemory.toc=(const char *)pHeader+pHeader->dataHeader.headerSize;
00929 dataMemory.flags=DLL_DATA_MEMORY|POINTER_TOC<<TOC_TYPE_SHIFT;
00930 } else {
00931
00932 *pErrorCode=U_INVALID_FORMAT_ERROR;
00933 return;
00934 }
00935
00936
00937 dataMemory.flags|=1UL<<SET_DATA_POINTER_SHIFT;
00938 setCommonICUData(&dataMemory);
00939 if(dataMemory.flags!=0) {
00940
00941 *pErrorCode=U_USING_DEFAULT_ERROR;
00942 }
00943 }
00944 }
00945
00946
00947
00948 static void
00949 setEntryNames(const char *type, const char *name,
00950 char *tocEntryName, char *dllEntryName) {
00951 while(*name!=0) {
00952 *tocEntryName=*name;
00953 if(*name=='.' || *name=='-') {
00954 *dllEntryName='_';
00955 } else {
00956 *dllEntryName=*name;
00957 }
00958 ++tocEntryName;
00959 ++dllEntryName;
00960 ++name;
00961 }
00962
00963 if(type!=NULL && *type!=0) {
00964 *tocEntryName++='.';
00965 *dllEntryName++='_';
00966 do {
00967 *tocEntryName++=*dllEntryName++=*type++;
00968 } while(*type!=0);
00969 }
00970
00971 *tocEntryName=*dllEntryName=0;
00972 }
00973
00974 static UDataMemory *
00975 doOpenChoice(const char *path, const char *type, const char *name,
00976 UDataMemoryIsAcceptable *isAcceptable, void *context,
00977 UErrorCode *pErrorCode) {
00978 char pathBuffer[1024];
00979 char tocEntryName[100], dllEntryName[100];
00980 UDataMemory dataMemory;
00981 UDataMemory *pCommonData, *pEntryData;
00982 const DataHeader *pHeader;
00983 const char *inBasename;
00984 char *basename, *suffix;
00985 UErrorCode errorCode=U_ZERO_ERROR;
00986 UBool isICUData= (UBool)(path==NULL);
00987
00988
00989 setEntryNames(type, name, tocEntryName, dllEntryName);
00990
00991
00992 uprv_memset(&dataMemory, 0, sizeof(UDataMemory));
00993 pathBuffer[0]=0;
00994 pCommonData=openCommonData(&dataMemory, path, isICUData, pathBuffer, &errorCode);
00995 #ifdef UDATA_DEBUG
00996 fprintf(stderr, "commonData;%p\n", pCommonData);
00997 fflush(stderr);
00998 #endif
00999
01000 if(U_SUCCESS(errorCode)) {
01001
01002 pHeader=pCommonData->lookupFn(pCommonData, tocEntryName, dllEntryName, &errorCode);
01003 #ifdef UDATA_DEBUG
01004 fprintf(stderr, "Common found: %p\n", pHeader);
01005 #endif
01006 if(pHeader!=NULL) {
01007
01008 if(pHeader->dataHeader.magic1==0xda && pHeader->dataHeader.magic2==0x27 &&
01009 pHeader->info.isBigEndian==U_IS_BIG_ENDIAN &&
01010 (isAcceptable==NULL || isAcceptable(context, type, name, &pHeader->info))
01011 ) {
01012
01013 if(pCommonData==&dataMemory) {
01014
01015 pEntryData=(UDataMemory *)uprv_malloc(2*sizeof(UDataMemory));
01016 if(pEntryData!=NULL) {
01017 pCommonData=pEntryData+1;
01018 uprv_memcpy(pCommonData, &dataMemory, sizeof(UDataMemory));
01019 }
01020 } else {
01021 pEntryData=(UDataMemory *)uprv_malloc(sizeof(UDataMemory));
01022 }
01023 if(pEntryData==NULL) {
01024 *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
01025 return NULL;
01026 }
01027 uprv_memset(pEntryData, 0, sizeof(UDataMemory));
01028 pEntryData->parent=pCommonData;
01029 pEntryData->pHeader=pHeader;
01030 pEntryData->flags=(pCommonData->flags&DATA_MEMORY_TYPE_MASK)|1UL<<DYNAMIC_DATA_MEMORY_SHIFT;
01031 #ifdef UDATA_DEBUG
01032 fprintf(stderr, " made data @%p\n", pEntryData);
01033 #endif
01034 return pEntryData;
01035 } else {
01036
01037 #ifdef UDATA_DEBUG
01038 fprintf(stderr, "Not acceptable\n");
01039 #endif
01040 errorCode=U_INVALID_FORMAT_ERROR;
01041 }
01042 }
01043
01044
01045 if(pCommonData==&dataMemory) {
01046 udata_close(&dataMemory);
01047 }
01048 }
01049
01050
01051 basename=setPathGetBasename(path, pathBuffer);
01052 if(isICUData) {
01053 inBasename=COMMON_DATA_NAME;
01054 } else {
01055 inBasename=findBasename(path);
01056 }
01057
01058 #ifdef UDATA_DEBUG
01059 fprintf(stderr, "looking for ind. file\n");
01060 #endif
01061
01062
01063 if(*inBasename!=0) {
01064 suffix=strcpy_returnEnd(basename, inBasename);
01065 *suffix++='_';
01066 uprv_strcpy(suffix, tocEntryName);
01067
01068 if( uprv_mapFile(&dataMemory, pathBuffer, basename) ||
01069 (basename!=pathBuffer && uprv_mapFile(&dataMemory, basename, basename))
01070 ) {
01071 pHeader=dataMemory.pHeader;
01072 if(pHeader->dataHeader.magic1==0xda && pHeader->dataHeader.magic2==0x27 &&
01073 pHeader->info.isBigEndian==U_IS_BIG_ENDIAN &&
01074 (isAcceptable==NULL || isAcceptable(context, type, name, &pHeader->info))
01075 ) {
01076
01077 pEntryData=(UDataMemory *)uprv_malloc(sizeof(UDataMemory));
01078 if(pEntryData==NULL) {
01079 uprv_unmapFile(&dataMemory);
01080 *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
01081 return NULL;
01082 }
01083 dataMemory.flags|=1UL<<DYNAMIC_DATA_MEMORY_SHIFT;
01084 uprv_memcpy(pEntryData, &dataMemory, sizeof(UDataMemory));
01085 return pEntryData;
01086 } else {
01087
01088 uprv_unmapFile(&dataMemory);
01089 errorCode=U_INVALID_FORMAT_ERROR;
01090 }
01091 }
01092 }
01093
01094
01095 uprv_strcpy(basename, tocEntryName);
01096 if( uprv_mapFile(&dataMemory, pathBuffer, basename) ||
01097 (basename!=pathBuffer && uprv_mapFile(&dataMemory, basename, basename))
01098 ) {
01099 pHeader=dataMemory.pHeader;
01100 if(pHeader->dataHeader.magic1==0xda && pHeader->dataHeader.magic2==0x27 &&
01101 pHeader->info.isBigEndian==U_IS_BIG_ENDIAN &&
01102 (isAcceptable==NULL || isAcceptable(context, type, name, &pHeader->info))
01103 ) {
01104
01105 pEntryData=(UDataMemory *)uprv_malloc(sizeof(UDataMemory));
01106 if(pEntryData==NULL) {
01107 uprv_unmapFile(&dataMemory);
01108 *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
01109 return NULL;
01110 }
01111 dataMemory.flags|=1UL<<DYNAMIC_DATA_MEMORY_SHIFT;
01112 uprv_memcpy(pEntryData, &dataMemory, sizeof(UDataMemory));
01113 return pEntryData;
01114 } else {
01115
01116 uprv_unmapFile(&dataMemory);
01117 errorCode=U_INVALID_FORMAT_ERROR;
01118 }
01119 }
01120
01121
01122 if(U_SUCCESS(*pErrorCode)) {
01123 if(U_SUCCESS(errorCode)) {
01124
01125 *pErrorCode=U_FILE_ACCESS_ERROR;
01126 } else {
01127
01128 *pErrorCode=errorCode;
01129 }
01130 }
01131 return NULL;
01132 }
01133
01134 static void
01135 unloadDataMemory(UDataMemory *pData) {
01136 if(!(pData->flags&(1UL<<SET_DATA_POINTER_SHIFT))) {
01137 switch(pData->flags&DATA_MEMORY_TYPE_MASK) {
01138 case FLAT_DATA_MEMORY:
01139 if(IS_MAP(pData->map)) {
01140 uprv_unmapFile(pData);
01141 }
01142 break;
01143 case DLL_DATA_MEMORY:
01144 if(IS_LIBRARY(pData->lib)) {
01145 UNLOAD_LIBRARY(pData->lib);
01146 }
01147 break;
01148 default:
01149 break;
01150 }
01151 }
01152 }
01153
01154
01155
01156 U_CAPI UDataMemory * U_EXPORT2
01157 udata_open(const char *path, const char *type, const char *name,
01158 UErrorCode *pErrorCode) {
01159 #ifdef UDATA_DEBUG
01160 fprintf(stderr, "udata_open(): Opening: %s . %s\n", name, type);fflush(stderr);
01161 #endif
01162
01163 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
01164 return NULL;
01165 } else if(name==NULL || *name==0) {
01166 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
01167 return NULL;
01168 } else {
01169 return doOpenChoice(path, type, name, NULL, NULL, pErrorCode);
01170 }
01171 }
01172
01173 U_CAPI UDataMemory * U_EXPORT2
01174 udata_openChoice(const char *path, const char *type, const char *name,
01175 UDataMemoryIsAcceptable *isAcceptable, void *context,
01176 UErrorCode *pErrorCode) {
01177 #ifdef UDATA_DEBUG
01178 fprintf(stderr, "udata_openChoice(): Opening: %s . %s\n", name, type);fflush(stderr);
01179 #endif
01180
01181 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
01182 return NULL;
01183 } else if(name==NULL || *name==0 || isAcceptable==NULL) {
01184 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
01185 return NULL;
01186 } else {
01187 return doOpenChoice(path, type, name, isAcceptable, context, pErrorCode);
01188 }
01189 }
01190
01191 U_CAPI void U_EXPORT2
01192 udata_close(UDataMemory *pData) {
01193 #ifdef UDATA_DEBUG
01194 fprintf(stderr, "udata_close()\n");fflush(stderr);
01195 #endif
01196
01197 if(pData!=NULL && IS_DATA_MEMORY_LOADED(pData)) {
01198 unloadDataMemory(pData);
01199 if(pData->flags&(1UL<<DYNAMIC_DATA_MEMORY_SHIFT)) {
01200 if(pData->parent==pData+1) {
01201
01202 unloadDataMemory(pData+1);
01203 }
01204 uprv_free(pData);
01205 } else {
01206 pData->flags=0;
01207 }
01208 }
01209 }
01210
01211 U_CAPI const void * U_EXPORT2
01212 udata_getMemory(UDataMemory *pData) {
01213 if(pData!=NULL && pData->pHeader!=NULL) {
01214 return (char *)(pData->pHeader)+pData->pHeader->dataHeader.headerSize;
01215 } else {
01216 return NULL;
01217 }
01218 }
01219
01220 U_CAPI void U_EXPORT2
01221 udata_getInfo(UDataMemory *pData, UDataInfo *pInfo) {
01222 if(pInfo!=NULL) {
01223 if(pData!=NULL && pData->pHeader!=NULL) {
01224 const UDataInfo *info=&pData->pHeader->info;
01225 uint16_t size=pInfo->size;
01226 if(size>info->size) {
01227 pInfo->size=info->size;
01228 }
01229 uprv_memcpy((uint16_t *)pInfo+1, (uint16_t *)info+1, size-2);
01230 } else {
01231 pInfo->size=0;
01232 }
01233 }
01234 }