michael@0: /* michael@0: ****************************************************************************** michael@0: * michael@0: * Copyright (C) 1999-2011, International Business Machines michael@0: * Corporation and others. All Rights Reserved. michael@0: * michael@0: ******************************************************************************/ michael@0: michael@0: michael@0: /*---------------------------------------------------------------------------------- michael@0: * michael@0: * UDataMemory A class-like struct that serves as a handle to a piece of memory michael@0: * that contains some ICU data (resource, converters, whatever.) michael@0: * michael@0: * When an application opens ICU data (with udata_open, for example, michael@0: * a UDataMemory * is returned. michael@0: * michael@0: *----------------------------------------------------------------------------------*/ michael@0: michael@0: #include "unicode/utypes.h" michael@0: #include "cmemory.h" michael@0: #include "unicode/udata.h" michael@0: michael@0: #include "udatamem.h" michael@0: michael@0: U_CFUNC void UDataMemory_init(UDataMemory *This) { michael@0: uprv_memset(This, 0, sizeof(UDataMemory)); michael@0: This->length=-1; michael@0: } michael@0: michael@0: michael@0: U_CFUNC void UDatamemory_assign(UDataMemory *dest, UDataMemory *source) { michael@0: /* UDataMemory Assignment. Destination UDataMemory must be initialized first. */ michael@0: UBool mallocedFlag = dest->heapAllocated; michael@0: uprv_memcpy(dest, source, sizeof(UDataMemory)); michael@0: dest->heapAllocated = mallocedFlag; michael@0: } michael@0: michael@0: U_CFUNC UDataMemory *UDataMemory_createNewInstance(UErrorCode *pErr) { michael@0: UDataMemory *This; michael@0: michael@0: if (U_FAILURE(*pErr)) { michael@0: return NULL; michael@0: } michael@0: This = uprv_malloc(sizeof(UDataMemory)); michael@0: if (This == NULL) { michael@0: *pErr = U_MEMORY_ALLOCATION_ERROR; } michael@0: else { michael@0: UDataMemory_init(This); michael@0: This->heapAllocated = TRUE; michael@0: } michael@0: return This; michael@0: } michael@0: michael@0: michael@0: U_CFUNC const DataHeader * michael@0: UDataMemory_normalizeDataPointer(const void *p) { michael@0: /* allow the data to be optionally prepended with an alignment-forcing double value */ michael@0: const DataHeader *pdh = (const DataHeader *)p; michael@0: if(pdh==NULL || (pdh->dataHeader.magic1==0xda && pdh->dataHeader.magic2==0x27)) { michael@0: return pdh; michael@0: } else { michael@0: #if U_PLATFORM == U_PF_OS400 michael@0: /* michael@0: TODO: Fix this once the compiler implements this feature. Keep in sync with genccode.c michael@0: michael@0: This is here because this platform can't currently put michael@0: const data into the read-only pages of an object or michael@0: shared library (service program). Only strings are allowed in read-only michael@0: pages, so we use char * strings to store the data. michael@0: michael@0: In order to prevent the beginning of the data from ever matching the michael@0: magic numbers we must skip the initial double. michael@0: [grhoten 4/24/2003] michael@0: */ michael@0: return (const DataHeader *)*((const void **)p+1); michael@0: #else michael@0: return (const DataHeader *)((const double *)p+1); michael@0: #endif michael@0: } michael@0: } michael@0: michael@0: michael@0: U_CFUNC void UDataMemory_setData (UDataMemory *This, const void *dataAddr) { michael@0: This->pHeader = UDataMemory_normalizeDataPointer(dataAddr); michael@0: } michael@0: michael@0: michael@0: U_CAPI void U_EXPORT2 michael@0: udata_close(UDataMemory *pData) { michael@0: if(pData!=NULL) { michael@0: uprv_unmapFile(pData); michael@0: if(pData->heapAllocated ) { michael@0: uprv_free(pData); michael@0: } else { michael@0: UDataMemory_init(pData); michael@0: } michael@0: } michael@0: } michael@0: michael@0: U_CAPI const void * U_EXPORT2 michael@0: udata_getMemory(UDataMemory *pData) { michael@0: if(pData!=NULL && pData->pHeader!=NULL) { michael@0: return (char *)(pData->pHeader)+udata_getHeaderSize(pData->pHeader); michael@0: } else { michael@0: return NULL; michael@0: } michael@0: } michael@0: michael@0: /** michael@0: * Get the length of the data item if possible. michael@0: * The length may be up to 15 bytes larger than the actual data. michael@0: * michael@0: * TODO Consider making this function public. michael@0: * It would have to return the actual length in more cases. michael@0: * For example, the length of the last item in a .dat package could be michael@0: * computed from the size of the whole .dat package minus the offset of the michael@0: * last item. michael@0: * The size of a file that was directly memory-mapped could be determined michael@0: * using some system API. michael@0: * michael@0: * In order to get perfect values for all data items, we may have to add a michael@0: * length field to UDataInfo, but that complicates data generation michael@0: * and may be overkill. michael@0: * michael@0: * @param pData The data item. michael@0: * @return the length of the data item, or -1 if not known michael@0: * @internal Currently used only in cintltst/udatatst.c michael@0: */ michael@0: U_CAPI int32_t U_EXPORT2 michael@0: udata_getLength(const UDataMemory *pData) { michael@0: if(pData!=NULL && pData->pHeader!=NULL && pData->length>=0) { michael@0: /* michael@0: * subtract the header size, michael@0: * return only the size of the actual data starting at udata_getMemory() michael@0: */ michael@0: return pData->length-udata_getHeaderSize(pData->pHeader); michael@0: } else { michael@0: return -1; michael@0: } michael@0: } michael@0: michael@0: /** michael@0: * Get the memory including the data header. michael@0: * Used in cintltst/udatatst.c michael@0: * @internal michael@0: */ michael@0: U_CAPI const void * U_EXPORT2 michael@0: udata_getRawMemory(const UDataMemory *pData) { michael@0: if(pData!=NULL && pData->pHeader!=NULL) { michael@0: return pData->pHeader; michael@0: } else { michael@0: return NULL; michael@0: } michael@0: } michael@0: michael@0: U_CFUNC UBool UDataMemory_isLoaded(const UDataMemory *This) { michael@0: return This->pHeader != NULL; michael@0: }