|
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 } |