]>
Commit | Line | Data |
---|---|---|
b75a7d8f A |
1 | /* |
2 | ****************************************************************************** | |
3 | * | |
374ca955 | 4 | * Copyright (C) 1999-2004, International Business Machines |
b75a7d8f A |
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 | void UDataMemory_init(UDataMemory *This) { | |
27 | uprv_memset(This, 0, sizeof(UDataMemory)); | |
374ca955 | 28 | This->length=-1; |
b75a7d8f A |
29 | } |
30 | ||
31 | ||
32 | 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 | 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 | 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 | 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) { | |
374ca955 | 104 | return (char *)(pData->pHeader)+udata_getHeaderSize(pData->pHeader); |
b75a7d8f A |
105 | } else { |
106 | return NULL; | |
107 | } | |
108 | } | |
109 | ||
374ca955 A |
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 | } | |
b75a7d8f A |
156 | |
157 | UBool UDataMemory_isLoaded(UDataMemory *This) { | |
158 | return This->pHeader != NULL; | |
159 | } | |
160 |