summaryrefslogtreecommitdiff
path: root/Build/source/libs/icu/icu-xetex/common/propname.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/libs/icu/icu-xetex/common/propname.cpp')
-rw-r--r--Build/source/libs/icu/icu-xetex/common/propname.cpp758
1 files changed, 758 insertions, 0 deletions
diff --git a/Build/source/libs/icu/icu-xetex/common/propname.cpp b/Build/source/libs/icu/icu-xetex/common/propname.cpp
new file mode 100644
index 00000000000..55e354044f3
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/common/propname.cpp
@@ -0,0 +1,758 @@
+/*
+**********************************************************************
+* Copyright (c) 2002-2006, International Business Machines
+* Corporation and others. All Rights Reserved.
+**********************************************************************
+* Author: Alan Liu
+* Created: October 30 2002
+* Since: ICU 2.4
+**********************************************************************
+*/
+#include "propname.h"
+#include "unicode/uchar.h"
+#include "unicode/udata.h"
+#include "umutex.h"
+#include "cmemory.h"
+#include "cstring.h"
+#include "ucln_cmn.h"
+#include "uarrsort.h"
+
+U_CDECL_BEGIN
+
+/**
+ * Get the next non-ignorable ASCII character from a property name
+ * and lowercases it.
+ * @return ((advance count for the name)<<8)|character
+ */
+static inline int32_t
+getASCIIPropertyNameChar(const char *name) {
+ int32_t i;
+ char c;
+
+ /* Ignore delimiters '-', '_', and ASCII White_Space */
+ for(i=0;
+ (c=name[i++])==0x2d || c==0x5f ||
+ c==0x20 || (0x09<=c && c<=0x0d);
+ ) {}
+
+ if(c!=0) {
+ return (i<<8)|(uint8_t)uprv_asciitolower((char)c);
+ } else {
+ return i<<8;
+ }
+}
+
+/**
+ * Get the next non-ignorable EBCDIC character from a property name
+ * and lowercases it.
+ * @return ((advance count for the name)<<8)|character
+ */
+static inline int32_t
+getEBCDICPropertyNameChar(const char *name) {
+ int32_t i;
+ char c;
+
+ /* Ignore delimiters '-', '_', and EBCDIC White_Space */
+ for(i=0;
+ (c=name[i++])==0x60 || c==0x6d ||
+ c==0x40 || c==0x05 || c==0x15 || c==0x25 || c==0x0b || c==0x0c || c==0x0d;
+ ) {}
+
+ if(c!=0) {
+ return (i<<8)|(uint8_t)uprv_ebcdictolower((char)c);
+ } else {
+ return i<<8;
+ }
+}
+
+/**
+ * Unicode property names and property value names are compared "loosely".
+ *
+ * UCD.html 4.0.1 says:
+ * For all property names, property value names, and for property values for
+ * Enumerated, Binary, or Catalog properties, use the following
+ * loose matching rule:
+ *
+ * LM3. Ignore case, whitespace, underscore ('_'), and hyphens.
+ *
+ * This function does just that, for (char *) name strings.
+ * It is almost identical to ucnv_compareNames() but also ignores
+ * C0 White_Space characters (U+0009..U+000d, and U+0085 on EBCDIC).
+ *
+ * @internal
+ */
+
+U_CAPI int32_t U_EXPORT2
+uprv_compareASCIIPropertyNames(const char *name1, const char *name2) {
+ int32_t rc, r1, r2;
+
+ for(;;) {
+ r1=getASCIIPropertyNameChar(name1);
+ r2=getASCIIPropertyNameChar(name2);
+
+ /* If we reach the ends of both strings then they match */
+ if(((r1|r2)&0xff)==0) {
+ return 0;
+ }
+
+ /* Compare the lowercased characters */
+ if(r1!=r2) {
+ rc=(r1&0xff)-(r2&0xff);
+ if(rc!=0) {
+ return rc;
+ }
+ }
+
+ name1+=r1>>8;
+ name2+=r2>>8;
+ }
+}
+
+U_CAPI int32_t U_EXPORT2
+uprv_compareEBCDICPropertyNames(const char *name1, const char *name2) {
+ int32_t rc, r1, r2;
+
+ for(;;) {
+ r1=getEBCDICPropertyNameChar(name1);
+ r2=getEBCDICPropertyNameChar(name2);
+
+ /* If we reach the ends of both strings then they match */
+ if(((r1|r2)&0xff)==0) {
+ return 0;
+ }
+
+ /* Compare the lowercased characters */
+ if(r1!=r2) {
+ rc=(r1&0xff)-(r2&0xff);
+ if(rc!=0) {
+ return rc;
+ }
+ }
+
+ name1+=r1>>8;
+ name2+=r2>>8;
+ }
+}
+
+U_CDECL_END
+
+U_NAMESPACE_BEGIN
+
+//----------------------------------------------------------------------
+// PropertyAliases implementation
+
+const char*
+PropertyAliases::chooseNameInGroup(Offset offset,
+ UPropertyNameChoice choice) const {
+ int32_t c = choice;
+ if (!offset || c < 0) {
+ return NULL;
+ }
+ const Offset* p = (const Offset*) getPointer(offset);
+ while (c-- > 0) {
+ if (*p++ < 0) return NULL;
+ }
+ Offset a = *p;
+ if (a < 0) a = -a;
+ return (const char*) getPointerNull(a);
+}
+
+const ValueMap*
+PropertyAliases::getValueMap(EnumValue prop) const {
+ NonContiguousEnumToOffset* e2o = (NonContiguousEnumToOffset*) getPointer(enumToValue_offset);
+ Offset a = e2o->getOffset(prop);
+ return (const ValueMap*) (a ? getPointerNull(a) : NULL);
+}
+
+inline const char*
+PropertyAliases::getPropertyName(EnumValue prop,
+ UPropertyNameChoice choice) const {
+ NonContiguousEnumToOffset* e2n = (NonContiguousEnumToOffset*) getPointer(enumToName_offset);
+ return chooseNameInGroup(e2n->getOffset(prop), choice);
+}
+
+inline EnumValue
+PropertyAliases::getPropertyEnum(const char* alias) const {
+ NameToEnum* n2e = (NameToEnum*) getPointer(nameToEnum_offset);
+ return n2e->getEnum(alias, *this);
+}
+
+inline const char*
+PropertyAliases::getPropertyValueName(EnumValue prop,
+ EnumValue value,
+ UPropertyNameChoice choice) const {
+ const ValueMap* vm = getValueMap(prop);
+ if (!vm) return NULL;
+ Offset a;
+ if (vm->enumToName_offset) {
+ a = ((EnumToOffset*) getPointer(vm->enumToName_offset))->
+ getOffset(value);
+ } else {
+ a = ((NonContiguousEnumToOffset*) getPointer(vm->ncEnumToName_offset))->
+ getOffset(value);
+ }
+ return chooseNameInGroup(a, choice);
+}
+
+inline EnumValue
+PropertyAliases::getPropertyValueEnum(EnumValue prop,
+ const char* alias) const {
+ const ValueMap* vm = getValueMap(prop);
+ if (!vm) return UCHAR_INVALID_CODE;
+ NameToEnum* n2e = (NameToEnum*) getPointer(vm->nameToEnum_offset);
+ return n2e->getEnum(alias, *this);
+}
+
+U_NAMESPACE_END
+U_NAMESPACE_USE
+
+//----------------------------------------------------------------------
+// UDataMemory structures
+
+static const PropertyAliases* PNAME = NULL;
+static UDataMemory* UDATA = NULL;
+
+//----------------------------------------------------------------------
+// UDataMemory loading/unloading
+
+/**
+ * udata callback to verify the zone data.
+ */
+U_CDECL_BEGIN
+static UBool U_CALLCONV
+isPNameAcceptable(void* /*context*/,
+ const char* /*type*/, const char* /*name*/,
+ const UDataInfo* info) {
+ return
+ info->size >= sizeof(UDataInfo) &&
+ info->isBigEndian == U_IS_BIG_ENDIAN &&
+ info->charsetFamily == U_CHARSET_FAMILY &&
+ info->dataFormat[0] == PNAME_SIG_0 &&
+ info->dataFormat[1] == PNAME_SIG_1 &&
+ info->dataFormat[2] == PNAME_SIG_2 &&
+ info->dataFormat[3] == PNAME_SIG_3 &&
+ info->formatVersion[0] == PNAME_FORMAT_VERSION;
+}
+
+static UBool U_CALLCONV pname_cleanup(void) {
+ if (UDATA) {
+ udata_close(UDATA);
+ UDATA = NULL;
+ }
+ PNAME = NULL;
+ return TRUE;
+}
+U_CDECL_END
+
+/**
+ * Load the property names data. Caller should check that data is
+ * not loaded BEFORE calling this function. Returns TRUE if the load
+ * succeeds.
+ */
+static UBool _load() {
+ UErrorCode ec = U_ZERO_ERROR;
+ UDataMemory* data =
+ udata_openChoice(0, PNAME_DATA_TYPE, PNAME_DATA_NAME,
+ isPNameAcceptable, 0, &ec);
+ if (U_SUCCESS(ec)) {
+ umtx_lock(NULL);
+ if (UDATA == NULL) {
+ UDATA = data;
+ PNAME = (const PropertyAliases*) udata_getMemory(UDATA);
+ ucln_common_registerCleanup(UCLN_COMMON_PNAME, pname_cleanup);
+ data = NULL;
+ }
+ umtx_unlock(NULL);
+ }
+ if (data) {
+ udata_close(data);
+ }
+ return PNAME!=NULL;
+}
+
+/**
+ * Inline function that expands to code that does a lazy load of the
+ * property names data. If the data is already loaded, avoids an
+ * unnecessary function call. If the data is not loaded, call _load()
+ * to load it, and return TRUE if the load succeeds.
+ */
+static inline UBool load() {
+ UBool f;
+ UMTX_CHECK(NULL, (PNAME!=NULL), f);
+ return f || _load();
+}
+
+//----------------------------------------------------------------------
+// Public API implementation
+
+// The C API is just a thin wrapper. Each function obtains a pointer
+// to the singleton PropertyAliases, and calls the appropriate method
+// on it. If it cannot obtain a pointer, because valid data is not
+// available, then it returns NULL or UCHAR_INVALID_CODE.
+
+U_CAPI const char* U_EXPORT2
+u_getPropertyName(UProperty property,
+ UPropertyNameChoice nameChoice) {
+ return load() ? PNAME->getPropertyName(property, nameChoice)
+ : NULL;
+}
+
+U_CAPI UProperty U_EXPORT2
+u_getPropertyEnum(const char* alias) {
+ UProperty p = load() ? (UProperty) PNAME->getPropertyEnum(alias)
+ : UCHAR_INVALID_CODE;
+ return p;
+}
+
+U_CAPI const char* U_EXPORT2
+u_getPropertyValueName(UProperty property,
+ int32_t value,
+ UPropertyNameChoice nameChoice) {
+ return load() ? PNAME->getPropertyValueName(property, value, nameChoice)
+ : NULL;
+}
+
+U_CAPI int32_t U_EXPORT2
+u_getPropertyValueEnum(UProperty property,
+ const char* alias) {
+ 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;
+ if (ds->outCharset==U_ASCII_FAMILY) {
+ cmp.propCompare=uprv_compareASCIIPropertyNames;
+ }
+ else {
+ cmp.propCompare=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\n",
+ tempMap->count);
+ 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;
+}
+
+int32_t
+PropertyAliases::swap(const UDataSwapper *ds,
+ const uint8_t *inBytes, int32_t length, uint8_t *outBytes,
+ UErrorCode *pErrorCode) {
+ const PropertyAliases *inAliases;
+ PropertyAliases *outAliases;
+ PropertyAliases aliases;
+
+ const ValueMap *inValueMaps;
+ ValueMap *outValueMaps;
+ ValueMap valueMap;
+
+ uint8_t *temp;
+
+ int32_t i;
+
+ inAliases=(const PropertyAliases *)inBytes;
+ outAliases=(PropertyAliases *)outBytes;
+
+ /* read the input PropertyAliases - all 16-bit values */
+ for(i=0; i<(int32_t)sizeof(PropertyAliases)/2; ++i) {
+ ((uint16_t *)&aliases)[i]=ds->readUInt16(((const uint16_t *)inBytes)[i]);
+ }
+
+ if(length>=0) {
+ if(length<aliases.total_size) {
+ udata_printError(ds, "upname_swap(): too few bytes (%d after header) for all of pnames.icu\n",
+ length);
+ *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
+ return 0;
+ }
+
+ /* copy the data for inaccessible bytes */
+ if(inBytes!=outBytes) {
+ uprv_memcpy(outBytes, inBytes, aliases.total_size);
+ }
+
+ /* swap the PropertyAliases class fields */
+ ds->swapArray16(ds, inAliases, sizeof(PropertyAliases), outAliases, pErrorCode);
+
+ /* swap the name groups */
+ ds->swapArray16(ds, inBytes+aliases.nameGroupPool_offset,
+ aliases.stringPool_offset-aliases.nameGroupPool_offset,
+ outBytes+aliases.nameGroupPool_offset, pErrorCode);
+
+ /* swap the strings */
+ udata_swapInvStringBlock(ds, inBytes+aliases.stringPool_offset,
+ aliases.total_size-aliases.stringPool_offset,
+ outBytes+aliases.stringPool_offset, pErrorCode);
+
+ /*
+ * alloc uint8_t temp[total_size] and reset it
+ * swap each top-level struct, put at least the count fields into temp
+ * use subclass-specific swap() functions
+ * enumerate value maps, for each
+ * if temp does not have count!=0 yet
+ * read count, put it into temp
+ * swap the array(s)
+ * resort strings in name->enum maps
+ * swap value maps
+ */
+ temp=(uint8_t *)uprv_malloc(aliases.total_size);
+ if(temp==NULL) {
+ udata_printError(ds, "upname_swap(): unable to allocate temp memory (%d bytes)\n",
+ aliases.total_size);
+ *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
+ return 0;
+ }
+ uprv_memset(temp, 0, aliases.total_size);
+
+ /* swap properties->name groups map */
+ NonContiguousEnumToOffset::swap(ds, inBytes, length, outBytes,
+ temp, aliases.enumToName_offset, pErrorCode);
+
+ /* swap name->properties map */
+ NameToEnum::swap(ds, inBytes, length, outBytes,
+ temp, aliases.nameToEnum_offset, pErrorCode);
+
+ /* swap properties->value maps map */
+ NonContiguousEnumToOffset::swap(ds, inBytes, length, outBytes,
+ temp, aliases.enumToValue_offset, pErrorCode);
+
+ /* enumerate all ValueMaps and swap them */
+ inValueMaps=(const ValueMap *)(inBytes+aliases.valueMap_offset);
+ outValueMaps=(ValueMap *)(outBytes+aliases.valueMap_offset);
+
+ for(i=0; i<aliases.valueMap_count; ++i) {
+ valueMap.enumToName_offset=udata_readInt16(ds, inValueMaps[i].enumToName_offset);
+ valueMap.ncEnumToName_offset=udata_readInt16(ds, inValueMaps[i].ncEnumToName_offset);
+ valueMap.nameToEnum_offset=udata_readInt16(ds, inValueMaps[i].nameToEnum_offset);
+
+ if(valueMap.enumToName_offset!=0) {
+ EnumToOffset::swap(ds, inBytes, length, outBytes,
+ temp, valueMap.enumToName_offset,
+ pErrorCode);
+ } else if(valueMap.ncEnumToName_offset!=0) {
+ NonContiguousEnumToOffset::swap(ds, inBytes, length, outBytes,
+ temp, valueMap.ncEnumToName_offset,
+ pErrorCode);
+ }
+ if(valueMap.nameToEnum_offset!=0) {
+ NameToEnum::swap(ds, inBytes, length, outBytes,
+ temp, valueMap.nameToEnum_offset,
+ pErrorCode);
+ }
+ }
+
+ /* swap the ValueMaps array itself */
+ ds->swapArray16(ds, inValueMaps, aliases.valueMap_count*sizeof(ValueMap),
+ outValueMaps, pErrorCode);
+
+ /* name groups and strings were swapped above */
+
+ /* release temp */
+ uprv_free(temp);
+ }
+
+ return aliases.total_size;
+}
+
+U_CAPI int32_t U_EXPORT2
+upname_swap(const UDataSwapper *ds,
+ const void *inData, int32_t length, void *outData,
+ UErrorCode *pErrorCode) {
+ const UDataInfo *pInfo;
+ int32_t headerSize;
+
+ const uint8_t *inBytes;
+ uint8_t *outBytes;
+
+ /* udata_swapDataHeader checks the arguments */
+ headerSize=udata_swapDataHeader(ds, inData, length, outData, pErrorCode);
+ if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
+ return 0;
+ }
+
+ /* check data format and format version */
+ pInfo=(const UDataInfo *)((const char *)inData+4);
+ if(!(
+ pInfo->dataFormat[0]==0x70 && /* dataFormat="pnam" */
+ pInfo->dataFormat[1]==0x6e &&
+ pInfo->dataFormat[2]==0x61 &&
+ pInfo->dataFormat[3]==0x6d &&
+ pInfo->formatVersion[0]==1
+ )) {
+ udata_printError(ds, "upname_swap(): data format %02x.%02x.%02x.%02x (format version %02x) is not recognized as pnames.icu\n",
+ pInfo->dataFormat[0], pInfo->dataFormat[1],
+ pInfo->dataFormat[2], pInfo->dataFormat[3],
+ pInfo->formatVersion[0]);
+ *pErrorCode=U_UNSUPPORTED_ERROR;
+ return 0;
+ }
+
+ inBytes=(const uint8_t *)inData+headerSize;
+ outBytes=(uint8_t *)outData+headerSize;
+
+ if(length>=0) {
+ length-=headerSize;
+ if(length<(int32_t)sizeof(PropertyAliases)) {
+ udata_printError(ds, "upname_swap(): too few bytes (%d after header) for pnames.icu\n",
+ length);
+ *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
+ return 0;
+ }
+ }
+
+ return headerSize+PropertyAliases::swap(ds, inBytes, length, outBytes, pErrorCode);
+}
+
+//eof