diff --git a/icu4c/source/common/ucmndata.c b/icu4c/source/common/ucmndata.c index 85afabf1204..0ac16c554fb 100644 --- a/icu4c/source/common/ucmndata.c +++ b/icu4c/source/common/ucmndata.c @@ -68,6 +68,7 @@ static uint32_t offsetTOCEntryCount(const UDataMemory *pData) { static const DataHeader * offsetTOCLookupFn(const UDataMemory *pData, const char *tocEntryName, + int32_t *pLength, UErrorCode *pErrorCode) { const UDataOffsetTOC *toc = (UDataOffsetTOC *)pData->toc; if(toc!=NULL) { @@ -95,6 +96,11 @@ offsetTOCLookupFn(const UDataMemory *pData, /* fprintf(stderr, "Found: %p\n",(base+toc[2*start+1])) */ fprintf(stderr, "Found it\n"); #endif + if((start+1)count) { + *pLength=(int32_t)(toc->entry[start+1].dataOffset-toc->entry[start].dataOffset); + } else { + *pLength=-1; + } return (const DataHeader *)&base[toc->entry[start].dataOffset]; } else { #ifdef UDATA_DEBUG @@ -124,6 +130,7 @@ static uint32_t pointerTOCEntryCount(const UDataMemory *pData) { static const DataHeader *pointerTOCLookupFn(const UDataMemory *pData, const char *name, + int32_t *pLength, UErrorCode *pErrorCode) { if(pData->toc!=NULL) { const PointerTOC *toc = (PointerTOC *)pData->toc; @@ -148,6 +155,7 @@ static const DataHeader *pointerTOCLookupFn(const UDataMemory *pData, if(uprv_strcmp(name, toc->entry[start].entryName)==0) { /* found it */ + *pLength=-1; return UDataMemory_normalizeDataPointer(toc->entry[start].pHeader); } else { return NULL; diff --git a/icu4c/source/common/ucmndata.h b/icu4c/source/common/ucmndata.h index 3079a4f6785..886ef32055b 100644 --- a/icu4c/source/common/ucmndata.h +++ b/icu4c/source/common/ucmndata.h @@ -64,6 +64,7 @@ typedef struct { typedef const DataHeader * (* LookupFn)(const UDataMemory *pData, const char *tocEntryName, + int32_t *pLength, UErrorCode *pErrorCode); typedef uint32_t diff --git a/icu4c/source/common/udata.c b/icu4c/source/common/udata.c index 47fcecca2b4..e95dc8378c1 100644 --- a/icu4c/source/common/udata.c +++ b/icu4c/source/common/udata.c @@ -1074,8 +1074,10 @@ doOpenChoice(const char *path, const char *type, const char *name, pCommonData=openCommonData(path, isICUData, &errorCode); /** search for pkg **/ if(U_SUCCESS(errorCode)) { + int32_t length; + /* look up the data piece in the common data */ - pHeader=pCommonData->vFuncs->Lookup(pCommonData, tocEntryName, &errorCode); + pHeader=pCommonData->vFuncs->Lookup(pCommonData, tocEntryName, &length, &errorCode); #ifdef UDATA_DEBUG fprintf(stderr, "pHeader=%p\n", pHeader); #endif @@ -1088,6 +1090,7 @@ doOpenChoice(const char *path, const char *type, const char *name, return NULL; } if (pEntryData != NULL) { + pEntryData->length = length; return pEntryData; } } diff --git a/icu4c/source/common/udatamem.c b/icu4c/source/common/udatamem.c index 6b39980cc3d..06a5308745b 100644 --- a/icu4c/source/common/udatamem.c +++ b/icu4c/source/common/udatamem.c @@ -25,6 +25,7 @@ void UDataMemory_init(UDataMemory *This) { uprv_memset(This, 0, sizeof(UDataMemory)); + This->length=-1; } @@ -106,6 +107,52 @@ udata_getMemory(UDataMemory *pData) { } } +/** + * Get the length of the data item if possible. + * The length may be up to 15 bytes larger than the actual data. + * + * TODO Consider making this function public. + * It would have to return the actual length in more cases. + * For example, the length of the last item in a .dat package could be + * computed from the size of the whole .dat package minus the offset of the + * last item. + * The size of a file that was directly memory-mapped could be determined + * using some system API. + * + * In order to get perfect values for all data items, we may have to add a + * length field to UDataInfo, but that complicates data generation + * and may be overkill. + * + * @param pData The data item. + * @return the length of the data item, or -1 if not known + * @internal Currently used only in cintltst/udatatst.c + */ +U_CAPI int32_t U_EXPORT2 +udata_getLength(UDataMemory *pData) { + if(pData!=NULL && pData->pHeader!=NULL && pData->length>=0) { + /* + * subtract the header size, + * return only the size of the actual data starting at udata_getMemory() + */ + return pData->length-pData->pHeader->dataHeader.headerSize; + } else { + return -1; + } +} + +/** + * Get the memory including the data header. + * Used in cintltst/udatatst.c + * @internal + */ +U_CAPI const void * U_EXPORT2 +udata_getRawMemory(UDataMemory *pData) { + if(pData!=NULL && pData->pHeader!=NULL) { + return pData->pHeader; + } else { + return NULL; + } +} UBool UDataMemory_isLoaded(UDataMemory *This) { return This->pHeader != NULL; diff --git a/icu4c/source/common/udatamem.h b/icu4c/source/common/udatamem.h index 840e674e0a4..d63d598de29 100644 --- a/icu4c/source/common/udatamem.h +++ b/icu4c/source/common/udatamem.h @@ -1,7 +1,7 @@ /* ****************************************************************************** * -* Copyright (C) 1999-2001, International Business Machines +* Copyright (C) 1999-2003, International Business Machines * Corporation and others. All Rights Reserved. * ******************************************************************************/ @@ -39,6 +39,7 @@ struct UDataMemory { /* Only non-null if a close operation should unmap */ /* the associated data, and additional info */ /* beyond the mapAddr is needed to do that. */ + int32_t length; /* Length of the data in bytes; -1 if unknown. */ }; UDataMemory *UDataMemory_createNewInstance(UErrorCode *pErr);