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