1/* 2****************************************************************************** 3* 4* Copyright (C) 1999-2011, International Business Machines 5* Corporation and others. All Rights Reserved. 6* 7******************************************************************************/ 8 9 10/*---------------------------------------------------------------------------------- 11 * 12 * UDataMemory A class-like struct that serves as a handle to a piece of memory 13 * that contains some ICU data (resource, converters, whatever.) 14 * 15 * When an application opens ICU data (with udata_open, for example, 16 * a UDataMemory * is returned. 17 * 18 *----------------------------------------------------------------------------------*/ 19 20#include "unicode/utypes.h" 21#include "cmemory.h" 22#include "unicode/udata.h" 23 24#include "udatamem.h" 25 26U_CFUNC void UDataMemory_init(UDataMemory *This) { 27 uprv_memset(This, 0, sizeof(UDataMemory)); 28 This->length=-1; 29} 30 31 32U_CFUNC void UDatamemory_assign(UDataMemory *dest, UDataMemory *source) { 33 /* UDataMemory Assignment. Destination UDataMemory must be initialized first. */ 34 UBool mallocedFlag = dest->heapAllocated; 35 uprv_memcpy(dest, source, sizeof(UDataMemory)); 36 dest->heapAllocated = mallocedFlag; 37} 38 39U_CFUNC UDataMemory *UDataMemory_createNewInstance(UErrorCode *pErr) { 40 UDataMemory *This; 41 42 if (U_FAILURE(*pErr)) { 43 return NULL; 44 } 45 This = uprv_malloc(sizeof(UDataMemory)); 46 if (This == NULL) { 47 *pErr = U_MEMORY_ALLOCATION_ERROR; } 48 else { 49 UDataMemory_init(This); 50 This->heapAllocated = TRUE; 51 } 52 return This; 53} 54 55 56U_CFUNC const DataHeader * 57UDataMemory_normalizeDataPointer(const void *p) { 58 /* allow the data to be optionally prepended with an alignment-forcing double value */ 59 const DataHeader *pdh = (const DataHeader *)p; 60 if(pdh==NULL || (pdh->dataHeader.magic1==0xda && pdh->dataHeader.magic2==0x27)) { 61 return pdh; 62 } else { 63#if U_PLATFORM == U_PF_OS400 64 /* 65 TODO: Fix this once the compiler implements this feature. Keep in sync with genccode.c 66 67 This is here because this platform can't currently put 68 const data into the read-only pages of an object or 69 shared library (service program). Only strings are allowed in read-only 70 pages, so we use char * strings to store the data. 71 72 In order to prevent the beginning of the data from ever matching the 73 magic numbers we must skip the initial double. 74 [grhoten 4/24/2003] 75 */ 76 return (const DataHeader *)*((const void **)p+1); 77#else 78 return (const DataHeader *)((const double *)p+1); 79#endif 80 } 81} 82 83 84U_CFUNC void UDataMemory_setData (UDataMemory *This, const void *dataAddr) { 85 This->pHeader = UDataMemory_normalizeDataPointer(dataAddr); 86} 87 88 89U_CAPI void U_EXPORT2 90udata_close(UDataMemory *pData) { 91 if(pData!=NULL) { 92 uprv_unmapFile(pData); 93 if(pData->heapAllocated ) { 94 uprv_free(pData); 95 } else { 96 UDataMemory_init(pData); 97 } 98 } 99} 100 101U_CAPI const void * U_EXPORT2 102udata_getMemory(UDataMemory *pData) { 103 if(pData!=NULL && pData->pHeader!=NULL) { 104 return (char *)(pData->pHeader)+udata_getHeaderSize(pData->pHeader); 105 } else { 106 return NULL; 107 } 108} 109 110/** 111 * Get the length of the data item if possible. 112 * The length may be up to 15 bytes larger than the actual data. 113 * 114 * TODO Consider making this function public. 115 * It would have to return the actual length in more cases. 116 * For example, the length of the last item in a .dat package could be 117 * computed from the size of the whole .dat package minus the offset of the 118 * last item. 119 * The size of a file that was directly memory-mapped could be determined 120 * using some system API. 121 * 122 * In order to get perfect values for all data items, we may have to add a 123 * length field to UDataInfo, but that complicates data generation 124 * and may be overkill. 125 * 126 * @param pData The data item. 127 * @return the length of the data item, or -1 if not known 128 * @internal Currently used only in cintltst/udatatst.c 129 */ 130U_CAPI int32_t U_EXPORT2 131udata_getLength(const UDataMemory *pData) { 132 if(pData!=NULL && pData->pHeader!=NULL && pData->length>=0) { 133 /* 134 * subtract the header size, 135 * return only the size of the actual data starting at udata_getMemory() 136 */ 137 return pData->length-udata_getHeaderSize(pData->pHeader); 138 } else { 139 return -1; 140 } 141} 142 143/** 144 * Get the memory including the data header. 145 * Used in cintltst/udatatst.c 146 * @internal 147 */ 148U_CAPI const void * U_EXPORT2 149udata_getRawMemory(const UDataMemory *pData) { 150 if(pData!=NULL && pData->pHeader!=NULL) { 151 return pData->pHeader; 152 } else { 153 return NULL; 154 } 155} 156 157U_CFUNC UBool UDataMemory_isLoaded(const UDataMemory *This) { 158 return This->pHeader != NULL; 159} 160