1fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius/* 2fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius******************************************************************************* 3fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius* Copyright (C) 2013-2014, International Business Machines 4fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius* Corporation and others. All Rights Reserved. 5fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius******************************************************************************* 6fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius* collationdatawriter.cpp 7fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius* 8fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius* created on: 2013aug06 9fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius* created by: Markus W. Scherer 10fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius*/ 11fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 12fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "unicode/utypes.h" 13fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 14fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#if !UCONFIG_NO_COLLATION 15fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 16fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "unicode/tblcoll.h" 17fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "unicode/udata.h" 18fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "unicode/uniset.h" 19fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "cmemory.h" 20fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "collationdata.h" 21fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "collationdatabuilder.h" 22fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "collationdatareader.h" 23fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "collationdatawriter.h" 24fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "collationfastlatin.h" 25fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "collationsettings.h" 26fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "collationtailoring.h" 27fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "uassert.h" 28fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "ucmndata.h" 29fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 30fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusU_NAMESPACE_BEGIN 31fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 32fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusuint8_t * 33fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusRuleBasedCollator::cloneRuleData(int32_t &length, UErrorCode &errorCode) const { 34fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(U_FAILURE(errorCode)) { return NULL; } 35fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius LocalMemory<uint8_t> buffer((uint8_t *)uprv_malloc(20000)); 36fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(buffer.isNull()) { 37fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius errorCode = U_MEMORY_ALLOCATION_ERROR; 38fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return NULL; 39fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 40fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius length = cloneBinary(buffer.getAlias(), 20000, errorCode); 41fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(errorCode == U_BUFFER_OVERFLOW_ERROR) { 42fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(buffer.allocateInsteadAndCopy(length, 0) == NULL) { 43fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius errorCode = U_MEMORY_ALLOCATION_ERROR; 44fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return NULL; 45fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 46fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius errorCode = U_ZERO_ERROR; 47fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius length = cloneBinary(buffer.getAlias(), length, errorCode); 48fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 49fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(U_FAILURE(errorCode)) { return NULL; } 50fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return buffer.orphan(); 51fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 52fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 53fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusint32_t 54fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusRuleBasedCollator::cloneBinary(uint8_t *dest, int32_t capacity, UErrorCode &errorCode) const { 55fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t indexes[CollationDataReader::IX_TOTAL_SIZE + 1]; 56fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return CollationDataWriter::writeTailoring( 57fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius *tailoring, *settings, indexes, dest, capacity, 58fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius errorCode); 59fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 60fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 61fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusstatic const UDataInfo dataInfo = { 62fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius sizeof(UDataInfo), 63fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 0, 64fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 65fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius U_IS_BIG_ENDIAN, 66fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius U_CHARSET_FAMILY, 67fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius U_SIZEOF_UCHAR, 68fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 0, 69fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 70fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius { 0x55, 0x43, 0x6f, 0x6c }, // dataFormat="UCol" 71fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius { 4, 0, 0, 0 }, // formatVersion 72fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius { 6, 3, 0, 0 } // dataVersion 73fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}; 74fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 75fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusint32_t 76fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusCollationDataWriter::writeBase(const CollationData &data, const CollationSettings &settings, 77fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const void *rootElements, int32_t rootElementsLength, 78fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t indexes[], uint8_t *dest, int32_t capacity, 79fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UErrorCode &errorCode) { 80fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return write(TRUE, NULL, 81fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius data, settings, 82fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius rootElements, rootElementsLength, 83fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius indexes, dest, capacity, errorCode); 84fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 85fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 86fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusint32_t 87fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusCollationDataWriter::writeTailoring(const CollationTailoring &t, const CollationSettings &settings, 88fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t indexes[], uint8_t *dest, int32_t capacity, 89fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UErrorCode &errorCode) { 90fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return write(FALSE, t.version, 91fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius *t.data, settings, 92fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius NULL, 0, 93fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius indexes, dest, capacity, errorCode); 94fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 95fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 96fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusint32_t 97fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusCollationDataWriter::write(UBool isBase, const UVersionInfo dataVersion, 98fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const CollationData &data, const CollationSettings &settings, 99fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const void *rootElements, int32_t rootElementsLength, 100fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t indexes[], uint8_t *dest, int32_t capacity, 101fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UErrorCode &errorCode) { 102fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(U_FAILURE(errorCode)) { return 0; } 103fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(capacity < 0 || (capacity > 0 && dest == NULL)) { 104fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius errorCode = U_ILLEGAL_ARGUMENT_ERROR; 105fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return 0; 106fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 107fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 108fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // Figure out which data items to write before settling on 109fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // the indexes length and writing offsets. 110fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // For any data item, we need to write the start and limit offsets, 111fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // so the indexes length must be at least index-of-start-offset + 2. 112fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t indexesLength; 113fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UBool hasMappings; 114fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UnicodeSet unsafeBackwardSet; 115fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const CollationData *baseData = data.base; 116fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 117fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t fastLatinVersion; 118fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(data.fastLatinTable != NULL) { 119fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius fastLatinVersion = (int32_t)CollationFastLatin::VERSION << 16; 120fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } else { 121fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius fastLatinVersion = 0; 122fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 123fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t fastLatinTableLength = 0; 124fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 125fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(isBase) { 126fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // For the root collator, we write an even number of indexes 127fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // so that we start with an 8-aligned offset. 128fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius indexesLength = CollationDataReader::IX_TOTAL_SIZE + 1; 129fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius U_ASSERT(settings.reorderCodesLength == 0); 130fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius hasMappings = TRUE; 131fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius unsafeBackwardSet = *data.unsafeBackwardSet; 132fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius fastLatinTableLength = data.fastLatinTableLength; 133fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } else if(baseData == NULL) { 134fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius hasMappings = FALSE; 135fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(settings.reorderCodesLength == 0) { 136fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // only options 137fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius indexesLength = CollationDataReader::IX_OPTIONS + 1; // no limit offset here 138fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } else { 139fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // only options, reorder codes, and the reorder table 140fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius indexesLength = CollationDataReader::IX_REORDER_TABLE_OFFSET + 2; 141fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 142fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } else { 143fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius hasMappings = TRUE; 144fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // Tailored mappings, and what else? 145fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // Check in ascending order of optional tailoring data items. 146fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius indexesLength = CollationDataReader::IX_CE32S_OFFSET + 2; 147fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(data.contextsLength != 0) { 148fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius indexesLength = CollationDataReader::IX_CONTEXTS_OFFSET + 2; 149fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 150fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius unsafeBackwardSet.addAll(*data.unsafeBackwardSet).removeAll(*baseData->unsafeBackwardSet); 151fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(!unsafeBackwardSet.isEmpty()) { 152fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius indexesLength = CollationDataReader::IX_UNSAFE_BWD_OFFSET + 2; 153fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 154fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(data.fastLatinTable != baseData->fastLatinTable) { 155fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius fastLatinTableLength = data.fastLatinTableLength; 156fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius indexesLength = CollationDataReader::IX_FAST_LATIN_TABLE_OFFSET + 2; 157fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 158fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 159fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 160fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t headerSize; 161fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(isBase) { 162fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius headerSize = 0; // udata_create() writes the header 163fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } else { 164fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius DataHeader header; 165fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius header.dataHeader.magic1 = 0xda; 166fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius header.dataHeader.magic2 = 0x27; 167fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius uprv_memcpy(&header.info, &dataInfo, sizeof(UDataInfo)); 168fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius uprv_memcpy(header.info.dataVersion, dataVersion, sizeof(UVersionInfo)); 169fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius headerSize = (int32_t)sizeof(header); 170fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius U_ASSERT((headerSize & 3) == 0); // multiple of 4 bytes 171fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(hasMappings && data.cesLength != 0) { 172fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // Sum of the sizes of the data items which are 173fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // not automatically multiples of 8 bytes and which are placed before the CEs. 174fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t sum = headerSize + (indexesLength + settings.reorderCodesLength) * 4; 175fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if((sum & 7) != 0) { 176fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // We need to add padding somewhere so that the 64-bit CEs are 8-aligned. 177fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // We add to the header size here. 178fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // Alternatively, we could increment the indexesLength 179fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // or add a few bytes to the reorderTable. 180fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius headerSize += 4; 181fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 182fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 183fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius header.dataHeader.headerSize = (uint16_t)headerSize; 184fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(headerSize <= capacity) { 185fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius uprv_memcpy(dest, &header, sizeof(header)); 186fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // Write 00 bytes so that the padding is not mistaken for a copyright string. 187fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius uprv_memset(dest + sizeof(header), 0, headerSize - (int32_t)sizeof(header)); 188fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius dest += headerSize; 189fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius capacity -= headerSize; 190fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } else { 191fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius dest = NULL; 192fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius capacity = 0; 193fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 194fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 195fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 196fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius indexes[CollationDataReader::IX_INDEXES_LENGTH] = indexesLength; 197fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius U_ASSERT((settings.options & ~0xffff) == 0); 198fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius indexes[CollationDataReader::IX_OPTIONS] = 199fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius data.numericPrimary | fastLatinVersion | settings.options; 200fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius indexes[CollationDataReader::IX_RESERVED2] = 0; 201fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius indexes[CollationDataReader::IX_RESERVED3] = 0; 202fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 203fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // Byte offsets of data items all start from the start of the indexes. 204fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // We add the headerSize at the very end. 205fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t totalSize = indexesLength * 4; 206fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 207fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(hasMappings && (isBase || data.jamoCE32s != baseData->jamoCE32s)) { 208fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius indexes[CollationDataReader::IX_JAMO_CE32S_START] = data.jamoCE32s - data.ce32s; 209fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } else { 210fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius indexes[CollationDataReader::IX_JAMO_CE32S_START] = -1; 211fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 212fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 213fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius indexes[CollationDataReader::IX_REORDER_CODES_OFFSET] = totalSize; 214fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius totalSize += settings.reorderCodesLength * 4; 215fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 216fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius indexes[CollationDataReader::IX_REORDER_TABLE_OFFSET] = totalSize; 217fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(settings.reorderTable != NULL) { 218fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius totalSize += 256; 219fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 220fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 221fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius indexes[CollationDataReader::IX_TRIE_OFFSET] = totalSize; 222fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(hasMappings) { 223fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UErrorCode errorCode2 = U_ZERO_ERROR; 224fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t length; 225fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(totalSize < capacity) { 226fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius length = utrie2_serialize(data.trie, dest + totalSize, 227fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius capacity - totalSize, &errorCode2); 228fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } else { 229fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius length = utrie2_serialize(data.trie, NULL, 0, &errorCode2); 230fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 231fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(U_FAILURE(errorCode2) && errorCode2 != U_BUFFER_OVERFLOW_ERROR) { 232fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius errorCode = errorCode2; 233fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return 0; 234fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 235fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // The trie size should be a multiple of 8 bytes due to the way 236fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // compactIndex2(UNewTrie2 *trie) currently works. 237fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius U_ASSERT((length & 7) == 0); 238fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius totalSize += length; 239fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 240fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 241fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius indexes[CollationDataReader::IX_RESERVED8_OFFSET] = totalSize; 242fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius indexes[CollationDataReader::IX_CES_OFFSET] = totalSize; 243fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(hasMappings && data.cesLength != 0) { 244fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius U_ASSERT(((headerSize + totalSize) & 7) == 0); 245fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius totalSize += data.cesLength * 8; 246fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 247fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 248fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius indexes[CollationDataReader::IX_RESERVED10_OFFSET] = totalSize; 249fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius indexes[CollationDataReader::IX_CE32S_OFFSET] = totalSize; 250fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(hasMappings) { 251fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius totalSize += data.ce32sLength * 4; 252fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 253fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 254fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius indexes[CollationDataReader::IX_ROOT_ELEMENTS_OFFSET] = totalSize; 255fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius totalSize += rootElementsLength * 4; 256fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 257fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius indexes[CollationDataReader::IX_CONTEXTS_OFFSET] = totalSize; 258fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(hasMappings) { 259fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius totalSize += data.contextsLength * 2; 260fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 261fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 262fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius indexes[CollationDataReader::IX_UNSAFE_BWD_OFFSET] = totalSize; 263fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(hasMappings && !unsafeBackwardSet.isEmpty()) { 264fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UErrorCode errorCode2 = U_ZERO_ERROR; 265fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t length; 266fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(totalSize < capacity) { 267fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius uint16_t *p = reinterpret_cast<uint16_t *>(dest + totalSize); 268fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius length = unsafeBackwardSet.serialize( 269fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius p, (capacity - totalSize) / 2, errorCode2); 270fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } else { 271fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius length = unsafeBackwardSet.serialize(NULL, 0, errorCode2); 272fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 273fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(U_FAILURE(errorCode2) && errorCode2 != U_BUFFER_OVERFLOW_ERROR) { 274fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius errorCode = errorCode2; 275fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return 0; 276fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 277fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius totalSize += length * 2; 278fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 279fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 280fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius indexes[CollationDataReader::IX_FAST_LATIN_TABLE_OFFSET] = totalSize; 281fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius totalSize += fastLatinTableLength * 2; 282fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 283fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius indexes[CollationDataReader::IX_SCRIPTS_OFFSET] = totalSize; 284fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(isBase) { 285fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius totalSize += data.scriptsLength * 2; 286fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 287fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 288fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius indexes[CollationDataReader::IX_COMPRESSIBLE_BYTES_OFFSET] = totalSize; 289fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(isBase) { 290fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius totalSize += 256; 291fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 292fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 293fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius indexes[CollationDataReader::IX_RESERVED18_OFFSET] = totalSize; 294fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius indexes[CollationDataReader::IX_TOTAL_SIZE] = totalSize; 295fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 296fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(totalSize > capacity) { 297fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius errorCode = U_BUFFER_OVERFLOW_ERROR; 298fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return headerSize + totalSize; 299fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 300fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 301fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius uprv_memcpy(dest, indexes, indexesLength * 4); 302fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius copyData(indexes, CollationDataReader::IX_REORDER_CODES_OFFSET, settings.reorderCodes, dest); 303fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius copyData(indexes, CollationDataReader::IX_REORDER_TABLE_OFFSET, settings.reorderTable, dest); 304fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // The trie has already been serialized into the dest buffer. 305fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius copyData(indexes, CollationDataReader::IX_CES_OFFSET, data.ces, dest); 306fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius copyData(indexes, CollationDataReader::IX_CE32S_OFFSET, data.ce32s, dest); 307fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius copyData(indexes, CollationDataReader::IX_ROOT_ELEMENTS_OFFSET, rootElements, dest); 308fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius copyData(indexes, CollationDataReader::IX_CONTEXTS_OFFSET, data.contexts, dest); 309fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // The unsafeBackwardSet has already been serialized into the dest buffer. 310fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius copyData(indexes, CollationDataReader::IX_FAST_LATIN_TABLE_OFFSET, data.fastLatinTable, dest); 311fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius copyData(indexes, CollationDataReader::IX_SCRIPTS_OFFSET, data.scripts, dest); 312fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius copyData(indexes, CollationDataReader::IX_COMPRESSIBLE_BYTES_OFFSET, data.compressibleBytes, dest); 313fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 314fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return headerSize + totalSize; 315fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 316fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 317fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusvoid 318fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusCollationDataWriter::copyData(const int32_t indexes[], int32_t startIndex, 319fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const void *src, uint8_t *dest) { 320fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t start = indexes[startIndex]; 321fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t limit = indexes[startIndex + 1]; 322fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(start < limit) { 323fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius uprv_memcpy(dest + start, src, limit - start); 324fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 325fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 326fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 327fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusU_NAMESPACE_END 328fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 329fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#endif // !UCONFIG_NO_COLLATION 330