1c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott******************************************************************************
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott*
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott*   Copyright (C) 1999-2004, International Business Machines
5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott*   Corporation and others.  All Rights Reserved.
6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott*
7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott******************************************************************************/
8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*----------------------------------------------------------------------------------
11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *
12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *  UDataMemory     A class-like struct that serves as a handle to a piece of memory
13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *                  that contains some ICU data (resource, converters, whatever.)
14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *
15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *                  When an application opens ICU data (with udata_open, for example,
16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *                  a UDataMemory * is returned.
17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *
18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *----------------------------------------------------------------------------------*/
19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "unicode/utypes.h"
21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "cmemory.h"
22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "unicode/udata.h"
23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "udatamem.h"
25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid UDataMemory_init(UDataMemory *This) {
27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    uprv_memset(This, 0, sizeof(UDataMemory));
28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    This->length=-1;
29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid UDatamemory_assign(UDataMemory *dest, UDataMemory *source) {
33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    /* UDataMemory Assignment.  Destination UDataMemory must be initialized first.  */
34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    UBool mallocedFlag = dest->heapAllocated;
35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    uprv_memcpy(dest, source, sizeof(UDataMemory));
36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    dest->heapAllocated = mallocedFlag;
37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottUDataMemory *UDataMemory_createNewInstance(UErrorCode *pErr) {
40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    UDataMemory *This;
41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (U_FAILURE(*pErr)) {
43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return NULL;
44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    This = uprv_malloc(sizeof(UDataMemory));
46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (This == NULL) {
47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        *pErr = U_MEMORY_ALLOCATION_ERROR; }
48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    else {
49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        UDataMemory_init(This);
50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        This->heapAllocated = TRUE;
51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return This;
53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst DataHeader *
57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottUDataMemory_normalizeDataPointer(const void *p) {
58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    /* allow the data to be optionally prepended with an alignment-forcing double value */
59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    const DataHeader *pdh = (const DataHeader *)p;
60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(pdh==NULL || (pdh->dataHeader.magic1==0xda && pdh->dataHeader.magic2==0x27)) {
61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return pdh;
62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifdef OS400
64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        /*
65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        TODO: Fix this once the compiler implements this feature. Keep in sync with genccode.c
66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        This is here because this platform can't currently put
68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        const data into the read-only pages of an object or
69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        shared library (service program). Only strings are allowed in read-only
70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        pages, so we use char * strings to store the data.
71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        In order to prevent the beginning of the data from ever matching the
73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        magic numbers we must skip the initial double.
74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        [grhoten 4/24/2003]
75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        */
76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return (const DataHeader *)*((const void **)p+1);
77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#else
78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return (const DataHeader *)((const double *)p+1);
79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid UDataMemory_setData (UDataMemory *This, const void *dataAddr) {
85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    This->pHeader = UDataMemory_normalizeDataPointer(dataAddr);
86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottU_CAPI void U_EXPORT2
90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottudata_close(UDataMemory *pData) {
91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(pData!=NULL) {
92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        uprv_unmapFile(pData);
93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if(pData->heapAllocated ) {
94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            uprv_free(pData);
95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        } else {
96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            UDataMemory_init(pData);
97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottU_CAPI const void * U_EXPORT2
102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottudata_getMemory(UDataMemory *pData) {
103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(pData!=NULL && pData->pHeader!=NULL) {
104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return (char *)(pData->pHeader)+udata_getHeaderSize(pData->pHeader);
105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return NULL;
107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/**
111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Get the length of the data item if possible.
112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * The length may be up to 15 bytes larger than the actual data.
113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *
114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * TODO Consider making this function public.
115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * It would have to return the actual length in more cases.
116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * For example, the length of the last item in a .dat package could be
117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * computed from the size of the whole .dat package minus the offset of the
118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * last item.
119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * The size of a file that was directly memory-mapped could be determined
120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * using some system API.
121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *
122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * In order to get perfect values for all data items, we may have to add a
123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * length field to UDataInfo, but that complicates data generation
124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * and may be overkill.
125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *
126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * @param pData The data item.
127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * @return the length of the data item, or -1 if not known
128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * @internal Currently used only in cintltst/udatatst.c
129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */
130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottU_CAPI int32_t U_EXPORT2
131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottudata_getLength(const UDataMemory *pData) {
132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(pData!=NULL && pData->pHeader!=NULL && pData->length>=0) {
133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        /*
134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott         * subtract the header size,
135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott         * return only the size of the actual data starting at udata_getMemory()
136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott         */
137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return pData->length-udata_getHeaderSize(pData->pHeader);
138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return -1;
140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/**
144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Get the memory including the data header.
145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Used in cintltst/udatatst.c
146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * @internal
147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */
148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottU_CAPI const void * U_EXPORT2
149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottudata_getRawMemory(const UDataMemory *pData) {
150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(pData!=NULL && pData->pHeader!=NULL) {
151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return pData->pHeader;
152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return NULL;
154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottUBool  UDataMemory_isLoaded(UDataMemory *This) {
158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return This->pHeader != NULL;
159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
161