1b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru/* 2b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru********************************************************************** 327f654740f2a26ad62a5c155af9199af9e69b889claireho* Copyright (C) 2008-2010, International Business Machines 4b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru* Corporation and others. All Rights Reserved. 5b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru********************************************************************** 6b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru*/ 7b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 8b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include "unicode/utypes.h" 9b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include "unicode/uspoof.h" 10b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include "unicode/unorm.h" 11b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include "unicode/uchar.h" 12b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include "unicode/uniset.h" 13b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include "utrie2.h" 14b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include "cmemory.h" 15b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include "cstring.h" 16b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include "udatamem.h" 17b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include "umutex.h" 18b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include "udataswp.h" 19b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include "uassert.h" 20b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include "uspoof_impl.h" 21b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 22b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#if !UCONFIG_NO_NORMALIZATION 23b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 24b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 25b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruU_NAMESPACE_BEGIN 26b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 27b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruUOBJECT_DEFINE_RTTI_IMPLEMENTATION(SpoofImpl) 28b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 29b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruSpoofImpl::SpoofImpl(SpoofData *data, UErrorCode &status) : 306d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru fMagic(0), fSpoofData(NULL), fAllowedCharsSet(NULL) , fAllowedLocales(NULL) { 31b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(status)) { 32b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return; 33b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 34b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fMagic = USPOOF_MAGIC; 35b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fSpoofData = data; 36b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fChecks = USPOOF_ALL_CHECKS; 37b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UnicodeSet *allowedCharsSet = new UnicodeSet(0, 0x10ffff); 38b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (allowedCharsSet == NULL) { 39b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru status = U_MEMORY_ALLOCATION_ERROR; 40b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 41b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru allowedCharsSet->freeze(); 42b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fAllowedCharsSet = allowedCharsSet; 43b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fAllowedLocales = uprv_strdup(""); 44b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 45b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 46b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 47b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruSpoofImpl::SpoofImpl() { 48b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fMagic = USPOOF_MAGIC; 49b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fSpoofData = NULL; 50b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fChecks = USPOOF_ALL_CHECKS; 51b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UnicodeSet *allowedCharsSet = new UnicodeSet(0, 0x10ffff); 52b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru allowedCharsSet->freeze(); 53b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fAllowedCharsSet = allowedCharsSet; 54b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fAllowedLocales = uprv_strdup(""); 55b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 56b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 57b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 58b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// Copy Constructor, used by the user level clone() function. 59b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruSpoofImpl::SpoofImpl(const SpoofImpl &src, UErrorCode &status) : 60b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fMagic(0), fSpoofData(NULL), fAllowedCharsSet(NULL) { 61b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(status)) { 62b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return; 63b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 64b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fMagic = src.fMagic; 65b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fChecks = src.fChecks; 66b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (src.fSpoofData != NULL) { 67b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fSpoofData = src.fSpoofData->addReference(); 68b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 69b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fCheckMask = src.fCheckMask; 70b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fAllowedCharsSet = static_cast<const UnicodeSet *>(src.fAllowedCharsSet->clone()); 71b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (fAllowedCharsSet == NULL) { 72b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru status = U_MEMORY_ALLOCATION_ERROR; 73b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 74b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fAllowedLocales = uprv_strdup(src.fAllowedLocales); 75b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 76b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 77b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruSpoofImpl::~SpoofImpl() { 78b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fMagic = 0; // head off application errors by preventing use of 79b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // of deleted objects. 80b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (fSpoofData != NULL) { 81b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fSpoofData->removeReference(); // Will delete if refCount goes to zero. 82b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 83b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru delete fAllowedCharsSet; 84b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_free((void *)fAllowedLocales); 85b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 86b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 87b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// 88b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// Incoming parameter check on Status and the SpoofChecker object 89b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// received from the C API. 90b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// 91b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruconst SpoofImpl *SpoofImpl::validateThis(const USpoofChecker *sc, UErrorCode &status) { 92b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(status)) { 93b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return NULL; 94b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 95b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (sc == NULL) { 96b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru status = U_ILLEGAL_ARGUMENT_ERROR; 97b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return NULL; 98b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru }; 99b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru SpoofImpl *This = (SpoofImpl *)sc; 100b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (This->fMagic != USPOOF_MAGIC || 101b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru This->fSpoofData == NULL) { 102b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru status = U_INVALID_FORMAT_ERROR; 103b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return NULL; 104b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 105b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (!SpoofData::validateDataVersion(This->fSpoofData->fRawData, status)) { 106b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return NULL; 107b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 108b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return This; 109b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 110b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 111b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruSpoofImpl *SpoofImpl::validateThis(USpoofChecker *sc, UErrorCode &status) { 112b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return const_cast<SpoofImpl *> 113b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru (SpoofImpl::validateThis(const_cast<const USpoofChecker *>(sc), status)); 114b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 115b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 116b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 117b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 118b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru//-------------------------------------------------------------------------------------- 119b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// 120b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// confusableLookup() This is the heart of the confusable skeleton generation 121b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// implementation. 122b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// 123b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// Given a source character, produce the corresponding 124b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// replacement character(s) 125b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// 126b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru//--------------------------------------------------------------------------------------- 127b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruint32_t SpoofImpl::confusableLookup(UChar32 inChar, int32_t tableMask, UChar *destBuf) const { 128b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 129b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // Binary search the spoof data key table for the inChar 130b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t *low = fSpoofData->fCFUKeys; 131b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t *mid = NULL; 132b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t *limit = low + fSpoofData->fRawData->fCFUKeysSize; 13350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UChar32 midc; 134b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru do { 13550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t delta = ((int32_t)(limit-low))/2; 136b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru mid = low + delta; 137b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru midc = *mid & 0x1fffff; 138b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (inChar == midc) { 139b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru goto foundChar; 140b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else if (inChar < midc) { 141b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru limit = mid; 142b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 143b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru low = mid; 144b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 145b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } while (low < limit-1); 146b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru mid = low; 147b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru midc = *mid & 0x1fffff; 148b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (inChar != midc) { 149b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // Char not found. It maps to itself. 150b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int i = 0; 151b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru U16_APPEND_UNSAFE(destBuf, i, inChar) 152b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return i; 153b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 154b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru foundChar: 155b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t keyFlags = *mid & 0xff000000; 156b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if ((keyFlags & tableMask) == 0) { 157b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // We found the right key char, but the entry doesn't pertain to the 158b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // table we need. See if there is an adjacent key that does 159b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (keyFlags & USPOOF_KEY_MULTIPLE_VALUES) { 160b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t *altMid; 161b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for (altMid = mid-1; (*altMid&0x00ffffff) == inChar; altMid--) { 162b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru keyFlags = *altMid & 0xff000000; 163b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (keyFlags & tableMask) { 164b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru mid = altMid; 165b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru goto foundKey; 166b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 167b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 168b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for (altMid = mid+1; (*altMid&0x00ffffff) == inChar; altMid++) { 169b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru keyFlags = *altMid & 0xff000000; 170b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (keyFlags & tableMask) { 171b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru mid = altMid; 172b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru goto foundKey; 173b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 174b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 175b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 176b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // No key entry for this char & table. 177b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // The input char maps to itself. 178b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int i = 0; 179b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru U16_APPEND_UNSAFE(destBuf, i, inChar) 180b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return i; 181b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 182b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 183b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru foundKey: 184b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t stringLen = USPOOF_KEY_LENGTH_FIELD(keyFlags) + 1; 18550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t keyTableIndex = (int32_t)(mid - fSpoofData->fCFUKeys); 186b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 187b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // Value is either a UChar (for strings of length 1) or 188b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // an index into the string table (for longer strings) 189b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uint16_t value = fSpoofData->fCFUValues[keyTableIndex]; 190b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (stringLen == 1) { 191b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru destBuf[0] = value; 192b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 1; 193b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 194b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 195b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // String length of 4 from the above lookup is used for all strings of length >= 4. 196b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // For these, get the real length from the string lengths table, 197b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // which maps string table indexes to lengths. 198b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // All strings of the same length are stored contiguously in the string table. 199b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // 'value' from the lookup above is the starting index for the desired string. 200b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 201b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t ix; 202b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (stringLen == 4) { 203b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t stringLengthsLimit = fSpoofData->fRawData->fCFUStringLengthsSize; 204b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for (ix = 0; ix < stringLengthsLimit; ix++) { 205b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (fSpoofData->fCFUStringLengths[ix].fLastString >= value) { 206b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru stringLen = fSpoofData->fCFUStringLengths[ix].fStrLength; 207b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 208b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 209b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 210b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru U_ASSERT(ix < stringLengthsLimit); 211b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 212b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 213b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru U_ASSERT(value + stringLen < fSpoofData->fRawData->fCFUStringTableLen); 214b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UChar *src = &fSpoofData->fCFUStrings[value]; 215b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for (ix=0; ix<stringLen; ix++) { 216b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru destBuf[ix] = src[ix]; 217b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 218b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return stringLen; 219b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 220b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 221b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 222b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru//--------------------------------------------------------------------------------------- 223b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// 224b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// wholeScriptCheck() 225b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// 226b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// Input text is already normalized to NFKD 227b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// Return the set of scripts, each of which can represent something that is 228b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// confusable with the input text. The script of the input text 229b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// is included; input consisting of characters from a single script will 230b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// always produce a result consisting of a set containing that script. 231b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// 232b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru//--------------------------------------------------------------------------------------- 233b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruvoid SpoofImpl::wholeScriptCheck( 234b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const UChar *text, int32_t length, ScriptSet *result, UErrorCode &status) const { 235b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 236b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t inputIdx = 0; 237b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UChar32 c; 238b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 239b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UTrie2 *table = 240b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru (fChecks & USPOOF_ANY_CASE) ? fSpoofData->fAnyCaseTrie : fSpoofData->fLowerCaseTrie; 241b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru result->setAll(); 242b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (inputIdx < length) { 243b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru U16_NEXT(text, inputIdx, length, c); 244b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uint32_t index = utrie2_get32(table, c); 245b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (index == 0) { 246b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // No confusables in another script for this char. 247b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // TODO: we should change the data to have sets with just the single script 248b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // bit for the script of this char. Gets rid of this special case. 249b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // Until then, grab the script from the char and intersect it with the set. 250b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UScriptCode cpScript = uscript_getScript(c, &status); 251b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru U_ASSERT(cpScript > USCRIPT_INHERITED); 252b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru result->intersect(cpScript); 253b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else if (index == 1) { 254b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // Script == Common or Inherited. Nothing to do. 255b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 256b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru result->intersect(fSpoofData->fScriptSets[index]); 257b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 258b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 259b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 260b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 261b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 262b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruvoid SpoofImpl::setAllowedLocales(const char *localesList, UErrorCode &status) { 263b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UnicodeSet allowedChars; 264b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UnicodeSet *tmpSet = NULL; 265b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *locStart = localesList; 266b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *locEnd = NULL; 267b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *localesListEnd = localesList + uprv_strlen(localesList); 268b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t localeListCount = 0; // Number of locales provided by caller. 269b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 270b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // Loop runs once per locale from the localesList, a comma separated list of locales. 271b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru do { 272b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru locEnd = uprv_strchr(locStart, ','); 273b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (locEnd == NULL) { 274b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru locEnd = localesListEnd; 275b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 276b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (*locStart == ' ') { 277b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru locStart++; 278b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 279b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *trimmedEnd = locEnd-1; 280b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (trimmedEnd > locStart && *trimmedEnd == ' ') { 281b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru trimmedEnd--; 282b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 283b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (trimmedEnd <= locStart) { 284b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 285b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 28650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const char *locale = uprv_strndup(locStart, (int32_t)(trimmedEnd + 1 - locStart)); 287b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru localeListCount++; 288b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 289b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // We have one locale from the locales list. 290b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // Add the script chars for this locale to the accumulating set of allowed chars. 291b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // If the locale is no good, we will be notified back via status. 292b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru addScriptChars(locale, &allowedChars, status); 293b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_free((void *)locale); 294b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(status)) { 295b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 296b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 297b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru locStart = locEnd + 1; 298b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } while (locStart < localesListEnd); 299b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 300b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // If our caller provided an empty list of locales, we disable the allowed characters checking 301b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (localeListCount == 0) { 302b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_free((void *)fAllowedLocales); 303b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fAllowedLocales = uprv_strdup(""); 304b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru tmpSet = new UnicodeSet(0, 0x10ffff); 305b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (fAllowedLocales == NULL || tmpSet == NULL) { 306b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru status = U_MEMORY_ALLOCATION_ERROR; 307b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return; 308b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 309b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru tmpSet->freeze(); 310b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru delete fAllowedCharsSet; 311b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fAllowedCharsSet = tmpSet; 312b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fCheckMask &= ~USPOOF_CHAR_LIMIT; 313b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return; 314b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 315b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 316b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 317b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // Add all common and inherited characters to the set of allowed chars. 318b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UnicodeSet tempSet; 319b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru tempSet.applyIntPropertyValue(UCHAR_SCRIPT, USCRIPT_COMMON, status); 320b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru allowedChars.addAll(tempSet); 321b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru tempSet.applyIntPropertyValue(UCHAR_SCRIPT, USCRIPT_INHERITED, status); 322b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru allowedChars.addAll(tempSet); 323b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 324b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // If anything went wrong, we bail out without changing 325b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // the state of the spoof checker. 326b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(status)) { 327b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return; 328b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 329b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 330b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // Store the updated spoof checker state. 331b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru tmpSet = static_cast<UnicodeSet *>(allowedChars.clone()); 332b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *tmpLocalesList = uprv_strdup(localesList); 333b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (tmpSet == NULL || tmpLocalesList == NULL) { 334b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru status = U_MEMORY_ALLOCATION_ERROR; 335b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return; 336b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 337b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_free((void *)fAllowedLocales); 338b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fAllowedLocales = tmpLocalesList; 339b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru tmpSet->freeze(); 340b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru delete fAllowedCharsSet; 341b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fAllowedCharsSet = tmpSet; 342b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fCheckMask |= USPOOF_CHAR_LIMIT; 343b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 344b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 345b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 346b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruconst char * SpoofImpl::getAllowedLocales(UErrorCode &/*status*/) { 347b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return fAllowedLocales; 348b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 349b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 350b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 351b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// Given a locale (a language), add all the characters from all of the scripts used with that language 352b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// to the allowedChars UnicodeSet 353b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 354b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruvoid SpoofImpl::addScriptChars(const char *locale, UnicodeSet *allowedChars, UErrorCode &status) { 355b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UScriptCode scripts[30]; 356b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 357b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t numScripts = uscript_getCode(locale, scripts, sizeof(scripts)/sizeof(UScriptCode), &status); 358b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(status)) { 359b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return; 360b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 361b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (status == U_USING_DEFAULT_WARNING) { 362b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru status = U_ILLEGAL_ARGUMENT_ERROR; 363b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return; 364b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 365b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UnicodeSet tmpSet; 366b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t i; 367b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for (i=0; i<numScripts; i++) { 368b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru tmpSet.applyIntPropertyValue(UCHAR_SCRIPT, scripts[i], status); 369b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru allowedChars->addAll(tmpSet); 370b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 371b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 372b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 373b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 374b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruint32_t SpoofImpl::scriptScan 375b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru (const UChar *text, int32_t length, int32_t &pos, UErrorCode &status) const { 376b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(status)) { 377b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 378b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 379b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t inputIdx = 0; 380b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UChar32 c; 381b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t scriptCount = 0; 382b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UScriptCode lastScript = USCRIPT_INVALID_CODE; 383b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UScriptCode sc = USCRIPT_INVALID_CODE; 384b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while ((inputIdx < length || length == -1) && scriptCount < 2) { 385b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru U16_NEXT(text, inputIdx, length, c); 386b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (c == 0 && length == -1) { 387b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 388b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 389b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru sc = uscript_getScript(c, &status); 390b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (sc == USCRIPT_COMMON || sc == USCRIPT_INHERITED || sc == USCRIPT_UNKNOWN) { 391b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru continue; 392b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 393b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (sc != lastScript) { 394b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru scriptCount++; 395b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru lastScript = sc; 396b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 397b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 398b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (scriptCount == 2) { 399b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pos = inputIdx; 400b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 401b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return scriptCount; 402b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 403b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 404b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 405b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// Convert a text format hex number. Utility function used by builder code. Static. 406b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// Input: UChar *string text. Output: a UChar32 407b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// Input has been pre-checked, and will have no non-hex chars. 408b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// The number must fall in the code point range of 0..0x10ffff 409b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// Static Function. 410b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruUChar32 SpoofImpl::ScanHex(const UChar *s, int32_t start, int32_t limit, UErrorCode &status) { 411b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(status)) { 412b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 413b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 414b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru U_ASSERT(limit-start > 0); 415b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uint32_t val = 0; 416b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int i; 417b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for (i=start; i<limit; i++) { 418b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int digitVal = s[i] - 0x30; 419b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (digitVal>9) { 420b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru digitVal = 0xa + (s[i] - 0x41); // Upper Case 'A' 421b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 422b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (digitVal>15) { 423b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru digitVal = 0xa + (s[i] - 0x61); // Lower Case 'a' 424b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 425b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru U_ASSERT(digitVal <= 0xf); 426b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru val <<= 4; 427b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru val += digitVal; 428b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 429b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (val > 0x10ffff) { 430b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru status = U_PARSE_ERROR; 431b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru val = 0; 432b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 433b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return (UChar32)val; 434b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 435b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 436b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 437b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 438b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru//---------------------------------------------------------------------------------------------- 439b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// 440b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// class SpoofData Implementation 441b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// 442b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru//---------------------------------------------------------------------------------------------- 443b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 444b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 445b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruUBool SpoofData::validateDataVersion(const SpoofDataHeader *rawData, UErrorCode &status) { 446b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(status) || 447b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru rawData == NULL || 448b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru rawData->fMagic != USPOOF_MAGIC || 449b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru rawData->fFormatVersion[0] > 1 || 450b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru rawData->fFormatVersion[1] > 0) { 451b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru status = U_INVALID_FORMAT_ERROR; 452b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return FALSE; 453b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 454b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return TRUE; 455b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 456b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 457b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// 458b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// SpoofData::getDefault() - return a wrapper around the spoof data that is 459b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// baked into the default ICU data. 460b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// 461b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruSpoofData *SpoofData::getDefault(UErrorCode &status) { 462b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // TODO: Cache it. Lazy create, keep until cleanup. 463b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 464b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UDataMemory *udm = udata_open(NULL, "cfu", "confusables", &status); 465b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(status)) { 466b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return NULL; 467b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 468b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru SpoofData *This = new SpoofData(udm, status); 469b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(status)) { 470b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru delete This; 471b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return NULL; 472b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 473b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (This == NULL) { 474b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru status = U_MEMORY_ALLOCATION_ERROR; 475b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 476b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return This; 477b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 478b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 479b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 480b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruSpoofData::SpoofData(UDataMemory *udm, UErrorCode &status) 481b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru{ 482b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reset(); 483b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(status)) { 484b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return; 485b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 486b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fRawData = reinterpret_cast<SpoofDataHeader *> 487b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ((char *)(udm->pHeader) + udm->pHeader->dataHeader.headerSize); 488b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fUDM = udm; 489b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru validateDataVersion(fRawData, status); 490b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru initPtrs(status); 491b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 492b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 493b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 494b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruSpoofData::SpoofData(const void *data, int32_t length, UErrorCode &status) 495b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru{ 496b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reset(); 497b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(status)) { 498b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return; 499b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 500b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if ((size_t)length < sizeof(SpoofDataHeader)) { 501b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru status = U_INVALID_FORMAT_ERROR; 502b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return; 503b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 504b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru void *ncData = const_cast<void *>(data); 505b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fRawData = static_cast<SpoofDataHeader *>(ncData); 506b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (length < fRawData->fLength) { 507b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru status = U_INVALID_FORMAT_ERROR; 508b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return; 509b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 510b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru validateDataVersion(fRawData, status); 511b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru initPtrs(status); 512b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 513b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 514b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 515b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// Spoof Data constructor for use from data builder. 516b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// Initializes a new, empty data area that will be populated later. 517b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruSpoofData::SpoofData(UErrorCode &status) { 518b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru reset(); 519b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(status)) { 520b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return; 521b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 522b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fDataOwned = true; 523b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fRefCount = 1; 524b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 525b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // The spoof header should already be sized to be a multiple of 16 bytes. 526b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // Just in case it's not, round it up. 527b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uint32_t initialSize = (sizeof(SpoofDataHeader) + 15) & ~15; 528b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru U_ASSERT(initialSize == sizeof(SpoofDataHeader)); 529b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 530b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fRawData = static_cast<SpoofDataHeader *>(uprv_malloc(initialSize)); 531b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fMemLimit = initialSize; 532b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (fRawData == NULL) { 533b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru status = U_MEMORY_ALLOCATION_ERROR; 534b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return; 535b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 536b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_memset(fRawData, 0, initialSize); 537b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 538b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fRawData->fMagic = USPOOF_MAGIC; 539b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fRawData->fFormatVersion[0] = 1; 540b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fRawData->fFormatVersion[1] = 0; 541b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fRawData->fFormatVersion[2] = 0; 542b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fRawData->fFormatVersion[3] = 0; 543b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru initPtrs(status); 544b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 545b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 546b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// reset() - initialize all fields. 547b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// Should be updated if any new fields are added. 548b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// Called by constructors to put things in a known initial state. 549b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruvoid SpoofData::reset() { 550b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fRawData = NULL; 551b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fDataOwned = FALSE; 552b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fUDM = NULL; 553b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fMemLimit = 0; 554b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fRefCount = 1; 555b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fCFUKeys = NULL; 556b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fCFUValues = NULL; 557b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fCFUStringLengths = NULL; 558b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fCFUStrings = NULL; 559b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fAnyCaseTrie = NULL; 560b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fLowerCaseTrie = NULL; 561b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fScriptSets = NULL; 562b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 563b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 564b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 565b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// SpoofData::initPtrs() 566b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// Initialize the pointers to the various sections of the raw data. 567b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// 568b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// This function is used both during the Trie building process (multiple 569b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// times, as the individual data sections are added), and 570b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// during the opening of a Spoof Checker from prebuilt data. 571b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// 572b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// The pointers for non-existent data sections (identified by an offset of 0) 573b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// are set to NULL. 574b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// 575b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// Note: During building the data, adding each new data section 576b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// reallocs the raw data area, which likely relocates it, which 577b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// in turn requires reinitializing all of the pointers into it, hence 578b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// multiple calls to this function during building. 579b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// 580b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruvoid SpoofData::initPtrs(UErrorCode &status) { 581b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fCFUKeys = NULL; 582b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fCFUValues = NULL; 583b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fCFUStringLengths = NULL; 584b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fCFUStrings = NULL; 585b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(status)) { 586b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return; 587b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 588b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (fRawData->fCFUKeys != 0) { 589b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fCFUKeys = (int32_t *)((char *)fRawData + fRawData->fCFUKeys); 590b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 591b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (fRawData->fCFUStringIndex != 0) { 592b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fCFUValues = (uint16_t *)((char *)fRawData + fRawData->fCFUStringIndex); 593b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 594b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (fRawData->fCFUStringLengths != 0) { 595b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fCFUStringLengths = (SpoofStringLengthsElement *)((char *)fRawData + fRawData->fCFUStringLengths); 596b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 597b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (fRawData->fCFUStringTable != 0) { 598b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fCFUStrings = (UChar *)((char *)fRawData + fRawData->fCFUStringTable); 599b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 600b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 601b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (fAnyCaseTrie == NULL && fRawData->fAnyCaseTrie != 0) { 602b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fAnyCaseTrie = utrie2_openFromSerialized(UTRIE2_16_VALUE_BITS, 603b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru (char *)fRawData + fRawData->fAnyCaseTrie, fRawData->fAnyCaseTrieLength, NULL, &status); 604b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 605b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (fLowerCaseTrie == NULL && fRawData->fLowerCaseTrie != 0) { 606b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fLowerCaseTrie = utrie2_openFromSerialized(UTRIE2_16_VALUE_BITS, 607b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru (char *)fRawData + fRawData->fLowerCaseTrie, fRawData->fLowerCaseTrieLength, NULL, &status); 608b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 609b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 610b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (fRawData->fScriptSets != 0) { 611b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fScriptSets = (ScriptSet *)((char *)fRawData + fRawData->fScriptSets); 612b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 613b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 614b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 615b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 616b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruSpoofData::~SpoofData() { 617b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru utrie2_close(fAnyCaseTrie); 618b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fAnyCaseTrie = NULL; 619b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru utrie2_close(fLowerCaseTrie); 620b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fLowerCaseTrie = NULL; 621b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (fDataOwned) { 622b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_free(fRawData); 623b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 624b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fRawData = NULL; 625b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (fUDM != NULL) { 626b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru udata_close(fUDM); 627b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 628b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fUDM = NULL; 629b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 630b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 631b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 632b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruvoid SpoofData::removeReference() { 633b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (umtx_atomic_dec(&fRefCount) == 0) { 634b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru delete this; 635b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 636b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 637b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 638b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 639b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruSpoofData *SpoofData::addReference() { 640b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru umtx_atomic_inc(&fRefCount); 641b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return this; 642b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 643b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 644b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 645b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruvoid *SpoofData::reserveSpace(int32_t numBytes, UErrorCode &status) { 646b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(status)) { 647b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return NULL; 648b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 649b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (!fDataOwned) { 650b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru U_ASSERT(FALSE); 651b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru status = U_INTERNAL_PROGRAM_ERROR; 652b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return NULL; 653b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 654b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 655b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru numBytes = (numBytes + 15) & ~15; // Round up to a multiple of 16 656b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uint32_t returnOffset = fMemLimit; 657b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fMemLimit += numBytes; 658b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fRawData = static_cast<SpoofDataHeader *>(uprv_realloc(fRawData, fMemLimit)); 659b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fRawData->fLength = fMemLimit; 660b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_memset((char *)fRawData + returnOffset, 0, numBytes); 661b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru initPtrs(status); 662b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return (char *)fRawData + returnOffset; 663b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 664b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 665b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 666b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru//---------------------------------------------------------------------------- 667b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// 668b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// ScriptSet implementation 669b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// 670b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru//---------------------------------------------------------------------------- 671b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruScriptSet::ScriptSet() { 672b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for (uint32_t i=0; i<sizeof(bits)/sizeof(uint32_t); i++) { 673b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru bits[i] = 0; 674b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 675b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 676b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 677b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruScriptSet::~ScriptSet() { 678b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 679b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 680b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruUBool ScriptSet::operator == (const ScriptSet &other) { 681b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for (uint32_t i=0; i<sizeof(bits)/sizeof(uint32_t); i++) { 682b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (bits[i] != other.bits[i]) { 683b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return FALSE; 684b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 685b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 686b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return TRUE; 687b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 688b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 689b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruvoid ScriptSet::Union(UScriptCode script) { 690b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uint32_t index = script / 32; 691b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uint32_t bit = 1 << (script & 31); 692b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru U_ASSERT(index < sizeof(bits)*4); 693b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru bits[index] |= bit; 694b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 695b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 696b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 697b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruvoid ScriptSet::Union(const ScriptSet &other) { 698b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for (uint32_t i=0; i<sizeof(bits)/sizeof(uint32_t); i++) { 699b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru bits[i] |= other.bits[i]; 700b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 701b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 702b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 703b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruvoid ScriptSet::intersect(const ScriptSet &other) { 704b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for (uint32_t i=0; i<sizeof(bits)/sizeof(uint32_t); i++) { 705b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru bits[i] &= other.bits[i]; 706b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 707b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 708b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 709b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruvoid ScriptSet::intersect(UScriptCode script) { 710b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uint32_t index = script / 32; 711b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uint32_t bit = 1 << (script & 31); 712b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru U_ASSERT(index < sizeof(bits)*4); 713b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uint32_t i; 714b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for (i=0; i<index; i++) { 715b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru bits[i] = 0; 716b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 717b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru bits[index] &= bit; 718b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for (i=index+1; i<sizeof(bits)/sizeof(uint32_t); i++) { 719b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru bits[i] = 0; 720b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 721b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 722b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 723b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 724b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruScriptSet & ScriptSet::operator =(const ScriptSet &other) { 725b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for (uint32_t i=0; i<sizeof(bits)/sizeof(uint32_t); i++) { 726b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru bits[i] = other.bits[i]; 727b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 728b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return *this; 729b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 730b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 731b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 732b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruvoid ScriptSet::setAll() { 733b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for (uint32_t i=0; i<sizeof(bits)/sizeof(uint32_t); i++) { 734b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru bits[i] = 0xffffffffu; 735b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 736b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 737b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 738b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 739b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruvoid ScriptSet::resetAll() { 740b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for (uint32_t i=0; i<sizeof(bits)/sizeof(uint32_t); i++) { 741b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru bits[i] = 0; 742b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 743b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 744b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 745b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruint32_t ScriptSet::countMembers() { 746b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // This bit counter is good for sparse numbers of '1's, which is 747b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // very much the case that we will usually have. 748b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t count = 0; 749b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for (uint32_t i=0; i<sizeof(bits)/sizeof(uint32_t); i++) { 750b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uint32_t x = bits[i]; 751b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (x > 0) { 752b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru count++; 753b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru x &= (x - 1); // and off the least significant one bit. 754b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 755b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 756b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return count; 757b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 758b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 759b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 760b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 761b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru//----------------------------------------------------------------------------- 762b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// 763b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// NFKDBuffer Implementation. 764b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// 765b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru//----------------------------------------------------------------------------- 766b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 767b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruNFKDBuffer::NFKDBuffer(const UChar *text, int32_t length, UErrorCode &status) { 768b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fNormalizedText = NULL; 769b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fNormalizedTextLength = 0; 770b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fOriginalText = text; 771b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(status)) { 772b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return; 773b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 774b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fNormalizedText = fSmallBuf; 775b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fNormalizedTextLength = unorm_normalize( 776b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru text, length, UNORM_NFKD, 0, fNormalizedText, USPOOF_STACK_BUFFER_SIZE, &status); 777b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (status == U_BUFFER_OVERFLOW_ERROR) { 778b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru status = U_ZERO_ERROR; 779b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fNormalizedText = (UChar *)uprv_malloc((fNormalizedTextLength+1)*sizeof(UChar)); 780b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (fNormalizedText == NULL) { 781b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru status = U_MEMORY_ALLOCATION_ERROR; 782b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 783b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fNormalizedTextLength = unorm_normalize(text, length, UNORM_NFKD, 0, 784b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fNormalizedText, fNormalizedTextLength+1, &status); 785b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 786b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 787b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 788b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 789b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 790b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruNFKDBuffer::~NFKDBuffer() { 791b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (fNormalizedText != fSmallBuf) { 792b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_free(fNormalizedText); 793b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 794b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fNormalizedText = 0; 795b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 796b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 797b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruconst UChar *NFKDBuffer::getBuffer() { 798b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return fNormalizedText; 799b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 800b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 801b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruint32_t NFKDBuffer::getLength() { 802b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return fNormalizedTextLength; 803b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 804b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 805b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 806b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 807b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 808b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 809b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruU_NAMESPACE_END 810b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 811b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruU_NAMESPACE_USE 812b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 813b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru//----------------------------------------------------------------------------- 814b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// 815b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// uspoof_swap - byte swap and char encoding swap of spoof data 816b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// 817b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru//----------------------------------------------------------------------------- 818b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruU_CAPI int32_t U_EXPORT2 819b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruuspoof_swap(const UDataSwapper *ds, const void *inData, int32_t length, void *outData, 820b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UErrorCode *status) { 821b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 822b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (status == NULL || U_FAILURE(*status)) { 823b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 824b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 825b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if(ds==NULL || inData==NULL || length<-1 || (length>0 && outData==NULL)) { 826b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status=U_ILLEGAL_ARGUMENT_ERROR; 827b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 828b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 829b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 830b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // 831b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // Check that the data header is for spoof data. 832b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // (Header contents are defined in gencfu.cpp) 833b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // 834b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const UDataInfo *pInfo = (const UDataInfo *)((const char *)inData+4); 835b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if(!( pInfo->dataFormat[0]==0x43 && /* dataFormat="Cfu " */ 836b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pInfo->dataFormat[1]==0x66 && 837b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pInfo->dataFormat[2]==0x75 && 838b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pInfo->dataFormat[3]==0x20 && 839b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pInfo->formatVersion[0]==1 )) { 840b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru udata_printError(ds, "uspoof_swap(): data format %02x.%02x.%02x.%02x " 841b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "(format version %02x %02x %02x %02x) is not recognized\n", 842b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pInfo->dataFormat[0], pInfo->dataFormat[1], 843b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pInfo->dataFormat[2], pInfo->dataFormat[3], 844b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pInfo->formatVersion[0], pInfo->formatVersion[1], 845b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pInfo->formatVersion[2], pInfo->formatVersion[3]); 846b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status=U_UNSUPPORTED_ERROR; 847b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 848b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 849b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 850b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // 851b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // Swap the data header. (This is the generic ICU Data Header, not the uspoof Specific 852b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // header). This swap also conveniently gets us 853b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // the size of the ICU d.h., which lets us locate the start 854b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // of the uspoof specific data. 855b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // 856b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t headerSize=udata_swapDataHeader(ds, inData, length, outData, status); 857b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 858b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 859b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // 860b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // Get the Spoof Data Header, and check that it appears to be OK. 861b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // 862b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // 863b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const uint8_t *inBytes =(const uint8_t *)inData+headerSize; 864b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru SpoofDataHeader *spoofDH = (SpoofDataHeader *)inBytes; 865b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (ds->readUInt32(spoofDH->fMagic) != USPOOF_MAGIC || 866b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ds->readUInt32(spoofDH->fLength) < sizeof(SpoofDataHeader)) 867b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru { 868b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru udata_printError(ds, "uspoof_swap(): Spoof Data header is invalid.\n"); 869b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status=U_UNSUPPORTED_ERROR; 870b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 871b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 872b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 873b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // 874b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // Prefight operation? Just return the size 875b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // 876b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t spoofDataLength = ds->readUInt32(spoofDH->fLength); 877b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t totalSize = headerSize + spoofDataLength; 878b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (length < 0) { 879b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return totalSize; 880b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 881b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 882b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // 883b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // Check that length passed in is consistent with length from Spoof data header. 884b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // 885b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (length < totalSize) { 886b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru udata_printError(ds, "uspoof_swap(): too few bytes (%d after ICU Data header) for spoof data.\n", 887b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru spoofDataLength); 888b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status=U_INDEX_OUTOFBOUNDS_ERROR; 889b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return 0; 890b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 891b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 892b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 893b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // 894b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // Swap the Data. Do the data itself first, then the Spoof Data Header, because 895b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // we need to reference the header to locate the data, and an 896b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // inplace swap of the header leaves it unusable. 897b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // 898b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uint8_t *outBytes = (uint8_t *)outData + headerSize; 899b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru SpoofDataHeader *outputDH = (SpoofDataHeader *)outBytes; 900b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 901b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t sectionStart; 902b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t sectionLength; 903b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 904b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // 905b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // If not swapping in place, zero out the output buffer before starting. 906b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // Gaps may exist between the individual sections, and these must be zeroed in 907b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // the output buffer. The simplest way to do that is to just zero the whole thing. 908b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // 909b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (inBytes != outBytes) { 910b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_memset(outBytes, 0, spoofDataLength); 911b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 912b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 913b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // Confusables Keys Section (fCFUKeys) 914b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru sectionStart = ds->readUInt32(spoofDH->fCFUKeys); 915b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru sectionLength = ds->readUInt32(spoofDH->fCFUKeysSize) * 4; 916b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ds->swapArray32(ds, inBytes+sectionStart, sectionLength, outBytes+sectionStart, status); 917b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 918b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // String Index Section 919b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru sectionStart = ds->readUInt32(spoofDH->fCFUStringIndex); 920b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru sectionLength = ds->readUInt32(spoofDH->fCFUStringIndexSize) * 2; 921b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ds->swapArray16(ds, inBytes+sectionStart, sectionLength, outBytes+sectionStart, status); 922b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 923b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // String Table Section 924b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru sectionStart = ds->readUInt32(spoofDH->fCFUStringTable); 925b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru sectionLength = ds->readUInt32(spoofDH->fCFUStringTableLen) * 2; 926b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ds->swapArray16(ds, inBytes+sectionStart, sectionLength, outBytes+sectionStart, status); 927b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 928b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // String Lengths Section 929b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru sectionStart = ds->readUInt32(spoofDH->fCFUStringLengths); 930b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru sectionLength = ds->readUInt32(spoofDH->fCFUStringLengthsSize) * 4; 931b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ds->swapArray16(ds, inBytes+sectionStart, sectionLength, outBytes+sectionStart, status); 932b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 933b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // Any Case Trie 934b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru sectionStart = ds->readUInt32(spoofDH->fAnyCaseTrie); 935b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru sectionLength = ds->readUInt32(spoofDH->fAnyCaseTrieLength); 936b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru utrie2_swap(ds, inBytes+sectionStart, sectionLength, outBytes+sectionStart, status); 937b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 938b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // Lower Case Trie 939b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru sectionStart = ds->readUInt32(spoofDH->fLowerCaseTrie); 940b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru sectionLength = ds->readUInt32(spoofDH->fLowerCaseTrieLength); 941b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru utrie2_swap(ds, inBytes+sectionStart, sectionLength, outBytes+sectionStart, status); 942b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 943b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // Script Sets. The data is an array of int32_t 944b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru sectionStart = ds->readUInt32(spoofDH->fScriptSets); 94527f654740f2a26ad62a5c155af9199af9e69b889claireho sectionLength = ds->readUInt32(spoofDH->fScriptSetsLength) * sizeof(ScriptSet); 946b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ds->swapArray32(ds, inBytes+sectionStart, sectionLength, outBytes+sectionStart, status); 947b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 948b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // And, last, swap the header itself. 949b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // int32_t fMagic // swap this 95027f654740f2a26ad62a5c155af9199af9e69b889claireho // uint8_t fFormatVersion[4] // Do not swap this, just copy 95127f654740f2a26ad62a5c155af9199af9e69b889claireho // int32_t fLength and all the rest // Swap the rest, all is 32 bit stuff. 952b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // 953b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uint32_t magic = ds->readUInt32(spoofDH->fMagic); 954b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ds->writeUInt32((uint32_t *)&outputDH->fMagic, magic); 95527f654740f2a26ad62a5c155af9199af9e69b889claireho uprv_memcpy(outputDH->fFormatVersion, spoofDH->fFormatVersion, sizeof(spoofDH->fFormatVersion)); 95627f654740f2a26ad62a5c155af9199af9e69b889claireho // swap starting at fLength 95727f654740f2a26ad62a5c155af9199af9e69b889claireho ds->swapArray32(ds, &spoofDH->fLength, sizeof(SpoofDataHeader)-8 /* minus magic and fFormatVersion[4] */, &outputDH->fLength, status); 958b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 959b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return totalSize; 960b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 961b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 962b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif 963b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 964b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 965