1b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* 2b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru******************************************************************************* 3b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* 4fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius* Copyright (C) 2005-2013, International Business Machines 5b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Corporation and others. All Rights Reserved. 6b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* 7b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru******************************************************************************* 8b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* file name: utext.cpp 9b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* encoding: US-ASCII 10b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* tab size: 8 (not used) 11b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* indentation:4 12b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* 13b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* created on: 2005apr12 14b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* created by: Markus W. Scherer 15b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/ 16b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 17b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/utypes.h" 18b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/ustring.h" 19b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/unistr.h" 20b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/chariter.h" 21b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/utext.h" 22103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#include "unicode/utf.h" 23103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#include "unicode/utf8.h" 24103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#include "unicode/utf16.h" 25b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "ustr_imp.h" 26b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cmemory.h" 27b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cstring.h" 28b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "uassert.h" 2950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include "putilimp.h" 30b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 31b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_NAMESPACE_USE 32b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 33b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define I32_FLAG(bitIndex) ((int32_t)1<<(bitIndex)) 34b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 35b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 36b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UBool 37b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruutext_access(UText *ut, int64_t index, UBool forward) { 38b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return ut->pFuncs->access(ut, index, forward); 39b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 40b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 41b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 42b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 43b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI UBool U_EXPORT2 44b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruutext_moveIndex32(UText *ut, int32_t delta) { 45b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UChar32 c; 46b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (delta > 0) { 47b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru do { 48b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(ut->chunkOffset>=ut->chunkLength && !utext_access(ut, ut->chunkNativeLimit, TRUE)) { 49b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return FALSE; 50b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 51b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru c = ut->chunkContents[ut->chunkOffset]; 52b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U16_IS_SURROGATE(c)) { 53b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru c = utext_next32(ut); 54b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (c == U_SENTINEL) { 55b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return FALSE; 56b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 57b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 58b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkOffset++; 59b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 60b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } while(--delta>0); 61b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 62b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else if (delta<0) { 63b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru do { 64b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(ut->chunkOffset<=0 && !utext_access(ut, ut->chunkNativeStart, FALSE)) { 65b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return FALSE; 66b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 67b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru c = ut->chunkContents[ut->chunkOffset-1]; 68b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U16_IS_SURROGATE(c)) { 69b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru c = utext_previous32(ut); 70b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (c == U_SENTINEL) { 71b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return FALSE; 72b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 73b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 74b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkOffset--; 75b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 76b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } while(++delta<0); 77b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 78b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 79b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return TRUE; 80b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 81b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 82b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 83b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI int64_t U_EXPORT2 84b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruutext_nativeLength(UText *ut) { 85b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return ut->pFuncs->nativeLength(ut); 86b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 87b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 88b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 89b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI UBool U_EXPORT2 90b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruutext_isLengthExpensive(const UText *ut) { 91b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UBool r = (ut->providerProperties & I32_FLAG(UTEXT_PROVIDER_LENGTH_IS_EXPENSIVE)) != 0; 92b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return r; 93b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 94b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 95b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 96b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI int64_t U_EXPORT2 97b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruutext_getNativeIndex(const UText *ut) { 98b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(ut->chunkOffset <= ut->nativeIndexingLimit) { 99b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return ut->chunkNativeStart+ut->chunkOffset; 100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return ut->pFuncs->mapOffsetToNative(ut); 102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI void U_EXPORT2 107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruutext_setNativeIndex(UText *ut, int64_t index) { 108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(index<ut->chunkNativeStart || index>=ut->chunkNativeLimit) { 109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // The desired position is outside of the current chunk. 110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Access the new position. Assume a forward iteration from here, 111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // which will also be optimimum for a single random access. 112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Reverse iterations may suffer slightly. 113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->pFuncs->access(ut, index, TRUE); 114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else if((int32_t)(index - ut->chunkNativeStart) <= ut->nativeIndexingLimit) { 115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // utf-16 indexing. 116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkOffset=(int32_t)(index-ut->chunkNativeStart); 117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkOffset=ut->pFuncs->mapNativeIndexToUTF16(ut, index); 119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // The convention is that the index must always be on a code point boundary. 121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Adjust the index position if it is in the middle of a surrogate pair. 122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ut->chunkOffset<ut->chunkLength) { 123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UChar c= ut->chunkContents[ut->chunkOffset]; 124103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (U16_IS_TRAIL(c)) { 125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ut->chunkOffset==0) { 126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->pFuncs->access(ut, ut->chunkNativeStart, FALSE); 127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ut->chunkOffset>0) { 129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UChar lead = ut->chunkContents[ut->chunkOffset-1]; 130103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (U16_IS_LEAD(lead)) { 131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkOffset--; 132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI int64_t U_EXPORT2 141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruutext_getPreviousNativeIndex(UText *ut) { 142b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Fast-path the common case. 144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Common means current position is not at the beginning of a chunk 145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // and the preceding character is not supplementary. 146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t i = ut->chunkOffset - 1; 148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int64_t result; 149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (i >= 0) { 150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UChar c = ut->chunkContents[i]; 151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U16_IS_TRAIL(c) == FALSE) { 152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (i <= ut->nativeIndexingLimit) { 153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru result = ut->chunkNativeStart + i; 154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkOffset = i; 156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru result = ut->pFuncs->mapOffsetToNative(ut); 157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkOffset++; 158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return result; 160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // If at the start of text, simply return 0. 164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ut->chunkOffset==0 && ut->chunkNativeStart==0) { 165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 0; 166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Harder, less common cases. We are at a chunk boundary, or on a surrogate. 169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Keep it simple, use other functions to handle the edges. 170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru utext_previous32(ut); 172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru result = UTEXT_GETNATIVEINDEX(ut); 173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru utext_next32(ut); 174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return result; 175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// utext_current32. Get the UChar32 at the current position. 180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// UText iteration position is always on a code point boundary, 181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// never on the trail half of a surrogate pair. 182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI UChar32 U_EXPORT2 184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruutext_current32(UText *ut) { 185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UChar32 c; 186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ut->chunkOffset==ut->chunkLength) { 187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Current position is just off the end of the chunk. 188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ut->pFuncs->access(ut, ut->chunkNativeLimit, TRUE) == FALSE) { 189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Off the end of the text. 190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return U_SENTINEL; 191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru c = ut->chunkContents[ut->chunkOffset]; 195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U16_IS_LEAD(c) == FALSE) { 196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Normal, non-supplementary case. 197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return c; 198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Possible supplementary char. 202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UChar32 trail = 0; 204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UChar32 supplementaryC = c; 205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if ((ut->chunkOffset+1) < ut->chunkLength) { 206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // The trail surrogate is in the same chunk. 207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru trail = ut->chunkContents[ut->chunkOffset+1]; 208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // The trail surrogate is in a different chunk. 210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Because we must maintain the iteration position, we need to switch forward 211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // into the new chunk, get the trail surrogate, then revert the chunk back to the 212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // original one. 213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // An edge case to be careful of: the entire text may end with an unpaired 214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // leading surrogate. The attempt to access the trail will fail, but 215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // the original position before the unpaired lead still needs to be restored. 216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int64_t nativePosition = ut->chunkNativeLimit; 217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t originalOffset = ut->chunkOffset; 218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ut->pFuncs->access(ut, nativePosition, TRUE)) { 219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru trail = ut->chunkContents[ut->chunkOffset]; 220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UBool r = ut->pFuncs->access(ut, nativePosition, FALSE); // reverse iteration flag loads preceding chunk 222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru U_ASSERT(r==TRUE); 223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkOffset = originalOffset; 224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(!r) { 225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return U_SENTINEL; 226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U16_IS_TRAIL(trail)) { 230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru supplementaryC = U16_GET_SUPPLEMENTARY(c, trail); 231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return supplementaryC; 233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI UChar32 U_EXPORT2 238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruutext_char32At(UText *ut, int64_t nativeIndex) { 239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UChar32 c = U_SENTINEL; 240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Fast path the common case. 242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (nativeIndex>=ut->chunkNativeStart && nativeIndex < ut->chunkNativeStart + ut->nativeIndexingLimit) { 243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkOffset = (int32_t)(nativeIndex - ut->chunkNativeStart); 244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru c = ut->chunkContents[ut->chunkOffset]; 245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U16_IS_SURROGATE(c) == FALSE) { 246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return c; 247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru utext_setNativeIndex(ut, nativeIndex); 252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (nativeIndex>=ut->chunkNativeStart && ut->chunkOffset<ut->chunkLength) { 253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru c = ut->chunkContents[ut->chunkOffset]; 254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U16_IS_SURROGATE(c)) { 255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // For surrogates, let current32() deal with the complications 256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // of supplementaries that may span chunk boundaries. 257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru c = utext_current32(ut); 258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 260b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return c; 261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 263b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI UChar32 U_EXPORT2 265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruutext_next32(UText *ut) { 266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UChar32 c; 267b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 268b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ut->chunkOffset >= ut->chunkLength) { 269b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ut->pFuncs->access(ut, ut->chunkNativeLimit, TRUE) == FALSE) { 270b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return U_SENTINEL; 271b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 272b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru c = ut->chunkContents[ut->chunkOffset++]; 275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U16_IS_LEAD(c) == FALSE) { 276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Normal case, not supplementary. 277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // (A trail surrogate seen here is just returned as is, as a surrogate value. 278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // It cannot be part of a pair.) 279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return c; 280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 282b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ut->chunkOffset >= ut->chunkLength) { 283b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ut->pFuncs->access(ut, ut->chunkNativeLimit, TRUE) == FALSE) { 284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // c is an unpaired lead surrogate at the end of the text. 285b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // return it as it is. 286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return c; 287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 289b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UChar32 trail = ut->chunkContents[ut->chunkOffset]; 290b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U16_IS_TRAIL(trail) == FALSE) { 291b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // c was an unpaired lead surrogate, not at the end of the text. 292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // return it as it is (unpaired). Iteration position is on the 293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // following character, possibly in the next chunk, where the 294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // trail surrogate would have been if it had existed. 295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return c; 296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 297b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UChar32 supplementary = U16_GET_SUPPLEMENTARY(c, trail); 299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkOffset++; // move iteration position over the trail surrogate. 300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return supplementary; 301b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 302b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 303b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 304b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI UChar32 U_EXPORT2 305b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruutext_previous32(UText *ut) { 306b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UChar32 c; 307b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 308b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ut->chunkOffset <= 0) { 309b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ut->pFuncs->access(ut, ut->chunkNativeStart, FALSE) == FALSE) { 310b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return U_SENTINEL; 311b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkOffset--; 314b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru c = ut->chunkContents[ut->chunkOffset]; 315b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U16_IS_TRAIL(c) == FALSE) { 316b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Normal case, not supplementary. 317b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // (A lead surrogate seen here is just returned as is, as a surrogate value. 318b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // It cannot be part of a pair.) 319b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return c; 320b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 321b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ut->chunkOffset <= 0) { 323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ut->pFuncs->access(ut, ut->chunkNativeStart, FALSE) == FALSE) { 324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // c is an unpaired trail surrogate at the start of the text. 325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // return it as it is. 326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return c; 327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UChar32 lead = ut->chunkContents[ut->chunkOffset-1]; 331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U16_IS_LEAD(lead) == FALSE) { 332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // c was an unpaired trail surrogate, not at the end of the text. 333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // return it as it is (unpaired). Iteration position is at c 334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return c; 335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UChar32 supplementary = U16_GET_SUPPLEMENTARY(lead, c); 338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkOffset--; // move iteration position over the lead surrogate. 339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return supplementary; 340b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 341b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 342b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 343b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 344b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI UChar32 U_EXPORT2 345b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruutext_next32From(UText *ut, int64_t index) { 346b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UChar32 c = U_SENTINEL; 347b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 348b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(index<ut->chunkNativeStart || index>=ut->chunkNativeLimit) { 349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Desired position is outside of the current chunk. 350b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(!ut->pFuncs->access(ut, index, TRUE)) { 351b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // no chunk available here 352b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return U_SENTINEL; 353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 354b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else if (index - ut->chunkNativeStart <= (int64_t)ut->nativeIndexingLimit) { 355b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Desired position is in chunk, with direct 1:1 native to UTF16 indexing 356b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkOffset = (int32_t)(index - ut->chunkNativeStart); 357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Desired position is in chunk, with non-UTF16 indexing. 359b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkOffset = ut->pFuncs->mapNativeIndexToUTF16(ut, index); 360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru c = ut->chunkContents[ut->chunkOffset++]; 363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U16_IS_SURROGATE(c)) { 364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Surrogates. Many edge cases. Use other functions that already 365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // deal with the problems. 366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru utext_setNativeIndex(ut, index); 367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru c = utext_next32(ut); 368b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return c; 370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 372b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 373b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI UChar32 U_EXPORT2 374b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruutext_previous32From(UText *ut, int64_t index) { 375b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 376b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Return the character preceding the specified index. 377b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Leave the iteration position at the start of the character that was returned. 378b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 379b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UChar32 cPrev; // The character preceding cCurr, which is what we will return. 380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Address the chunk containg the position preceding the incoming index 382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // A tricky edge case: 383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // We try to test the requested native index against the chunkNativeStart to determine 384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // whether the character preceding the one at the index is in the current chunk. 385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // BUT, this test can fail with UTF-8 (or any other multibyte encoding), when the 386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // requested index is on something other than the first position of the first char. 387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(index<=ut->chunkNativeStart || index>ut->chunkNativeLimit) { 389b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Requested native index is outside of the current chunk. 390b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(!ut->pFuncs->access(ut, index, FALSE)) { 391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // no chunk available here 392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return U_SENTINEL; 393b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else if(index - ut->chunkNativeStart <= (int64_t)ut->nativeIndexingLimit) { 395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Direct UTF-16 indexing. 396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkOffset = (int32_t)(index - ut->chunkNativeStart); 397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkOffset=ut->pFuncs->mapNativeIndexToUTF16(ut, index); 399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ut->chunkOffset==0 && !ut->pFuncs->access(ut, index, FALSE)) { 400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // no chunk available here 401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return U_SENTINEL; 402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 404b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 405b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 406b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Simple case with no surrogates. 407b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 408b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkOffset--; 409b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru cPrev = ut->chunkContents[ut->chunkOffset]; 410b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 411b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U16_IS_SURROGATE(cPrev)) { 412b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Possible supplementary. Many edge cases. 413b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Let other functions do the heavy lifting. 414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru utext_setNativeIndex(ut, index); 415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru cPrev = utext_previous32(ut); 416b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 417b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return cPrev; 418b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 419b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI int32_t U_EXPORT2 422b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruutext_extract(UText *ut, 423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int64_t start, int64_t limit, 424b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UChar *dest, int32_t destCapacity, 425b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UErrorCode *status) { 426b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return ut->pFuncs->extract(ut, start, limit, dest, destCapacity, status); 427b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 428b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 429b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 430b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 431b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI UBool U_EXPORT2 432b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruutext_equals(const UText *a, const UText *b) { 433b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (a==NULL || b==NULL || 434b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru a->magic != UTEXT_MAGIC || 435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru b->magic != UTEXT_MAGIC) { 436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Null or invalid arguments don't compare equal to anything. 437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return FALSE; 438b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 439b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 440b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (a->pFuncs != b->pFuncs) { 441b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Different types of text providers. 442b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return FALSE; 443b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 444b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (a->context != b->context) { 446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Different sources (different strings) 447b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return FALSE; 448b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 449b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (utext_getNativeIndex(a) != utext_getNativeIndex(b)) { 450b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Different current position in the string. 451b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return FALSE; 452b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 453b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 454b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return TRUE; 455b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 456b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 457b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI UBool U_EXPORT2 458b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruutext_isWritable(const UText *ut) 459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 460b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UBool b = (ut->providerProperties & I32_FLAG(UTEXT_PROVIDER_WRITABLE)) != 0; 461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return b; 462b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 464b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI void U_EXPORT2 466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruutext_freeze(UText *ut) { 467b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Zero out the WRITABLE flag. 468b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->providerProperties &= ~(I32_FLAG(UTEXT_PROVIDER_WRITABLE)); 469b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 470b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 471b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 472b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI UBool U_EXPORT2 473b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruutext_hasMetaData(const UText *ut) 474b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 475b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UBool b = (ut->providerProperties & I32_FLAG(UTEXT_PROVIDER_HAS_META_DATA)) != 0; 476b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return b; 477b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 478b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 479b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 480b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 481b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI int32_t U_EXPORT2 482b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruutext_replace(UText *ut, 483b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int64_t nativeStart, int64_t nativeLimit, 484b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const UChar *replacementText, int32_t replacementLength, 485b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UErrorCode *status) 486b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 487b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(*status)) { 488b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 0; 489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 490b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if ((ut->providerProperties & I32_FLAG(UTEXT_PROVIDER_WRITABLE)) == 0) { 491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *status = U_NO_WRITE_PERMISSION; 492b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 0; 493b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 494b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t i = ut->pFuncs->replace(ut, nativeStart, nativeLimit, replacementText, replacementLength, status); 495b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return i; 496b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 497b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 498b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI void U_EXPORT2 499b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruutext_copy(UText *ut, 500b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int64_t nativeStart, int64_t nativeLimit, 501b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int64_t destIndex, 502b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UBool move, 503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UErrorCode *status) 504b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 505b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(*status)) { 506b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if ((ut->providerProperties & I32_FLAG(UTEXT_PROVIDER_WRITABLE)) == 0) { 509b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *status = U_NO_WRITE_PERMISSION; 510b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 511b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->pFuncs->copy(ut, nativeStart, nativeLimit, destIndex, move, status); 513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 514b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 515b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 516b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 517b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI UText * U_EXPORT2 518b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruutext_clone(UText *dest, const UText *src, UBool deep, UBool readOnly, UErrorCode *status) { 519b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UText *result; 520b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru result = src->pFuncs->clone(dest, src, deep, status); 521b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (readOnly) { 522b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru utext_freeze(result); 523b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 524b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return result; 525b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 526b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 527b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 528b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 529b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//------------------------------------------------------------------------------ 530b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 531b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// UText common functions implementation 532b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 533b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//------------------------------------------------------------------------------ 534b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 535b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 536b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// UText.flags bit definitions 537b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 538b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruenum { 539b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UTEXT_HEAP_ALLOCATED = 1, // 1 if ICU has allocated this UText struct on the heap. 540b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 0 if caller provided storage for the UText. 541b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 542b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UTEXT_EXTRA_HEAP_ALLOCATED = 2, // 1 if ICU has allocated extra storage as a separate 543b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // heap block. 544b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 0 if there is no separate allocation. Either no extra 545b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // storage was requested, or it is appended to the end 546b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // of the main UText storage. 547b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 548b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UTEXT_OPEN = 4 // 1 if this UText is currently open 549b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 0 if this UText is not open. 550b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}; 551b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 552b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 553b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 554b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Extended form of a UText. The purpose is to aid in computing the total size required 555b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// when a provider asks for a UText to be allocated with extra storage. 556b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 557b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustruct ExtendedUText { 558b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UText ut; 559b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UAlignedMemory extension; 560b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}; 561b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 562b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const UText emptyText = UTEXT_INITIALIZER; 563b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 564b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI UText * U_EXPORT2 565b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruutext_setup(UText *ut, int32_t extraSpace, UErrorCode *status) { 566b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(*status)) { 567b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return ut; 568b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 569b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 570b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ut == NULL) { 571b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // We need to heap-allocate storage for the new UText 572b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t spaceRequired = sizeof(UText); 573b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (extraSpace > 0) { 574b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru spaceRequired = sizeof(ExtendedUText) + extraSpace - sizeof(UAlignedMemory); 575b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 576b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut = (UText *)uprv_malloc(spaceRequired); 577b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ut == NULL) { 578b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *status = U_MEMORY_ALLOCATION_ERROR; 579c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru return NULL; 580b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 581b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *ut = emptyText; 582b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->flags |= UTEXT_HEAP_ALLOCATED; 583b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (spaceRequired>0) { 584b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->extraSize = extraSpace; 585b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->pExtra = &((ExtendedUText *)ut)->extension; 586b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 587b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 588b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 589b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // We have been supplied with an already existing UText. 590b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Verify that it really appears to be a UText. 591b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ut->magic != UTEXT_MAGIC) { 592b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 593b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return ut; 594b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 595b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // If the ut is already open and there's a provider supplied close 596b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // function, call it. 597b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if ((ut->flags & UTEXT_OPEN) && ut->pFuncs->close != NULL) { 598b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->pFuncs->close(ut); 599b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 600b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->flags &= ~UTEXT_OPEN; 601b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 602b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // If extra space was requested by our caller, check whether 603b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // sufficient already exists, and allocate new if needed. 604b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (extraSpace > ut->extraSize) { 605b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Need more space. If there is existing separately allocated space, 606b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // delete it first, then allocate new space. 607b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ut->flags & UTEXT_EXTRA_HEAP_ALLOCATED) { 608b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uprv_free(ut->pExtra); 609b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->extraSize = 0; 610b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 611b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->pExtra = uprv_malloc(extraSpace); 612b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ut->pExtra == NULL) { 613b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *status = U_MEMORY_ALLOCATION_ERROR; 614b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 615b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->extraSize = extraSpace; 616b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->flags |= UTEXT_EXTRA_HEAP_ALLOCATED; 617b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 618b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 619b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 620b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_SUCCESS(*status)) { 621b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->flags |= UTEXT_OPEN; 622b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 623b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Initialize all remaining fields of the UText. 624b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 625b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->context = NULL; 626b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkContents = NULL; 627b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->p = NULL; 628b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->q = NULL; 629b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->r = NULL; 630b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->a = 0; 631b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->b = 0; 632b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->c = 0; 633b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkOffset = 0; 634b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkLength = 0; 635b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkNativeStart = 0; 636b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkNativeLimit = 0; 637b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->nativeIndexingLimit = 0; 638b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->providerProperties = 0; 639b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->privA = 0; 640b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->privB = 0; 641b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->privC = 0; 642b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->privP = NULL; 643b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ut->pExtra!=NULL && ut->extraSize>0) 644b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uprv_memset(ut->pExtra, 0, ut->extraSize); 645b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 646b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 647b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return ut; 648b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 649b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 650b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 651b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI UText * U_EXPORT2 652b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruutext_close(UText *ut) { 653b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ut==NULL || 654b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->magic != UTEXT_MAGIC || 655b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru (ut->flags & UTEXT_OPEN) == 0) 656b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { 657b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // The supplied ut is not an open UText. 658b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Do nothing. 659b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return ut; 660b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 661b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 662b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // If the provider gave us a close function, call it now. 663b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // This will clean up anything allocated specifically by the provider. 664b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ut->pFuncs->close != NULL) { 665b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->pFuncs->close(ut); 666b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 667b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->flags &= ~UTEXT_OPEN; 668b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 669b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // If we (the framework) allocated the UText or subsidiary storage, 670b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // delete it. 671b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ut->flags & UTEXT_EXTRA_HEAP_ALLOCATED) { 672b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uprv_free(ut->pExtra); 673b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->pExtra = NULL; 674b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->flags &= ~UTEXT_EXTRA_HEAP_ALLOCATED; 675b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->extraSize = 0; 676b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 677b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 678b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Zero out function table of the closed UText. This is a defensive move, 679b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // inteded to cause applications that inadvertantly use a closed 680b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // utext to crash with null pointer errors. 681b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->pFuncs = NULL; 682b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 683b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ut->flags & UTEXT_HEAP_ALLOCATED) { 684b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // This UText was allocated by UText setup. We need to free it. 685b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Clear magic, so we can detect if the user messes up and immediately 686b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // tries to reopen another UText using the deleted storage. 687b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->magic = 0; 688b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uprv_free(ut); 689b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut = NULL; 690b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 691b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return ut; 692b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 693b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 694b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 695b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 696b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 697b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 698b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// invalidateChunk Reset a chunk to have no contents, so that the next call 699b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// to access will cause new data to load. 700b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// This is needed when copy/move/replace operate directly on the 701b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// backing text, potentially putting it out of sync with the 702b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// contents in the chunk. 703b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 704b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void 705b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruinvalidateChunk(UText *ut) { 706b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkLength = 0; 707b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkNativeLimit = 0; 708b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkNativeStart = 0; 709b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkOffset = 0; 710b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->nativeIndexingLimit = 0; 711b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 712b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 713b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 714b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// pinIndex Do range pinning on a native index parameter. 715b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 64 bit pinning is done in place. 716b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 32 bit truncated result is returned as a convenience for 717b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// use in providers that don't need 64 bits. 718b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int32_t 719b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerupinIndex(int64_t &index, int64_t limit) { 720b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (index<0) { 721b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru index = 0; 722b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else if (index > limit) { 723b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru index = limit; 724b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 725b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return (int32_t)index; 726b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 727b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 728b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 729b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CDECL_BEGIN 730b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 731b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 732b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Pointer relocation function, 733b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// a utility used by shallow clone. 734b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Adjust a pointer that refers to something within one UText (the source) 735b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// to refer to the same relative offset within a another UText (the target) 736b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 737b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void adjustPointer(UText *dest, const void **destPtr, const UText *src) { 738b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // convert all pointers to (char *) so that byte address arithmetic will work. 739b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru char *dptr = (char *)*destPtr; 740b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru char *dUText = (char *)dest; 741b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru char *sUText = (char *)src; 742b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 743b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (dptr >= (char *)src->pExtra && dptr < ((char*)src->pExtra)+src->extraSize) { 744b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // target ptr was to something within the src UText's pExtra storage. 745b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // relocate it into the target UText's pExtra region. 746b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *destPtr = ((char *)dest->pExtra) + (dptr - (char *)src->pExtra); 747b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else if (dptr>=sUText && dptr < sUText+src->sizeOfStruct) { 748b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // target ptr was pointing to somewhere within the source UText itself. 749b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Move it to the same offset within the target UText. 750b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *destPtr = dUText + (dptr-sUText); 751b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 752b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 753b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 754b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 755b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 756b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Clone. This is a generic copy-the-utext-by-value clone function that can be 757b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// used as-is with some utext types, and as a helper by other clones. 758b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 759b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UText * U_CALLCONV 760b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerushallowTextClone(UText * dest, const UText * src, UErrorCode * status) { 761b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(*status)) { 762b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return NULL; 763b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 764b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t srcExtraSize = src->extraSize; 765b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 766b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 767b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Use the generic text_setup to allocate storage if required. 768b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 769b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru dest = utext_setup(dest, srcExtraSize, status); 770b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(*status)) { 771b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return dest; 772b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 773b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 774b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 775b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // flags (how the UText was allocated) and the pointer to the 776b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // extra storage must retain the values in the cloned utext that 777b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // were set up by utext_setup. Save them separately before 778b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // copying the whole struct. 779b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 780b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru void *destExtra = dest->pExtra; 781b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t flags = dest->flags; 782b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 783b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 784b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 785b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Copy the whole UText struct by value. 786b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Any "Extra" storage is copied also. 787b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 788b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int sizeToCopy = src->sizeOfStruct; 789b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (sizeToCopy > dest->sizeOfStruct) { 790b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru sizeToCopy = dest->sizeOfStruct; 791b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 792b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uprv_memcpy(dest, src, sizeToCopy); 793b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru dest->pExtra = destExtra; 794b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru dest->flags = flags; 795b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (srcExtraSize > 0) { 796b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uprv_memcpy(dest->pExtra, src->pExtra, srcExtraSize); 797b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 798b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 799b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 800b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Relocate any pointers in the target that refer to the UText itself 801b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // to point to the cloned copy rather than the original source. 802b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 803b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru adjustPointer(dest, &dest->context, src); 804b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru adjustPointer(dest, &dest->p, src); 805b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru adjustPointer(dest, &dest->q, src); 806b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru adjustPointer(dest, &dest->r, src); 80750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho adjustPointer(dest, (const void **)&dest->chunkContents, src); 808b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 809fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // The newly shallow-cloned UText does _not_ own the underlying storage for the text. 810fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // (The source for the clone may or may not have owned the text.) 811fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 812fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius dest->providerProperties &= ~I32_FLAG(UTEXT_PROVIDER_OWNS_TEXT); 813fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 814b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return dest; 815b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 816b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 817b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 818b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CDECL_END 819b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 820b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 821b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 822b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//------------------------------------------------------------------------------ 823b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 824b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// UText implementation for UTF-8 char * strings (read-only) 825b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Limitation: string length must be <= 0x7fffffff in length. 826b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// (length must for in an int32_t variable) 827b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 828b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Use of UText data members: 829b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// context pointer to UTF-8 string 830b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// utext.b is the input string length (bytes). 831b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// utext.c Length scanned so far in string 832b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// (for optimizing finding length of zero terminated strings.) 833b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// utext.p pointer to the current buffer 834b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// utext.q pointer to the other buffer. 835b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 836b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//------------------------------------------------------------------------------ 837b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 838b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Chunk size. 839b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Must be less than 85, because of byte mapping from UChar indexes to native indexes. 840b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Worst case is three native bytes to one UChar. (Supplemenaries are 4 native bytes 841b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// to two UChars.) 842b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 843b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruenum { UTF8_TEXT_CHUNK_SIZE=32 }; 844b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 845b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 846b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// UTF8Buf Two of these structs will be set up in the UText's extra allocated space. 847b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Each contains the UChar chunk buffer, the to and from native maps, and 848b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// header info. 849b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 850b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// because backwards iteration fills the buffers starting at the end and 851b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// working towards the front, the filled part of the buffers may not begin 852b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// at the start of the available storage for the buffers. 853b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 854b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Buffer size is one bigger than the specified UTF8_TEXT_CHUNK_SIZE to allow for 855b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// the last character added being a supplementary, and thus requiring a surrogate 856b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// pair. Doing this is simpler than checking for the edge case. 857b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 858b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 859b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustruct UTF8Buf { 860b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t bufNativeStart; // Native index of first char in UChar buf 861b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t bufNativeLimit; // Native index following last char in buf. 862b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t bufStartIdx; // First filled position in buf. 863b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t bufLimitIdx; // Limit of filled range in buf. 864b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t bufNILimit; // Limit of native indexing part of buf 865b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t toUCharsMapStart; // Native index corresponding to 866b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // mapToUChars[0]. 867b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Set to bufNativeStart when filling forwards. 868b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Set to computed value when filling backwards. 869b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 870b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UChar buf[UTF8_TEXT_CHUNK_SIZE+4]; // The UChar buffer. Requires one extra position beyond the 871b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // the chunk size, to allow for surrogate at the end. 872b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Length must be identical to mapToNative array, below, 873b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // because of the way indexing works when the array is 874b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // filled backwards during a reverse iteration. Thus, 875b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // the additional extra size. 876b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uint8_t mapToNative[UTF8_TEXT_CHUNK_SIZE+4]; // map UChar index in buf to 877b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // native offset from bufNativeStart. 878b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Requires two extra slots, 879b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // one for a supplementary starting in the last normal position, 880b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // and one for an entry for the buffer limit position. 881b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uint8_t mapToUChars[UTF8_TEXT_CHUNK_SIZE*3+6]; // Map native offset from bufNativeStart to 882b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // correspoding offset in filled part of buf. 883b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t align; 884b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}; 885b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 886b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CDECL_BEGIN 887b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 888b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 889b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// utf8TextLength 890b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 891b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Get the length of the string. If we don't already know it, 892b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// we'll need to scan for the trailing nul. 893b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 894b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int64_t U_CALLCONV 895b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruutf8TextLength(UText *ut) { 896b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ut->b < 0) { 897b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Zero terminated string, and we haven't scanned to the end yet. 898b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Scan it now. 899b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const char *r = (const char *)ut->context + ut->c; 900b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru while (*r != 0) { 901b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru r++; 902b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 903b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if ((r - (const char *)ut->context) < 0x7fffffff) { 904b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->b = (int32_t)(r - (const char *)ut->context); 905b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 906b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Actual string was bigger (more than 2 gig) than we 907b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // can handle. Clip it to 2 GB. 908b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->b = 0x7fffffff; 909b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 910b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->providerProperties &= ~I32_FLAG(UTEXT_PROVIDER_LENGTH_IS_EXPENSIVE); 911b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 912b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return ut->b; 913b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 914b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 915b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 916b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 917b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 918b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 919b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 920b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UBool U_CALLCONV 921b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruutf8TextAccess(UText *ut, int64_t index, UBool forward) { 922b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 923b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Apologies to those who are allergic to goto statements. 924b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Consider each goto to a labelled block to be the equivalent of 925b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // call the named block as if it were a function(); 926b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // return; 927b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 928b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const uint8_t *s8=(const uint8_t *)ut->context; 929b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UTF8Buf *u8b = NULL; 930b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t length = ut->b; // Length of original utf-8 931b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t ix= (int32_t)index; // Requested index, trimmed to 32 bits. 932b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t mapIndex = 0; 933b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (index<0) { 934b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ix=0; 935b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else if (index > 0x7fffffff) { 936b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Strings with 64 bit lengths not supported by this UTF-8 provider. 937b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ix = 0x7fffffff; 938b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 939b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 940b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Pin requested index to the string length. 941b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ix>length) { 942b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (length>=0) { 943b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ix=length; 94450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else if (ix>=ut->c) { 945b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Zero terminated string, and requested index is beyond 946b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // the region that has already been scanned. 947b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Scan up to either the end of the string or to the 948b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // requested position, whichever comes first. 949b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru while (ut->c<ix && s8[ut->c]!=0) { 950b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->c++; 951b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 952b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // TODO: support for null terminated string length > 32 bits. 953b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (s8[ut->c] == 0) { 954b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // We just found the actual length of the string. 955b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Trim the requested index back to that. 956b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ix = ut->c; 957b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->b = ut->c; 958b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru length = ut->c; 959b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->providerProperties &= ~I32_FLAG(UTEXT_PROVIDER_LENGTH_IS_EXPENSIVE); 960b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 961b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 962b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 963b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 964b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 965b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Dispatch to the appropriate action for a forward iteration request. 966b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 967b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (forward) { 968b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ix==ut->chunkNativeLimit) { 969b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Check for normal sequential iteration cases first. 970b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ix==length) { 971b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Just reached end of string 972b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Don't swap buffers, but do set the 973b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // current buffer position. 974b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkOffset = ut->chunkLength; 975b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return FALSE; 976b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 977b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // End of current buffer. 978b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // check whether other buffer already has what we need. 979b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UTF8Buf *altB = (UTF8Buf *)ut->q; 980b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ix>=altB->bufNativeStart && ix<altB->bufNativeLimit) { 981b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru goto swapBuffers; 982b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 983b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 984b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 985b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 986b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // A random access. Desired index could be in either or niether buf. 987b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // For optimizing the order of testing, first check for the index 988b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // being in the other buffer. This will be the case for uses that 989b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // move back and forth over a fairly limited range 990b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { 991b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru u8b = (UTF8Buf *)ut->q; // the alternate buffer 992b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ix>=u8b->bufNativeStart && ix<u8b->bufNativeLimit) { 993b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Requested index is in the other buffer. 994b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru goto swapBuffers; 995b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 996b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ix == length) { 997b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Requested index is end-of-string. 998b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // (this is the case of randomly seeking to the end. 999b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // The case of iterating off the end is handled earlier.) 1000b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ix == ut->chunkNativeLimit) { 1001b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Current buffer extends up to the end of the string. 1002b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Leave it as the current buffer. 1003b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkOffset = ut->chunkLength; 1004b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return FALSE; 1005b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1006b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ix == u8b->bufNativeLimit) { 1007b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Alternate buffer extends to the end of string. 1008b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Swap it in as the current buffer. 1009b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru goto swapBuffersAndFail; 1010b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1011b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1012b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Neither existing buffer extends to the end of the string. 1013b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru goto makeStubBuffer; 1014b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1015b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1016b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ix<ut->chunkNativeStart || ix>=ut->chunkNativeLimit) { 1017b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Requested index is in neither buffer. 1018b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru goto fillForward; 1019b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1020b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1021b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Requested index is in this buffer. 1022b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru u8b = (UTF8Buf *)ut->p; // the current buffer 1023b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru mapIndex = ix - u8b->toUCharsMapStart; 1024b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkOffset = u8b->mapToUChars[mapIndex] - u8b->bufStartIdx; 1025b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return TRUE; 1026b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1027b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1028b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1029b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1030b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1031b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 1032b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Dispatch to the appropriate action for a 1033b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Backwards Diretion iteration request. 1034b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 1035b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ix==ut->chunkNativeStart) { 1036b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Check for normal sequential iteration cases first. 1037b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ix==0) { 1038b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Just reached the start of string 1039b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Don't swap buffers, but do set the 1040b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // current buffer position. 1041b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkOffset = 0; 1042b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return FALSE; 1043b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 1044b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Start of current buffer. 1045b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // check whether other buffer already has what we need. 1046b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UTF8Buf *altB = (UTF8Buf *)ut->q; 1047b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ix>altB->bufNativeStart && ix<=altB->bufNativeLimit) { 1048b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru goto swapBuffers; 1049b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1050b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1051b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1052b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1053b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // A random access. Desired index could be in either or niether buf. 1054b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // For optimizing the order of testing, 1055b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Most likely case: in the other buffer. 1056b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Second most likely: in neither buffer. 1057b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Unlikely, but must work: in the current buffer. 1058b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru u8b = (UTF8Buf *)ut->q; // the alternate buffer 1059b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ix>u8b->bufNativeStart && ix<=u8b->bufNativeLimit) { 1060b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Requested index is in the other buffer. 1061b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru goto swapBuffers; 1062b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1063b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Requested index is start-of-string. 1064b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // (this is the case of randomly seeking to the start. 1065b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // The case of iterating off the start is handled earlier.) 1066b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ix==0) { 1067b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (u8b->bufNativeStart==0) { 1068b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Alternate buffer contains the data for the start string. 1069b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Make it be the current buffer. 1070b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru goto swapBuffersAndFail; 1071b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 1072b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Request for data before the start of string, 1073b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // neither buffer is usable. 1074b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // set up a zero-length buffer. 1075b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru goto makeStubBuffer; 1076b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1077b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1078b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1079b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ix<=ut->chunkNativeStart || ix>ut->chunkNativeLimit) { 1080b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Requested index is in neither buffer. 1081b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru goto fillReverse; 1082b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1083b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1084b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Requested index is in this buffer. 1085b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Set the utf16 buffer index. 1086b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru u8b = (UTF8Buf *)ut->p; 1087b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru mapIndex = ix - u8b->toUCharsMapStart; 1088b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkOffset = u8b->mapToUChars[mapIndex] - u8b->bufStartIdx; 1089b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ut->chunkOffset==0) { 1090b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // This occurs when the first character in the text is 1091b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // a multi-byte UTF-8 char, and the requested index is to 1092b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // one of the trailing bytes. Because there is no preceding , 1093b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // character, this access fails. We can't pick up on the 1094b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // situation sooner because the requested index is not zero. 1095b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return FALSE; 1096b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 1097b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return TRUE; 1098b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1099b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruswapBuffers: 1103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // The alternate buffer (ut->q) has the string data that was requested. 1104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Swap the primary and alternate buffers, and set the 1105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // chunk index into the new primary buffer. 1106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { 1107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru u8b = (UTF8Buf *)ut->q; 1108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->q = ut->p; 1109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->p = u8b; 1110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkContents = &u8b->buf[u8b->bufStartIdx]; 1111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkLength = u8b->bufLimitIdx - u8b->bufStartIdx; 1112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkNativeStart = u8b->bufNativeStart; 1113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkNativeLimit = u8b->bufNativeLimit; 1114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->nativeIndexingLimit = u8b->bufNILimit; 1115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Index into the (now current) chunk 1117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Use the map to set the chunk index. It's more trouble than it's worth 1118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // to check whether native indexing can be used. 1119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru U_ASSERT(ix>=u8b->bufNativeStart); 1120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru U_ASSERT(ix<=u8b->bufNativeLimit); 1121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru mapIndex = ix - u8b->toUCharsMapStart; 1122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru U_ASSERT(mapIndex>=0); 1123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru U_ASSERT(mapIndex<(int32_t)sizeof(u8b->mapToUChars)); 1124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkOffset = u8b->mapToUChars[mapIndex] - u8b->bufStartIdx; 1125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return TRUE; 1127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru swapBuffersAndFail: 1131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // We got a request for either the start or end of the string, 1132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // with iteration continuing in the out-of-bounds direction. 1133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // The alternate buffer already contains the data up to the 1134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // start/end. 1135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Swap the buffers, then return failure, indicating that we couldn't 1136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // make things correct for continuing the iteration in the requested 1137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // direction. The position & buffer are correct should the 1138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // user decide to iterate in the opposite direction. 1139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru u8b = (UTF8Buf *)ut->q; 1140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->q = ut->p; 1141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->p = u8b; 1142b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkContents = &u8b->buf[u8b->bufStartIdx]; 1143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkLength = u8b->bufLimitIdx - u8b->bufStartIdx; 1144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkNativeStart = u8b->bufNativeStart; 1145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkNativeLimit = u8b->bufNativeLimit; 1146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->nativeIndexingLimit = u8b->bufNILimit; 1147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Index into the (now current) chunk 1149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // For this function (swapBuffersAndFail), the requested index 1150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // will always be at either the start or end of the chunk. 1151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ix==u8b->bufNativeLimit) { 1152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkOffset = ut->chunkLength; 1153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 1154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkOffset = 0; 1155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru U_ASSERT(ix == u8b->bufNativeStart); 1156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return FALSE; 1158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerumakeStubBuffer: 1160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // The user has done a seek/access past the start or end 1161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // of the string. Rather than loading data that is likely 1162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // to never be used, just set up a zero-length buffer at 1163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // the position. 1164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru u8b = (UTF8Buf *)ut->q; 1165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru u8b->bufNativeStart = ix; 1166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru u8b->bufNativeLimit = ix; 1167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru u8b->bufStartIdx = 0; 1168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru u8b->bufLimitIdx = 0; 1169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru u8b->bufNILimit = 0; 1170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru u8b->toUCharsMapStart = ix; 1171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru u8b->mapToNative[0] = 0; 1172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru u8b->mapToUChars[0] = 0; 1173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru goto swapBuffersAndFail; 1174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerufillForward: 1178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { 1179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Move the incoming index to a code point boundary. 1180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru U8_SET_CP_START(s8, 0, ix); 1181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Swap the UText buffers. 1183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // We want to fill what was previously the alternate buffer, 1184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // and make what was the current buffer be the new alternate. 1185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UTF8Buf *u8b = (UTF8Buf *)ut->q; 1186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->q = ut->p; 1187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->p = u8b; 1188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t strLen = ut->b; 1190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UBool nulTerminated = FALSE; 1191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (strLen < 0) { 1192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru strLen = 0x7fffffff; 1193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru nulTerminated = TRUE; 1194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UChar *buf = u8b->buf; 1197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uint8_t *mapToNative = u8b->mapToNative; 1198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uint8_t *mapToUChars = u8b->mapToUChars; 1199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t destIx = 0; 1200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t srcIx = ix; 1201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UBool seenNonAscii = FALSE; 120250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UChar32 c = 0; 1203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Fill the chunk buffer and mapping arrays. 1205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru while (destIx<UTF8_TEXT_CHUNK_SIZE) { 1206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru c = s8[srcIx]; 1207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (c>0 && c<0x80) { 1208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Special case ASCII range for speed. 1209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // zero is excluded to simplify bounds checking. 121050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho buf[destIx] = (UChar)c; 121150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho mapToNative[destIx] = (uint8_t)(srcIx - ix); 121250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho mapToUChars[srcIx-ix] = (uint8_t)destIx; 1213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru srcIx++; 1214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru destIx++; 1215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 1216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // General case, handle everything. 1217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (seenNonAscii == FALSE) { 1218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru seenNonAscii = TRUE; 1219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru u8b->bufNILimit = destIx; 1220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t cIx = srcIx; 1223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t dIx = destIx; 1224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t dIxSaved = destIx; 12258393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius U8_NEXT_OR_FFFD(s8, srcIx, strLen, c); 1226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (c==0 && nulTerminated) { 1227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru srcIx--; 1228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 1229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru U16_APPEND_UNSAFE(buf, destIx, c); 1232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru do { 123350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho mapToNative[dIx++] = (uint8_t)(cIx - ix); 1234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } while (dIx < destIx); 1235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru do { 123750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho mapToUChars[cIx++ - ix] = (uint8_t)dIxSaved; 1238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } while (cIx < srcIx); 1239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (srcIx>=strLen) { 1241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 1242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // store Native <--> Chunk Map entries for the end of the buffer. 1247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // There is no actual character here, but the index position is valid. 124850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho mapToNative[destIx] = (uint8_t)(srcIx - ix); 124950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho mapToUChars[srcIx - ix] = (uint8_t)destIx; 1250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // fill in Buffer descriptor 1252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru u8b->bufNativeStart = ix; 1253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru u8b->bufNativeLimit = srcIx; 1254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru u8b->bufStartIdx = 0; 1255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru u8b->bufLimitIdx = destIx; 1256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (seenNonAscii == FALSE) { 1257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru u8b->bufNILimit = destIx; 1258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru u8b->toUCharsMapStart = u8b->bufNativeStart; 1260b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Set UText chunk to refer to this buffer. 1262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkContents = buf; 1263b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkOffset = 0; 1264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkLength = u8b->bufLimitIdx; 1265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkNativeStart = u8b->bufNativeStart; 1266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkNativeLimit = u8b->bufNativeLimit; 1267b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->nativeIndexingLimit = u8b->bufNILimit; 1268b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1269b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // For zero terminated strings, keep track of the maximum point 1270b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // scanned so far. 1271b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (nulTerminated && srcIx>ut->c) { 1272b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->c = srcIx; 1273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (c==0) { 1274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // We scanned to the end. 1275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Remember the actual length. 1276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->b = srcIx; 1277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->providerProperties &= ~I32_FLAG(UTEXT_PROVIDER_LENGTH_IS_EXPENSIVE); 1278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return TRUE; 1281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1282b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1283b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerufillReverse: 1285b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { 1286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Move the incoming index to a code point boundary. 1287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Can only do this if the incoming index is somewhere in the interior of the string. 1288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // If index is at the end, there is no character there to look at. 1289b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ix != ut->b) { 1290b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru U8_SET_CP_START(s8, 0, ix); 1291b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Swap the UText buffers. 1294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // We want to fill what was previously the alternate buffer, 1295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // and make what was the current buffer be the new alternate. 1296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UTF8Buf *u8b = (UTF8Buf *)ut->q; 1297b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->q = ut->p; 1298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->p = u8b; 1299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UChar *buf = u8b->buf; 1301b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uint8_t *mapToNative = u8b->mapToNative; 1302b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uint8_t *mapToUChars = u8b->mapToUChars; 1303b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t toUCharsMapStart = ix - (UTF8_TEXT_CHUNK_SIZE*3 + 1); 1304b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t destIx = UTF8_TEXT_CHUNK_SIZE+2; // Start in the overflow region 1305b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // at end of buffer to leave room 1306b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // for a surrogate pair at the 1307b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // buffer start. 1308b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t srcIx = ix; 1309b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t bufNILimit = destIx; 1310b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UChar32 c; 1311b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Map to/from Native Indexes, fill in for the position at the end of 1313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // the buffer. 1314b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 131550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho mapToNative[destIx] = (uint8_t)(srcIx - toUCharsMapStart); 131650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho mapToUChars[srcIx - toUCharsMapStart] = (uint8_t)destIx; 1317b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1318b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Fill the chunk buffer 1319b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Work backwards, filling from the end of the buffer towards the front. 1320b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 1321b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru while (destIx>2 && (srcIx - toUCharsMapStart > 5) && (srcIx > 0)) { 1322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru srcIx--; 1323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru destIx--; 1324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Get last byte of the UTF-8 character 1326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru c = s8[srcIx]; 1327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (c<0x80) { 1328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Special case ASCII range for speed. 132950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho buf[destIx] = (UChar)c; 133050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho mapToUChars[srcIx - toUCharsMapStart] = (uint8_t)destIx; 133150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho mapToNative[destIx] = (uint8_t)(srcIx - toUCharsMapStart); 1332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 1333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // General case, handle everything non-ASCII. 1334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t sIx = srcIx; // ix of last byte of multi-byte u8 char 1336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Get the full character from the UTF8 string. 13388393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius // use code derived from tbe macros in utf8.h 1339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Leaves srcIx pointing at the first byte of the UTF-8 char. 1340b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 13418393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius c=utf8_prevCharSafeBody(s8, 0, &srcIx, c, -3); 13428393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius // leaves srcIx at first byte of the multi-byte char. 1343b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1344b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Store the character in UTF-16 buffer. 1345b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (c<0x10000) { 134650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho buf[destIx] = (UChar)c; 134750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho mapToNative[destIx] = (uint8_t)(srcIx - toUCharsMapStart); 1348b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 1349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru buf[destIx] = U16_TRAIL(c); 135050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho mapToNative[destIx] = (uint8_t)(srcIx - toUCharsMapStart); 1351b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru buf[--destIx] = U16_LEAD(c); 135250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho mapToNative[destIx] = (uint8_t)(srcIx - toUCharsMapStart); 1353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1354b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1355b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Fill in the map from native indexes to UChars buf index. 1356b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru do { 135750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho mapToUChars[sIx-- - toUCharsMapStart] = (uint8_t)destIx; 1358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } while (sIx >= srcIx); 1359b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Set native indexing limit to be the current position. 1361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // We are processing a non-ascii, non-native-indexing char now; 1362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // the limit will be here if the rest of the chars to be 1363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // added to this buffer are ascii. 1364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru bufNILimit = destIx; 1365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru u8b->bufNativeStart = srcIx; 1368b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru u8b->bufNativeLimit = ix; 1369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru u8b->bufStartIdx = destIx; 1370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru u8b->bufLimitIdx = UTF8_TEXT_CHUNK_SIZE+2; 1371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru u8b->bufNILimit = bufNILimit - u8b->bufStartIdx; 1372b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru u8b->toUCharsMapStart = toUCharsMapStart; 1373b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1374b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkContents = &buf[u8b->bufStartIdx]; 1375b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkLength = u8b->bufLimitIdx - u8b->bufStartIdx; 1376b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkOffset = ut->chunkLength; 1377b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkNativeStart = u8b->bufNativeStart; 1378b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkNativeLimit = u8b->bufNativeLimit; 1379b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->nativeIndexingLimit = u8b->bufNILimit; 1380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return TRUE; 1381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 1388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// This is a slightly modified copy of u_strFromUTF8, 1389b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Inserts a Replacement Char rather than failing on invalid UTF-8 1390b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Removes unnecessary features. 1391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 1392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UChar* 1393b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruutext_strFromUTF8(UChar *dest, 1394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t destCapacity, 1395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t *pDestLength, 1396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const char* src, 1397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t srcLength, // required. NUL terminated not supported. 1398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UErrorCode *pErrorCode 1399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ) 1400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 1401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UChar *pDest = dest; 1403103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius UChar *pDestLimit = (dest!=NULL)?(dest+destCapacity):NULL; 1404b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UChar32 ch=0; 1405b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t index = 0; 1406b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t reqLength = 0; 1407b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uint8_t* pSrc = (uint8_t*) src; 1408b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1409b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1410b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru while((index < srcLength)&&(pDest<pDestLimit)){ 1411b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ch = pSrc[index++]; 1412b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(ch <=0x7f){ 1413b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *pDest++=(UChar)ch; 1414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru }else{ 14158393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius ch=utf8_nextCharSafeBody(pSrc, &index, srcLength, ch, -3); 141650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if(U_IS_BMP(ch)){ 1417b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *(pDest++)=(UChar)ch; 1418b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru }else{ 1419103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius *(pDest++)=U16_LEAD(ch); 1420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(pDest<pDestLimit){ 1421103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius *(pDest++)=U16_TRAIL(ch); 1422b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru }else{ 1423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru reqLength++; 1424b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 1425b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1426b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1427b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1428b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1429b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru /* donot fill the dest buffer just count the UChars needed */ 1430b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru while(index < srcLength){ 1431b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ch = pSrc[index++]; 1432b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(ch <= 0x7f){ 1433b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru reqLength++; 1434b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru }else{ 14358393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius ch=utf8_nextCharSafeBody(pSrc, &index, srcLength, ch, -3); 143650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho reqLength+=U16_LENGTH(ch); 1437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1438b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1439b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1440b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru reqLength+=(int32_t)(pDest - dest); 1441b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1442b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(pDestLength){ 1443b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *pDestLength = reqLength; 1444b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru /* Terminate the buffer */ 1447b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru u_terminateUChars(dest,destCapacity,reqLength,pErrorCode); 1448b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1449b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return dest; 1450b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1451b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1452b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1453b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1454b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int32_t U_CALLCONV 1455b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruutf8TextExtract(UText *ut, 1456b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int64_t start, int64_t limit, 1457b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UChar *dest, int32_t destCapacity, 1458b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UErrorCode *pErrorCode) { 1459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(U_FAILURE(*pErrorCode)) { 1460b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 0; 1461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1462b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(destCapacity<0 || (dest==NULL && destCapacity>0)) { 1463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; 1464b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 0; 1465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t length = ut->b; 1467b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t start32 = pinIndex(start, length); 1468b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t limit32 = pinIndex(limit, length); 1469b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1470b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(start32>limit32) { 1471b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR; 1472b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 0; 1473b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1474b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1475b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1476b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // adjust the incoming indexes to land on code point boundaries if needed. 1477b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // adjust by no more than three, because that is the largest number of trail bytes 1478b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // in a well formed UTF8 character. 1479b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const uint8_t *buf = (const uint8_t *)ut->context; 1480b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int i; 1481b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (start32 < ut->chunkNativeLimit) { 1482b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (i=0; i<3; i++) { 148350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U8_IS_SINGLE(buf[start32]) || U8_IS_LEAD(buf[start32]) || start32==0) { 1484b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 1485b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1486b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru start32--; 1487b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1488b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1490b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (limit32 < ut->chunkNativeLimit) { 1491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (i=0; i<3; i++) { 149250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U8_IS_SINGLE(buf[limit32]) || U8_IS_LEAD(buf[limit32]) || limit32==0) { 1493b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 1494b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1495b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru limit32--; 1496b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1497b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1498b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1499b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Do the actual extract. 1500b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t destLength=0; 1501b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru utext_strFromUTF8(dest, destCapacity, &destLength, 1502b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru (const char *)ut->context+start32, limit32-start32, 1503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru pErrorCode); 150450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho utf8TextAccess(ut, limit32, TRUE); 1505b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return destLength; 1506b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 1509b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// utf8TextMapOffsetToNative 1510b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 1511b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Map a chunk (UTF-16) offset to a native index. 1512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int64_t U_CALLCONV 1513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruutf8TextMapOffsetToNative(const UText *ut) { 1514b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 1515b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UTF8Buf *u8b = (UTF8Buf *)ut->p; 1516b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru U_ASSERT(ut->chunkOffset>ut->nativeIndexingLimit && ut->chunkOffset<=ut->chunkLength); 1517b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t nativeOffset = u8b->mapToNative[ut->chunkOffset + u8b->bufStartIdx] + u8b->toUCharsMapStart; 1518b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru U_ASSERT(nativeOffset >= ut->chunkNativeStart && nativeOffset <= ut->chunkNativeLimit); 1519b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return nativeOffset; 1520b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1521b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1522b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 1523b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Map a native index to the corrsponding chunk offset 1524b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 1525b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int32_t U_CALLCONV 1526b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruutf8TextMapIndexToUTF16(const UText *ut, int64_t index64) { 1527b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru U_ASSERT(index64 <= 0x7fffffff); 1528b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t index = (int32_t)index64; 1529b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UTF8Buf *u8b = (UTF8Buf *)ut->p; 1530b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru U_ASSERT(index>=ut->chunkNativeStart+ut->nativeIndexingLimit); 1531b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru U_ASSERT(index<=ut->chunkNativeLimit); 1532b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t mapIndex = index - u8b->toUCharsMapStart; 1533b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t offset = u8b->mapToUChars[mapIndex] - u8b->bufStartIdx; 1534b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru U_ASSERT(offset>=0 && offset<=ut->chunkLength); 1535b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return offset; 1536b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1537b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1538b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UText * U_CALLCONV 1539b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruutf8TextClone(UText *dest, const UText *src, UBool deep, UErrorCode *status) 1540b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 1541b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // First do a generic shallow clone. Does everything needed for the UText struct itself. 1542b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru dest = shallowTextClone(dest, src, status); 1543b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1544b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // For deep clones, make a copy of the string. 1545b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // The copied storage is owned by the newly created clone. 1546b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 1547b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // TODO: There is an isssue with using utext_nativeLength(). 1548b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // That function is non-const in cases where the input was NUL terminated 1549b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // and the length has not yet been determined. 1550b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // This function (clone()) is const. 1551b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // There potentially a thread safety issue lurking here. 1552b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 1553b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (deep && U_SUCCESS(*status)) { 1554b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t len = (int32_t)utext_nativeLength((UText *)src); 1555b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru char *copyStr = (char *)uprv_malloc(len+1); 1556b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (copyStr == NULL) { 1557b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *status = U_MEMORY_ALLOCATION_ERROR; 1558b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 1559b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uprv_memcpy(copyStr, src->context, len+1); 1560b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru dest->context = copyStr; 1561b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru dest->providerProperties |= I32_FLAG(UTEXT_PROVIDER_OWNS_TEXT); 1562b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1563b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1564b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return dest; 1565b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1566b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1567b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1568b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void U_CALLCONV 1569b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruutf8TextClose(UText *ut) { 1570b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Most of the work of close is done by the generic UText framework close. 1571b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // All that needs to be done here is to delete the UTF8 string if the UText 1572b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // owns it. This occurs if the UText was created by cloning. 1573b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ut->providerProperties & I32_FLAG(UTEXT_PROVIDER_OWNS_TEXT)) { 1574b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru char *s = (char *)ut->context; 1575b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uprv_free(s); 1576b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->context = NULL; 1577b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1578b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1579b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1580b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CDECL_END 1581b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1582b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1583fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusstatic const struct UTextFuncs utf8Funcs = 1584b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 1585b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru sizeof(UTextFuncs), 1586b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 0, 0, 0, // Reserved alignment padding 1587b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru utf8TextClone, 1588b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru utf8TextLength, 1589b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru utf8TextAccess, 1590b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru utf8TextExtract, 1591b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru NULL, /* replace*/ 1592b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru NULL, /* copy */ 1593b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru utf8TextMapOffsetToNative, 1594b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru utf8TextMapIndexToUTF16, 1595b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru utf8TextClose, 1596b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru NULL, // spare 1 1597b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru NULL, // spare 2 1598b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru NULL // spare 3 1599b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}; 1600b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1601b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1602b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char gEmptyString[] = {0}; 1603b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1604b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI UText * U_EXPORT2 1605b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruutext_openUTF8(UText *ut, const char *s, int64_t length, UErrorCode *status) { 1606b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(U_FAILURE(*status)) { 1607b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return NULL; 1608b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1609b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if(s==NULL && length==0) { 1610b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru s = gEmptyString; 1611b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1612b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1613b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(s==NULL || length<-1 || length>INT32_MAX) { 1614b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *status=U_ILLEGAL_ARGUMENT_ERROR; 1615b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return NULL; 1616b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1617b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1618b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut = utext_setup(ut, sizeof(UTF8Buf) * 2, status); 1619b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(*status)) { 1620b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return ut; 1621b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1622b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1623b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->pFuncs = &utf8Funcs; 1624b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->context = s; 1625b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->b = (int32_t)length; 1626b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->c = (int32_t)length; 1627b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ut->c < 0) { 1628b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->c = 0; 1629b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->providerProperties |= I32_FLAG(UTEXT_PROVIDER_LENGTH_IS_EXPENSIVE); 1630b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1631b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->p = ut->pExtra; 1632b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->q = (char *)ut->pExtra + sizeof(UTF8Buf); 1633b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return ut; 1634b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1635b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1636b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1637b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1638b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1639b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1640b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1641b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1642b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1643b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1644b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//------------------------------------------------------------------------------ 1645b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 1646b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// UText implementation wrapper for Replaceable (read/write) 1647b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 1648b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Use of UText data members: 1649b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// context pointer to Replaceable. 1650b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// p pointer to Replaceable if it is owned by the UText. 1651b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 1652b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//------------------------------------------------------------------------------ 1653b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1654b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1655b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1656b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// minimum chunk size for this implementation: 3 1657b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// to allow for possible trimming for code point boundaries 1658b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruenum { REP_TEXT_CHUNK_SIZE=10 }; 1659b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1660b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustruct ReplExtra { 1661b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru /* 1662b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Chunk UChars. 1663b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * +1 to simplify filling with surrogate pair at the end. 1664b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */ 1665b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UChar s[REP_TEXT_CHUNK_SIZE+1]; 1666b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}; 1667b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1668b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1669b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CDECL_BEGIN 1670b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1671b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UText * U_CALLCONV 1672b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerurepTextClone(UText *dest, const UText *src, UBool deep, UErrorCode *status) { 1673b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // First do a generic shallow clone. Does everything needed for the UText struct itself. 1674b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru dest = shallowTextClone(dest, src, status); 1675b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1676b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // For deep clones, make a copy of the Replaceable. 1677b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // The copied Replaceable storage is owned by the newly created UText clone. 1678b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // A non-NULL pointer in UText.p is the signal to the close() function to delete 1679b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // it. 1680b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 1681b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (deep && U_SUCCESS(*status)) { 1682b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const Replaceable *replSrc = (const Replaceable *)src->context; 1683b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru dest->context = replSrc->clone(); 1684b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru dest->providerProperties |= I32_FLAG(UTEXT_PROVIDER_OWNS_TEXT); 1685b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1686b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // with deep clone, the copy is writable, even when the source is not. 1687b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru dest->providerProperties |= I32_FLAG(UTEXT_PROVIDER_WRITABLE); 1688b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1689b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return dest; 1690b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1691b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1692b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1693b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void U_CALLCONV 1694b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerurepTextClose(UText *ut) { 1695b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Most of the work of close is done by the generic UText framework close. 1696b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // All that needs to be done here is delete the Replaceable if the UText 1697b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // owns it. This occurs if the UText was created by cloning. 1698b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ut->providerProperties & I32_FLAG(UTEXT_PROVIDER_OWNS_TEXT)) { 1699b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru Replaceable *rep = (Replaceable *)ut->context; 1700b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru delete rep; 1701b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->context = NULL; 1702b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1703b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1704b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1705b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1706b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int64_t U_CALLCONV 1707b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerurepTextLength(UText *ut) { 1708b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const Replaceable *replSrc = (const Replaceable *)ut->context; 1709b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t len = replSrc->length(); 1710b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return len; 1711b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1712b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1713b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1714b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UBool U_CALLCONV 1715b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerurepTextAccess(UText *ut, int64_t index, UBool forward) { 1716b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const Replaceable *rep=(const Replaceable *)ut->context; 1717b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t length=rep->length(); // Full length of the input text (bigger than a chunk) 1718b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1719b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // clip the requested index to the limits of the text. 1720b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t index32 = pinIndex(index, length); 1721b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru U_ASSERT(index<=INT32_MAX); 1722b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1723b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1724b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru /* 1725b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Compute start/limit boundaries around index, for a segment of text 1726b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * to be extracted. 1727b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * To allow for the possibility that our user gave an index to the trailing 1728b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * half of a surrogate pair, we must request one extra preceding UChar when 1729b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * going in the forward direction. This will ensure that the buffer has the 1730b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * entire code point at the specified index. 1731b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */ 1732b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(forward) { 1733b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1734b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (index32>=ut->chunkNativeStart && index32<ut->chunkNativeLimit) { 1735b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Buffer already contains the requested position. 1736b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkOffset = (int32_t)(index - ut->chunkNativeStart); 1737b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return TRUE; 1738b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1739b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (index32>=length && ut->chunkNativeLimit==length) { 1740b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Request for end of string, and buffer already extends up to it. 1741b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Can't get the data, but don't change the buffer. 1742b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkOffset = length - (int32_t)ut->chunkNativeStart; 1743b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return FALSE; 1744b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1745b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1746b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkNativeLimit = index + REP_TEXT_CHUNK_SIZE - 1; 1747b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Going forward, so we want to have the buffer with stuff at and beyond 1748b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // the requested index. The -1 gets us one code point before the 1749b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // requested index also, to handle the case of the index being on 1750b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // a trail surrogate of a surrogate pair. 1751b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(ut->chunkNativeLimit > length) { 1752b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkNativeLimit = length; 1753b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1754b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // unless buffer ran off end, start is index-1. 1755b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkNativeStart = ut->chunkNativeLimit - REP_TEXT_CHUNK_SIZE; 1756b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(ut->chunkNativeStart < 0) { 1757b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkNativeStart = 0; 1758b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1759b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 1760b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Reverse iteration. Fill buffer with data preceding the requested index. 1761b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (index32>ut->chunkNativeStart && index32<=ut->chunkNativeLimit) { 1762b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Requested position already in buffer. 1763b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkOffset = index32 - (int32_t)ut->chunkNativeStart; 1764b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return TRUE; 1765b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1766b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (index32==0 && ut->chunkNativeStart==0) { 1767b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Request for start, buffer already begins at start. 1768b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // No data, but keep the buffer as is. 1769b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkOffset = 0; 1770b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return FALSE; 1771b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1772b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1773b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Figure out the bounds of the chunk to extract for reverse iteration. 1774b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Need to worry about chunk not splitting surrogate pairs, and while still 1775b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // containing the data we need. 1776b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Fix by requesting a chunk that includes an extra UChar at the end. 1777b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // If this turns out to be a lead surrogate, we can lop it off and still have 1778b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // the data we wanted. 1779b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkNativeStart = index32 + 1 - REP_TEXT_CHUNK_SIZE; 1780b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ut->chunkNativeStart < 0) { 1781b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkNativeStart = 0; 1782b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1783b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1784b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkNativeLimit = index32 + 1; 1785b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ut->chunkNativeLimit > length) { 1786b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkNativeLimit = length; 1787b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1788b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1789b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1790b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Extract the new chunk of text from the Replaceable source. 1791b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ReplExtra *ex = (ReplExtra *)ut->pExtra; 1792b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // UnicodeString with its buffer a writable alias to the chunk buffer 1793b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UnicodeString buffer(ex->s, 0 /*buffer length*/, REP_TEXT_CHUNK_SIZE /*buffer capacity*/); 1794b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru rep->extractBetween((int32_t)ut->chunkNativeStart, (int32_t)ut->chunkNativeLimit, buffer); 1795b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1796b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkContents = ex->s; 1797b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkLength = (int32_t)(ut->chunkNativeLimit - ut->chunkNativeStart); 1798b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkOffset = (int32_t)(index32 - ut->chunkNativeStart); 1799b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1800b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Surrogate pairs from the input text must not span chunk boundaries. 1801b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // If end of chunk could be the start of a surrogate, trim it off. 1802b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ut->chunkNativeLimit < length && 1803b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru U16_IS_LEAD(ex->s[ut->chunkLength-1])) { 1804b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkLength--; 1805b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkNativeLimit--; 1806b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ut->chunkOffset > ut->chunkLength) { 1807b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkOffset = ut->chunkLength; 1808b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1809b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1810b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1811b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // if the first UChar in the chunk could be the trailing half of a surrogate pair, 1812b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // trim it off. 1813b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(ut->chunkNativeStart>0 && U16_IS_TRAIL(ex->s[0])) { 1814b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ++(ut->chunkContents); 1815b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ++(ut->chunkNativeStart); 1816b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru --(ut->chunkLength); 1817b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru --(ut->chunkOffset); 1818b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1819b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1820b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // adjust the index/chunkOffset to a code point boundary 1821b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru U16_SET_CP_START(ut->chunkContents, 0, ut->chunkOffset); 1822b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1823b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Use fast indexing for get/setNativeIndex() 1824b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->nativeIndexingLimit = ut->chunkLength; 1825b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1826b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return TRUE; 1827b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1828b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1829b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1830b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1831b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int32_t U_CALLCONV 1832b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerurepTextExtract(UText *ut, 1833b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int64_t start, int64_t limit, 1834b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UChar *dest, int32_t destCapacity, 1835b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UErrorCode *status) { 1836b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const Replaceable *rep=(const Replaceable *)ut->context; 1837b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t length=rep->length(); 1838b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1839b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(U_FAILURE(*status)) { 1840b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 0; 1841b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1842b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(destCapacity<0 || (dest==NULL && destCapacity>0)) { 1843b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *status=U_ILLEGAL_ARGUMENT_ERROR; 1844b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1845b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(start>limit) { 1846b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *status=U_INDEX_OUTOFBOUNDS_ERROR; 1847b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 0; 1848b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1849b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1850b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t start32 = pinIndex(start, length); 1851b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t limit32 = pinIndex(limit, length); 1852b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1853b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // adjust start, limit if they point to trail half of surrogates 1854b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (start32<length && U16_IS_TRAIL(rep->charAt(start32)) && 1855b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru U_IS_SUPPLEMENTARY(rep->char32At(start32))){ 1856b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru start32--; 1857b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1858b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (limit32<length && U16_IS_TRAIL(rep->charAt(limit32)) && 1859b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru U_IS_SUPPLEMENTARY(rep->char32At(limit32))){ 1860b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru limit32--; 1861b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1862b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1863b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru length=limit32-start32; 1864b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(length>destCapacity) { 1865b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru limit32 = start32 + destCapacity; 1866b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1867b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UnicodeString buffer(dest, 0, destCapacity); // writable alias 1868b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru rep->extractBetween(start32, limit32, buffer); 186950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho repTextAccess(ut, limit32, TRUE); 1870fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 1871b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return u_terminateUChars(dest, destCapacity, length, status); 1872b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1873b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1874b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int32_t U_CALLCONV 1875b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerurepTextReplace(UText *ut, 1876b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int64_t start, int64_t limit, 1877b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const UChar *src, int32_t length, 1878b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UErrorCode *status) { 1879b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru Replaceable *rep=(Replaceable *)ut->context; 1880b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t oldLength; 1881b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1882b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(U_FAILURE(*status)) { 1883b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 0; 1884b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1885b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(src==NULL && length!=0) { 1886b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *status=U_ILLEGAL_ARGUMENT_ERROR; 1887b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 0; 1888b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1889b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru oldLength=rep->length(); // will subtract from new length 1890b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(start>limit ) { 1891b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *status=U_INDEX_OUTOFBOUNDS_ERROR; 1892b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 0; 1893b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1894b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1895b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t start32 = pinIndex(start, oldLength); 1896b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t limit32 = pinIndex(limit, oldLength); 1897b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1898b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Snap start & limit to code point boundaries. 1899b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (start32<oldLength && U16_IS_TRAIL(rep->charAt(start32)) && 1900b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru start32>0 && U16_IS_LEAD(rep->charAt(start32-1))) 1901b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { 1902b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru start32--; 1903b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1904b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (limit32<oldLength && U16_IS_LEAD(rep->charAt(limit32-1)) && 1905b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru U16_IS_TRAIL(rep->charAt(limit32))) 1906b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { 1907b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru limit32++; 1908b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1909b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1910b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Do the actual replace operation using methods of the Replaceable class 1911b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UnicodeString replStr((UBool)(length<0), src, length); // read-only alias 1912b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru rep->handleReplaceBetween(start32, limit32, replStr); 1913b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t newLength = rep->length(); 1914b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t lengthDelta = newLength - oldLength; 1915b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1916b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Is the UText chunk buffer OK? 1917b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ut->chunkNativeLimit > start32) { 1918b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // this replace operation may have impacted the current chunk. 1919b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // invalidate it, which will force a reload on the next access. 1920b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru invalidateChunk(ut); 1921b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1922b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1923b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // set the iteration position to the end of the newly inserted replacement text. 1924b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t newIndexPos = limit32 + lengthDelta; 1925b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru repTextAccess(ut, newIndexPos, TRUE); 1926b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1927b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return lengthDelta; 1928b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1929b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1930b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1931b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void U_CALLCONV 1932b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerurepTextCopy(UText *ut, 1933b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int64_t start, int64_t limit, 1934b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int64_t destIndex, 1935b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UBool move, 1936b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UErrorCode *status) 1937b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 1938b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru Replaceable *rep=(Replaceable *)ut->context; 1939b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t length=rep->length(); 1940b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1941b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(U_FAILURE(*status)) { 1942b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 1943b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1944b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (start>limit || (start<destIndex && destIndex<limit)) 1945b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { 1946b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *status=U_INDEX_OUTOFBOUNDS_ERROR; 1947b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 1948b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1949b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1950b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t start32 = pinIndex(start, length); 1951b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t limit32 = pinIndex(limit, length); 1952b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t destIndex32 = pinIndex(destIndex, length); 1953b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1954b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // TODO: snap input parameters to code point boundaries. 1955b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1956b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(move) { 1957b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // move: copy to destIndex, then replace original with nothing 1958b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t segLength=limit32-start32; 1959b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru rep->copy(start32, limit32, destIndex32); 1960b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(destIndex32<start32) { 1961b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru start32+=segLength; 1962b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru limit32+=segLength; 1963b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1964b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru rep->handleReplaceBetween(start32, limit32, UnicodeString()); 1965b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 1966b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // copy 1967b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru rep->copy(start32, limit32, destIndex32); 1968b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1969b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1970b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // If the change to the text touched the region in the chunk buffer, 1971b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // invalidate the buffer. 1972b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t firstAffectedIndex = destIndex32; 1973b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (move && start32<firstAffectedIndex) { 1974b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru firstAffectedIndex = start32; 1975b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1976b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (firstAffectedIndex < ut->chunkNativeLimit) { 1977b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // changes may have affected range covered by the chunk 1978b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru invalidateChunk(ut); 1979b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1980b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1981b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Put iteration position at the newly inserted (moved) block, 1982b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t nativeIterIndex = destIndex32 + limit32 - start32; 1983b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (move && destIndex32>start32) { 1984b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // moved a block of text towards the end of the string. 1985b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru nativeIterIndex = destIndex32; 1986b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1987b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1988b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Set position, reload chunk if needed. 1989b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru repTextAccess(ut, nativeIterIndex, TRUE); 1990b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1991b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1992fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusstatic const struct UTextFuncs repFuncs = 1993b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 1994b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru sizeof(UTextFuncs), 1995b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 0, 0, 0, // Reserved alignment padding 1996b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru repTextClone, 1997b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru repTextLength, 1998b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru repTextAccess, 1999b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru repTextExtract, 2000fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius repTextReplace, 2001fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius repTextCopy, 2002b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru NULL, // MapOffsetToNative, 2003b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru NULL, // MapIndexToUTF16, 2004b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru repTextClose, 2005b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru NULL, // spare 1 2006b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru NULL, // spare 2 2007b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru NULL // spare 3 2008b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}; 2009b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2010b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2011b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI UText * U_EXPORT2 2012b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruutext_openReplaceable(UText *ut, Replaceable *rep, UErrorCode *status) 2013b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 2014b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(U_FAILURE(*status)) { 2015b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return NULL; 2016b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2017b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(rep==NULL) { 2018b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *status=U_ILLEGAL_ARGUMENT_ERROR; 2019b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return NULL; 2020b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2021b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut = utext_setup(ut, sizeof(ReplExtra), status); 2022b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2023b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->providerProperties = I32_FLAG(UTEXT_PROVIDER_WRITABLE); 2024b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(rep->hasMetaData()) { 2025b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->providerProperties |=I32_FLAG(UTEXT_PROVIDER_HAS_META_DATA); 2026b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2027b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2028b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->pFuncs = &repFuncs; 2029b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->context = rep; 2030b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return ut; 2031b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2032b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2033b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CDECL_END 2034b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2035b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2036b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2037b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2038b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2039b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2040b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2041b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2042b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//------------------------------------------------------------------------------ 2043b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 2044b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// UText implementation for UnicodeString (read/write) and 2045b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// for const UnicodeString (read only) 2046b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// (same implementation, only the flags are different) 2047b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 2048b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Use of UText data members: 2049b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// context pointer to UnicodeString 2050b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// p pointer to UnicodeString IF this UText owns the string 2051b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// and it must be deleted on close(). NULL otherwise. 2052b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 2053b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//------------------------------------------------------------------------------ 2054b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2055b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CDECL_BEGIN 2056b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2057b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2058b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UText * U_CALLCONV 2059b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruunistrTextClone(UText *dest, const UText *src, UBool deep, UErrorCode *status) { 2060b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // First do a generic shallow clone. Does everything needed for the UText struct itself. 2061b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru dest = shallowTextClone(dest, src, status); 2062b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2063b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // For deep clones, make a copy of the UnicodeSring. 2064b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // The copied UnicodeString storage is owned by the newly created UText clone. 2065b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // A non-NULL pointer in UText.p is the signal to the close() function to delete 2066b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // the UText. 2067b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 2068b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (deep && U_SUCCESS(*status)) { 2069b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const UnicodeString *srcString = (const UnicodeString *)src->context; 2070b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru dest->context = new UnicodeString(*srcString); 2071b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru dest->providerProperties |= I32_FLAG(UTEXT_PROVIDER_OWNS_TEXT); 2072b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2073b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // with deep clone, the copy is writable, even when the source is not. 2074b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru dest->providerProperties |= I32_FLAG(UTEXT_PROVIDER_WRITABLE); 2075b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2076b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return dest; 2077b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2078b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2079b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void U_CALLCONV 2080b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruunistrTextClose(UText *ut) { 2081b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Most of the work of close is done by the generic UText framework close. 2082b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // All that needs to be done here is delete the UnicodeString if the UText 2083b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // owns it. This occurs if the UText was created by cloning. 2084b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ut->providerProperties & I32_FLAG(UTEXT_PROVIDER_OWNS_TEXT)) { 2085b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UnicodeString *str = (UnicodeString *)ut->context; 2086b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru delete str; 2087b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->context = NULL; 2088b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2089b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2090b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2091b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2092b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int64_t U_CALLCONV 2093b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruunistrTextLength(UText *t) { 2094b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return ((const UnicodeString *)t->context)->length(); 2095b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2096b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2097b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2098b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UBool U_CALLCONV 2099b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruunistrTextAccess(UText *ut, int64_t index, UBool forward) { 2100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t length = ut->chunkLength; 2101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkOffset = pinIndex(index, length); 2102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Check whether request is at the start or end 2104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UBool retVal = (forward && index<length) || (!forward && index>0); 2105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return retVal; 2106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int32_t U_CALLCONV 2111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruunistrTextExtract(UText *t, 2112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int64_t start, int64_t limit, 2113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UChar *dest, int32_t destCapacity, 2114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UErrorCode *pErrorCode) { 2115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const UnicodeString *us=(const UnicodeString *)t->context; 2116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t length=us->length(); 2117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(U_FAILURE(*pErrorCode)) { 2119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 0; 2120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(destCapacity<0 || (dest==NULL && destCapacity>0)) { 2122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; 2123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(start<0 || start>limit) { 2125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR; 2126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 0; 2127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t start32 = start<length ? us->getChar32Start((int32_t)start) : length; 2130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t limit32 = limit<length ? us->getChar32Start((int32_t)limit) : length; 2131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru length=limit32-start32; 2133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (destCapacity>0 && dest!=NULL) { 2134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t trimmedLength = length; 2135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(trimmedLength>destCapacity) { 2136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru trimmedLength=destCapacity; 2137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru us->extract(start32, trimmedLength, dest); 213950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t->chunkOffset = start32+trimmedLength; 214050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 214150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho t->chunkOffset = start32; 2142b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru u_terminateUChars(dest, destCapacity, length, pErrorCode); 2144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return length; 2145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int32_t U_CALLCONV 2148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruunistrTextReplace(UText *ut, 2149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int64_t start, int64_t limit, 2150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const UChar *src, int32_t length, 2151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UErrorCode *pErrorCode) { 2152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UnicodeString *us=(UnicodeString *)ut->context; 2153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t oldLength; 2154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(U_FAILURE(*pErrorCode)) { 2156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 0; 2157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(src==NULL && length!=0) { 2159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; 2160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(start>limit) { 2162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR; 2163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 0; 2164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru oldLength=us->length(); 2166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t start32 = pinIndex(start, oldLength); 2167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t limit32 = pinIndex(limit, oldLength); 2168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (start32 < oldLength) { 2169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru start32 = us->getChar32Start(start32); 2170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (limit32 < oldLength) { 2172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru limit32 = us->getChar32Start(limit32); 2173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // replace 2176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru us->replace(start32, limit32-start32, src, length); 2177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t newLength = us->length(); 2178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Update the chunk description. 2180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkContents = us->getBuffer(); 2181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkLength = newLength; 2182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkNativeLimit = newLength; 2183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->nativeIndexingLimit = newLength; 2184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Set iteration position to the point just following the newly inserted text. 2186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t lengthDelta = newLength - oldLength; 2187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkOffset = limit32 + lengthDelta; 2188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return lengthDelta; 2190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void U_CALLCONV 2193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruunistrTextCopy(UText *ut, 2194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int64_t start, int64_t limit, 2195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int64_t destIndex, 2196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UBool move, 2197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UErrorCode *pErrorCode) { 2198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UnicodeString *us=(UnicodeString *)ut->context; 2199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t length=us->length(); 2200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(U_FAILURE(*pErrorCode)) { 2202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 2203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t start32 = pinIndex(start, length); 2205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t limit32 = pinIndex(limit, length); 2206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t destIndex32 = pinIndex(destIndex, length); 2207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if( start32>limit32 || (start32<destIndex32 && destIndex32<limit32)) { 2209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR; 2210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 2211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(move) { 2214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // move: copy to destIndex, then replace original with nothing 2215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t segLength=limit32-start32; 2216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru us->copy(start32, limit32, destIndex32); 2217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(destIndex32<start32) { 2218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru start32+=segLength; 2219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru us->replace(start32, segLength, NULL, 0); 2221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 2222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // copy 2223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru us->copy(start32, limit32, destIndex32); 2224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // update chunk description, set iteration position. 2227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkContents = us->getBuffer(); 2228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (move==FALSE) { 2229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // copy operation, string length grows 2230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkLength += limit32-start32; 2231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkNativeLimit = ut->chunkLength; 2232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->nativeIndexingLimit = ut->chunkLength; 2233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Iteration position to end of the newly inserted text. 2236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkOffset = destIndex32+limit32-start32; 2237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (move && destIndex32>start32) { 2238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkOffset = destIndex32; 2239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2243fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusstatic const struct UTextFuncs unistrFuncs = 2244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 2245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru sizeof(UTextFuncs), 2246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 0, 0, 0, // Reserved alignment padding 2247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru unistrTextClone, 2248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru unistrTextLength, 2249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru unistrTextAccess, 2250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru unistrTextExtract, 2251fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius unistrTextReplace, 2252fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius unistrTextCopy, 2253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru NULL, // MapOffsetToNative, 2254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru NULL, // MapIndexToUTF16, 2255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru unistrTextClose, 2256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru NULL, // spare 1 2257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru NULL, // spare 2 2258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru NULL // spare 3 2259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}; 2260b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2263b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CDECL_END 2264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI UText * U_EXPORT2 2267b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruutext_openUnicodeString(UText *ut, UnicodeString *s, UErrorCode *status) { 2268b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho ut = utext_openConstUnicodeString(ut, s, status); 2269b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_SUCCESS(*status)) { 2270b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho ut->providerProperties |= I32_FLAG(UTEXT_PROVIDER_WRITABLE); 2271b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2272b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return ut; 2273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI UText * U_EXPORT2 2278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruutext_openConstUnicodeString(UText *ut, const UnicodeString *s, UErrorCode *status) { 2279b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_SUCCESS(*status) && s->isBogus()) { 2280b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // The UnicodeString is bogus, but we still need to detach the UText 2281b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // from whatever it was hooked to before, if anything. 2282b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho utext_openUChars(ut, NULL, 0, status); 2283b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho *status = U_ILLEGAL_ARGUMENT_ERROR; 2284b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return ut; 2285b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 2286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut = utext_setup(ut, 0, status); 2287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // note: use the standard (writable) function table for UnicodeString. 2288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // The flag settings disable writing, so having the functions in 2289b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // the table is harmless. 2290b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_SUCCESS(*status)) { 2291b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->pFuncs = &unistrFuncs; 2292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->context = s; 2293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->providerProperties = I32_FLAG(UTEXT_PROVIDER_STABLE_CHUNKS); 2294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkContents = s->getBuffer(); 2295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkLength = s->length(); 2296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkNativeStart = 0; 2297b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkNativeLimit = ut->chunkLength; 2298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->nativeIndexingLimit = ut->chunkLength; 2299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return ut; 2301b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2302b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2303b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//------------------------------------------------------------------------------ 2304b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 2305b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// UText implementation for const UChar * strings 2306b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 2307b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Use of UText data members: 2308b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// context pointer to UnicodeString 2309b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// a length. -1 if not yet known. 2310b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 2311b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// TODO: support 64 bit lengths. 2312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 2313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//------------------------------------------------------------------------------ 2314b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2315b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CDECL_BEGIN 2316b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2317b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2318b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UText * U_CALLCONV 2319b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruucstrTextClone(UText *dest, const UText * src, UBool deep, UErrorCode * status) { 2320b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // First do a generic shallow clone. 2321b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru dest = shallowTextClone(dest, src, status); 2322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // For deep clones, make a copy of the string. 2324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // The copied storage is owned by the newly created clone. 2325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // A non-NULL pointer in UText.p is the signal to the close() function to delete 2326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // it. 2327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 2328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (deep && U_SUCCESS(*status)) { 2329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru U_ASSERT(utext_nativeLength(dest) < INT32_MAX); 2330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t len = (int32_t)utext_nativeLength(dest); 2331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // The cloned string IS going to be NUL terminated, whether or not the original was. 2333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const UChar *srcStr = (const UChar *)src->context; 2334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UChar *copyStr = (UChar *)uprv_malloc((len+1) * sizeof(UChar)); 2335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (copyStr == NULL) { 2336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *status = U_MEMORY_ALLOCATION_ERROR; 2337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 2338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int64_t i; 2339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (i=0; i<len; i++) { 2340b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru copyStr[i] = srcStr[i]; 2341b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2342b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru copyStr[len] = 0; 2343b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru dest->context = copyStr; 2344b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru dest->providerProperties |= I32_FLAG(UTEXT_PROVIDER_OWNS_TEXT); 2345b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2346b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2347b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return dest; 2348b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2350b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2351b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void U_CALLCONV 2352b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruucstrTextClose(UText *ut) { 2353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Most of the work of close is done by the generic UText framework close. 2354b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // All that needs to be done here is delete the string if the UText 2355b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // owns it. This occurs if the UText was created by cloning. 2356b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ut->providerProperties & I32_FLAG(UTEXT_PROVIDER_OWNS_TEXT)) { 2357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UChar *s = (UChar *)ut->context; 2358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uprv_free(s); 2359b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->context = NULL; 2360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int64_t U_CALLCONV 2366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruucstrTextLength(UText *ut) { 2367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ut->a < 0) { 2368b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // null terminated, we don't yet know the length. Scan for it. 2369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Access is not convenient for doing this 2370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // because the current interation postion can't be changed. 2371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const UChar *str = (const UChar *)ut->context; 2372b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (;;) { 2373b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (str[ut->chunkNativeLimit] == 0) { 2374b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 2375b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2376b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkNativeLimit++; 2377b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2378b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->a = ut->chunkNativeLimit; 2379b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkLength = (int32_t)ut->chunkNativeLimit; 2380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->nativeIndexingLimit = ut->chunkLength; 2381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->providerProperties &= ~I32_FLAG(UTEXT_PROVIDER_LENGTH_IS_EXPENSIVE); 2382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return ut->a; 2384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UBool U_CALLCONV 2388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruucstrTextAccess(UText *ut, int64_t index, UBool forward) { 2389b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const UChar *str = (const UChar *)ut->context; 2390b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // pin the requested index to the bounds of the string, 2392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // and set current iteration position. 2393b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (index<0) { 2394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru index = 0; 2395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else if (index < ut->chunkNativeLimit) { 2396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // The request data is within the chunk as it is known so far. 2397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Put index on a code point boundary. 2398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru U16_SET_CP_START(str, 0, index); 2399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else if (ut->a >= 0) { 2400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // We know the length of this string, and the user is requesting something 2401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // at or beyond the length. Pin the requested index to the length. 2402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru index = ut->a; 2403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 2404b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Null terminated string, length not yet known, and the requested index 2405b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // is beyond where we have scanned so far. 2406b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Scan to 32 UChars beyond the requested index. The strategy here is 2407b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // to avoid fully scanning a long string when the caller only wants to 2408b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // see a few characters at its beginning. 2409b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t scanLimit = (int32_t)index + 32; 2410b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if ((index + 32)>INT32_MAX || (index + 32)<0 ) { // note: int64 expression 2411b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru scanLimit = INT32_MAX; 2412b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2413b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t chunkLimit = (int32_t)ut->chunkNativeLimit; 2415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (; chunkLimit<scanLimit; chunkLimit++) { 2416b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (str[chunkLimit] == 0) { 2417b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // We found the end of the string. Remember it, pin the requested index to it, 2418b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // and bail out of here. 2419b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->a = chunkLimit; 2420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkLength = chunkLimit; 2421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->nativeIndexingLimit = chunkLimit; 2422b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (index >= chunkLimit) { 2423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru index = chunkLimit; 2424b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 2425b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru U16_SET_CP_START(str, 0, index); 2426b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2427b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2428b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkNativeLimit = chunkLimit; 2429b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->providerProperties &= ~I32_FLAG(UTEXT_PROVIDER_LENGTH_IS_EXPENSIVE); 2430b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru goto breakout; 2431b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2432b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2433b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // We scanned through the next batch of UChars without finding the end. 2434b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru U16_SET_CP_START(str, 0, index); 2435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (chunkLimit == INT32_MAX) { 2436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Scanned to the limit of a 32 bit length. 2437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Forceably trim the overlength string back so length fits in int32 2438b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // TODO: add support for 64 bit strings. 2439b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->a = chunkLimit; 2440b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkLength = chunkLimit; 2441b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->nativeIndexingLimit = chunkLimit; 2442b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (index > chunkLimit) { 2443b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru index = chunkLimit; 2444b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkNativeLimit = chunkLimit; 2446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->providerProperties &= ~I32_FLAG(UTEXT_PROVIDER_LENGTH_IS_EXPENSIVE); 2447b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 2448b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // The endpoint of a chunk must not be left in the middle of a surrogate pair. 2449b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // If the current end is on a lead surrogate, back the end up by one. 2450b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // It doesn't matter if the end char happens to be an unpaired surrogate, 2451b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // and it's simpler not to worry about it. 2452b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U16_IS_LEAD(str[chunkLimit-1])) { 2453b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru --chunkLimit; 2454b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2455b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // Null-terminated chunk with end still unknown. 2456b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // Update the chunk length to reflect what has been scanned thus far. 2457b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // That the full length is still unknown is (still) flagged by 2458b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // ut->a being < 0. 2459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkNativeLimit = chunkLimit; 2460b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ut->nativeIndexingLimit = chunkLimit; 2461b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ut->chunkLength = chunkLimit; 2462b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2464b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querubreakout: 2466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru U_ASSERT(index<=INT32_MAX); 2467b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkOffset = (int32_t)index; 2468b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2469b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Check whether request is at the start or end 2470b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UBool retVal = (forward && index<ut->chunkNativeLimit) || (!forward && index>0); 2471b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return retVal; 2472b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2473b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2474b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2475b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2476b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int32_t U_CALLCONV 2477b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruucstrTextExtract(UText *ut, 2478b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int64_t start, int64_t limit, 2479b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UChar *dest, int32_t destCapacity, 2480b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UErrorCode *pErrorCode) 2481b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 2482b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(U_FAILURE(*pErrorCode)) { 2483b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 0; 2484b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2485b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(destCapacity<0 || (dest==NULL && destCapacity>0) || start>limit) { 2486b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; 2487b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 0; 2488b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2490b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho //const UChar *s=(const UChar *)ut->context; 2491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t si, di; 2492b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2493b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t start32; 2494b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t limit32; 2495b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2496b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Access the start. Does two things we need: 2497b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Pins 'start' to the length of the string, if it came in out-of-bounds. 2498b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Snaps 'start' to the beginning of a code point. 2499b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ucstrTextAccess(ut, start, TRUE); 2500b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho const UChar *s=ut->chunkContents; 2501b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho start32 = ut->chunkOffset; 2502b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t strLength=(int32_t)ut->a; 2504b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (strLength >= 0) { 2505b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru limit32 = pinIndex(limit, strLength); 2506b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 2507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru limit32 = pinIndex(limit, INT32_MAX); 2508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2509b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru di = 0; 2510b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (si=start32; si<limit32; si++) { 2511b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (strLength<0 && s[si]==0) { 2512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Just hit the end of a null-terminated string. 2513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->a = si; // set string length for this UText 2514b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkNativeLimit = si; 2515b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkLength = si; 2516b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->nativeIndexingLimit = si; 2517b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru strLength = si; 2518b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 2519b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2520103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius U_ASSERT(di>=0); /* to ensure di never exceeds INT32_MAX, which must not happen logically */ 2521b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (di<destCapacity) { 2522b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // only store if there is space. 2523b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru dest[di] = s[si]; 2524b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 2525b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (strLength>=0) { 2526b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // We have filled the destination buffer, and the string length is known. 2527b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Cut the loop short. There is no need to scan string termination. 252850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho di = limit32 - start32; 2529b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru si = limit32; 2530b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 2531b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2532b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2533b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru di++; 2534b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2535b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2536b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // If the limit index points to a lead surrogate of a pair, 2537b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // add the corresponding trail surrogate to the destination. 2538b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (si>0 && U16_IS_LEAD(s[si-1]) && 2539b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ((si<strLength || strLength<0) && U16_IS_TRAIL(s[si]))) 2540b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { 2541b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (di<destCapacity) { 2542b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // store only if there is space in the output buffer. 2543b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru dest[di++] = s[si++]; 2544b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2545b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2546b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2547b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Put iteration position at the point just following the extracted text 254850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ut->chunkOffset = uprv_min(strLength, start32 + destCapacity); 2549b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2550b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Add a terminating NUL if space in the buffer permits, 2551b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // and set the error status as required. 2552b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru u_terminateUChars(dest, destCapacity, di, pErrorCode); 2553b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return di; 2554b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2555b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2556fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusstatic const struct UTextFuncs ucstrFuncs = 2557b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 2558b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru sizeof(UTextFuncs), 2559b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 0, 0, 0, // Reserved alignment padding 2560b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ucstrTextClone, 2561b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ucstrTextLength, 2562b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ucstrTextAccess, 2563b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ucstrTextExtract, 2564b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru NULL, // Replace 2565b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru NULL, // Copy 2566b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru NULL, // MapOffsetToNative, 2567b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru NULL, // MapIndexToUTF16, 2568b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ucstrTextClose, 2569b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru NULL, // spare 1 2570b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru NULL, // spare 2 2571b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru NULL, // spare 3 2572b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}; 2573b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2574b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CDECL_END 2575b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2576b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const UChar gEmptyUString[] = {0}; 2577b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2578b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI UText * U_EXPORT2 2579b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruutext_openUChars(UText *ut, const UChar *s, int64_t length, UErrorCode *status) { 2580b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(*status)) { 2581b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return NULL; 2582b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2583b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if(s==NULL && length==0) { 2584b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru s = gEmptyUString; 2585b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 2586b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (s==NULL || length < -1 || length>INT32_MAX) { 2587b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 2588b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return NULL; 2589b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2590b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut = utext_setup(ut, 0, status); 2591b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_SUCCESS(*status)) { 2592b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->pFuncs = &ucstrFuncs; 2593b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->context = s; 2594b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->providerProperties = I32_FLAG(UTEXT_PROVIDER_STABLE_CHUNKS); 2595b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (length==-1) { 2596b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->providerProperties |= I32_FLAG(UTEXT_PROVIDER_LENGTH_IS_EXPENSIVE); 2597b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2598b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->a = length; 2599b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkContents = s; 2600b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkNativeStart = 0; 2601b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkNativeLimit = length>=0? length : 0; 2602b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkLength = (int32_t)ut->chunkNativeLimit; 2603b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkOffset = 0; 2604b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->nativeIndexingLimit = ut->chunkLength; 2605b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2606b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return ut; 2607b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2608b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2609b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2610b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//------------------------------------------------------------------------------ 2611b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 2612b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// UText implementation for text from ICU CharacterIterators 2613b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 2614b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Use of UText data members: 2615b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// context pointer to the CharacterIterator 2616b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// a length of the full text. 2617b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// p pointer to buffer 1 2618b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// b start index of local buffer 1 contents 2619b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// q pointer to buffer 2 2620b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// c start index of local buffer 2 contents 2621b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// r pointer to the character iterator if the UText owns it. 2622b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Null otherwise. 2623b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 2624b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//------------------------------------------------------------------------------ 2625b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define CIBufSize 16 2626b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2627b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CDECL_BEGIN 2628b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void U_CALLCONV 2629b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerucharIterTextClose(UText *ut) { 2630b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Most of the work of close is done by the generic UText framework close. 2631b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // All that needs to be done here is delete the CharacterIterator if the UText 2632b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // owns it. This occurs if the UText was created by cloning. 2633b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru CharacterIterator *ci = (CharacterIterator *)ut->r; 2634b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru delete ci; 2635b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->r = NULL; 2636b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2637b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2638b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int64_t U_CALLCONV 2639b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerucharIterTextLength(UText *ut) { 2640b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return (int32_t)ut->a; 2641b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2642b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2643b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UBool U_CALLCONV 2644b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerucharIterTextAccess(UText *ut, int64_t index, UBool forward) { 2645b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru CharacterIterator *ci = (CharacterIterator *)ut->context; 2646b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2647b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t clippedIndex = (int32_t)index; 2648b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (clippedIndex<0) { 2649b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru clippedIndex=0; 2650b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else if (clippedIndex>=ut->a) { 2651b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru clippedIndex=(int32_t)ut->a; 2652b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2653b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t neededIndex = clippedIndex; 2654b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (!forward && neededIndex>0) { 2655b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // reverse iteration, want the position just before what was asked for. 2656b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru neededIndex--; 2657b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else if (forward && neededIndex==ut->a && neededIndex>0) { 2658b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Forward iteration, don't ask for something past the end of the text. 2659b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru neededIndex--; 2660b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2661b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2662b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Find the native index of the start of the buffer containing what we want. 2663b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru neededIndex -= neededIndex % CIBufSize; 2664b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2665b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UChar *buf = NULL; 2666b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UBool needChunkSetup = TRUE; 2667b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int i; 2668b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ut->chunkNativeStart == neededIndex) { 2669b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // The buffer we want is already the current chunk. 2670b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru needChunkSetup = FALSE; 2671b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else if (ut->b == neededIndex) { 2672b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // The first buffer (buffer p) has what we need. 2673b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru buf = (UChar *)ut->p; 2674b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else if (ut->c == neededIndex) { 2675b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // The second buffer (buffer q) has what we need. 2676b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru buf = (UChar *)ut->q; 2677b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 2678b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Neither buffer already has what we need. 2679b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Load new data from the character iterator. 2680b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Use the buf that is not the current buffer. 2681b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru buf = (UChar *)ut->p; 2682b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ut->p == ut->chunkContents) { 2683b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru buf = (UChar *)ut->q; 2684b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2685b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ci->setIndex(neededIndex); 2686b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (i=0; i<CIBufSize; i++) { 2687b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru buf[i] = ci->nextPostInc(); 2688b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (i+neededIndex > ut->a) { 2689b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 2690b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2691b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2692b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2693b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2694b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // We have a buffer with the data we need. 2695b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Set it up as the current chunk, if it wasn't already. 2696b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (needChunkSetup) { 2697b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkContents = buf; 2698b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkLength = CIBufSize; 2699b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkNativeStart = neededIndex; 2700b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkNativeLimit = neededIndex + CIBufSize; 2701b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ut->chunkNativeLimit > ut->a) { 2702b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkNativeLimit = ut->a; 2703b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkLength = (int32_t)(ut->chunkNativeLimit)-(int32_t)(ut->chunkNativeStart); 2704b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2705b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->nativeIndexingLimit = ut->chunkLength; 2706b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru U_ASSERT(ut->chunkOffset>=0 && ut->chunkOffset<=CIBufSize); 2707b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2708b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkOffset = clippedIndex - (int32_t)ut->chunkNativeStart; 2709b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UBool success = (forward? ut->chunkOffset<ut->chunkLength : ut->chunkOffset>0); 2710b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return success; 2711b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2712b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2713b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UText * U_CALLCONV 2714b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerucharIterTextClone(UText *dest, const UText *src, UBool deep, UErrorCode * status) { 2715b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(*status)) { 2716b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return NULL; 2717b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2718b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2719b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (deep) { 2720b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // There is no CharacterIterator API for cloning the underlying text storage. 2721b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *status = U_UNSUPPORTED_ERROR; 2722b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return NULL; 2723b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 2724b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru CharacterIterator *srcCI =(CharacterIterator *)src->context; 2725b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru srcCI = srcCI->clone(); 2726b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru dest = utext_openCharacterIterator(dest, srcCI, status); 2727b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // cast off const on getNativeIndex. 2728b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // For CharacterIterator based UTexts, this is safe, the operation is const. 2729b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int64_t ix = utext_getNativeIndex((UText *)src); 2730b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru utext_setNativeIndex(dest, ix); 2731b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru dest->r = srcCI; // flags that this UText owns the CharacterIterator 2732b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2733b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return dest; 2734b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2735b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2736b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int32_t U_CALLCONV 2737b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerucharIterTextExtract(UText *ut, 2738b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int64_t start, int64_t limit, 2739b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UChar *dest, int32_t destCapacity, 2740b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UErrorCode *status) 2741b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 2742b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(U_FAILURE(*status)) { 2743b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 0; 2744b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2745b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(destCapacity<0 || (dest==NULL && destCapacity>0) || start>limit) { 2746b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *status=U_ILLEGAL_ARGUMENT_ERROR; 2747b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 0; 2748b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2749b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t length = (int32_t)ut->a; 2750b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t start32 = pinIndex(start, length); 2751b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t limit32 = pinIndex(limit, length); 2752b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t desti = 0; 2753b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t srci; 275450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t copyLimit; 2755b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2756b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru CharacterIterator *ci = (CharacterIterator *)ut->context; 2757b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ci->setIndex32(start32); // Moves ix to lead of surrogate pair, if needed. 2758b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru srci = ci->getIndex(); 275950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho copyLimit = srci; 2760b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru while (srci<limit32) { 2761b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UChar32 c = ci->next32PostInc(); 2762b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t len = U16_LENGTH(c); 2763103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius U_ASSERT(desti+len>0); /* to ensure desti+len never exceeds MAX_INT32, which must not happen logically */ 2764b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (desti+len <= destCapacity) { 2765b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru U16_APPEND_UNSAFE(dest, desti, c); 276650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho copyLimit = srci+len; 2767b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 2768b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru desti += len; 2769b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *status = U_BUFFER_OVERFLOW_ERROR; 2770b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2771b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru srci += len; 2772b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2773fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 277450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho charIterTextAccess(ut, copyLimit, TRUE); 2775b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2776b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru u_terminateUChars(dest, destCapacity, desti, status); 2777b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return desti; 2778b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2779b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2780fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusstatic const struct UTextFuncs charIterFuncs = 2781b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 2782b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru sizeof(UTextFuncs), 2783b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 0, 0, 0, // Reserved alignment padding 2784b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru charIterTextClone, 2785b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru charIterTextLength, 2786b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru charIterTextAccess, 2787b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru charIterTextExtract, 2788b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru NULL, // Replace 2789b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru NULL, // Copy 2790b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru NULL, // MapOffsetToNative, 2791b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru NULL, // MapIndexToUTF16, 2792b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru charIterTextClose, 2793b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru NULL, // spare 1 2794b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru NULL, // spare 2 2795b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru NULL // spare 3 2796b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}; 2797b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CDECL_END 2798b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2799b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2800b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI UText * U_EXPORT2 2801b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruutext_openCharacterIterator(UText *ut, CharacterIterator *ci, UErrorCode *status) { 2802b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(*status)) { 2803b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return NULL; 2804b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2805b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2806b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ci->startIndex() > 0) { 2807b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // No support for CharacterIterators that do not start indexing from zero. 2808b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *status = U_UNSUPPORTED_ERROR; 2809b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return NULL; 2810b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2811b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2812b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Extra space in UText for 2 buffers of CIBufSize UChars each. 2813b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t extraSpace = 2 * CIBufSize * sizeof(UChar); 2814b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut = utext_setup(ut, extraSpace, status); 2815b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_SUCCESS(*status)) { 2816b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->pFuncs = &charIterFuncs; 2817b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->context = ci; 2818b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->providerProperties = 0; 2819b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->a = ci->endIndex(); // Length of text 2820b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->p = ut->pExtra; // First buffer 2821b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->b = -1; // Native index of first buffer contents 2822b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->q = (UChar*)ut->pExtra+CIBufSize; // Second buffer 2823b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->c = -1; // Native index of second buffer contents 2824b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2825b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Initialize current chunk contents to be empty. 2826b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // First access will fault something in. 2827b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Note: The initial nativeStart and chunkOffset must sum to zero 2828b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // so that getNativeIndex() will correctly compute to zero 2829b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // if no call to Access() has ever been made. They can't be both 2830b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // zero without Access() thinking that the chunk is valid. 2831b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkContents = (UChar *)ut->p; 2832b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkNativeStart = -1; 2833b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkOffset = 1; 2834b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkNativeLimit = 0; 2835b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->chunkLength = 0; 2836b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ut->nativeIndexingLimit = ut->chunkOffset; // enables native indexing 2837b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2838b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return ut; 2839b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2840