+// swap formatVersion 4 or 5 ----------------------------------------------- ***
+
+// The following are copied from CollationDataReader, trading an awkward copy of constants
+// for an awkward relocation of the i18n collationdatareader.h file into the common library.
+// Keep them in sync!
+
+enum {
+ IX_INDEXES_LENGTH, // 0
+ IX_OPTIONS,
+ IX_RESERVED2,
+ IX_RESERVED3,
+
+ IX_JAMO_CE32S_START, // 4
+ IX_REORDER_CODES_OFFSET,
+ IX_REORDER_TABLE_OFFSET,
+ IX_TRIE_OFFSET,
+
+ IX_RESERVED8_OFFSET, // 8
+ IX_CES_OFFSET,
+ IX_RESERVED10_OFFSET,
+ IX_CE32S_OFFSET,
+
+ IX_ROOT_ELEMENTS_OFFSET, // 12
+ IX_CONTEXTS_OFFSET,
+ IX_UNSAFE_BWD_OFFSET,
+ IX_FAST_LATIN_TABLE_OFFSET,
+
+ IX_SCRIPTS_OFFSET, // 16
+ IX_COMPRESSIBLE_BYTES_OFFSET,
+ IX_RESERVED18_OFFSET,
+ IX_TOTAL_SIZE
+};
+
+int32_t
+swapFormatVersion4(const UDataSwapper *ds,
+ const void *inData, int32_t length, void *outData,
+ UErrorCode &errorCode) {
+ if(U_FAILURE(errorCode)) { return 0; }
+
+ const uint8_t *inBytes=(const uint8_t *)inData;
+ uint8_t *outBytes=(uint8_t *)outData;
+
+ const int32_t *inIndexes=(const int32_t *)inBytes;
+ int32_t indexes[IX_TOTAL_SIZE+1];
+
+ // Need at least IX_INDEXES_LENGTH and IX_OPTIONS.
+ if(0<=length && length<8) {
+ udata_printError(ds, "ucol_swap(formatVersion=4): too few bytes "
+ "(%d after header) for collation data\n",
+ length);
+ errorCode=U_INDEX_OUTOFBOUNDS_ERROR;
+ return 0;
+ }
+
+ int32_t indexesLength=indexes[0]=udata_readInt32(ds, inIndexes[0]);
+ if(0<=length && length<(indexesLength*4)) {
+ udata_printError(ds, "ucol_swap(formatVersion=4): too few bytes "
+ "(%d after header) for collation data\n",
+ length);
+ errorCode=U_INDEX_OUTOFBOUNDS_ERROR;
+ return 0;
+ }
+
+ for(int32_t i=1; i<=IX_TOTAL_SIZE && i<indexesLength; ++i) {
+ indexes[i]=udata_readInt32(ds, inIndexes[i]);
+ }
+ for(int32_t i=indexesLength; i<=IX_TOTAL_SIZE; ++i) {
+ indexes[i]=-1;
+ }
+ inIndexes=NULL; // Make sure we do not accidentally use these instead of indexes[].
+
+ // Get the total length of the data.
+ int32_t size;
+ if(indexesLength>IX_TOTAL_SIZE) {
+ size=indexes[IX_TOTAL_SIZE];
+ } else if(indexesLength>IX_REORDER_CODES_OFFSET) {
+ size=indexes[indexesLength-1];
+ } else {
+ size=indexesLength*4;
+ }
+ if(length<0) { return size; }
+
+ if(length<size) {
+ udata_printError(ds, "ucol_swap(formatVersion=4): too few bytes "
+ "(%d after header) for collation data\n",
+ length);
+ errorCode=U_INDEX_OUTOFBOUNDS_ERROR;
+ return 0;
+ }
+
+ // Copy the data for inaccessible bytes and arrays of bytes.
+ if(inBytes!=outBytes) {
+ uprv_memcpy(outBytes, inBytes, size);
+ }
+
+ // Swap the int32_t indexes[].
+ ds->swapArray32(ds, inBytes, indexesLength * 4, outBytes, &errorCode);
+
+ // The following is a modified version of CollationDataReader::read().
+ // Here we use indexes[] not inIndexes[] because
+ // the inIndexes[] may not be in this machine's endianness.
+ int32_t index; // one of the indexes[] slots
+ int32_t offset; // byte offset for the index part
+ // int32_t length; // number of bytes in the index part
+
+ index = IX_REORDER_CODES_OFFSET;
+ offset = indexes[index];
+ length = indexes[index + 1] - offset;
+ if(length > 0) {
+ ds->swapArray32(ds, inBytes + offset, length, outBytes + offset, &errorCode);
+ }
+
+ // Skip the IX_REORDER_TABLE_OFFSET byte array.
+
+ index = IX_TRIE_OFFSET;
+ offset = indexes[index];
+ length = indexes[index + 1] - offset;
+ if(length > 0) {
+ utrie2_swap(ds, inBytes + offset, length, outBytes + offset, &errorCode);
+ }
+
+ index = IX_RESERVED8_OFFSET;
+ offset = indexes[index];
+ length = indexes[index + 1] - offset;
+ if(length > 0) {
+ udata_printError(ds, "ucol_swap(formatVersion=4): unknown data at IX_RESERVED8_OFFSET\n", length);
+ errorCode = U_UNSUPPORTED_ERROR;
+ return 0;
+ }
+
+ index = IX_CES_OFFSET;
+ offset = indexes[index];
+ length = indexes[index + 1] - offset;
+ if(length > 0) {
+ ds->swapArray64(ds, inBytes + offset, length, outBytes + offset, &errorCode);
+ }
+
+ index = IX_RESERVED10_OFFSET;
+ offset = indexes[index];
+ length = indexes[index + 1] - offset;
+ if(length > 0) {
+ udata_printError(ds, "ucol_swap(formatVersion=4): unknown data at IX_RESERVED10_OFFSET\n", length);
+ errorCode = U_UNSUPPORTED_ERROR;
+ return 0;
+ }
+
+ index = IX_CE32S_OFFSET;
+ offset = indexes[index];
+ length = indexes[index + 1] - offset;
+ if(length > 0) {
+ ds->swapArray32(ds, inBytes + offset, length, outBytes + offset, &errorCode);
+ }
+
+ index = IX_ROOT_ELEMENTS_OFFSET;
+ offset = indexes[index];
+ length = indexes[index + 1] - offset;
+ if(length > 0) {
+ ds->swapArray32(ds, inBytes + offset, length, outBytes + offset, &errorCode);
+ }
+
+ index = IX_CONTEXTS_OFFSET;
+ offset = indexes[index];
+ length = indexes[index + 1] - offset;
+ if(length > 0) {
+ ds->swapArray16(ds, inBytes + offset, length, outBytes + offset, &errorCode);
+ }
+
+ index = IX_UNSAFE_BWD_OFFSET;
+ offset = indexes[index];
+ length = indexes[index + 1] - offset;
+ if(length > 0) {
+ ds->swapArray16(ds, inBytes + offset, length, outBytes + offset, &errorCode);
+ }
+
+ index = IX_FAST_LATIN_TABLE_OFFSET;
+ offset = indexes[index];
+ length = indexes[index + 1] - offset;
+ if(length > 0) {
+ ds->swapArray16(ds, inBytes + offset, length, outBytes + offset, &errorCode);
+ }
+
+ index = IX_SCRIPTS_OFFSET;
+ offset = indexes[index];
+ length = indexes[index + 1] - offset;
+ if(length > 0) {
+ ds->swapArray16(ds, inBytes + offset, length, outBytes + offset, &errorCode);
+ }
+
+ // Skip the IX_COMPRESSIBLE_BYTES_OFFSET byte array.
+
+ index = IX_RESERVED18_OFFSET;
+ offset = indexes[index];
+ length = indexes[index + 1] - offset;
+ if(length > 0) {
+ udata_printError(ds, "ucol_swap(formatVersion=4): unknown data at IX_RESERVED18_OFFSET\n", length);
+ errorCode = U_UNSUPPORTED_ERROR;
+ return 0;
+ }
+
+ return size;
+}
+
+} // namespace
+