- return load() ? PNAME->getPropertyValueEnum(property, alias)
- : (int32_t)UCHAR_INVALID_CODE;
-}
-
-/* data swapping ------------------------------------------------------------ */
-
-/*
- * Sub-structure-swappers use the temp array (which is as large as the
- * actual data) for intermediate storage,
- * as well as to indicate if a particular structure has been swapped already.
- * The temp array is initially reset to all 0.
- * pos is the byte offset of the sub-structure in the inBytes/outBytes/temp arrays.
- */
-
-int32_t
-EnumToOffset::swap(const UDataSwapper *ds,
- const uint8_t *inBytes, int32_t length, uint8_t *outBytes,
- uint8_t *temp, int32_t pos,
- UErrorCode *pErrorCode) {
- const EnumToOffset *inMap;
- EnumToOffset *outMap, *tempMap;
- int32_t size;
-
- tempMap=(EnumToOffset *)(temp+pos);
- if(tempMap->enumStart!=0 || tempMap->enumLimit!=0) {
- /* this map was swapped already */
- size=tempMap->getSize();
- return size;
- }
-
- inMap=(const EnumToOffset *)(inBytes+pos);
- outMap=(EnumToOffset *)(outBytes+pos);
-
- tempMap->enumStart=udata_readInt32(ds, inMap->enumStart);
- tempMap->enumLimit=udata_readInt32(ds, inMap->enumLimit);
- size=tempMap->getSize();
-
- if(length>=0) {
- if(length<(pos+size)) {
- if(length<(int32_t)sizeof(PropertyAliases)) {
- udata_printError(ds, "upname_swap(EnumToOffset): too few bytes (%d after header)\n"
- " for pnames.icu EnumToOffset{%d..%d} at %d\n",
- length, tempMap->enumStart, tempMap->enumLimit, pos);
- *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
- return 0;
- }
- }
-
- /* swap enumStart and enumLimit */
- ds->swapArray32(ds, inMap, 2*sizeof(EnumValue), outMap, pErrorCode);
-
- /* swap _offsetArray[] */
- ds->swapArray16(ds, inMap->getOffsetArray(), (tempMap->enumLimit-tempMap->enumStart)*sizeof(Offset),
- outMap->getOffsetArray(), pErrorCode);
- }
-
- return size;
-}
-
-int32_t
-NonContiguousEnumToOffset::swap(const UDataSwapper *ds,
- const uint8_t *inBytes, int32_t length, uint8_t *outBytes,
- uint8_t *temp, int32_t pos,
- UErrorCode *pErrorCode) {
- const NonContiguousEnumToOffset *inMap;
- NonContiguousEnumToOffset *outMap, *tempMap;
- int32_t size;
-
- tempMap=(NonContiguousEnumToOffset *)(temp+pos);
- if(tempMap->count!=0) {
- /* this map was swapped already */
- size=tempMap->getSize();
- return size;
- }
-
- inMap=(const NonContiguousEnumToOffset *)(inBytes+pos);
- outMap=(NonContiguousEnumToOffset *)(outBytes+pos);
-
- tempMap->count=udata_readInt32(ds, inMap->count);
- size=tempMap->getSize();
-
- if(length>=0) {
- if(length<(pos+size)) {
- if(length<(int32_t)sizeof(PropertyAliases)) {
- udata_printError(ds, "upname_swap(NonContiguousEnumToOffset): too few bytes (%d after header)\n"
- " for pnames.icu NonContiguousEnumToOffset[%d] at %d\n",
- length, tempMap->count, pos);
- *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
- return 0;
- }
- }
-
- /* swap count and _enumArray[] */
- length=(1+tempMap->count)*sizeof(EnumValue);
- ds->swapArray32(ds, inMap, length,
- outMap, pErrorCode);
-
- /* swap _offsetArray[] */
- pos+=length;
- ds->swapArray16(ds, inBytes+pos, tempMap->count*sizeof(Offset),
- outBytes+pos, pErrorCode);
- }
-
- return size;
-}
-
-struct NameAndIndex {
- Offset name, index;
-};
-
-U_CDECL_BEGIN
-typedef int32_t U_CALLCONV PropNameCompareFn(const char *name1, const char *name2);
-
-struct CompareContext {
- const char *chars;
- PropNameCompareFn *propCompare;
-};
-
-static int32_t U_CALLCONV
-upname_compareRows(const void *context, const void *left, const void *right) {
- CompareContext *cmp=(CompareContext *)context;
- return cmp->propCompare(cmp->chars+((const NameAndIndex *)left)->name,
- cmp->chars+((const NameAndIndex *)right)->name);
-}
-U_CDECL_END
-
-int32_t
-NameToEnum::swap(const UDataSwapper *ds,
- const uint8_t *inBytes, int32_t length, uint8_t *outBytes,
- uint8_t *temp, int32_t pos,
- UErrorCode *pErrorCode) {
- const NameToEnum *inMap;
- NameToEnum *outMap, *tempMap;
-
- const EnumValue *inEnumArray;
- EnumValue *outEnumArray;
-
- const Offset *inNameArray;
- Offset *outNameArray;
-
- NameAndIndex *sortArray;
- CompareContext cmp;
-
- int32_t i, size, oldIndex;
-
- tempMap=(NameToEnum *)(temp+pos);
- if(tempMap->count!=0) {
- /* this map was swapped already */
- size=tempMap->getSize();
- return size;
- }
-
- inMap=(const NameToEnum *)(inBytes+pos);
- outMap=(NameToEnum *)(outBytes+pos);
-
- tempMap->count=udata_readInt32(ds, inMap->count);
- size=tempMap->getSize();
-
- if(length>=0) {
- if(length<(pos+size)) {
- if(length<(int32_t)sizeof(PropertyAliases)) {
- udata_printError(ds, "upname_swap(NameToEnum): too few bytes (%d after header)\n"
- " for pnames.icu NameToEnum[%d] at %d\n",
- length, tempMap->count, pos);
- *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
- return 0;
- }
- }
-
- /* swap count */
- ds->swapArray32(ds, inMap, 4, outMap, pErrorCode);
-
- inEnumArray=inMap->getEnumArray();
- outEnumArray=outMap->getEnumArray();
-
- inNameArray=(const Offset *)(inEnumArray+tempMap->count);
- outNameArray=(Offset *)(outEnumArray+tempMap->count);
-
- if(ds->inCharset==ds->outCharset) {
- /* no need to sort, just swap the enum/name arrays */
- ds->swapArray32(ds, inEnumArray, tempMap->count*4, outEnumArray, pErrorCode);
- ds->swapArray16(ds, inNameArray, tempMap->count*2, outNameArray, pErrorCode);
- return size;
- }
-
- /*
- * The name and enum arrays are sorted by names and must be resorted
- * if inCharset!=outCharset.
- * We use the corresponding part of the temp array to sort an array
- * of pairs of name offsets and sorting indexes.
- * Then the sorting indexes are used to permutate-swap the name and enum arrays.
- *
- * The outBytes must already contain the swapped strings.
- */
- sortArray=(NameAndIndex *)tempMap->getEnumArray();
- for(i=0; i<tempMap->count; ++i) {
- sortArray[i].name=udata_readInt16(ds, inNameArray[i]);
- sortArray[i].index=(Offset)i;
- }
-
- /*
- * use a stable sort to avoid shuffling of equal strings,
- * which makes testing harder
- */
- cmp.chars=(const char *)outBytes;
- cmp.propCompare=
- ds->outCharset==U_ASCII_FAMILY ?
- uprv_compareASCIIPropertyNames :
- uprv_compareEBCDICPropertyNames;
- uprv_sortArray(sortArray, tempMap->count, sizeof(NameAndIndex),
- upname_compareRows, &cmp,
- TRUE, pErrorCode);
- if(U_FAILURE(*pErrorCode)) {
- udata_printError(ds, "upname_swap(NameToEnum).uprv_sortArray(%d items) failed - %s\n",
- tempMap->count, u_errorName(*pErrorCode));
- return 0;
- }
-
- /* copy/swap/permutate _enumArray[] and _nameArray[] */
- if(inEnumArray!=outEnumArray) {
- for(i=0; i<tempMap->count; ++i) {
- oldIndex=sortArray[i].index;
- ds->swapArray32(ds, inEnumArray+oldIndex, 4, outEnumArray+i, pErrorCode);
- ds->swapArray16(ds, inNameArray+oldIndex, 2, outNameArray+i, pErrorCode);
- }
- } else {
- /*
- * in-place swapping: need to permutate into a temporary array
- * and then copy back to not destroy the data
- */
- EnumValue *tempEnumArray;
- Offset *oldIndexes;
-
- /* write name offsets directly from sortArray */
- for(i=0; i<tempMap->count; ++i) {
- ds->writeUInt16((uint16_t *)outNameArray+i, (uint16_t)sortArray[i].name);
- }
-
- /*
- * compress the oldIndexes into a separate array to make space for tempEnumArray
- * the tempMap _nameArray becomes oldIndexes[], getting the index
- * values from the 2D sortArray[],
- * while sortArray=tempMap _enumArray[] becomes tempEnumArray[]
- * this saves us allocating more memory
- *
- * it works because sizeof(NameAndIndex)<=sizeof(EnumValue)
- * and because the nameArray[] can be used for oldIndexes[]
- */
- tempEnumArray=(EnumValue *)sortArray;
- oldIndexes=(Offset *)(sortArray+tempMap->count);
-
- /* copy sortArray[].index values into oldIndexes[] */
- for(i=0; i<tempMap->count; ++i) {
- oldIndexes[i]=sortArray[i].index;
- }
-
- /* permutate inEnumArray[] into tempEnumArray[] */
- for(i=0; i<tempMap->count; ++i) {
- ds->swapArray32(ds, inEnumArray+oldIndexes[i], 4, tempEnumArray+i, pErrorCode);
- }
-
- /* copy tempEnumArray[] to outEnumArray[] */
- uprv_memcpy(outEnumArray, tempEnumArray, tempMap->count*4);
- }
- }
-
- return size;