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