/src/icu/icu4c/source/common/udatamem.cpp
Line | Count | Source |
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 | | |
28 | 232k | U_CFUNC void UDataMemory_init(UDataMemory *This) { |
29 | 232k | uprv_memset(This, 0, sizeof(UDataMemory)); |
30 | 232k | This->length=-1; |
31 | 232k | } |
32 | | |
33 | | |
34 | 26 | U_CFUNC void UDatamemory_assign(UDataMemory *dest, UDataMemory *source) { |
35 | | /* UDataMemory Assignment. Destination UDataMemory must be initialized first. */ |
36 | 26 | UBool mallocedFlag = dest->heapAllocated; |
37 | 26 | uprv_memcpy(dest, source, sizeof(UDataMemory)); |
38 | 26 | dest->heapAllocated = mallocedFlag; |
39 | 26 | } |
40 | | |
41 | 27.7k | U_CFUNC UDataMemory *UDataMemory_createNewInstance(UErrorCode *pErr) { |
42 | 27.7k | UDataMemory *This; |
43 | | |
44 | 27.7k | if (U_FAILURE(*pErr)) { |
45 | 0 | return nullptr; |
46 | 0 | } |
47 | 27.7k | This = (UDataMemory *)uprv_malloc(sizeof(UDataMemory)); |
48 | 27.7k | if (This == nullptr) { |
49 | 0 | *pErr = U_MEMORY_ALLOCATION_ERROR; } |
50 | 27.7k | else { |
51 | 27.7k | UDataMemory_init(This); |
52 | 27.7k | This->heapAllocated = true; |
53 | 27.7k | } |
54 | 27.7k | return This; |
55 | 27.7k | } |
56 | | |
57 | | U_CFUNC const DataHeader* |
58 | 26 | UDataMemory_normalizeDataPointer(const void* p U_LIFETIME_BOUND) { |
59 | | /* allow the data to be optionally prepended with an alignment-forcing double value */ |
60 | 26 | const DataHeader *pdh = (const DataHeader *)p; |
61 | 26 | if(pdh==nullptr || (pdh->dataHeader.magic1==0xda && pdh->dataHeader.magic2==0x27)) { |
62 | 26 | return pdh; |
63 | 26 | } else { |
64 | | #if U_PLATFORM == U_PF_OS400 |
65 | | /* |
66 | | TODO: Fix this once the compiler implements this feature. Keep in sync with genccode.c |
67 | | |
68 | | This is here because this platform can't currently put |
69 | | const data into the read-only pages of an object or |
70 | | shared library (service program). Only strings are allowed in read-only |
71 | | pages, so we use char * strings to store the data. |
72 | | |
73 | | In order to prevent the beginning of the data from ever matching the |
74 | | magic numbers we must skip the initial double. |
75 | | [grhoten 4/24/2003] |
76 | | */ |
77 | | return (const DataHeader *)*((const void **)p+1); |
78 | | #else |
79 | 0 | return (const DataHeader *)((const double *)p+1); |
80 | 0 | #endif |
81 | 0 | } |
82 | 26 | } |
83 | | |
84 | | |
85 | 26 | U_CFUNC void UDataMemory_setData (UDataMemory *This, const void *dataAddr) { |
86 | 26 | This->pHeader = UDataMemory_normalizeDataPointer(dataAddr); |
87 | 26 | } |
88 | | |
89 | | |
90 | | U_CAPI void U_EXPORT2 |
91 | 21.0k | udata_close(UDataMemory *pData) { |
92 | 21.0k | if(pData!=nullptr) { |
93 | 21.0k | uprv_unmapFile(pData); |
94 | 21.0k | if(pData->heapAllocated ) { |
95 | 21.0k | uprv_free(pData); |
96 | 21.0k | } else { |
97 | 0 | UDataMemory_init(pData); |
98 | 0 | } |
99 | 21.0k | } |
100 | 21.0k | } |
101 | | |
102 | | U_CAPI const void* U_EXPORT2 |
103 | 6.87k | udata_getMemory(UDataMemory* pData U_LIFETIME_BOUND) { |
104 | 6.87k | if(pData!=nullptr && pData->pHeader!=nullptr) { |
105 | 6.87k | return (char *)(pData->pHeader)+udata_getHeaderSize(pData->pHeader); |
106 | 6.87k | } else { |
107 | 0 | return nullptr; |
108 | 0 | } |
109 | 6.87k | } |
110 | | |
111 | | /** |
112 | | * Get the length of the data item if possible. |
113 | | * The length may be up to 15 bytes larger than the actual data. |
114 | | * |
115 | | * TODO Consider making this function public. |
116 | | * It would have to return the actual length in more cases. |
117 | | * For example, the length of the last item in a .dat package could be |
118 | | * computed from the size of the whole .dat package minus the offset of the |
119 | | * last item. |
120 | | * The size of a file that was directly memory-mapped could be determined |
121 | | * using some system API. |
122 | | * |
123 | | * In order to get perfect values for all data items, we may have to add a |
124 | | * length field to UDataInfo, but that complicates data generation |
125 | | * and may be overkill. |
126 | | * |
127 | | * @param pData The data item. |
128 | | * @return the length of the data item, or -1 if not known |
129 | | * @internal Currently used only in cintltst/udatatst.c |
130 | | */ |
131 | | U_CAPI int32_t U_EXPORT2 |
132 | 2 | udata_getLength(const UDataMemory *pData) { |
133 | 2 | if(pData!=nullptr && pData->pHeader!=nullptr && pData->length>=0) { |
134 | | /* |
135 | | * subtract the header size, |
136 | | * return only the size of the actual data starting at udata_getMemory() |
137 | | */ |
138 | 2 | return pData->length-udata_getHeaderSize(pData->pHeader); |
139 | 2 | } else { |
140 | 0 | return -1; |
141 | 0 | } |
142 | 2 | } |
143 | | |
144 | | /** |
145 | | * Get the memory including the data header. |
146 | | * Used in cintltst/udatatst.c |
147 | | * @internal |
148 | | */ |
149 | | U_CAPI const void* U_EXPORT2 |
150 | 0 | udata_getRawMemory(const UDataMemory* pData U_LIFETIME_BOUND) { |
151 | 0 | if(pData!=nullptr && pData->pHeader!=nullptr) { |
152 | 0 | return pData->pHeader; |
153 | 0 | } else { |
154 | 0 | return nullptr; |
155 | 0 | } |
156 | 0 | } |
157 | | |
158 | 24 | U_CFUNC UBool UDataMemory_isLoaded(const UDataMemory *This) { |
159 | 24 | return This->pHeader != nullptr; |
160 | 24 | } |