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