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