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 26 U_CFUNC void UDataMemory_init(UDataMemory *This) { 27 uprv_memset(This, 0, sizeof(UDataMemory)); 28 This->length=-1; 29 } 30 31 32 U_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 39 U_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 56 U_CFUNC const DataHeader * 57 UDataMemory_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 84 U_CFUNC void UDataMemory_setData (UDataMemory *This, const void *dataAddr) { 85 This->pHeader = UDataMemory_normalizeDataPointer(dataAddr); 86 } 87 88 89 U_CAPI void U_EXPORT2 90 udata_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 101 U_CAPI const void * U_EXPORT2 102 udata_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 */ 130 U_CAPI int32_t U_EXPORT2 131 udata_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 */ 148 U_CAPI const void * U_EXPORT2 149 udata_getRawMemory(const UDataMemory *pData) { 150 if(pData!=NULL && pData->pHeader!=NULL) { 151 return pData->pHeader; 152 } else { 153 return NULL; 154 } 155 } 156 157 U_CFUNC UBool UDataMemory_isLoaded(const UDataMemory *This) { 158 return This->pHeader != NULL; 159 } 160