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
28U_CFUNC void UDataMemory_init(UDataMemory *This) {
29 uprv_memset(This, 0, sizeof(UDataMemory));
30 This->length=-1;
31}
32
33
34U_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
41U_CFUNC UDataMemory *UDataMemory_createNewInstance(UErrorCode *pErr) {
42 UDataMemory *This;
43
44 if (U_FAILURE(*pErr)) {
45 return nullptr;
46 }
47 This = (UDataMemory *)uprv_malloc(sizeof(UDataMemory));
48 if (This == nullptr) {
49 *pErr = U_MEMORY_ALLOCATION_ERROR; }
50 else {
51 UDataMemory_init(This);
52 This->heapAllocated = true;
53 }
54 return This;
55}
56
57
58U_CFUNC const DataHeader *
59UDataMemory_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==nullptr || (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
86U_CFUNC void UDataMemory_setData (UDataMemory *This, const void *dataAddr) {
87 This->pHeader = UDataMemory_normalizeDataPointer(dataAddr);
88}
89
90
91U_CAPI void U_EXPORT2
92udata_close(UDataMemory *pData) {
93 if(pData!=nullptr) {
94 uprv_unmapFile(pData);
95 if(pData->heapAllocated ) {
96 uprv_free(pData);
97 } else {
98 UDataMemory_init(pData);
99 }
100 }
101}
102
103U_CAPI const void * U_EXPORT2
104udata_getMemory(UDataMemory *pData) {
105 if(pData!=nullptr && pData->pHeader!=nullptr) {
106 return (char *)(pData->pHeader)+udata_getHeaderSize(pData->pHeader);
107 } else {
108 return nullptr;
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 */
132U_CAPI int32_t U_EXPORT2
133udata_getLength(const UDataMemory *pData) {
134 if(pData!=nullptr && pData->pHeader!=nullptr && 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 */
150U_CAPI const void * U_EXPORT2
151udata_getRawMemory(const UDataMemory *pData) {
152 if(pData!=nullptr && pData->pHeader!=nullptr) {
153 return pData->pHeader;
154 } else {
155 return nullptr;
156 }
157}
158
159U_CFUNC UBool UDataMemory_isLoaded(const UDataMemory *This) {
160 return This->pHeader != nullptr;
161}
162