1f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* 2f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)******************************************************************************* 3f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* 4f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* Copyright (C) 2003-2010, International Business Machines 5f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* Corporation and others. All Rights Reserved. 6f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* 7f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)******************************************************************************* 8f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* file name: ucol_swp.c 9f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* encoding: US-ASCII 10f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* tab size: 8 (not used) 11f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* indentation:4 12f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* 13f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* created on: 2003sep10 14f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* created by: Markus W. Scherer 15f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* 16f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* Swap collation binaries. 17f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)*/ 18f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 19f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "unicode/udata.h" /* UDataInfo */ 20f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "utrie.h" 21f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "udataswp.h" 22f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "cmemory.h" 23f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "ucol_imp.h" 24f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "ucol_swp.h" 25f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 26f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* swapping ----------------------------------------------------------------- */ 27f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 28f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* 29f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * This performs data swapping for a folded trie (see utrie.c for details). 30f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 31f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 32f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CAPI int32_t U_EXPORT2 33f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)utrie_swap(const UDataSwapper *ds, 34f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const void *inData, int32_t length, void *outData, 35f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UErrorCode *pErrorCode) { 36f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const UTrieHeader *inTrie; 37f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UTrieHeader trie; 38f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t size; 39f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UBool dataIs32; 40f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 41f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) { 42f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return 0; 43f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 44f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(ds==NULL || inData==NULL || (length>=0 && outData==NULL)) { 45f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; 46f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return 0; 47f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 48f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 49f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* setup and swapping */ 50f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(length>=0 && (uint32_t)length<sizeof(UTrieHeader)) { 51f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR; 52f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return 0; 53f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 54f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 55f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) inTrie=(const UTrieHeader *)inData; 56f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) trie.signature=ds->readUInt32(inTrie->signature); 57f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) trie.options=ds->readUInt32(inTrie->options); 58f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) trie.indexLength=udata_readInt32(ds, inTrie->indexLength); 59f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) trie.dataLength=udata_readInt32(ds, inTrie->dataLength); 60f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 61f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if( trie.signature!=0x54726965 || 62f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) (trie.options&UTRIE_OPTIONS_SHIFT_MASK)!=UTRIE_SHIFT || 63f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ((trie.options>>UTRIE_OPTIONS_INDEX_SHIFT)&UTRIE_OPTIONS_SHIFT_MASK)!=UTRIE_INDEX_SHIFT || 64f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) trie.indexLength<UTRIE_BMP_INDEX_LENGTH || 65f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) (trie.indexLength&(UTRIE_SURROGATE_BLOCK_COUNT-1))!=0 || 66f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) trie.dataLength<UTRIE_DATA_BLOCK_LENGTH || 67f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) (trie.dataLength&(UTRIE_DATA_GRANULARITY-1))!=0 || 68f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ((trie.options&UTRIE_OPTIONS_LATIN1_IS_LINEAR)!=0 && trie.dataLength<(UTRIE_DATA_BLOCK_LENGTH+0x100)) 69f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ) { 70f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *pErrorCode=U_INVALID_FORMAT_ERROR; /* not a UTrie */ 71f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return 0; 72f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 73f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 74f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) dataIs32=(UBool)((trie.options&UTRIE_OPTIONS_DATA_IS_32_BIT)!=0); 75f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) size=sizeof(UTrieHeader)+trie.indexLength*2+trie.dataLength*(dataIs32?4:2); 76f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 77f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(length>=0) { 78f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UTrieHeader *outTrie; 79f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 80f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(length<size) { 81f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR; 82f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return 0; 83f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 84f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 85f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) outTrie=(UTrieHeader *)outData; 86f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 87f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* swap the header */ 88f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ds->swapArray32(ds, inTrie, sizeof(UTrieHeader), outTrie, pErrorCode); 89f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 90f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* swap the index and the data */ 91f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(dataIs32) { 92f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ds->swapArray16(ds, inTrie+1, trie.indexLength*2, outTrie+1, pErrorCode); 93f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ds->swapArray32(ds, (const uint16_t *)(inTrie+1)+trie.indexLength, trie.dataLength*4, 94f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) (uint16_t *)(outTrie+1)+trie.indexLength, pErrorCode); 95f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else { 96f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ds->swapArray16(ds, inTrie+1, (trie.indexLength+trie.dataLength)*2, outTrie+1, pErrorCode); 97f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 98f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 99f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 100f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return size; 101f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 102f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 103f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#if !UCONFIG_NO_COLLATION 104f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 105f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* Modified copy of the beginning of ucol_swapBinary(). */ 106f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CAPI UBool U_EXPORT2 107f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ucol_looksLikeCollationBinary(const UDataSwapper *ds, 108f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const void *inData, int32_t length) { 109f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const uint8_t *inBytes; 110f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const UCATableHeader *inHeader; 111f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UCATableHeader header; 112f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 113f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(ds==NULL || inData==NULL || length<-1) { 114f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return FALSE; 115f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 116f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 117f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) inBytes=(const uint8_t *)inData; 118f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) inHeader=(const UCATableHeader *)inData; 119f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 120f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* 121f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * The collation binary must contain at least the UCATableHeader, 122f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * starting with its size field. 123f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * sizeof(UCATableHeader)==42*4 in ICU 2.8 124f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * check the length against the header size before reading the size field 125f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 126f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) uprv_memset(&header, 0, sizeof(header)); 127f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(length<0) { 128f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) header.size=udata_readInt32(ds, inHeader->size); 129f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else if((length<(42*4) || length<(header.size=udata_readInt32(ds, inHeader->size)))) { 130f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return FALSE; 131f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 132f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 133f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) header.magic=ds->readUInt32(inHeader->magic); 134f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(!( 135f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) header.magic==UCOL_HEADER_MAGIC && 136f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) inHeader->formatVersion[0]==3 /*&& 137f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) inHeader->formatVersion[1]>=0*/ 138f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) )) { 139f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return FALSE; 140f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 141f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 142f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(inHeader->isBigEndian!=ds->inIsBigEndian || inHeader->charSetFamily!=ds->inCharset) { 143f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return FALSE; 144f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 145f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 146f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return TRUE; 147f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 148f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 149f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* swap a header-less collation binary, inside a resource bundle or ucadata.icu */ 150f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CAPI int32_t U_EXPORT2 151f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ucol_swapBinary(const UDataSwapper *ds, 152f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const void *inData, int32_t length, void *outData, 153f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UErrorCode *pErrorCode) { 154f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const uint8_t *inBytes; 155f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) uint8_t *outBytes; 156f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 157f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const UCATableHeader *inHeader; 158f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UCATableHeader *outHeader; 159f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UCATableHeader header; 160f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 161f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) uint32_t count; 162f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 163f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* argument checking in case we were not called from ucol_swap() */ 164f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) { 165f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return 0; 166f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 167f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(ds==NULL || inData==NULL || length<-1 || (length>0 && outData==NULL)) { 168f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; 169f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return 0; 170f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 171f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 172f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) inBytes=(const uint8_t *)inData; 173f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) outBytes=(uint8_t *)outData; 174f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 175f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) inHeader=(const UCATableHeader *)inData; 176f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) outHeader=(UCATableHeader *)outData; 177f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 178f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* 179f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * The collation binary must contain at least the UCATableHeader, 180f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * starting with its size field. 181f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * sizeof(UCATableHeader)==42*4 in ICU 2.8 182f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * check the length against the header size before reading the size field 183f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 184f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) uprv_memset(&header, 0, sizeof(header)); 185f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(length<0) { 186f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) header.size=udata_readInt32(ds, inHeader->size); 187f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else if((length<(42*4) || length<(header.size=udata_readInt32(ds, inHeader->size)))) { 188f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) udata_printError(ds, "ucol_swapBinary(): too few bytes (%d after header) for collation data\n", 189f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) length); 190f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR; 191f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return 0; 192f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 193f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 194f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) header.magic=ds->readUInt32(inHeader->magic); 195f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(!( 196f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) header.magic==UCOL_HEADER_MAGIC && 197f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) inHeader->formatVersion[0]==3 /*&& 198f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) inHeader->formatVersion[1]>=0*/ 199f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) )) { 200f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) udata_printError(ds, "ucol_swapBinary(): magic 0x%08x or format version %02x.%02x is not a collation binary\n", 201f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) header.magic, 202f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) inHeader->formatVersion[0], inHeader->formatVersion[1]); 203f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *pErrorCode=U_UNSUPPORTED_ERROR; 204f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return 0; 205f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 206f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 207f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(inHeader->isBigEndian!=ds->inIsBigEndian || inHeader->charSetFamily!=ds->inCharset) { 208f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) udata_printError(ds, "ucol_swapBinary(): endianness %d or charset %d does not match the swapper\n", 209f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) inHeader->isBigEndian, inHeader->charSetFamily); 210f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *pErrorCode=U_INVALID_FORMAT_ERROR; 211f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return 0; 212f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 213f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 214f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(length>=0) { 215f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* copy everything, takes care of data that needs no swapping */ 216f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(inBytes!=outBytes) { 217f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) uprv_memcpy(outBytes, inBytes, header.size); 218f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 219f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 220f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* swap the necessary pieces in the order of their occurrence in the data */ 221f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 222f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* read more of the UCATableHeader (the size field was read above) */ 223f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) header.options= ds->readUInt32(inHeader->options); 224f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) header.UCAConsts= ds->readUInt32(inHeader->UCAConsts); 225f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) header.contractionUCACombos= ds->readUInt32(inHeader->contractionUCACombos); 226f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) header.mappingPosition= ds->readUInt32(inHeader->mappingPosition); 227f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) header.expansion= ds->readUInt32(inHeader->expansion); 228f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) header.contractionIndex= ds->readUInt32(inHeader->contractionIndex); 229f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) header.contractionCEs= ds->readUInt32(inHeader->contractionCEs); 230f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) header.contractionSize= ds->readUInt32(inHeader->contractionSize); 231f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) header.endExpansionCE= ds->readUInt32(inHeader->endExpansionCE); 232f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) header.expansionCESize= ds->readUInt32(inHeader->expansionCESize); 233f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) header.endExpansionCECount= udata_readInt32(ds, inHeader->endExpansionCECount); 234f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) header.contractionUCACombosSize=udata_readInt32(ds, inHeader->contractionUCACombosSize); 235f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) header.scriptToLeadByte= ds->readUInt32(inHeader->scriptToLeadByte); 236f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) header.leadByteToScript= ds->readUInt32(inHeader->leadByteToScript); 237f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 238f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* swap the 32-bit integers in the header */ 239f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ds->swapArray32(ds, inHeader, (int32_t)((const char *)&inHeader->jamoSpecial-(const char *)inHeader), 240f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) outHeader, pErrorCode); 241f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ds->swapArray32(ds, &(inHeader->scriptToLeadByte), sizeof(header.scriptToLeadByte) + sizeof(header.leadByteToScript), 242f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) &(outHeader->scriptToLeadByte), pErrorCode); 243f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* set the output platform properties */ 244f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) outHeader->isBigEndian=ds->outIsBigEndian; 245f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) outHeader->charSetFamily=ds->outCharset; 246f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 247f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* swap the options */ 248f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(header.options!=0) { 249f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ds->swapArray32(ds, inBytes+header.options, header.expansion-header.options, 250f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) outBytes+header.options, pErrorCode); 251f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 252f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 253f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* swap the expansions */ 254f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(header.mappingPosition!=0 && header.expansion!=0) { 255f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(header.contractionIndex!=0) { 256f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* expansions bounded by contractions */ 257f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) count=header.contractionIndex-header.expansion; 258f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else { 259f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* no contractions: expansions bounded by the main trie */ 260f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) count=header.mappingPosition-header.expansion; 261f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 262f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ds->swapArray32(ds, inBytes+header.expansion, (int32_t)count, 263f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) outBytes+header.expansion, pErrorCode); 264f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 265f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 266f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* swap the contractions */ 267f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(header.contractionSize!=0) { 268f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* contractionIndex: UChar[] */ 269f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ds->swapArray16(ds, inBytes+header.contractionIndex, header.contractionSize*2, 270f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) outBytes+header.contractionIndex, pErrorCode); 271f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 272f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* contractionCEs: CEs[] */ 273f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ds->swapArray32(ds, inBytes+header.contractionCEs, header.contractionSize*4, 274f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) outBytes+header.contractionCEs, pErrorCode); 275f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 276f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 277f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* swap the main trie */ 278f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(header.mappingPosition!=0) { 279f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) count=header.endExpansionCE-header.mappingPosition; 280f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) utrie_swap(ds, inBytes+header.mappingPosition, (int32_t)count, 281f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) outBytes+header.mappingPosition, pErrorCode); 282f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 283f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 284f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* swap the max expansion table */ 285f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(header.endExpansionCECount!=0) { 286f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ds->swapArray32(ds, inBytes+header.endExpansionCE, header.endExpansionCECount*4, 287f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) outBytes+header.endExpansionCE, pErrorCode); 288f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 289f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 290f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* expansionCESize, unsafeCP, contrEndCP: uint8_t[], no need to swap */ 291f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 292f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* swap UCA constants */ 293f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(header.UCAConsts!=0) { 294f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* 295f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * if UCAConsts!=0 then contractionUCACombos because we are swapping 296f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * the UCA data file, and we know that the UCA contains contractions 297f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 298f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) count=header.contractionUCACombos-header.UCAConsts; 299f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ds->swapArray32(ds, inBytes+header.UCAConsts, header.contractionUCACombos-header.UCAConsts, 300f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) outBytes+header.UCAConsts, pErrorCode); 301f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 302f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 303f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* swap UCA contractions */ 304f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(header.contractionUCACombosSize!=0) { 305f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) count=header.contractionUCACombosSize*inHeader->contractionUCACombosWidth*U_SIZEOF_UCHAR; 306f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ds->swapArray16(ds, inBytes+header.contractionUCACombos, (int32_t)count, 307f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) outBytes+header.contractionUCACombos, pErrorCode); 308f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 309f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 310f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* swap the script to lead bytes */ 311f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(header.scriptToLeadByte!=0) { 312f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int indexCount = ds->readUInt16(*((uint16_t*)(inBytes+header.scriptToLeadByte))); // each entry = 2 * uint16 313f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int dataCount = ds->readUInt16(*((uint16_t*)(inBytes+header.scriptToLeadByte + 2))); // each entry = uint16 314f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ds->swapArray16(ds, inBytes+header.scriptToLeadByte, 315f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 4 + (4 * indexCount) + (2 * dataCount), 316f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) outBytes+header.scriptToLeadByte, pErrorCode); 317f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 318f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 319f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* swap the lead byte to scripts */ 320f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(header.leadByteToScript!=0) { 321f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int indexCount = ds->readUInt16(*((uint16_t*)(inBytes+header.leadByteToScript))); // each entry = uint16 322f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int dataCount = ds->readUInt16(*((uint16_t*)(inBytes+header.leadByteToScript + 2))); // each entry = uint16 323f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ds->swapArray16(ds, inBytes+header.leadByteToScript, 324f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 4 + (2 * indexCount) + (2 * dataCount), 325f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) outBytes+header.leadByteToScript, pErrorCode); 326f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 327f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 328f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 329f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return header.size; 330f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 331f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 332f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* swap ICU collation data like ucadata.icu */ 333f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CAPI int32_t U_EXPORT2 334f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ucol_swap(const UDataSwapper *ds, 335f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const void *inData, int32_t length, void *outData, 336f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UErrorCode *pErrorCode) { 337f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 338f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const UDataInfo *pInfo; 339f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t headerSize, collationSize; 340f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 341f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* udata_swapDataHeader checks the arguments */ 342f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) headerSize=udata_swapDataHeader(ds, inData, length, outData, pErrorCode); 343f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) { 344f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return 0; 345f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 346f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 347f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* check data format and format version */ 348f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pInfo=(const UDataInfo *)((const char *)inData+4); 349f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(!( 350f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pInfo->dataFormat[0]==0x55 && /* dataFormat="UCol" */ 351f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pInfo->dataFormat[1]==0x43 && 352f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pInfo->dataFormat[2]==0x6f && 353f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pInfo->dataFormat[3]==0x6c && 354f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pInfo->formatVersion[0]==3 /*&& 355f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pInfo->formatVersion[1]>=0*/ 356f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) )) { 357f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) udata_printError(ds, "ucol_swap(): data format %02x.%02x.%02x.%02x (format version %02x.%02x) is not a collation file\n", 358f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pInfo->dataFormat[0], pInfo->dataFormat[1], 359f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pInfo->dataFormat[2], pInfo->dataFormat[3], 360f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pInfo->formatVersion[0], pInfo->formatVersion[1]); 361f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *pErrorCode=U_UNSUPPORTED_ERROR; 362f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return 0; 363f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 364f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 365f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) collationSize=ucol_swapBinary(ds, 366f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) (const char *)inData+headerSize, 367f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) length>=0 ? length-headerSize : -1, 368f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) (char *)outData+headerSize, 369f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pErrorCode); 370f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(U_SUCCESS(*pErrorCode)) { 371f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return headerSize+collationSize; 372f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else { 373f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return 0; 374f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 375f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 376f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 377f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* swap inverse UCA collation data (invuca.icu) */ 378f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CAPI int32_t U_EXPORT2 379f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ucol_swapInverseUCA(const UDataSwapper *ds, 380f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const void *inData, int32_t length, void *outData, 381f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UErrorCode *pErrorCode) { 382f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const UDataInfo *pInfo; 383f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t headerSize; 384f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 385f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const uint8_t *inBytes; 386f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) uint8_t *outBytes; 387f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 388f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const InverseUCATableHeader *inHeader; 389f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) InverseUCATableHeader *outHeader; 390f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) InverseUCATableHeader header={ 0,0,0,0,0,{0,0,0,0},{0,0,0,0,0,0,0,0} }; 391f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 392f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* udata_swapDataHeader checks the arguments */ 393f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) headerSize=udata_swapDataHeader(ds, inData, length, outData, pErrorCode); 394f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) { 395f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return 0; 396f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 397f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 398f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* check data format and format version */ 399f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pInfo=(const UDataInfo *)((const char *)inData+4); 400f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(!( 401f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pInfo->dataFormat[0]==0x49 && /* dataFormat="InvC" */ 402f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pInfo->dataFormat[1]==0x6e && 403f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pInfo->dataFormat[2]==0x76 && 404f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pInfo->dataFormat[3]==0x43 && 405f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pInfo->formatVersion[0]==2 && 406f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pInfo->formatVersion[1]>=1 407f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) )) { 408f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) udata_printError(ds, "ucol_swapInverseUCA(): data format %02x.%02x.%02x.%02x (format version %02x.%02x) is not an inverse UCA collation file\n", 409f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pInfo->dataFormat[0], pInfo->dataFormat[1], 410f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pInfo->dataFormat[2], pInfo->dataFormat[3], 411f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pInfo->formatVersion[0], pInfo->formatVersion[1]); 412f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *pErrorCode=U_UNSUPPORTED_ERROR; 413f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return 0; 414f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 415f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 416f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) inBytes=(const uint8_t *)inData+headerSize; 417f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) outBytes=(uint8_t *)outData+headerSize; 418f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 419f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) inHeader=(const InverseUCATableHeader *)inBytes; 420f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) outHeader=(InverseUCATableHeader *)outBytes; 421f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 422f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* 423f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * The inverse UCA collation binary must contain at least the InverseUCATableHeader, 424f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * starting with its size field. 425f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * sizeof(UCATableHeader)==8*4 in ICU 2.8 426f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * check the length against the header size before reading the size field 427f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 428f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(length<0) { 429f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) header.byteSize=udata_readInt32(ds, inHeader->byteSize); 430f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else if( 431f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ((length-headerSize)<(8*4) || 432f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) (uint32_t)(length-headerSize)<(header.byteSize=udata_readInt32(ds, inHeader->byteSize))) 433f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ) { 434f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) udata_printError(ds, "ucol_swapInverseUCA(): too few bytes (%d after header) for inverse UCA collation data\n", 435f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) length); 436f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR; 437f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return 0; 438f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 439f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 440f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(length>=0) { 441f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* copy everything, takes care of data that needs no swapping */ 442f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(inBytes!=outBytes) { 443f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) uprv_memcpy(outBytes, inBytes, header.byteSize); 444f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 445f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 446f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* swap the necessary pieces in the order of their occurrence in the data */ 447f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 448f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* read more of the InverseUCATableHeader (the byteSize field was read above) */ 449f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) header.tableSize= ds->readUInt32(inHeader->tableSize); 450f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) header.contsSize= ds->readUInt32(inHeader->contsSize); 451f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) header.table= ds->readUInt32(inHeader->table); 452f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) header.conts= ds->readUInt32(inHeader->conts); 453f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 454f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* swap the 32-bit integers in the header */ 455f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ds->swapArray32(ds, inHeader, 5*4, outHeader, pErrorCode); 456f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 457f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* swap the inverse table; tableSize counts uint32_t[3] rows */ 458f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ds->swapArray32(ds, inBytes+header.table, header.tableSize*3*4, 459f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) outBytes+header.table, pErrorCode); 460f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 461f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* swap the continuation table; contsSize counts UChars */ 462f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ds->swapArray16(ds, inBytes+header.conts, header.contsSize*U_SIZEOF_UCHAR, 463f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) outBytes+header.conts, pErrorCode); 464f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 465f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 466f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return headerSize+header.byteSize; 467f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 468f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 469f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#endif /* #if !UCONFIG_NO_COLLATION */ 470