mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-07 22:44:49 +00:00
ICU-1075 udata.c restructured, split into separate files, hopefully making code clearer, dependencies clearer.
Functionality pretty much unchanged. X-SVN-Rev: 5716
This commit is contained in:
parent
9036c7f6ea
commit
412f48860e
8 changed files with 1002 additions and 786 deletions
|
@ -181,6 +181,10 @@ SOURCE=.\ucln_cmn.c
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ucmndata.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ucmp16.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
@ -258,6 +262,10 @@ SOURCE=.\udata.c
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\udatamem.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\uhash.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
@ -270,6 +278,11 @@ SOURCE=.\uloc.c
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\umapfile.c
|
||||
# ADD CPP /Ze
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\umemstrm.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
@ -784,6 +797,10 @@ SOURCE=.\ucln_cmn.h
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ucmndata.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ucmp16.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
@ -928,6 +945,10 @@ InputPath=.\unicode\udata.h
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\udatamem.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\uhash.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
@ -986,6 +1007,10 @@ InputPath=.\unicode\umachine.h
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\umapfile.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\umemstrm.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
|
223
icu4c/source/common/ucmndata.c
Normal file
223
icu4c/source/common/ucmndata.c
Normal file
|
@ -0,0 +1,223 @@
|
|||
/*
|
||||
******************************************************************************
|
||||
*
|
||||
* Copyright (C) 1999-2001, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*
|
||||
******************************************************************************
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------------
|
||||
*
|
||||
* UCommonData An abstract interface for dealing with ICU Common Data Files.
|
||||
* ICU Common Data Files are a grouping of a number of individual
|
||||
* data items (resources, converters, tables, anything) into a
|
||||
* single file or dll. The combined format includes a table of
|
||||
* contents for locating the individual items by name.
|
||||
*
|
||||
* Two formats for the table of contents are supported, which is
|
||||
* why there is an abstract inteface involved.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "unicode/utypes.h"
|
||||
#include "unicode/udata.h"
|
||||
#include "cstring.h"
|
||||
#include "ucmndata.h"
|
||||
#include "udatamem.h"
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------------*
|
||||
* *
|
||||
* Pointer TOCs. TODO: This form of table-of-contents should be removed because *
|
||||
* DLLs must be relocated on loading to correct the pointer values *
|
||||
* and this operation makes shared memory mapping of the data *
|
||||
* much less likely to work. *
|
||||
* *
|
||||
*----------------------------------------------------------------------------------*/
|
||||
typedef struct {
|
||||
const char *entryName;
|
||||
const DataHeader *pHeader;
|
||||
} PointerTOCEntry;
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------------*
|
||||
* *
|
||||
* entry point lookup implementations *
|
||||
* *
|
||||
*----------------------------------------------------------------------------------*/
|
||||
static uint32_t offsetTOCEntryCount(const UDataMemory *pData) {
|
||||
uint32_t count = *(const uint32_t *)pData->toc;
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
static const DataHeader *
|
||||
offsetTOCLookupFn(const UDataMemory *pData,
|
||||
const char *tocEntryName,
|
||||
UErrorCode *pErrorCode) {
|
||||
|
||||
if(pData->toc!=NULL) {
|
||||
const char *base=(const char *)pData->toc;
|
||||
uint32_t *toc=(uint32_t *)pData->toc;
|
||||
uint32_t start, limit, number;
|
||||
|
||||
/* perform a binary search for the data in the common data's table of contents */
|
||||
start=0;
|
||||
limit=*toc++; /* number of names in this table of contents */
|
||||
if (limit == 0) { /* Stub common data library used during build is empty. */
|
||||
return NULL;
|
||||
}
|
||||
while(start<limit-1) {
|
||||
number=(start+limit)/2;
|
||||
if(uprv_strcmp(tocEntryName, base+toc[2*number])<0) {
|
||||
limit=number;
|
||||
} else {
|
||||
start=number;
|
||||
}
|
||||
}
|
||||
|
||||
if(uprv_strcmp(tocEntryName, base+toc[2*start])==0) {
|
||||
/* found it */
|
||||
#ifdef UDATA_DEBUG
|
||||
fprintf(stderr, "Found: %p\n",(base+toc[2*start+1]));
|
||||
#endif
|
||||
return (const DataHeader *)(base+toc[2*start+1]);
|
||||
} else {
|
||||
#ifdef UDATA_DEBUG
|
||||
fprintf(stderr, "Not found.\n");
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
#ifdef UDATA_DEBUG
|
||||
fprintf(stderr, "returning header\n");
|
||||
#endif
|
||||
|
||||
return pData->pHeader;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static uint32_t pointerTOCEntryCount(const UDataMemory *pData) {
|
||||
uint32_t count = *(const uint32_t *)pData->toc;
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
static const DataHeader *pointerTOCLookupFn(const UDataMemory *pData,
|
||||
const char *tocEntryName,
|
||||
UErrorCode *pErrorCode) {
|
||||
#ifdef UDATA_DEBUG
|
||||
fprintf(stderr, "ptrTOC[%p] looking for %s/%s\n",
|
||||
pData,
|
||||
tocEntryName,dllEntryName);
|
||||
#endif
|
||||
if(pData->toc!=NULL) {
|
||||
const PointerTOCEntry *toc=(const PointerTOCEntry *)((const uint32_t *)pData->toc+2);
|
||||
uint32_t start, limit, number;
|
||||
|
||||
/* perform a binary search for the data in the common data's table of contents */
|
||||
start=0;
|
||||
limit=*(const uint32_t *)pData->toc; /* number of names in this table of contents */
|
||||
|
||||
#ifdef UDATA_DEBUG
|
||||
fprintf(stderr, " # of ents: %d\n", limit);
|
||||
fflush(stderr);
|
||||
#endif
|
||||
|
||||
if (limit == 0) { /* Stub common data library used during build is empty. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while(start<limit-1) {
|
||||
number=(start+limit)/2;
|
||||
if(uprv_strcmp(tocEntryName, toc[number].entryName)<0) {
|
||||
limit=number;
|
||||
} else {
|
||||
start=number;
|
||||
}
|
||||
}
|
||||
|
||||
if(uprv_strcmp(tocEntryName, toc[start].entryName)==0) {
|
||||
/* found it */
|
||||
#ifdef UDATA_DEBUG
|
||||
fprintf(stderr, "FOUND: %p\n",
|
||||
normalizeDataPointer(toc[start].pHeader));
|
||||
#endif
|
||||
|
||||
return normalizeDataPointer(toc[start].pHeader);
|
||||
} else {
|
||||
#ifdef UDATA_DEBUG
|
||||
fprintf(stderr, "NOT found\n");
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
#ifdef UDATA_DEBUG
|
||||
fprintf(stderr, "Returning header\n");
|
||||
#endif
|
||||
return pData->pHeader;
|
||||
}
|
||||
}
|
||||
|
||||
static commonDataFuncs CmnDFuncs = {offsetTOCLookupFn, offsetTOCEntryCount};
|
||||
static commonDataFuncs ToCPFuncs = {pointerTOCLookupFn, pointerTOCEntryCount};
|
||||
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*
|
||||
* *
|
||||
* checkCommonData Validate the format of a common data file. *
|
||||
* Fill in the virtual function ptr based on TOC type *
|
||||
* If the data is invalid, close the UDataMemory *
|
||||
* and set the appropriate error code. *
|
||||
* *
|
||||
*----------------------------------------------------------------------*/
|
||||
void checkCommonData(UDataMemory *udm, UErrorCode *err) {
|
||||
if (U_FAILURE(*err)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(!(udm->pHeader->dataHeader.magic1==0xda &&
|
||||
udm->pHeader->dataHeader.magic2==0x27 &&
|
||||
udm->pHeader->info.isBigEndian==U_IS_BIG_ENDIAN &&
|
||||
udm->pHeader->info.charsetFamily==U_CHARSET_FAMILY)
|
||||
) {
|
||||
/* header not valid */
|
||||
*err=U_INVALID_FORMAT_ERROR;
|
||||
}
|
||||
else if (udm->pHeader->info.dataFormat[0]==0x43 &&
|
||||
udm->pHeader->info.dataFormat[1]==0x6d &&
|
||||
udm->pHeader->info.dataFormat[2]==0x6e &&
|
||||
udm->pHeader->info.dataFormat[3]==0x44 &&
|
||||
udm->pHeader->info.formatVersion[0]==1
|
||||
) {
|
||||
/* dataFormat="CmnD" */
|
||||
udm->vFuncs = &CmnDFuncs;
|
||||
udm->toc=(const char *)udm->pHeader+udm->pHeader->dataHeader.headerSize;
|
||||
}
|
||||
else if(udm->pHeader->info.dataFormat[0]==0x54 &&
|
||||
udm->pHeader->info.dataFormat[1]==0x6f &&
|
||||
udm->pHeader->info.dataFormat[2]==0x43 &&
|
||||
udm->pHeader->info.dataFormat[3]==0x50 &&
|
||||
udm->pHeader->info.formatVersion[0]==1
|
||||
) {
|
||||
/* dataFormat="ToCP" */
|
||||
udm->vFuncs = &ToCPFuncs;
|
||||
udm->toc=(const char *)udm->pHeader+udm->pHeader->dataHeader.headerSize;
|
||||
}
|
||||
else {
|
||||
/* dataFormat not recognized */
|
||||
*err=U_INVALID_FORMAT_ERROR;
|
||||
}
|
||||
|
||||
if (U_FAILURE(*err)) {
|
||||
/* If the data is no good and we memory-mapped it ourselves,
|
||||
* close the memory mapping so it doesn't leak. Note that this has
|
||||
* no effect on non-memory mapped data, other than clearing fields in udm.
|
||||
*/
|
||||
udata_close(udm);
|
||||
}
|
||||
}
|
||||
|
81
icu4c/source/common/ucmndata.h
Normal file
81
icu4c/source/common/ucmndata.h
Normal file
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
******************************************************************************
|
||||
*
|
||||
* Copyright (C) 1999-2001, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*
|
||||
******************************************************************************
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------------
|
||||
*
|
||||
* UCommonData An abstract interface for dealing with ICU Common Data Files.
|
||||
* ICU Common Data Files are a grouping of a number of individual
|
||||
* data items (resources, converters, tables, anything) into a
|
||||
* single file or dll. The combined format includes a table of
|
||||
* contents for locating the individual items by name.
|
||||
*
|
||||
* Two formats for the table of contents are supported, which is
|
||||
* why there is an abstract inteface involved.
|
||||
*
|
||||
* These functions are part of the ICU internal implementation, and
|
||||
* are not inteded to be used directly by applications.
|
||||
*/
|
||||
|
||||
#ifndef __UCMNDATA_H__
|
||||
#define __UCMNDATA_H__
|
||||
|
||||
#include "unicode/udata.h"
|
||||
#include "umapfile.h"
|
||||
|
||||
|
||||
#define COMMON_DATA_NAME U_ICUDATA_NAME
|
||||
|
||||
typedef struct {
|
||||
uint16_t headerSize;
|
||||
uint8_t magic1;
|
||||
uint8_t magic2;
|
||||
} MappedData;
|
||||
|
||||
|
||||
typedef struct {
|
||||
MappedData dataHeader;
|
||||
UDataInfo info;
|
||||
} DataHeader;
|
||||
|
||||
|
||||
/*
|
||||
* "Virtual" functions for data lookup.
|
||||
* To call one, given a UDataMemory *p, the code looks like this:
|
||||
* p->vFuncs.Lookup(p, tocEntryName, pErrorCode);
|
||||
* (I sure do wish this was written in C++, not C)
|
||||
*/
|
||||
|
||||
typedef const DataHeader *
|
||||
(* LookupFn)(const UDataMemory *pData,
|
||||
const char *tocEntryName,
|
||||
UErrorCode *pErrorCode);
|
||||
|
||||
typedef uint32_t
|
||||
(* NumEntriesFn)(const UDataMemory *pData);
|
||||
|
||||
typedef struct {
|
||||
LookupFn Lookup;
|
||||
NumEntriesFn NumEntries;
|
||||
} commonDataFuncs;
|
||||
|
||||
|
||||
/*
|
||||
* Functions to check whether a UDataMemory refers to memory containing
|
||||
* a recognizable header and table of contents a Common Data Format
|
||||
*
|
||||
* If a valid header and TOC are found,
|
||||
* set the CommonDataFuncs function dispatch vector in the UDataMemory
|
||||
* to point to the right functions for the TOC type.
|
||||
* otherwise
|
||||
* set an errorcode.
|
||||
*/
|
||||
void checkCommonData(UDataMemory *pData, UErrorCode *pErrorCode);
|
||||
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load diff
99
icu4c/source/common/udatamem.c
Normal file
99
icu4c/source/common/udatamem.c
Normal file
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
******************************************************************************
|
||||
*
|
||||
* Copyright (C) 1999-2001, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*
|
||||
******************************************************************************
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------------
|
||||
*
|
||||
* UDataMemory A class-like struct that serves as a handle to a piece of memory
|
||||
* that contains some ICU data (resource, converters, whatever.)
|
||||
*
|
||||
* When an application opens ICU data (with udata_open, for example,
|
||||
* a UDataMemory * is returned.
|
||||
*
|
||||
*----------------------------------------------------------------------------------*/
|
||||
|
||||
#include "unicode/utypes.h"
|
||||
#include "unicode/putil.h"
|
||||
#include "cmemory.h"
|
||||
#include "cstring.h"
|
||||
#include "unicode/udata.h"
|
||||
|
||||
#include "udatamem.h"
|
||||
|
||||
void UDataMemory_init(UDataMemory *This) {
|
||||
uprv_memset(This, 0, sizeof(UDataMemory));
|
||||
}
|
||||
|
||||
|
||||
void UDatamemory_assign(UDataMemory *dest, UDataMemory *source) {
|
||||
/* UDataMemory Assignment. Destination UDataMemory must be initialized first. */
|
||||
UBool mallocedFlag = dest->heapAllocated;
|
||||
uprv_memcpy(dest, source, sizeof(UDataMemory));
|
||||
dest->heapAllocated = mallocedFlag;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
const DataHeader *
|
||||
normalizeDataPointer(const void *p) {
|
||||
/* allow the data to be optionally prepended with an alignment-forcing double value */
|
||||
const DataHeader *pdh = (const DataHeader *)p;
|
||||
if(pdh==NULL || (pdh->dataHeader.magic1==0xda && pdh->dataHeader.magic2==0x27)) {
|
||||
return pdh;
|
||||
} else {
|
||||
return (const DataHeader *)((const double *)p+1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void UDataMemory_setData (UDataMemory *This, const void *dataAddr) {
|
||||
This->pHeader = normalizeDataPointer(dataAddr);
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
U_CAPI const void * U_EXPORT2
|
||||
udata_getMemory(UDataMemory *pData) {
|
||||
if(pData!=NULL && pData->pHeader!=NULL) {
|
||||
return (char *)(pData->pHeader)+pData->pHeader->dataHeader.headerSize;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
UBool UDataMemory_isLoaded(UDataMemory *This) {
|
||||
return This->pHeader != NULL;
|
||||
}
|
||||
|
47
icu4c/source/common/udatamem.h
Normal file
47
icu4c/source/common/udatamem.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
******************************************************************************
|
||||
*
|
||||
* Copyright (C) 1999-2001, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------------
|
||||
*
|
||||
* UDataMemory A class-like struct that serves as a handle to a piece of memory
|
||||
* that contains some ICU data (resource, converters, whatever.)
|
||||
*
|
||||
* When an application opens ICU data (with udata_open, for example,
|
||||
* a UDataMemory * is returned.
|
||||
*
|
||||
*----------------------------------------------------------------------------------*/
|
||||
#ifndef __UDATAMEM_H__
|
||||
#define __UDATAMEM_H__
|
||||
|
||||
#include "ucmndata.h"
|
||||
|
||||
typedef struct UDataMemory {
|
||||
void *map; /* Handle, or whatever. OS dependent. */
|
||||
/* Only set if a close operation should unmap the */
|
||||
/* associated data. */
|
||||
const void *mapAddr; /* For mapped or allocated memory, the start addr. */
|
||||
/* Needed to allow unmapping. */
|
||||
|
||||
|
||||
commonDataFuncs *vFuncs; /* Function Pointers for accessing TOC */
|
||||
const void *toc; /* For common memory, to find pieces within. */
|
||||
const DataHeader *pHeader; /* Header. For common data, header is at top of file */
|
||||
UBool heapAllocated; /* True if this UDataMemObject is on the heap */
|
||||
/* and thus needs to be deleted when closed. */
|
||||
} UDataMemory;
|
||||
|
||||
UDataMemory *UDataMemory_createNewInstance(UErrorCode *pErr);
|
||||
void UDatamemory_assign (UDataMemory *dest, UDataMemory *source);
|
||||
void UDataMemory_init (UDataMemory *This);
|
||||
UBool UDataMemory_isLoaded(UDataMemory *This);
|
||||
void UDataMemory_setData (UDataMemory *This, const void *dataAddr);
|
||||
|
||||
|
||||
const DataHeader *normalizeDataPointer(const void *p);
|
||||
#endif
|
379
icu4c/source/common/umapfile.c
Normal file
379
icu4c/source/common/umapfile.c
Normal file
|
@ -0,0 +1,379 @@
|
|||
/*
|
||||
******************************************************************************
|
||||
*
|
||||
* Copyright (C) 1999-2001, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*
|
||||
******************************************************************************
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------------
|
||||
*
|
||||
* Memory mapped file wrappers for use by the ICU Data Implementation
|
||||
* All of the platform-specific implementation for mapping data files
|
||||
* is here. The rest of the ICU Data implementation uses only the
|
||||
* wrapper functions.
|
||||
*
|
||||
*----------------------------------------------------------------------------------*/
|
||||
#include "unicode/utypes.h"
|
||||
|
||||
|
||||
#include "udatamem.h"
|
||||
#include "umapfile.h"
|
||||
|
||||
|
||||
/* memory-mapping base definitions ------------------------------------------ */
|
||||
|
||||
|
||||
#define MAP_WIN32 1
|
||||
#define MAP_POSIX 2
|
||||
#define MAP_FILE_STREAM 3
|
||||
#define MAP_390DLL 4
|
||||
|
||||
#ifdef WIN32
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# define NOGDI
|
||||
# define NOUSER
|
||||
# define NOSERVICE
|
||||
# define NOIME
|
||||
# define NOMCX
|
||||
# include <windows.h>
|
||||
|
||||
typedef HANDLE MemoryMap;
|
||||
|
||||
# define IS_MAP(map) ((map)!=NULL)
|
||||
|
||||
# define MAP_IMPLEMENTATION MAP_WIN32
|
||||
|
||||
/* ### Todo: auto detect mmap(). Until then, just add your platform here. */
|
||||
#elif HAVE_MMAP || defined(U_LINUX) || defined(POSIX) || defined(U_SOLARIS) || defined(AIX) || defined(HPUX) || defined(OS390) || defined(PTX)
|
||||
typedef size_t MemoryMap;
|
||||
|
||||
# define IS_MAP(map) ((map)!=0)
|
||||
|
||||
# include <unistd.h>
|
||||
# include <sys/mman.h>
|
||||
# include <sys/stat.h>
|
||||
# include <fcntl.h>
|
||||
|
||||
# ifndef MAP_FAILED
|
||||
# define MAP_FAILED ((void*)-1)
|
||||
# endif
|
||||
|
||||
# define MAP_IMPLEMENTATION MAP_POSIX
|
||||
|
||||
#elif OS390
|
||||
/* No memory mapping for 390 batch mode. Fake it using dll loading. */
|
||||
# include <dll.h>
|
||||
# define MAP_IMPLEMENTATION MAP_390DLL
|
||||
|
||||
#else /* unknown platform, no memory map implementation: use FileStream/uprv_malloc() instead */
|
||||
|
||||
# include "filestrm.h"
|
||||
|
||||
typedef void *MemoryMap;
|
||||
|
||||
# define IS_MAP(map) ((map)!=NULL)
|
||||
|
||||
# define MAP_IMPLEMENTATION MAP_FILE_STREAM
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------------*
|
||||
* *
|
||||
* Memory Mapped File support. Platform dependent implementation of functions *
|
||||
* used by the rest of the implementation. *
|
||||
* *
|
||||
*----------------------------------------------------------------------------------*/
|
||||
#if MAP_IMPLEMENTATION==MAP_WIN32
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* create an unnamed Windows file-mapping object for the specified file */
|
||||
map=CreateFileMapping(file, NULL, 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;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
uprv_unmapFile(UDataMemory *pData) {
|
||||
if(pData!=NULL && pData->map!=NULL) {
|
||||
UnmapViewOfFile(pData->pHeader);
|
||||
CloseHandle(pData->map);
|
||||
pData->pHeader=NULL;
|
||||
pData->map=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#elif MAP_IMPLEMENTATION==MAP_POSIX
|
||||
static UBool
|
||||
uprv_mapFile(UDataMemory *pData, const char *path) {
|
||||
int fd;
|
||||
int length;
|
||||
struct stat mystat;
|
||||
const 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 */
|
||||
#ifndef 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) {
|
||||
|
||||
# ifdef UDATA_DEBUG
|
||||
perror("mmap");
|
||||
# endif
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
# ifdef UDATA_DEBUG
|
||||
fprintf(stderr, "mmap of %s [%d bytes] succeeded, -> 0x%X\n", path, length, data);
|
||||
fflush(stderr);
|
||||
# endif
|
||||
|
||||
pData->map=length;
|
||||
pData->pHeader=(const DataHeader *)data;
|
||||
pData->mapAddr = data;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
uprv_unmapFile(UDataMemory *pData) {
|
||||
if(pData!=NULL && pData->map>0) {
|
||||
if(munmap((void *)pData->mapAddr, pData->map)==-1) {
|
||||
# ifdef UDATA_DEBUG
|
||||
perror("munmap");
|
||||
# endif
|
||||
}
|
||||
pData->pHeader=NULL;
|
||||
pData->map=0;
|
||||
pData->mapAddr=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#elif MAP_IMPLEMENTATION==MAP_FILE_STREAM
|
||||
static UBool
|
||||
uprv_mapFile(UDataMemory *pData, const char *path) {
|
||||
FileStream *file;
|
||||
int32_t fileLength;
|
||||
void *p;
|
||||
|
||||
UDataMemory_init(pData); /* Clear the output struct. */
|
||||
/* open the input file */
|
||||
file=T_FileStream_open(path, "rb");
|
||||
if(file==NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* get the file length */
|
||||
fileLength=T_FileStream_size(file);
|
||||
if(T_FileStream_error(file) || fileLength<=20) {
|
||||
T_FileStream_close(file);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* allocate the data structure */
|
||||
p=uprv_malloc(fileLength);
|
||||
if(p==NULL) {
|
||||
T_FileStream_close(file);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* read the file */
|
||||
if(fileLength!=T_FileStream_read(file, p, fileLength)) {
|
||||
uprv_free(p);
|
||||
T_FileStream_close(file);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
T_FileStream_close(file);
|
||||
pData->map=p;
|
||||
pData->pHeader=(const DataHeader *)p;
|
||||
pData->mapAddr=p;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
uprv_unmapFile(UDataMemory *pData) {
|
||||
if(pData!=NULL && pData->map!=NULL) {
|
||||
uprv_free(pData->map);
|
||||
pData->map = NULL;
|
||||
pData->mapAddr = NULL;
|
||||
pData->pHeader = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#elif MAP_IMPLEMENTATION==MAP_390DLL
|
||||
/* 390 specific Library Loading.
|
||||
* This is the only platform left that dynamically loads an ICU Data Library.
|
||||
* All other platforms use .data files when dynamic loading is required, but
|
||||
* this turn out to be awkward to support in 390 batch mode.
|
||||
*
|
||||
* The idea here is to hide the fact that 390 is using dll loading from the
|
||||
* rest of ICU, and make it look like there is file loading happening.
|
||||
*
|
||||
*/
|
||||
|
||||
uprv_mapFile(UDataMemory *pData, const char *path) {
|
||||
/* TODO: turn the path into a dll name, try to load it,
|
||||
* if successful, set the the pHeader field of the UDataMemory
|
||||
* to the data address.
|
||||
*
|
||||
* (If path has a ".dat" extension, take it off and add on whatever
|
||||
* the standard shared library extension is?)
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
void uprv_unmapFile(UDataMemory *pData) {
|
||||
if(pData!=NULL && pData->map!=NULL) {
|
||||
/* TODO: whatever. Doesn't really need to do anything. */
|
||||
}
|
||||
}
|
||||
|
||||
# define RTLD_LAZY 0
|
||||
# define RTLD_GLOBAL 0
|
||||
|
||||
static void *dlopen(const char *filename, int flag) {
|
||||
dllhandle *handle;
|
||||
|
||||
# ifdef UDATA_DEBUG
|
||||
fprintf(stderr, "dllload: %s ", filename);
|
||||
# endif
|
||||
handle=dllload(filename);
|
||||
# ifdef UDATA_DEBUG
|
||||
fprintf(stderr, " -> %08X\n", handle );
|
||||
# endif
|
||||
return handle;
|
||||
}
|
||||
|
||||
static void *dlsym(void *h, const char *symbol) {
|
||||
void *val=0;
|
||||
val=dllqueryvar((dllhandle*)h,symbol);
|
||||
# ifdef UDATA_DEBUG
|
||||
fprintf(stderr, "dllqueryvar(%08X, %s) -> %08X\n", h, symbol, val);
|
||||
# endif
|
||||
return val;
|
||||
}
|
||||
|
||||
static int dlclose(void *handle) {
|
||||
# ifdef UDATA_DEBUG
|
||||
fprintf(stderr, "dllfree: %08X\n", handle);
|
||||
# endif
|
||||
return dllfree((dllhandle*)handle);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* TODO: the following code is just a mish-mash of pieces from the
|
||||
* previous OS390 data library loading code that might be useful
|
||||
* in putting together something that works.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
Library lib;
|
||||
inBasename=U_ICUDATA_NAME"_390";
|
||||
suffix=strcpy_returnEnd(basename, inBasename);
|
||||
uprv_strcpy(suffix, LIB_SUFFIX);
|
||||
|
||||
if (uprv_isOS390BatchMode()) {
|
||||
/* ### 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 entry names than a typical file system. */
|
||||
if (s390dll) {
|
||||
lib=LOAD_LIBRARY("//IXMICUD1", "//IXMICUD1");
|
||||
}
|
||||
else {
|
||||
/* U_ICUDATA_NAME should always have the correct name */
|
||||
/* 390port: BUT FOR BATCH MODE IT IS AN EXCEPTION ... */
|
||||
/* 390port: THE NEXT LINE OF CODE WILL NOT WORK !!!!! */
|
||||
/*lib=LOAD_LIBRARY("//" U_ICUDATA_NAME, "//" U_ICUDATA_NAME);*/
|
||||
lib=LOAD_LIBRARY("//IXMICUDA", "//IXMICUDA"); /*390port*/
|
||||
}
|
||||
}
|
||||
|
||||
lib=LOAD_LIBRARY(pathBuffer, basename);
|
||||
if(!IS_LIBRARY(lib) && basename!=pathBuffer) {
|
||||
/* try basename only next */
|
||||
lib=LOAD_LIBRARY(basename, basename);
|
||||
}
|
||||
|
||||
if(IS_LIBRARY(lib)) {
|
||||
/* we have a data DLL - what kind of lookup do we need here? */
|
||||
char entryName[100];
|
||||
const DataHeader *pHeader;
|
||||
*basename=0;
|
||||
}
|
||||
|
||||
checkCommonData(&tData, pErrorCode);
|
||||
if (U_SUCCESS(*pErrorCode)) {
|
||||
/* Don't close the old data - someone might be using it
|
||||
* May need to change the global to be a pointer rather than a static struct
|
||||
* to get a clean switch-over.
|
||||
*/
|
||||
setCommonICUData(&tData);
|
||||
|
||||
}
|
||||
|
||||
umtx_unlock(NULL);
|
||||
return TRUE; /* SUCCESS? */
|
||||
#endif
|
||||
|
||||
#else
|
||||
# error MAP_IMPLEMENTATION is set incorrectly
|
||||
#endif
|
||||
|
||||
|
32
icu4c/source/common/umapfile.h
Normal file
32
icu4c/source/common/umapfile.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
******************************************************************************
|
||||
*
|
||||
* Copyright (C) 1999-2001, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*
|
||||
******************************************************************************
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------------
|
||||
*
|
||||
* Memory mapped file wrappers for use by the ICU Data Implementation
|
||||
*
|
||||
* Porting note: The implementation of these functions is very platform specific.
|
||||
* Not all platforms can do real memory mapping. Those that can't
|
||||
* still must implement these functions, getting the data into memory using
|
||||
* whatever means are available.
|
||||
*
|
||||
* These functions are part of the ICU internal implementation, and
|
||||
* are not inteded to be used directly by applications.
|
||||
*
|
||||
*----------------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef __UMAPFILE_H__
|
||||
#define __UMAPFILE_H__
|
||||
|
||||
typedef struct UDataMemory UDataMemory;
|
||||
|
||||
UBool uprv_mapFile(UDataMemory *pdm, const char *path);
|
||||
void uprv_unmapFile(UDataMemory *pData);
|
||||
|
||||
#endif
|
Loading…
Add table
Reference in a new issue