Home | History | Annotate | Download | only in common
      1 /*
      2 ******************************************************************************
      3 *
      4 *   Copyright (C) 1999-2010, 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 #ifdef 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