1/*
2*******************************************************************************
3*
4*   Copyright (C) 2003-2014, International Business Machines
5*   Corporation and others.  All Rights Reserved.
6*
7*******************************************************************************
8*   file name:  udataswp.h
9*   encoding:   US-ASCII
10*   tab size:   8 (not used)
11*   indentation:4
12*
13*   created on: 2003jun05
14*   created by: Markus W. Scherer
15*
16*   Definitions for ICU data transformations for different platforms,
17*   changing between big- and little-endian data and/or between
18*   charset families (ASCII<->EBCDIC).
19*/
20
21#ifndef __UDATASWP_H__
22#define __UDATASWP_H__
23
24#include <stdarg.h>
25#include "unicode/utypes.h"
26
27/* forward declaration */
28
29U_CDECL_BEGIN
30
31struct UDataSwapper;
32typedef struct UDataSwapper UDataSwapper;
33
34/**
35 * Function type for data transformation.
36 * Transforms data, or just returns the length of the data if
37 * the input length is -1.
38 * Swap functions assume that their data pointers are aligned properly.
39 *
40 * Quick implementation outline:
41 * (best to copy and adapt and existing swapper implementation)
42 * check that the data looks like the expected format
43 * if(length<0) {
44 *   preflight:
45 *   never dereference outData
46 *   read inData and determine the data size
47 *   assume that inData is long enough for this
48 * } else {
49 *   outData can be NULL if length==0
50 *   inData==outData (in-place swapping) possible but not required!
51 *   verify that length>=(actual size)
52 *   if there is a chance that not every byte up to size is reached
53 *     due to padding etc.:
54 *   if(inData!=outData) {
55 *     memcpy(outData, inData, actual size);
56 *   }
57 *   swap contents
58 * }
59 * return actual size
60 *
61 * Further implementation notes:
62 * - read integers from inData before swapping them
63 *   because in-place swapping can make them unreadable
64 * - compareInvChars compares a local Unicode string with already-swapped
65 *   output charset strings
66 *
67 * @param ds Pointer to UDataSwapper containing global data about the
68 *           transformation and function pointers for handling primitive
69 *           types.
70 * @param inData Pointer to the input data to be transformed or examined.
71 * @param length Length of the data, counting bytes. May be -1 for preflighting.
72 *               If length>=0, then transform the data.
73 *               If length==-1, then only determine the length of the data.
74 *               The length cannot be determined from the data itself for all
75 *               types of data (e.g., not for simple arrays of integers).
76 * @param outData Pointer to the output data buffer.
77 *                If length>=0 (transformation), then the output buffer must
78 *                have a capacity of at least length.
79 *                If length==-1, then outData will not be used and can be NULL.
80 * @param pErrorCode ICU UErrorCode parameter, must not be NULL and must
81 *                   fulfill U_SUCCESS on input.
82 * @return The actual length of the data.
83 *
84 * @see UDataSwapper
85 * @internal ICU 2.8
86 */
87typedef int32_t U_CALLCONV
88UDataSwapFn(const UDataSwapper *ds,
89            const void *inData, int32_t length, void *outData,
90            UErrorCode *pErrorCode);
91
92/**
93 * Convert one uint16_t from input to platform endianness.
94 * @internal ICU 2.8
95 */
96typedef uint16_t U_CALLCONV
97UDataReadUInt16(uint16_t x);
98
99/**
100 * Convert one uint32_t from input to platform endianness.
101 * @internal ICU 2.8
102 */
103typedef uint32_t U_CALLCONV
104UDataReadUInt32(uint32_t x);
105
106/**
107 * Convert one uint16_t from platform to input endianness.
108 * @internal ICU 2.8
109 */
110typedef void U_CALLCONV
111UDataWriteUInt16(uint16_t *p, uint16_t x);
112
113/**
114 * Convert one uint32_t from platform to input endianness.
115 * @internal ICU 2.8
116 */
117typedef void U_CALLCONV
118UDataWriteUInt32(uint32_t *p, uint32_t x);
119
120/**
121 * Compare invariant-character strings, one in the output data and the
122 * other one caller-provided in Unicode.
123 * An output data string is compared because strings are usually swapped
124 * before the rest of the data, to allow for sorting of string tables
125 * according to the output charset.
126 * You can use -1 for the length parameters of NUL-terminated strings as usual.
127 * Returns Unicode code point order for invariant characters.
128 * @internal ICU 2.8
129 */
130typedef int32_t U_CALLCONV
131UDataCompareInvChars(const UDataSwapper *ds,
132                     const char *outString, int32_t outLength,
133                     const UChar *localString, int32_t localLength);
134
135/**
136 * Function for message output when an error occurs during data swapping.
137 * A format string and variable number of arguments are passed
138 * like for vprintf().
139 *
140 * @param context A function-specific context pointer.
141 * @param fmt The format string.
142 * @param args The arguments for format string inserts.
143 *
144 * @internal ICU 2.8
145 */
146typedef void U_CALLCONV
147UDataPrintError(void *context, const char *fmt, va_list args);
148
149struct UDataSwapper {
150    /** Input endianness. @internal ICU 2.8 */
151    UBool inIsBigEndian;
152    /** Input charset family. @see U_CHARSET_FAMILY @internal ICU 2.8 */
153    uint8_t inCharset;
154    /** Output endianness. @internal ICU 2.8 */
155    UBool outIsBigEndian;
156    /** Output charset family. @see U_CHARSET_FAMILY @internal ICU 2.8 */
157    uint8_t outCharset;
158
159    /* basic functions for reading data values */
160
161    /** Convert one uint16_t from input to platform endianness. @internal ICU 2.8 */
162    UDataReadUInt16 *readUInt16;
163    /** Convert one uint32_t from input to platform endianness. @internal ICU 2.8 */
164    UDataReadUInt32 *readUInt32;
165    /** Compare an invariant-character output string with a local one. @internal ICU 2.8 */
166    UDataCompareInvChars *compareInvChars;
167
168    /* basic functions for writing data values */
169
170    /** Convert one uint16_t from platform to input endianness. @internal ICU 2.8 */
171    UDataWriteUInt16 *writeUInt16;
172    /** Convert one uint32_t from platform to input endianness. @internal ICU 2.8 */
173    UDataWriteUInt32 *writeUInt32;
174
175    /* basic functions for data transformations */
176
177    /** Transform an array of 16-bit integers. @internal ICU 2.8 */
178    UDataSwapFn *swapArray16;
179    /** Transform an array of 32-bit integers. @internal ICU 2.8 */
180    UDataSwapFn *swapArray32;
181    /** Transform an array of 64-bit integers. @internal ICU 53 */
182    UDataSwapFn *swapArray64;
183    /** Transform an invariant-character string. @internal ICU 2.8 */
184    UDataSwapFn *swapInvChars;
185
186    /**
187     * Function for message output when an error occurs during data swapping.
188     * Can be NULL.
189     * @internal ICU 2.8
190     */
191    UDataPrintError *printError;
192    /** Context pointer for printError. @internal ICU 2.8 */
193    void *printErrorContext;
194};
195
196U_CDECL_END
197
198U_CAPI UDataSwapper * U_EXPORT2
199udata_openSwapper(UBool inIsBigEndian, uint8_t inCharset,
200                  UBool outIsBigEndian, uint8_t outCharset,
201                  UErrorCode *pErrorCode);
202
203/**
204 * Open a UDataSwapper for the given input data and the specified output
205 * characteristics.
206 * Values of -1 for any of the characteristics mean the local platform's
207 * characteristics.
208 *
209 * @see udata_swap
210 * @internal ICU 2.8
211 */
212U_CAPI UDataSwapper * U_EXPORT2
213udata_openSwapperForInputData(const void *data, int32_t length,
214                              UBool outIsBigEndian, uint8_t outCharset,
215                              UErrorCode *pErrorCode);
216
217U_CAPI void U_EXPORT2
218udata_closeSwapper(UDataSwapper *ds);
219
220/**
221 * Read the beginning of an ICU data piece, recognize magic bytes,
222 * swap the structure.
223 * Set a U_UNSUPPORTED_ERROR if it does not look like an ICU data piece.
224 *
225 * @return The size of the data header, in bytes.
226 *
227 * @internal ICU 2.8
228 */
229U_CAPI int32_t U_EXPORT2
230udata_swapDataHeader(const UDataSwapper *ds,
231                     const void *inData, int32_t length, void *outData,
232                     UErrorCode *pErrorCode);
233
234/**
235 * Convert one int16_t from input to platform endianness.
236 * @internal ICU 2.8
237 */
238U_CAPI int16_t U_EXPORT2
239udata_readInt16(const UDataSwapper *ds, int16_t x);
240
241/**
242 * Convert one int32_t from input to platform endianness.
243 * @internal ICU 2.8
244 */
245U_CAPI int32_t U_EXPORT2
246udata_readInt32(const UDataSwapper *ds, int32_t x);
247
248/**
249 * Swap a block of invariant, NUL-terminated strings, but not padding
250 * bytes after the last string.
251 * @internal
252 */
253U_CAPI int32_t U_EXPORT2
254udata_swapInvStringBlock(const UDataSwapper *ds,
255                         const void *inData, int32_t length, void *outData,
256                         UErrorCode *pErrorCode);
257
258U_CAPI void U_EXPORT2
259udata_printError(const UDataSwapper *ds,
260                 const char *fmt,
261                 ...);
262
263/* internal exports from putil.c -------------------------------------------- */
264
265/* declared here to keep them out of the public putil.h */
266
267/**
268 * Swap invariant char * strings ASCII->EBCDIC.
269 * @internal
270 */
271U_CAPI int32_t U_EXPORT2
272uprv_ebcdicFromAscii(const UDataSwapper *ds,
273                     const void *inData, int32_t length, void *outData,
274                     UErrorCode *pErrorCode);
275
276/**
277 * Copy invariant ASCII char * strings and verify they are invariant.
278 * @internal
279 */
280U_CFUNC int32_t
281uprv_copyAscii(const UDataSwapper *ds,
282               const void *inData, int32_t length, void *outData,
283               UErrorCode *pErrorCode);
284
285/**
286 * Swap invariant char * strings EBCDIC->ASCII.
287 * @internal
288 */
289U_CFUNC int32_t
290uprv_asciiFromEbcdic(const UDataSwapper *ds,
291                     const void *inData, int32_t length, void *outData,
292                     UErrorCode *pErrorCode);
293
294/**
295 * Copy invariant EBCDIC char * strings and verify they are invariant.
296 * @internal
297 */
298U_CFUNC int32_t
299uprv_copyEbcdic(const UDataSwapper *ds,
300                const void *inData, int32_t length, void *outData,
301                UErrorCode *pErrorCode);
302
303/**
304 * Compare ASCII invariant char * with Unicode invariant UChar *
305 * @internal
306 */
307U_CFUNC int32_t
308uprv_compareInvAscii(const UDataSwapper *ds,
309                     const char *outString, int32_t outLength,
310                     const UChar *localString, int32_t localLength);
311
312/**
313 * Compare EBCDIC invariant char * with Unicode invariant UChar *
314 * @internal
315 */
316U_CFUNC int32_t
317uprv_compareInvEbcdic(const UDataSwapper *ds,
318                      const char *outString, int32_t outLength,
319                      const UChar *localString, int32_t localLength);
320
321/* material... -------------------------------------------------------------- */
322
323#if 0
324
325/* udata.h */
326
327/**
328 * Public API function in udata.c
329 *
330 * Same as udata_openChoice() but automatically swaps the data.
331 * isAcceptable, if not NULL, may accept data with endianness and charset family
332 * different from the current platform's properties.
333 * If the data is acceptable and the platform properties do not match, then
334 * the swap function is called to swap an allocated version of the data.
335 * Preflighting may or may not be performed depending on whether the size of
336 * the loaded data item is known.
337 *
338 * @param isAcceptable Same as for udata_openChoice(). May be NULL.
339 *
340 * @internal ICU 2.8
341 */
342U_CAPI UDataMemory * U_EXPORT2
343udata_openSwap(const char *path, const char *type, const char *name,
344               UDataMemoryIsAcceptable *isAcceptable, void *isAcceptableContext,
345               UDataSwapFn *swap,
346               UDataPrintError *printError, void *printErrorContext,
347               UErrorCode *pErrorCode);
348
349#endif
350
351#endif
352