2 **********************************************************************
3 * Copyright (c) 2002-2009, International Business Machines
4 * Corporation and others. All Rights Reserved.
5 **********************************************************************
7 * Created: October 30 2002
9 **********************************************************************
12 #include "unicode/uchar.h"
13 #include "unicode/udata.h"
23 * Get the next non-ignorable ASCII character from a property name
25 * @return ((advance count for the name)<<8)|character
28 getASCIIPropertyNameChar(const char *name
) {
32 /* Ignore delimiters '-', '_', and ASCII White_Space */
34 (c
=name
[i
++])==0x2d || c
==0x5f ||
35 c
==0x20 || (0x09<=c
&& c
<=0x0d);
39 return (i
<<8)|(uint8_t)uprv_asciitolower((char)c
);
46 * Get the next non-ignorable EBCDIC character from a property name
48 * @return ((advance count for the name)<<8)|character
51 getEBCDICPropertyNameChar(const char *name
) {
55 /* Ignore delimiters '-', '_', and EBCDIC White_Space */
57 (c
=name
[i
++])==0x60 || c
==0x6d ||
58 c
==0x40 || c
==0x05 || c
==0x15 || c
==0x25 || c
==0x0b || c
==0x0c || c
==0x0d;
62 return (i
<<8)|(uint8_t)uprv_ebcdictolower((char)c
);
69 * Unicode property names and property value names are compared "loosely".
71 * UCD.html 4.0.1 says:
72 * For all property names, property value names, and for property values for
73 * Enumerated, Binary, or Catalog properties, use the following
74 * loose matching rule:
76 * LM3. Ignore case, whitespace, underscore ('_'), and hyphens.
78 * This function does just that, for (char *) name strings.
79 * It is almost identical to ucnv_compareNames() but also ignores
80 * C0 White_Space characters (U+0009..U+000d, and U+0085 on EBCDIC).
85 U_CAPI
int32_t U_EXPORT2
86 uprv_compareASCIIPropertyNames(const char *name1
, const char *name2
) {
90 r1
=getASCIIPropertyNameChar(name1
);
91 r2
=getASCIIPropertyNameChar(name2
);
93 /* If we reach the ends of both strings then they match */
94 if(((r1
|r2
)&0xff)==0) {
98 /* Compare the lowercased characters */
100 rc
=(r1
&0xff)-(r2
&0xff);
111 U_CAPI
int32_t U_EXPORT2
112 uprv_compareEBCDICPropertyNames(const char *name1
, const char *name2
) {
116 r1
=getEBCDICPropertyNameChar(name1
);
117 r2
=getEBCDICPropertyNameChar(name2
);
119 /* If we reach the ends of both strings then they match */
120 if(((r1
|r2
)&0xff)==0) {
124 /* Compare the lowercased characters */
126 rc
=(r1
&0xff)-(r2
&0xff);
141 //----------------------------------------------------------------------
142 // PropertyAliases implementation
145 PropertyAliases::chooseNameInGroup(Offset offset
,
146 UPropertyNameChoice choice
) const {
148 if (!offset
|| c
< 0) {
151 const Offset
* p
= (const Offset
*) getPointer(offset
);
153 if (*p
++ < 0) return NULL
;
157 return (const char*) getPointerNull(a
);
161 PropertyAliases::getValueMap(EnumValue prop
) const {
162 NonContiguousEnumToOffset
* e2o
= (NonContiguousEnumToOffset
*) getPointer(enumToValue_offset
);
163 Offset a
= e2o
->getOffset(prop
);
164 return (const ValueMap
*) (a
? getPointerNull(a
) : NULL
);
168 PropertyAliases::getPropertyName(EnumValue prop
,
169 UPropertyNameChoice choice
) const {
170 NonContiguousEnumToOffset
* e2n
= (NonContiguousEnumToOffset
*) getPointer(enumToName_offset
);
171 return chooseNameInGroup(e2n
->getOffset(prop
), choice
);
175 PropertyAliases::getPropertyEnum(const char* alias
) const {
176 NameToEnum
* n2e
= (NameToEnum
*) getPointer(nameToEnum_offset
);
177 return n2e
->getEnum(alias
, *this);
181 PropertyAliases::getPropertyValueName(EnumValue prop
,
183 UPropertyNameChoice choice
) const {
184 const ValueMap
* vm
= getValueMap(prop
);
185 if (!vm
) return NULL
;
187 if (vm
->enumToName_offset
) {
188 a
= ((EnumToOffset
*) getPointer(vm
->enumToName_offset
))->
191 a
= ((NonContiguousEnumToOffset
*) getPointer(vm
->ncEnumToName_offset
))->
194 return chooseNameInGroup(a
, choice
);
198 PropertyAliases::getPropertyValueEnum(EnumValue prop
,
199 const char* alias
) const {
200 const ValueMap
* vm
= getValueMap(prop
);
201 if (!vm
) return UCHAR_INVALID_CODE
;
202 NameToEnum
* n2e
= (NameToEnum
*) getPointer(vm
->nameToEnum_offset
);
203 return n2e
->getEnum(alias
, *this);
209 //----------------------------------------------------------------------
210 // UDataMemory structures
212 static const PropertyAliases
* PNAME
= NULL
;
213 static UDataMemory
* UDATA
= NULL
;
215 //----------------------------------------------------------------------
216 // UDataMemory loading/unloading
219 * udata callback to verify the zone data.
222 static UBool U_CALLCONV
223 isPNameAcceptable(void* /*context*/,
224 const char* /*type*/, const char* /*name*/,
225 const UDataInfo
* info
) {
227 info
->size
>= sizeof(UDataInfo
) &&
228 info
->isBigEndian
== U_IS_BIG_ENDIAN
&&
229 info
->charsetFamily
== U_CHARSET_FAMILY
&&
230 info
->dataFormat
[0] == PNAME_SIG_0
&&
231 info
->dataFormat
[1] == PNAME_SIG_1
&&
232 info
->dataFormat
[2] == PNAME_SIG_2
&&
233 info
->dataFormat
[3] == PNAME_SIG_3
&&
234 info
->formatVersion
[0] == PNAME_FORMAT_VERSION
;
237 static UBool U_CALLCONV
pname_cleanup(void) {
248 * Load the property names data. Caller should check that data is
249 * not loaded BEFORE calling this function. Returns TRUE if the load
252 static UBool
_load() {
253 UErrorCode ec
= U_ZERO_ERROR
;
255 udata_openChoice(0, PNAME_DATA_TYPE
, PNAME_DATA_NAME
,
256 isPNameAcceptable
, 0, &ec
);
261 PNAME
= (const PropertyAliases
*) udata_getMemory(UDATA
);
262 ucln_common_registerCleanup(UCLN_COMMON_PNAME
, pname_cleanup
);
274 * Inline function that expands to code that does a lazy load of the
275 * property names data. If the data is already loaded, avoids an
276 * unnecessary function call. If the data is not loaded, call _load()
277 * to load it, and return TRUE if the load succeeds.
279 static inline UBool
load() {
281 UMTX_CHECK(NULL
, (PNAME
!=NULL
), f
);
285 //----------------------------------------------------------------------
286 // Public API implementation
288 // The C API is just a thin wrapper. Each function obtains a pointer
289 // to the singleton PropertyAliases, and calls the appropriate method
290 // on it. If it cannot obtain a pointer, because valid data is not
291 // available, then it returns NULL or UCHAR_INVALID_CODE.
293 U_CAPI
const char* U_EXPORT2
294 u_getPropertyName(UProperty property
,
295 UPropertyNameChoice nameChoice
) {
296 return load() ? PNAME
->getPropertyName(property
, nameChoice
)
300 U_CAPI UProperty U_EXPORT2
301 u_getPropertyEnum(const char* alias
) {
302 UProperty p
= load() ? (UProperty
) PNAME
->getPropertyEnum(alias
)
303 : UCHAR_INVALID_CODE
;
307 U_CAPI
const char* U_EXPORT2
308 u_getPropertyValueName(UProperty property
,
310 UPropertyNameChoice nameChoice
) {
311 return load() ? PNAME
->getPropertyValueName(property
, value
, nameChoice
)
315 U_CAPI
int32_t U_EXPORT2
316 u_getPropertyValueEnum(UProperty property
,
318 return load() ? PNAME
->getPropertyValueEnum(property
, alias
)
319 : (int32_t)UCHAR_INVALID_CODE
;
322 /* data swapping ------------------------------------------------------------ */
325 * Sub-structure-swappers use the temp array (which is as large as the
326 * actual data) for intermediate storage,
327 * as well as to indicate if a particular structure has been swapped already.
328 * The temp array is initially reset to all 0.
329 * pos is the byte offset of the sub-structure in the inBytes/outBytes/temp arrays.
333 EnumToOffset::swap(const UDataSwapper
*ds
,
334 const uint8_t *inBytes
, int32_t length
, uint8_t *outBytes
,
335 uint8_t *temp
, int32_t pos
,
336 UErrorCode
*pErrorCode
) {
337 const EnumToOffset
*inMap
;
338 EnumToOffset
*outMap
, *tempMap
;
341 tempMap
=(EnumToOffset
*)(temp
+pos
);
342 if(tempMap
->enumStart
!=0 || tempMap
->enumLimit
!=0) {
343 /* this map was swapped already */
344 size
=tempMap
->getSize();
348 inMap
=(const EnumToOffset
*)(inBytes
+pos
);
349 outMap
=(EnumToOffset
*)(outBytes
+pos
);
351 tempMap
->enumStart
=udata_readInt32(ds
, inMap
->enumStart
);
352 tempMap
->enumLimit
=udata_readInt32(ds
, inMap
->enumLimit
);
353 size
=tempMap
->getSize();
356 if(length
<(pos
+size
)) {
357 if(length
<(int32_t)sizeof(PropertyAliases
)) {
358 udata_printError(ds
, "upname_swap(EnumToOffset): too few bytes (%d after header)\n"
359 " for pnames.icu EnumToOffset{%d..%d} at %d\n",
360 length
, tempMap
->enumStart
, tempMap
->enumLimit
, pos
);
361 *pErrorCode
=U_INDEX_OUTOFBOUNDS_ERROR
;
366 /* swap enumStart and enumLimit */
367 ds
->swapArray32(ds
, inMap
, 2*sizeof(EnumValue
), outMap
, pErrorCode
);
369 /* swap _offsetArray[] */
370 ds
->swapArray16(ds
, inMap
->getOffsetArray(), (tempMap
->enumLimit
-tempMap
->enumStart
)*sizeof(Offset
),
371 outMap
->getOffsetArray(), pErrorCode
);
378 NonContiguousEnumToOffset::swap(const UDataSwapper
*ds
,
379 const uint8_t *inBytes
, int32_t length
, uint8_t *outBytes
,
380 uint8_t *temp
, int32_t pos
,
381 UErrorCode
*pErrorCode
) {
382 const NonContiguousEnumToOffset
*inMap
;
383 NonContiguousEnumToOffset
*outMap
, *tempMap
;
386 tempMap
=(NonContiguousEnumToOffset
*)(temp
+pos
);
387 if(tempMap
->count
!=0) {
388 /* this map was swapped already */
389 size
=tempMap
->getSize();
393 inMap
=(const NonContiguousEnumToOffset
*)(inBytes
+pos
);
394 outMap
=(NonContiguousEnumToOffset
*)(outBytes
+pos
);
396 tempMap
->count
=udata_readInt32(ds
, inMap
->count
);
397 size
=tempMap
->getSize();
400 if(length
<(pos
+size
)) {
401 if(length
<(int32_t)sizeof(PropertyAliases
)) {
402 udata_printError(ds
, "upname_swap(NonContiguousEnumToOffset): too few bytes (%d after header)\n"
403 " for pnames.icu NonContiguousEnumToOffset[%d] at %d\n",
404 length
, tempMap
->count
, pos
);
405 *pErrorCode
=U_INDEX_OUTOFBOUNDS_ERROR
;
410 /* swap count and _enumArray[] */
411 length
=(1+tempMap
->count
)*sizeof(EnumValue
);
412 ds
->swapArray32(ds
, inMap
, length
,
415 /* swap _offsetArray[] */
417 ds
->swapArray16(ds
, inBytes
+pos
, tempMap
->count
*sizeof(Offset
),
418 outBytes
+pos
, pErrorCode
);
424 struct NameAndIndex
{
429 typedef int32_t U_CALLCONV
PropNameCompareFn(const char *name1
, const char *name2
);
431 struct CompareContext
{
433 PropNameCompareFn
*propCompare
;
436 static int32_t U_CALLCONV
437 upname_compareRows(const void *context
, const void *left
, const void *right
) {
438 CompareContext
*cmp
=(CompareContext
*)context
;
439 return cmp
->propCompare(cmp
->chars
+((const NameAndIndex
*)left
)->name
,
440 cmp
->chars
+((const NameAndIndex
*)right
)->name
);
445 NameToEnum::swap(const UDataSwapper
*ds
,
446 const uint8_t *inBytes
, int32_t length
, uint8_t *outBytes
,
447 uint8_t *temp
, int32_t pos
,
448 UErrorCode
*pErrorCode
) {
449 const NameToEnum
*inMap
;
450 NameToEnum
*outMap
, *tempMap
;
452 const EnumValue
*inEnumArray
;
453 EnumValue
*outEnumArray
;
455 const Offset
*inNameArray
;
456 Offset
*outNameArray
;
458 NameAndIndex
*sortArray
;
461 int32_t i
, size
, oldIndex
;
463 tempMap
=(NameToEnum
*)(temp
+pos
);
464 if(tempMap
->count
!=0) {
465 /* this map was swapped already */
466 size
=tempMap
->getSize();
470 inMap
=(const NameToEnum
*)(inBytes
+pos
);
471 outMap
=(NameToEnum
*)(outBytes
+pos
);
473 tempMap
->count
=udata_readInt32(ds
, inMap
->count
);
474 size
=tempMap
->getSize();
477 if(length
<(pos
+size
)) {
478 if(length
<(int32_t)sizeof(PropertyAliases
)) {
479 udata_printError(ds
, "upname_swap(NameToEnum): too few bytes (%d after header)\n"
480 " for pnames.icu NameToEnum[%d] at %d\n",
481 length
, tempMap
->count
, pos
);
482 *pErrorCode
=U_INDEX_OUTOFBOUNDS_ERROR
;
488 ds
->swapArray32(ds
, inMap
, 4, outMap
, pErrorCode
);
490 inEnumArray
=inMap
->getEnumArray();
491 outEnumArray
=outMap
->getEnumArray();
493 inNameArray
=(const Offset
*)(inEnumArray
+tempMap
->count
);
494 outNameArray
=(Offset
*)(outEnumArray
+tempMap
->count
);
496 if(ds
->inCharset
==ds
->outCharset
) {
497 /* no need to sort, just swap the enum/name arrays */
498 ds
->swapArray32(ds
, inEnumArray
, tempMap
->count
*4, outEnumArray
, pErrorCode
);
499 ds
->swapArray16(ds
, inNameArray
, tempMap
->count
*2, outNameArray
, pErrorCode
);
504 * The name and enum arrays are sorted by names and must be resorted
505 * if inCharset!=outCharset.
506 * We use the corresponding part of the temp array to sort an array
507 * of pairs of name offsets and sorting indexes.
508 * Then the sorting indexes are used to permutate-swap the name and enum arrays.
510 * The outBytes must already contain the swapped strings.
512 sortArray
=(NameAndIndex
*)tempMap
->getEnumArray();
513 for(i
=0; i
<tempMap
->count
; ++i
) {
514 sortArray
[i
].name
=udata_readInt16(ds
, inNameArray
[i
]);
515 sortArray
[i
].index
=(Offset
)i
;
519 * use a stable sort to avoid shuffling of equal strings,
520 * which makes testing harder
522 cmp
.chars
=(const char *)outBytes
;
523 if (ds
->outCharset
==U_ASCII_FAMILY
) {
524 cmp
.propCompare
=uprv_compareASCIIPropertyNames
;
527 cmp
.propCompare
=uprv_compareEBCDICPropertyNames
;
529 uprv_sortArray(sortArray
, tempMap
->count
, sizeof(NameAndIndex
),
530 upname_compareRows
, &cmp
,
532 if(U_FAILURE(*pErrorCode
)) {
533 udata_printError(ds
, "upname_swap(NameToEnum).uprv_sortArray(%d items) failed\n",
538 /* copy/swap/permutate _enumArray[] and _nameArray[] */
539 if(inEnumArray
!=outEnumArray
) {
540 for(i
=0; i
<tempMap
->count
; ++i
) {
541 oldIndex
=sortArray
[i
].index
;
542 ds
->swapArray32(ds
, inEnumArray
+oldIndex
, 4, outEnumArray
+i
, pErrorCode
);
543 ds
->swapArray16(ds
, inNameArray
+oldIndex
, 2, outNameArray
+i
, pErrorCode
);
547 * in-place swapping: need to permutate into a temporary array
548 * and then copy back to not destroy the data
550 EnumValue
*tempEnumArray
;
553 /* write name offsets directly from sortArray */
554 for(i
=0; i
<tempMap
->count
; ++i
) {
555 ds
->writeUInt16((uint16_t *)outNameArray
+i
, (uint16_t)sortArray
[i
].name
);
559 * compress the oldIndexes into a separate array to make space for tempEnumArray
560 * the tempMap _nameArray becomes oldIndexes[], getting the index
561 * values from the 2D sortArray[],
562 * while sortArray=tempMap _enumArray[] becomes tempEnumArray[]
563 * this saves us allocating more memory
565 * it works because sizeof(NameAndIndex)<=sizeof(EnumValue)
566 * and because the nameArray[] can be used for oldIndexes[]
568 tempEnumArray
=(EnumValue
*)sortArray
;
569 oldIndexes
=(Offset
*)(sortArray
+tempMap
->count
);
571 /* copy sortArray[].index values into oldIndexes[] */
572 for(i
=0; i
<tempMap
->count
; ++i
) {
573 oldIndexes
[i
]=sortArray
[i
].index
;
576 /* permutate inEnumArray[] into tempEnumArray[] */
577 for(i
=0; i
<tempMap
->count
; ++i
) {
578 ds
->swapArray32(ds
, inEnumArray
+oldIndexes
[i
], 4, tempEnumArray
+i
, pErrorCode
);
581 /* copy tempEnumArray[] to outEnumArray[] */
582 uprv_memcpy(outEnumArray
, tempEnumArray
, tempMap
->count
*4);
590 PropertyAliases::swap(const UDataSwapper
*ds
,
591 const uint8_t *inBytes
, int32_t length
, uint8_t *outBytes
,
592 UErrorCode
*pErrorCode
) {
593 const PropertyAliases
*inAliases
;
594 PropertyAliases
*outAliases
;
595 PropertyAliases aliases
;
597 const ValueMap
*inValueMaps
;
598 ValueMap
*outValueMaps
;
603 inAliases
=(const PropertyAliases
*)inBytes
;
604 outAliases
=(PropertyAliases
*)outBytes
;
606 /* read the input PropertyAliases - all 16-bit values */
607 for(i
=0; i
<(int32_t)sizeof(PropertyAliases
)/2; ++i
) {
608 ((uint16_t *)&aliases
)[i
]=ds
->readUInt16(((const uint16_t *)inBytes
)[i
]);
612 if(length
<aliases
.total_size
) {
613 udata_printError(ds
, "upname_swap(): too few bytes (%d after header) for all of pnames.icu\n",
615 *pErrorCode
=U_INDEX_OUTOFBOUNDS_ERROR
;
619 /* copy the data for inaccessible bytes */
620 if(inBytes
!=outBytes
) {
621 uprv_memcpy(outBytes
, inBytes
, aliases
.total_size
);
624 /* swap the PropertyAliases class fields */
625 ds
->swapArray16(ds
, inAliases
, sizeof(PropertyAliases
), outAliases
, pErrorCode
);
627 /* swap the name groups */
628 ds
->swapArray16(ds
, inBytes
+aliases
.nameGroupPool_offset
,
629 aliases
.stringPool_offset
-aliases
.nameGroupPool_offset
,
630 outBytes
+aliases
.nameGroupPool_offset
, pErrorCode
);
632 /* swap the strings */
633 udata_swapInvStringBlock(ds
, inBytes
+aliases
.stringPool_offset
,
634 aliases
.total_size
-aliases
.stringPool_offset
,
635 outBytes
+aliases
.stringPool_offset
, pErrorCode
);
638 * alloc uint8_t temp[total_size] and reset it
639 * swap each top-level struct, put at least the count fields into temp
640 * use subclass-specific swap() functions
641 * enumerate value maps, for each
642 * if temp does not have count!=0 yet
643 * read count, put it into temp
645 * resort strings in name->enum maps
648 LocalMemory
<uint8_t> temp
;
649 if(temp
.allocateInsteadAndReset(aliases
.total_size
)==NULL
) {
650 udata_printError(ds
, "upname_swap(): unable to allocate temp memory (%d bytes)\n",
652 *pErrorCode
=U_MEMORY_ALLOCATION_ERROR
;
656 /* swap properties->name groups map */
657 NonContiguousEnumToOffset::swap(ds
, inBytes
, length
, outBytes
,
658 temp
.getAlias(), aliases
.enumToName_offset
, pErrorCode
);
660 /* swap name->properties map */
661 NameToEnum::swap(ds
, inBytes
, length
, outBytes
,
662 temp
.getAlias(), aliases
.nameToEnum_offset
, pErrorCode
);
664 /* swap properties->value maps map */
665 NonContiguousEnumToOffset::swap(ds
, inBytes
, length
, outBytes
,
666 temp
.getAlias(), aliases
.enumToValue_offset
, pErrorCode
);
668 /* enumerate all ValueMaps and swap them */
669 inValueMaps
=(const ValueMap
*)(inBytes
+aliases
.valueMap_offset
);
670 outValueMaps
=(ValueMap
*)(outBytes
+aliases
.valueMap_offset
);
672 for(i
=0; i
<aliases
.valueMap_count
; ++i
) {
673 valueMap
.enumToName_offset
=udata_readInt16(ds
, inValueMaps
[i
].enumToName_offset
);
674 valueMap
.ncEnumToName_offset
=udata_readInt16(ds
, inValueMaps
[i
].ncEnumToName_offset
);
675 valueMap
.nameToEnum_offset
=udata_readInt16(ds
, inValueMaps
[i
].nameToEnum_offset
);
677 if(valueMap
.enumToName_offset
!=0) {
678 EnumToOffset::swap(ds
, inBytes
, length
, outBytes
,
679 temp
.getAlias(), valueMap
.enumToName_offset
,
681 } else if(valueMap
.ncEnumToName_offset
!=0) {
682 NonContiguousEnumToOffset::swap(ds
, inBytes
, length
, outBytes
,
683 temp
.getAlias(), valueMap
.ncEnumToName_offset
,
686 if(valueMap
.nameToEnum_offset
!=0) {
687 NameToEnum::swap(ds
, inBytes
, length
, outBytes
,
688 temp
.getAlias(), valueMap
.nameToEnum_offset
,
693 /* swap the ValueMaps array itself */
694 ds
->swapArray16(ds
, inValueMaps
, aliases
.valueMap_count
*sizeof(ValueMap
),
695 outValueMaps
, pErrorCode
);
697 /* name groups and strings were swapped above */
700 return aliases
.total_size
;
703 U_CAPI
int32_t U_EXPORT2
704 upname_swap(const UDataSwapper
*ds
,
705 const void *inData
, int32_t length
, void *outData
,
706 UErrorCode
*pErrorCode
) {
707 const UDataInfo
*pInfo
;
710 const uint8_t *inBytes
;
713 /* udata_swapDataHeader checks the arguments */
714 headerSize
=udata_swapDataHeader(ds
, inData
, length
, outData
, pErrorCode
);
715 if(pErrorCode
==NULL
|| U_FAILURE(*pErrorCode
)) {
719 /* check data format and format version */
720 pInfo
=(const UDataInfo
*)((const char *)inData
+4);
722 pInfo
->dataFormat
[0]==0x70 && /* dataFormat="pnam" */
723 pInfo
->dataFormat
[1]==0x6e &&
724 pInfo
->dataFormat
[2]==0x61 &&
725 pInfo
->dataFormat
[3]==0x6d &&
726 pInfo
->formatVersion
[0]==1
728 udata_printError(ds
, "upname_swap(): data format %02x.%02x.%02x.%02x (format version %02x) is not recognized as pnames.icu\n",
729 pInfo
->dataFormat
[0], pInfo
->dataFormat
[1],
730 pInfo
->dataFormat
[2], pInfo
->dataFormat
[3],
731 pInfo
->formatVersion
[0]);
732 *pErrorCode
=U_UNSUPPORTED_ERROR
;
736 inBytes
=(const uint8_t *)inData
+headerSize
;
737 outBytes
=(uint8_t *)outData
+headerSize
;
741 if(length
<(int32_t)sizeof(PropertyAliases
)) {
742 udata_printError(ds
, "upname_swap(): too few bytes (%d after header) for pnames.icu\n",
744 *pErrorCode
=U_INDEX_OUTOFBOUNDS_ERROR
;
749 return headerSize
+PropertyAliases::swap(ds
, inBytes
, length
, outBytes
, pErrorCode
);