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