]> git.saurik.com Git - apple/icu.git/blame - icuSources/tools/toolutil/swapimpl.cpp
ICU-400.42.tar.gz
[apple/icu.git] / icuSources / tools / toolutil / swapimpl.cpp
CommitLineData
73c04bcf
A
1/*
2*******************************************************************************
3*
46f4442e 4* Copyright (C) 2005-2008, International Business Machines
73c04bcf
A
5* Corporation and others. All Rights Reserved.
6*
7*******************************************************************************
8* file name: swapimpl.cpp
9* encoding: US-ASCII
10* tab size: 8 (not used)
11* indentation:4
12*
13* created on: 2005may05
14* created by: Markus W. Scherer
15*
16* Data file swapping functions moved here from the common library
17* because some data is hardcoded in ICU4C and needs not be swapped any more.
18* Moving the functions here simplifies testing (for code coverage) because
19* we need not jump through hoops (like adding snapshots of these files
20* to testdata).
21*
22* The declarations for these functions remain in the internal header files
23* in icu/source/common/
24*/
25
26#include "unicode/utypes.h"
27#include "unicode/putil.h"
28#include "unicode/udata.h"
29#include "cmemory.h"
30#include "cstring.h"
31#include "uinvchar.h"
32#include "uassert.h"
33#include "uarrsort.h"
34#include "ucmndata.h"
35#include "udataswp.h"
36
37/* swapping implementations in common */
38
39#include "uresdata.h"
40#include "ucnv_io.h"
41#include "uprops.h"
42#include "ucase.h"
43#include "ubidi_props.h"
44#include "ucol_swp.h"
45#include "ucnv_bld.h"
46#include "unormimp.h"
47#include "sprpimpl.h"
48#include "propname.h"
49#include "rbbidata.h"
50#include "triedict.h"
51
52/* swapping implementations in i18n */
53
54/* definitions */
55
56#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
57
58/* Unicode properties data swapping ----------------------------------------- */
59
60U_CAPI int32_t U_EXPORT2
61uprops_swap(const UDataSwapper *ds,
62 const void *inData, int32_t length, void *outData,
63 UErrorCode *pErrorCode) {
64 const UDataInfo *pInfo;
65 int32_t headerSize, i;
66
67 int32_t dataIndexes[UPROPS_INDEX_COUNT];
68 const int32_t *inData32;
69
70 /* udata_swapDataHeader checks the arguments */
71 headerSize=udata_swapDataHeader(ds, inData, length, outData, pErrorCode);
72 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
73 return 0;
74 }
75
76 /* check data format and format version */
77 pInfo=(const UDataInfo *)((const char *)inData+4);
78 if(!(
79 pInfo->dataFormat[0]==0x55 && /* dataFormat="UPro" */
80 pInfo->dataFormat[1]==0x50 &&
81 pInfo->dataFormat[2]==0x72 &&
82 pInfo->dataFormat[3]==0x6f &&
46f4442e 83 (pInfo->formatVersion[0]==3 || pInfo->formatVersion[0]==4 || pInfo->formatVersion[0]==5) &&
73c04bcf
A
84 pInfo->formatVersion[2]==UTRIE_SHIFT &&
85 pInfo->formatVersion[3]==UTRIE_INDEX_SHIFT
86 )) {
87 udata_printError(ds, "uprops_swap(): data format %02x.%02x.%02x.%02x (format version %02x) is not a Unicode properties file\n",
88 pInfo->dataFormat[0], pInfo->dataFormat[1],
89 pInfo->dataFormat[2], pInfo->dataFormat[3],
90 pInfo->formatVersion[0]);
91 *pErrorCode=U_UNSUPPORTED_ERROR;
92 return 0;
93 }
94
95 /* the properties file must contain at least the indexes array */
96 if(length>=0 && (length-headerSize)<(int32_t)sizeof(dataIndexes)) {
97 udata_printError(ds, "uprops_swap(): too few bytes (%d after header) for a Unicode properties file\n",
98 length-headerSize);
99 *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
100 return 0;
101 }
102
103 /* read the indexes */
104 inData32=(const int32_t *)((const char *)inData+headerSize);
105 for(i=0; i<UPROPS_INDEX_COUNT; ++i) {
106 dataIndexes[i]=udata_readInt32(ds, inData32[i]);
107 }
108
109 /*
110 * comments are copied from the data format description in genprops/store.c
111 * indexes[] constants are in uprops.h
112 */
113 if(length>=0) {
114 int32_t *outData32;
115
116 if((length-headerSize)<(4*dataIndexes[UPROPS_RESERVED_INDEX])) {
117 udata_printError(ds, "uprops_swap(): too few bytes (%d after header) for a Unicode properties file\n",
118 length-headerSize);
119 *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
120 return 0;
121 }
122
123 outData32=(int32_t *)((char *)outData+headerSize);
124
125 /* copy everything for inaccessible data (padding) */
126 if(inData32!=outData32) {
127 uprv_memcpy(outData32, inData32, 4*dataIndexes[UPROPS_RESERVED_INDEX]);
128 }
129
130 /* swap the indexes[16] */
131 ds->swapArray32(ds, inData32, 4*UPROPS_INDEX_COUNT, outData32, pErrorCode);
132
133 /*
134 * swap the main properties UTrie
135 * PT serialized properties trie, see utrie.h (byte size: 4*(i0-16))
136 */
137 utrie_swap(ds,
138 inData32+UPROPS_INDEX_COUNT,
139 4*(dataIndexes[UPROPS_PROPS32_INDEX]-UPROPS_INDEX_COUNT),
140 outData32+UPROPS_INDEX_COUNT,
141 pErrorCode);
142
143 /*
144 * swap the properties and exceptions words
145 * P const uint32_t props32[i1-i0];
146 * E const uint32_t exceptions[i2-i1];
147 */
148 ds->swapArray32(ds,
149 inData32+dataIndexes[UPROPS_PROPS32_INDEX],
150 4*(dataIndexes[UPROPS_EXCEPTIONS_TOP_INDEX]-dataIndexes[UPROPS_PROPS32_INDEX]),
151 outData32+dataIndexes[UPROPS_PROPS32_INDEX],
152 pErrorCode);
153
154 /*
155 * swap the UChars
156 * U const UChar uchars[2*(i3-i2)];
157 */
158 ds->swapArray16(ds,
159 inData32+dataIndexes[UPROPS_EXCEPTIONS_TOP_INDEX],
160 4*(dataIndexes[UPROPS_ADDITIONAL_TRIE_INDEX]-dataIndexes[UPROPS_EXCEPTIONS_TOP_INDEX]),
161 outData32+dataIndexes[UPROPS_EXCEPTIONS_TOP_INDEX],
162 pErrorCode);
163
164 /*
165 * swap the additional UTrie
166 * i3 additionalTrieIndex; -- 32-bit unit index to the additional trie for more properties
167 */
168 utrie_swap(ds,
169 inData32+dataIndexes[UPROPS_ADDITIONAL_TRIE_INDEX],
170 4*(dataIndexes[UPROPS_ADDITIONAL_VECTORS_INDEX]-dataIndexes[UPROPS_ADDITIONAL_TRIE_INDEX]),
171 outData32+dataIndexes[UPROPS_ADDITIONAL_TRIE_INDEX],
172 pErrorCode);
173
174 /*
175 * swap the properties vectors
176 * PV const uint32_t propsVectors[(i6-i4)/i5][i5]==uint32_t propsVectors[i6-i4];
177 */
178 ds->swapArray32(ds,
179 inData32+dataIndexes[UPROPS_ADDITIONAL_VECTORS_INDEX],
180 4*(dataIndexes[UPROPS_RESERVED_INDEX]-dataIndexes[UPROPS_ADDITIONAL_VECTORS_INDEX]),
181 outData32+dataIndexes[UPROPS_ADDITIONAL_VECTORS_INDEX],
182 pErrorCode);
183 }
184
185 /* i6 reservedItemIndex; -- 32-bit unit index to the top of the properties vectors table */
186 return headerSize+4*dataIndexes[UPROPS_RESERVED_INDEX];
187}
188
189/* Unicode case mapping data swapping --------------------------------------- */
190
191U_CAPI int32_t U_EXPORT2
192ucase_swap(const UDataSwapper *ds,
193 const void *inData, int32_t length, void *outData,
194 UErrorCode *pErrorCode) {
195 const UDataInfo *pInfo;
196 int32_t headerSize;
197
198 const uint8_t *inBytes;
199 uint8_t *outBytes;
200
201 const int32_t *inIndexes;
202 int32_t indexes[16];
203
204 int32_t i, offset, count, size;
205
206 /* udata_swapDataHeader checks the arguments */
207 headerSize=udata_swapDataHeader(ds, inData, length, outData, pErrorCode);
208 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
209 return 0;
210 }
211
212 /* check data format and format version */
213 pInfo=(const UDataInfo *)((const char *)inData+4);
214 if(!(
215 pInfo->dataFormat[0]==UCASE_FMT_0 && /* dataFormat="cAsE" */
216 pInfo->dataFormat[1]==UCASE_FMT_1 &&
217 pInfo->dataFormat[2]==UCASE_FMT_2 &&
218 pInfo->dataFormat[3]==UCASE_FMT_3 &&
219 pInfo->formatVersion[0]==1 &&
220 pInfo->formatVersion[2]==UTRIE_SHIFT &&
221 pInfo->formatVersion[3]==UTRIE_INDEX_SHIFT
222 )) {
223 udata_printError(ds, "ucase_swap(): data format %02x.%02x.%02x.%02x (format version %02x) is not recognized as case mapping data\n",
224 pInfo->dataFormat[0], pInfo->dataFormat[1],
225 pInfo->dataFormat[2], pInfo->dataFormat[3],
226 pInfo->formatVersion[0]);
227 *pErrorCode=U_UNSUPPORTED_ERROR;
228 return 0;
229 }
230
231 inBytes=(const uint8_t *)inData+headerSize;
232 outBytes=(uint8_t *)outData+headerSize;
233
234 inIndexes=(const int32_t *)inBytes;
235
236 if(length>=0) {
237 length-=headerSize;
238 if(length<16*4) {
239 udata_printError(ds, "ucase_swap(): too few bytes (%d after header) for case mapping data\n",
240 length);
241 *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
242 return 0;
243 }
244 }
245
246 /* read the first 16 indexes (ICU 3.2/format version 1: UCASE_IX_TOP==16, might grow) */
247 for(i=0; i<16; ++i) {
248 indexes[i]=udata_readInt32(ds, inIndexes[i]);
249 }
250
251 /* get the total length of the data */
252 size=indexes[UCASE_IX_LENGTH];
253
254 if(length>=0) {
255 if(length<size) {
256 udata_printError(ds, "ucase_swap(): too few bytes (%d after header) for all of case mapping data\n",
257 length);
258 *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
259 return 0;
260 }
261
262 /* copy the data for inaccessible bytes */
263 if(inBytes!=outBytes) {
264 uprv_memcpy(outBytes, inBytes, size);
265 }
266
267 offset=0;
268
269 /* swap the int32_t indexes[] */
270 count=indexes[UCASE_IX_INDEX_TOP]*4;
271 ds->swapArray32(ds, inBytes, count, outBytes, pErrorCode);
272 offset+=count;
273
274 /* swap the UTrie */
275 count=indexes[UCASE_IX_TRIE_SIZE];
276 utrie_swap(ds, inBytes+offset, count, outBytes+offset, pErrorCode);
277 offset+=count;
278
279 /* swap the uint16_t exceptions[] and unfold[] */
280 count=(indexes[UCASE_IX_EXC_LENGTH]+indexes[UCASE_IX_UNFOLD_LENGTH])*2;
281 ds->swapArray16(ds, inBytes+offset, count, outBytes+offset, pErrorCode);
282 offset+=count;
283
284 U_ASSERT(offset==size);
285 }
286
287 return headerSize+size;
288}
289
290/* Unicode bidi/shaping data swapping --------------------------------------- */
291
292U_CAPI int32_t U_EXPORT2
293ubidi_swap(const UDataSwapper *ds,
294 const void *inData, int32_t length, void *outData,
295 UErrorCode *pErrorCode) {
296 const UDataInfo *pInfo;
297 int32_t headerSize;
298
299 const uint8_t *inBytes;
300 uint8_t *outBytes;
301
302 const int32_t *inIndexes;
303 int32_t indexes[16];
304
305 int32_t i, offset, count, size;
306
307 /* udata_swapDataHeader checks the arguments */
308 headerSize=udata_swapDataHeader(ds, inData, length, outData, pErrorCode);
309 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
310 return 0;
311 }
312
313 /* check data format and format version */
314 pInfo=(const UDataInfo *)((const char *)inData+4);
315 if(!(
316 pInfo->dataFormat[0]==UBIDI_FMT_0 && /* dataFormat="BiDi" */
317 pInfo->dataFormat[1]==UBIDI_FMT_1 &&
318 pInfo->dataFormat[2]==UBIDI_FMT_2 &&
319 pInfo->dataFormat[3]==UBIDI_FMT_3 &&
320 pInfo->formatVersion[0]==1 &&
321 pInfo->formatVersion[2]==UTRIE_SHIFT &&
322 pInfo->formatVersion[3]==UTRIE_INDEX_SHIFT
323 )) {
324 udata_printError(ds, "ubidi_swap(): data format %02x.%02x.%02x.%02x (format version %02x) is not recognized as bidi/shaping data\n",
325 pInfo->dataFormat[0], pInfo->dataFormat[1],
326 pInfo->dataFormat[2], pInfo->dataFormat[3],
327 pInfo->formatVersion[0]);
328 *pErrorCode=U_UNSUPPORTED_ERROR;
329 return 0;
330 }
331
332 inBytes=(const uint8_t *)inData+headerSize;
333 outBytes=(uint8_t *)outData+headerSize;
334
335 inIndexes=(const int32_t *)inBytes;
336
337 if(length>=0) {
338 length-=headerSize;
339 if(length<16*4) {
340 udata_printError(ds, "ubidi_swap(): too few bytes (%d after header) for bidi/shaping data\n",
341 length);
342 *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
343 return 0;
344 }
345 }
346
347 /* read the first 16 indexes (ICU 3.4/format version 1: UBIDI_IX_TOP==16, might grow) */
348 for(i=0; i<16; ++i) {
349 indexes[i]=udata_readInt32(ds, inIndexes[i]);
350 }
351
352 /* get the total length of the data */
353 size=indexes[UBIDI_IX_LENGTH];
354
355 if(length>=0) {
356 if(length<size) {
357 udata_printError(ds, "ubidi_swap(): too few bytes (%d after header) for all of bidi/shaping data\n",
358 length);
359 *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
360 return 0;
361 }
362
363 /* copy the data for inaccessible bytes */
364 if(inBytes!=outBytes) {
365 uprv_memcpy(outBytes, inBytes, size);
366 }
367
368 offset=0;
369
370 /* swap the int32_t indexes[] */
371 count=indexes[UBIDI_IX_INDEX_TOP]*4;
372 ds->swapArray32(ds, inBytes, count, outBytes, pErrorCode);
373 offset+=count;
374
375 /* swap the UTrie */
376 count=indexes[UBIDI_IX_TRIE_SIZE];
377 utrie_swap(ds, inBytes+offset, count, outBytes+offset, pErrorCode);
378 offset+=count;
379
380 /* swap the uint32_t mirrors[] */
381 count=indexes[UBIDI_IX_MIRROR_LENGTH]*4;
382 ds->swapArray32(ds, inBytes+offset, count, outBytes+offset, pErrorCode);
383 offset+=count;
384
385 /* just skip the uint8_t jgArray[] */
386 count=indexes[UBIDI_IX_JG_LIMIT]-indexes[UBIDI_IX_JG_START];
387 offset+=count;
388
389 U_ASSERT(offset==size);
390 }
391
392 return headerSize+size;
393}
394
395/* Unicode normalization data swapping -------------------------------------- */
396
397#if !UCONFIG_NO_NORMALIZATION
398
399U_CAPI int32_t U_EXPORT2
400unorm_swap(const UDataSwapper *ds,
401 const void *inData, int32_t length, void *outData,
402 UErrorCode *pErrorCode) {
403 const UDataInfo *pInfo;
404 int32_t headerSize;
405
406 const uint8_t *inBytes;
407 uint8_t *outBytes;
408
409 const int32_t *inIndexes;
410 int32_t indexes[32];
411
412 int32_t i, offset, count, size;
413
414 /* udata_swapDataHeader checks the arguments */
415 headerSize=udata_swapDataHeader(ds, inData, length, outData, pErrorCode);
416 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
417 return 0;
418 }
419
420 /* check data format and format version */
421 pInfo=(const UDataInfo *)((const char *)inData+4);
422 if(!(
423 pInfo->dataFormat[0]==0x4e && /* dataFormat="Norm" */
424 pInfo->dataFormat[1]==0x6f &&
425 pInfo->dataFormat[2]==0x72 &&
426 pInfo->dataFormat[3]==0x6d &&
427 pInfo->formatVersion[0]==2
428 )) {
429 udata_printError(ds, "unorm_swap(): data format %02x.%02x.%02x.%02x (format version %02x) is not recognized as unorm.icu\n",
430 pInfo->dataFormat[0], pInfo->dataFormat[1],
431 pInfo->dataFormat[2], pInfo->dataFormat[3],
432 pInfo->formatVersion[0]);
433 *pErrorCode=U_UNSUPPORTED_ERROR;
434 return 0;
435 }
436
437 inBytes=(const uint8_t *)inData+headerSize;
438 outBytes=(uint8_t *)outData+headerSize;
439
440 inIndexes=(const int32_t *)inBytes;
441
442 if(length>=0) {
443 length-=headerSize;
444 if(length<32*4) {
445 udata_printError(ds, "unorm_swap(): too few bytes (%d after header) for unorm.icu\n",
446 length);
447 *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
448 return 0;
449 }
450 }
451
452 /* read the first 32 indexes (ICU 2.8/format version 2.2: _NORM_INDEX_TOP==32, might grow) */
453 for(i=0; i<32; ++i) {
454 indexes[i]=udata_readInt32(ds, inIndexes[i]);
455 }
456
457 /* calculate the total length of the data */
458 size=
459 32*4+ /* size of indexes[] */
460 indexes[_NORM_INDEX_TRIE_SIZE]+
461 indexes[_NORM_INDEX_UCHAR_COUNT]*2+
462 indexes[_NORM_INDEX_COMBINE_DATA_COUNT]*2+
463 indexes[_NORM_INDEX_FCD_TRIE_SIZE]+
464 indexes[_NORM_INDEX_AUX_TRIE_SIZE]+
465 indexes[_NORM_INDEX_CANON_SET_COUNT]*2;
466
467 if(length>=0) {
468 if(length<size) {
469 udata_printError(ds, "unorm_swap(): too few bytes (%d after header) for all of unorm.icu\n",
470 length);
471 *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
472 return 0;
473 }
474
475 /* copy the data for inaccessible bytes */
476 if(inBytes!=outBytes) {
477 uprv_memcpy(outBytes, inBytes, size);
478 }
479
480 offset=0;
481
482 /* swap the indexes[] */
483 count=32*4;
484 ds->swapArray32(ds, inBytes, count, outBytes, pErrorCode);
485 offset+=count;
486
487 /* swap the main UTrie */
488 count=indexes[_NORM_INDEX_TRIE_SIZE];
489 utrie_swap(ds, inBytes+offset, count, outBytes+offset, pErrorCode);
490 offset+=count;
491
492 /* swap the uint16_t extraData[] and the uint16_t combiningTable[] */
493 count=(indexes[_NORM_INDEX_UCHAR_COUNT]+indexes[_NORM_INDEX_COMBINE_DATA_COUNT])*2;
494 ds->swapArray16(ds, inBytes+offset, count, outBytes+offset, pErrorCode);
495 offset+=count;
496
497 /* swap the FCD UTrie */
498 count=indexes[_NORM_INDEX_FCD_TRIE_SIZE];
499 if(count!=0) {
500 utrie_swap(ds, inBytes+offset, count, outBytes+offset, pErrorCode);
501 offset+=count;
502 }
503
504 /* swap the aux UTrie */
505 count=indexes[_NORM_INDEX_AUX_TRIE_SIZE];
506 if(count!=0) {
507 utrie_swap(ds, inBytes+offset, count, outBytes+offset, pErrorCode);
508 offset+=count;
509 }
510
511 /* swap the uint16_t combiningTable[] */
512 count=indexes[_NORM_INDEX_CANON_SET_COUNT]*2;
513 ds->swapArray16(ds, inBytes+offset, count, outBytes+offset, pErrorCode);
514 offset+=count;
515 }
516
517 return headerSize+size;
518}
519
520#endif
521
522/* swap any data (except a .dat package) ------------------------------------ */
523
524static const struct {
525 uint8_t dataFormat[4];
526 UDataSwapFn *swapFn;
527} swapFns[]={
528 { { 0x52, 0x65, 0x73, 0x42 }, ures_swap }, /* dataFormat="ResB" */
529#if !UCONFIG_NO_LEGACY_CONVERSION
530 { { 0x63, 0x6e, 0x76, 0x74 }, ucnv_swap }, /* dataFormat="cnvt" */
531#endif
532#if !UCONFIG_NO_CONVERSION
533 { { 0x43, 0x76, 0x41, 0x6c }, ucnv_swapAliases }, /* dataFormat="CvAl" */
534#endif
535#if !UCONFIG_NO_IDNA
536 { { 0x53, 0x50, 0x52, 0x50 }, usprep_swap }, /* dataFormat="SPRP" */
537#endif
538 /* insert data formats here, descending by expected frequency of occurrence */
539 { { 0x55, 0x50, 0x72, 0x6f }, uprops_swap }, /* dataFormat="UPro" */
540
541 { { UCASE_FMT_0, UCASE_FMT_1, UCASE_FMT_2, UCASE_FMT_3 },
542 ucase_swap }, /* dataFormat="cAsE" */
543
544 { { UBIDI_FMT_0, UBIDI_FMT_1, UBIDI_FMT_2, UBIDI_FMT_3 },
545 ubidi_swap }, /* dataFormat="BiDi" */
546
547#if !UCONFIG_NO_NORMALIZATION
548 { { 0x4e, 0x6f, 0x72, 0x6d }, unorm_swap }, /* dataFormat="Norm" */
549#endif
550#if !UCONFIG_NO_COLLATION
551 { { 0x55, 0x43, 0x6f, 0x6c }, ucol_swap }, /* dataFormat="UCol" */
552 { { 0x49, 0x6e, 0x76, 0x43 }, ucol_swapInverseUCA },/* dataFormat="InvC" */
553#endif
554#if !UCONFIG_NO_BREAK_ITERATION
555 { { 0x42, 0x72, 0x6b, 0x20 }, ubrk_swap }, /* dataFormat="Brk " */
556 { { 0x54, 0x72, 0x44, 0x63 }, triedict_swap }, /* dataFormat="TrDc " */
557#endif
558 { { 0x70, 0x6e, 0x61, 0x6d }, upname_swap }, /* dataFormat="pnam" */
559 { { 0x75, 0x6e, 0x61, 0x6d }, uchar_swapNames } /* dataFormat="unam" */
560};
561
562U_CAPI int32_t U_EXPORT2
563udata_swap(const UDataSwapper *ds,
564 const void *inData, int32_t length, void *outData,
565 UErrorCode *pErrorCode) {
566 char dataFormatChars[4];
567 const UDataInfo *pInfo;
568 int32_t headerSize, i, swappedLength;
569
570 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
571 return 0;
572 }
573
574 /*
575 * Preflight the header first; checks for illegal arguments, too.
576 * Do not swap the header right away because the format-specific swapper
577 * will swap it, get the headerSize again, and also use the header
578 * information. Otherwise we would have to pass some of the information
579 * and not be able to use the UDataSwapFn signature.
580 */
581 headerSize=udata_swapDataHeader(ds, inData, -1, NULL, pErrorCode);
582
583 /*
584 * If we wanted udata_swap() to also handle non-loadable data like a UTrie,
585 * then we could check here for further known magic values and structures.
586 */
587 if(U_FAILURE(*pErrorCode)) {
588 return 0; /* the data format was not recognized */
589 }
590
591 pInfo=(const UDataInfo *)((const char *)inData+4);
592
593 {
594 /* convert the data format from ASCII to Unicode to the system charset */
595 UChar u[4]={
596 pInfo->dataFormat[0], pInfo->dataFormat[1],
597 pInfo->dataFormat[2], pInfo->dataFormat[3]
598 };
599
600 if(uprv_isInvariantUString(u, 4)) {
601 u_UCharsToChars(u, dataFormatChars, 4);
602 } else {
603 dataFormatChars[0]=dataFormatChars[1]=dataFormatChars[2]=dataFormatChars[3]='?';
604 }
605 }
606
607 /* dispatch to the swap function for the dataFormat */
608 for(i=0; i<LENGTHOF(swapFns); ++i) {
609 if(0==memcmp(swapFns[i].dataFormat, pInfo->dataFormat, 4)) {
610 swappedLength=swapFns[i].swapFn(ds, inData, length, outData, pErrorCode);
611
612 if(U_FAILURE(*pErrorCode)) {
613 udata_printError(ds, "udata_swap(): failure swapping data format %02x.%02x.%02x.%02x (\"%c%c%c%c\") - %s\n",
614 pInfo->dataFormat[0], pInfo->dataFormat[1],
615 pInfo->dataFormat[2], pInfo->dataFormat[3],
616 dataFormatChars[0], dataFormatChars[1],
617 dataFormatChars[2], dataFormatChars[3],
618 u_errorName(*pErrorCode));
619 } else if(swappedLength<(length-15)) {
620 /* swapped less than expected */
621 udata_printError(ds, "udata_swap() warning: swapped only %d out of %d bytes - data format %02x.%02x.%02x.%02x (\"%c%c%c%c\")\n",
622 swappedLength, length,
623 pInfo->dataFormat[0], pInfo->dataFormat[1],
624 pInfo->dataFormat[2], pInfo->dataFormat[3],
625 dataFormatChars[0], dataFormatChars[1],
626 dataFormatChars[2], dataFormatChars[3],
627 u_errorName(*pErrorCode));
628 }
629
630 return swappedLength;
631 }
632 }
633
634 /* the dataFormat was not recognized */
635 udata_printError(ds, "udata_swap(): unknown data format %02x.%02x.%02x.%02x (\"%c%c%c%c\")\n",
636 pInfo->dataFormat[0], pInfo->dataFormat[1],
637 pInfo->dataFormat[2], pInfo->dataFormat[3],
638 dataFormatChars[0], dataFormatChars[1],
639 dataFormatChars[2], dataFormatChars[3]);
640
641 *pErrorCode=U_UNSUPPORTED_ERROR;
642 return 0;
643}