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 
29 U_CDECL_BEGIN
30 
31 struct UDataSwapper;
32 typedef 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  */
87 typedef int32_t U_CALLCONV
88 UDataSwapFn(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  */
96 typedef uint16_t U_CALLCONV
97 UDataReadUInt16(uint16_t x);
98 
99 /**
100  * Convert one uint32_t from input to platform endianness.
101  * @internal ICU 2.8
102  */
103 typedef uint32_t U_CALLCONV
104 UDataReadUInt32(uint32_t x);
105 
106 /**
107  * Convert one uint16_t from platform to input endianness.
108  * @internal ICU 2.8
109  */
110 typedef void U_CALLCONV
111 UDataWriteUInt16(uint16_t *p, uint16_t x);
112 
113 /**
114  * Convert one uint32_t from platform to input endianness.
115  * @internal ICU 2.8
116  */
117 typedef void U_CALLCONV
118 UDataWriteUInt32(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  */
130 typedef int32_t U_CALLCONV
131 UDataCompareInvChars(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  */
146 typedef void U_CALLCONV
147 UDataPrintError(void *context, const char *fmt, va_list args);
148 
149 struct 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 
196 U_CDECL_END
197 
198 U_CAPI UDataSwapper * U_EXPORT2
199 udata_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  */
212 U_CAPI UDataSwapper * U_EXPORT2
213 udata_openSwapperForInputData(const void *data, int32_t length,
214                               UBool outIsBigEndian, uint8_t outCharset,
215                               UErrorCode *pErrorCode);
216 
217 U_CAPI void U_EXPORT2
218 udata_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  */
229 U_CAPI int32_t U_EXPORT2
230 udata_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  */
238 U_CAPI int16_t U_EXPORT2
239 udata_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  */
245 U_CAPI int32_t U_EXPORT2
246 udata_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  */
253 U_CAPI int32_t U_EXPORT2
254 udata_swapInvStringBlock(const UDataSwapper *ds,
255                          const void *inData, int32_t length, void *outData,
256                          UErrorCode *pErrorCode);
257 
258 U_CAPI void U_EXPORT2
259 udata_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  */
271 U_CAPI int32_t U_EXPORT2
272 uprv_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  */
280 U_CFUNC int32_t
281 uprv_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  */
289 U_CFUNC int32_t
290 uprv_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  */
298 U_CFUNC int32_t
299 uprv_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  */
307 U_CFUNC int32_t
308 uprv_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  */
316 U_CFUNC int32_t
317 uprv_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  */
342 U_CAPI UDataMemory * U_EXPORT2
343 udata_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