ICU-3944 text access, work in progress

X-SVN-Rev: 17868
This commit is contained in:
Andy Heninger 2005-06-13 05:12:32 +00:00
parent 2832adcd2f
commit 0560bbd46b
5 changed files with 1149 additions and 662 deletions

File diff suppressed because it is too large Load Diff

View File

@ -601,6 +601,7 @@ typedef enum UErrorCode {
U_INVALID_STATE_ERROR = 27, /**< Requested operation can not be completed with ICU in its current state */ U_INVALID_STATE_ERROR = 27, /**< Requested operation can not be completed with ICU in its current state */
U_COLLATOR_VERSION_MISMATCH = 28, /**< Collator version is not compatible with the base version */ U_COLLATOR_VERSION_MISMATCH = 28, /**< Collator version is not compatible with the base version */
U_USELESS_COLLATOR_ERROR = 29, /**< Collator is options only and no base is specified */ U_USELESS_COLLATOR_ERROR = 29, /**< Collator is options only and no base is specified */
U_NO_WRITE_PERMISSION = 30, /**< Attempt to modify read-only or constant data. */
U_STANDARD_ERROR_LIMIT, /**< This must always be the last value to indicate the limit for standard errors */ U_STANDARD_ERROR_LIMIT, /**< This must always be the last value to indicate the limit for standard errors */
/* /*

View File

@ -22,120 +22,239 @@
#include "cmemory.h" #include "cmemory.h"
#include "cstring.h" #include "cstring.h"
U_NAMESPACE_BEGIN
#define I32_FLAG(bitIndex) ((int32_t)1<<(bitIndex)) #define I32_FLAG(bitIndex) ((int32_t)1<<(bitIndex))
/*---------------------------------------------------------------------------
*
* UTextIterator implementation. Note: the most common UTextIterator
* functions are inline, implemented in
* utext.h
*
* ---------------------------------------------------------------------------*/
UTextIterator::UTextIterator(UText *text) { static UBool
t=text; utext_access(UText *ut, int32_t index, UBool forward) {
chunk.sizeOfStruct=(uint16_t)sizeof(UTextChunk); return ut->access(ut, index, forward, &ut->chunk);
chunk.padding=0;
setChunkInvalid(0);
providerProperties=t->properties(t);
} }
// U_DRAFT UBool U_EXPORT2
// setChunkInvalid() This is called when the iterator position is set outside utext_moveIndex(UText *ut, int32_t delta) {
// of the current range of the chunk. The index position is
// kept, but chunk contents are set such that an attempt to
// access data will fail.
void
UTextIterator::setChunkInvalid(int32_t index) {
chunk.contents=NULL;
chunk.length=chunkOffset=0;
chunk.start=chunk.limit=index;
chunk.nonUTF16Indexes=FALSE;
}
UBool
UTextIterator::access(int32_t index, UBool forward) {
chunkOffset=t->access(t, index, forward, &chunk);
if(chunkOffset>=0) {
return TRUE;
} else {
// no chunk available here
// TODO: Possibly cleaner end-of-string bail-out.
setChunkInvalid(index);
return FALSE;
}
}
UBool
UTextIterator::moveIndex(int32_t delta) {
UBool retval = TRUE; UBool retval = TRUE;
if(delta>0) { if(delta>0) {
do { do {
if(chunkOffset>=chunk.length && !access(chunk.limit, TRUE)) { if(ut->chunk.offset>=ut->chunk.length && !utext_access(ut, ut->chunk.limit, TRUE)) {
retval = FALSE; retval = FALSE;
break; break;
} }
U16_FWD_1(chunk.contents, chunkOffset, chunk.length); U16_FWD_1(ut->chunk.contents, ut->chunk.offset, ut->chunk.length);
} while(--delta>0); } while(--delta>0);
} else if (delta<0) { } else if (delta<0) {
do { do {
if(chunkOffset<=0 && !access(chunk.start, FALSE)) { if(ut->chunk.offset<=0 && !utext_access(ut, ut->chunk.start, FALSE)) {
retval = FALSE; retval = FALSE;
break; break;
} }
U16_BACK_1(chunk.contents, 0, chunkOffset); U16_BACK_1(ut->chunk.contents, 0, ut->chunk.offset);
} while(++delta<0); } while(++delta<0);
} else { }
// Delta == 0.
// Need to trim current postion to be within the bounds of the text.
if (chunkOffset>=0 && chunkOffset<chunk.length) {
// Current position is within the current chunk.
// No action needed.
} else if (chunk.start<=0) {
// Current position is <= 0, and outside of the current chunk.
// can only get negative if someone did a setIndex(negative value).
// Trim position back to zero.
setChunkInvalid(0);
} else {
// Current postion is past the current chunk bounds.
// Force trim to length of text by doing a text access.
access(chunk.limit, FALSE);
}
}
return retval; return retval;
} }
int32_t U_DRAFT int32_t U_EXPORT2
UTextIterator::length() { utext_length(UText *ut) {
return t->length(t); return ut->length(ut);
}
U_DRAFT int32_t U_EXPORT2
utext_getIndex(UText *ut) {
if(!ut->chunk.nonUTF16Indexes || ut->chunk.offset==0) {
return ut->chunk.start+ut->chunk.offset;
} else {
return ut->mapOffsetToNative(ut, &ut->chunk, ut->chunk.offset);
}
} }
UChar32 U_DRAFT void U_EXPORT2
UTextIterator::getSupplementary() { utext_setIndex(UText *ut, int32_t index) {
UChar32 c; // TODO - revise for keeping index always valid.
U16_GET(chunk.contents, 0, chunkOffset, chunk.length, c); if(index<ut->chunk.start || ut->chunk.limit<index) {
if (U16_IS_TRAIL(chunk.contents[chunkOffset]) && U_IS_SUPPLEMENTARY(c)) { // The desired position is outside of the current chunk. Invalidate it and
// Incoming position pointed to the trailing supplementary pair. // leave it to next32() or previous32() to access the text
// Move ourselves back to the lead. // in the desired direction.
chunkOffset--; ut->access(ut, index, TRUE, &ut->chunk);
} else if(ut->chunk.nonUTF16Indexes) {
ut->chunk.offset=ut->mapIndexToUTF16(ut, &ut->chunk, index);
} else {
ut->chunk.offset=index-ut->chunk.start;
// Our convention is that the index must always be on a code point boundary.
// If we are somewhere in the middle of a utf-16 buffer, check that new index
// is not in the middle of a surrogate pair.
if (index>ut->chunk.start && index < ut->chunk.limit) { // TODO: clean up end-of-chunk / end of input handling. Everywhere.
UChar c = ut->chunk.contents[ut->chunk.offset];
if (U16_TRAIL(c)) {
utext_current(ut); // force index onto a code point boundary.
}
}
}
}
U_DRAFT UChar32 U_EXPORT2
utext_current(UText *ut) {
UChar32 c = U_SENTINEL;
if (ut->chunk.offset < ut->chunk.length) {
c = ut->chunk.contents[ut->chunk.offset];
if (U16_IS_SURROGATE(c)) {
// looking at a surrogate. Could be unpaired, need to be careful.
// Speed doesn't matter, will be very rare.
UChar32 char16AtIndex = c;
U16_GET(ut->chunk.contents, 0, ut->chunk.offset, ut->chunk.length, c);
if (U16_IS_TRAIL(char16AtIndex) && U_IS_SUPPLEMENTARY(c)) {
// Incoming position pointed to the trailing part of a supplementary pair.
// Move offset to point to the lead surrogate. This is needed because utext_current()
// is used internally to force code point alignment. When called from
// the outside we should always be pre-aligned, but this check doesn't hurt.
ut->chunk.offset--;
}
}
} }
return c; return c;
} }
U_DRAFT UChar32 U_EXPORT2
utext_next32(UText *ut) {
UTextChunk *chunk = &ut->chunk;
int32_t offset = chunk->offset;
UChar32 c = U_SENTINEL;
UBool if (offset >= chunk->length) {
UTextIterator::compare(const UChar *s, int32_t length, UBool codePointOrder) { if (ut->access(ut, chunk->limit, TRUE, chunk) == FALSE) {
goto next32_return;
}
offset = chunk->offset;
}
c = chunk->contents[offset++];
if (U16_IS_SURROGATE(c)) {
// looking at a surrogate. Could be unpaired, need to be careful.
// Speed doesn't matter, will be very rare.
c = utext_current(ut);
if (U_IS_SUPPLEMENTARY(c)) {
offset++;
}
}
chunk->offset = offset;
next32_return:
return c;
}
U_DRAFT UChar32 U_EXPORT2
utext_previous32(UText *ut) {
UTextChunk *chunk = &ut->chunk;
int32_t offset = chunk->offset;
UChar32 c = U_SENTINEL;
if (offset <= 0) {
if (ut->access(ut, chunk->start, FALSE, chunk) == FALSE) {
goto prev32_return;
}
offset = chunk->offset;
}
c = chunk->contents[--offset];
chunk->offset = offset;
if (U16_IS_SURROGATE(c)) {
// Note that utext_current() will move the chunk offset to the lead surrogate
// if we come in referring to trail half of a surrogate pair.
c = utext_current(ut);
}
prev32_return:
return c;
}
U_DRAFT UChar32 U_EXPORT2
utext_next32From(UText *ut, int32_t index) {
int32_t offset; // index into the chunk buffer containing the desired char.
UTextChunk *chunk = &ut->chunk;
UChar32 c = U_SENTINEL;
if(index<chunk->start || index>=chunk->limit) {
if(!ut->access(ut, index, TRUE, chunk)) {
// no chunk available here
goto next32return;
}
offset = chunk->offset;
} else if(chunk->nonUTF16Indexes) {
offset=ut->mapIndexToUTF16(ut, chunk, index);
} else {
offset = index - chunk->start;
}
c = chunk->contents[offset++];
if (U16_IS_SURROGATE(c)) {
// Surrogate code unit. Could be pointing at either half of a pair, or at
// an unpaired surrogate. Let utext_current() do the work. Speed doesn't matter.
chunk->offset = offset;
c = utext_current(ut);
if (U_IS_SUPPLEMENTARY(c)) {
offset++;
}
}
chunk->offset = offset;
next32return:
return c;
}
U_DRAFT UChar32 U_EXPORT2
utext_previous32From(UText *ut, int32_t index) {
int32_t offset; // index into the chunk buffer containing the desired char.
UTextChunk *chunk = &ut->chunk;
UChar32 c = U_SENTINEL;
if(index<=chunk->start || index>chunk->limit) {
if(!ut->access(ut, index, FALSE, chunk)) {
// no chunk available here
goto prev32return;
}
offset = chunk->offset;
} else if(chunk->nonUTF16Indexes) {
offset=ut->mapIndexToUTF16(ut, chunk, index);
} else {
offset = index - chunk->start;
}
offset--;
c = chunk->contents[offset];
chunk->offset = offset;
if (U16_IS_SURROGATE(c)) {
c = utext_current(ut); // get supplementary char if not unpaired surrogate,
// and adjust offset to start.
}
prev32return:
return c;
}
U_DRAFT int32_t U_EXPORT2
utext_extract(UText *ut,
int32_t start, int32_t limit,
UChar *dest, int32_t destCapacity,
UErrorCode *status) {
return ut->extract(ut, start, limit, dest, destCapacity, status);
}
U_DRAFT UBool U_EXPORT2
utext_compare(UText *ut, const UChar *s, int32_t length, UBool codePointOrder) {
int32_t segLength, result; int32_t segLength, result;
if(length<0) { if(length<0) {
@ -146,15 +265,15 @@ UTextIterator::compare(const UChar *s, int32_t length, UBool codePointOrder) {
} }
for(;;) { for(;;) {
// compare starting from the current position in the current chunk // compare starting from the current position in the current chunk
segLength=chunk.length-chunkOffset; segLength=ut->chunk.length-ut->chunk.offset;
if(segLength>length) { if(segLength>length) {
segLength=length; segLength=length;
} }
result=u_strCompare( result=u_strCompare(
chunk.contents+chunkOffset, segLength, ut->chunk.contents+ut->chunk.offset, segLength,
s, length, s, length,
codePointOrder); codePointOrder);
chunkOffset+=segLength; ut->chunk.offset+=segLength;
if(result!=0) { if(result!=0) {
return result; return result;
} }
@ -166,15 +285,13 @@ UTextIterator::compare(const UChar *s, int32_t length, UBool codePointOrder) {
return 0; return 0;
} }
if(!access(chunk.limit, TRUE)) { if(!ut->access(ut, ut->chunk.limit, TRUE, &ut->chunk)) {
// the text ends before the string does // the text ends before the string does
return -1; return -1;
} }
} }
return 0; return 0;
} }
U_NAMESPACE_END
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -265,7 +382,7 @@ utext_setup(UText *ut, int32_t extraSpace, UErrorCode *status) {
} }
U_DRAFT void U_EXPORT2 U_DRAFT UText * U_EXPORT2
utext_close(UText *ut) { utext_close(UText *ut) {
if (ut==NULL || if (ut==NULL ||
ut->magic != UTEXT_MAGIC || ut->magic != UTEXT_MAGIC ||
@ -273,7 +390,7 @@ utext_close(UText *ut) {
{ {
// The supplied ut is not an open UText. // The supplied ut is not an open UText.
// Do nothing. // Do nothing.
return; return ut;
} }
// If the provider gave us a close function, call it now. // If the provider gave us a close function, call it now.
@ -295,11 +412,36 @@ utext_close(UText *ut) {
// tries to reopen another UText using the deleted storage. // tries to reopen another UText using the deleted storage.
ut->magic = 0; ut->magic = 0;
uprv_free(ut); uprv_free(ut);
ut = NULL;
} }
return ut;
} }
//
// resetChunk When an access fails for attempting to get text that is out-of-range
// this function puts the chunk into a benign state with the index at the
// at the requested position.
//
// If there is a pre-existing chunk that is adjacent to the index
// preserve the chunk, otherwise set up a dummy zero length chunk.
//
static void
resetChunk(UTextChunk *chunk, int32_t index) {
if (index==chunk->limit) {
chunk->offset = chunk->length;
} else if (index==chunk->start) {
chunk->offset = 0;
} else {
chunk->length = 0;
chunk->start = index;
chunk->limit = index;
chunk->offset = 0;
}
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -310,7 +452,7 @@ utext_close(UText *ut) {
U_CDECL_BEGIN U_CDECL_BEGIN
static UText * U_CALLCONV static UText * U_CALLCONV
noopTextClone(const UText * /* t */) { noopTextClone(UText * /* dest */, const UText * /*src*/, UBool /*deep*/, UErrorCode * /*status*/) {
return NULL; // not supported return NULL; // not supported
} }
@ -326,10 +468,10 @@ noopTextLength(UText * /* t */) {
return 0; return 0;
} }
static int32_t U_CALLCONV static UBool U_CALLCONV
noopTextAccess(UText * /* t */, int32_t /* index */, UBool /* forward*/, noopTextAccess(UText * /* t */, int32_t /* index */, UBool /* forward*/,
UTextChunk * /* chunk */) { UTextChunk * /* chunk */) {
return -1; return FALSE;
} }
static int32_t U_CALLCONV static int32_t U_CALLCONV
@ -422,7 +564,10 @@ utf8TextLength(UText *ut) {
return ut->b; return ut->b;
} }
static int32_t U_CALLCONV
static UBool U_CALLCONV
utf8TextAccess(UText *ut, int32_t index, UBool forward, UTextChunk *chunk) { utf8TextAccess(UText *ut, int32_t index, UBool forward, UTextChunk *chunk) {
const uint8_t *s8=(const uint8_t *)ut->context; const uint8_t *s8=(const uint8_t *)ut->context;
UChar32 c; UChar32 c;
@ -433,9 +578,16 @@ utf8TextAccess(UText *ut, int32_t index, UBool forward, UTextChunk *chunk) {
UChar *u16buf = ut8e->s; UChar *u16buf = ut8e->s;
int32_t *map = ut8e->map; int32_t *map = ut8e->map;
if (index<0) {
index = 0;
} else if (index>length) {
index = length;
}
if(forward) { if(forward) {
if(length<=index) { if(index >= length) {
return -1; resetChunk(chunk, length);
return FALSE;
} }
chunk->start=index; chunk->start=index;
@ -473,12 +625,14 @@ utf8TextAccess(UText *ut, int32_t index, UBool forward, UTextChunk *chunk) {
chunk->length = i; chunk->length = i;
chunk->limit = index; chunk->limit = index;
ut->q = map; ut->q = map;
return 0; // chunkOffset corresponding to index chunk->offset = 0; // chunkOffset corresponding to index
return TRUE;
} else { } else {
// Reverse Access. The chunk buffer must be filled so as to contain the // Reverse Access. The chunk buffer must be filled so as to contain the
// character preceding the specified index. // character preceding the specified index.
if(index<=0) { if(index<=0) {
return -1; resetChunk(chunk, 0);
return FALSE;
} }
chunk->limit=index; chunk->limit=index;
@ -530,10 +684,11 @@ utf8TextAccess(UText *ut, int32_t index, UBool forward, UTextChunk *chunk) {
chunk->nonUTF16Indexes=TRUE; chunk->nonUTF16Indexes=TRUE;
} }
// Common reverse iteration, for both UTF16 and non-UTIF16 indexes. // Common reverse iteration, for both UTF16 and non-UTIF16 indexes.
chunk->contents=u16buf+i; chunk->contents = u16buf+i;
chunk->length=(UTF8_TEXT_CHUNK_SIZE)-i; chunk->length = (UTF8_TEXT_CHUNK_SIZE)-i;
chunk->start=index; chunk->start = index;
return chunk->length; // chunkOffset corresponding to index chunk->offset = chunk->length; // chunkOffset corresponding to index
return TRUE;
} }
} }
@ -659,16 +814,18 @@ sbcsTextLength(UText *t) {
return ((SBCSText *)t)->length; return ((SBCSText *)t)->length;
} }
static int32_t U_CALLCONV static UBool U_CALLCONV
sbcsTextAccess(UText *t, int32_t index, UBool forward, UTextChunk *chunk) { sbcsTextAccess(UText *ut, int32_t index, UBool forward, UTextChunk *chunk) {
SBCSText *ts=(SBCSText *)t; SBCSText *ts=(SBCSText *)ut;
const uint8_t *s8=(const uint8_t *)ts->context; const uint8_t *s8=(const uint8_t *)ts->context;
int32_t i, count, length=ts->length; int32_t i, count, length=ts->length;
chunk->nonUTF16Indexes=FALSE; chunk->nonUTF16Indexes=FALSE;
if(forward) { if(forward) {
if(length<=index) { if(length<=index) {
return -1; resetChunk(chunk, length);
return FALSE;
} }
count=length-index; count=length-index;
@ -682,10 +839,12 @@ sbcsTextAccess(UText *t, int32_t index, UBool forward, UTextChunk *chunk) {
chunk->contents=ts->s; chunk->contents=ts->s;
chunk->length=i; chunk->length=i;
chunk->limit=index; chunk->limit=index;
return 0; // chunkOffset corresponding to index chunk->offset = 0; // chunkOffset corresponding to index
return TRUE;
} else { } else {
if(index<=0) { if(index<=0) {
return -1; resetChunk(chunk, 0);
return FALSE;
} }
if(index<=SBCS_TEXT_CHUNK_SIZE) { if(index<=SBCS_TEXT_CHUNK_SIZE) {
@ -700,7 +859,8 @@ sbcsTextAccess(UText *t, int32_t index, UBool forward, UTextChunk *chunk) {
chunk->contents=ts->s; chunk->contents=ts->s;
chunk->length=count; chunk->length=count;
chunk->start=index; chunk->start=index;
return count; // chunkOffset corresponding to index chunk->offset=count; // chunkOffset corresponding to index
return TRUE;
} }
} }
@ -1103,7 +1263,9 @@ U_CDECL_BEGIN
*/ */
static UText * U_CALLCONV static UText * U_CALLCONV
unistrTextClone(const UText *t) { unistrTextClone(UText * /* dest */, const UText * /*src*/, UBool /*deep*/, UErrorCode * /*status*/) {
// TODO: fix this.
#if 0
UText *t2=(UText *)uprv_malloc(sizeof(UText)); UText *t2=(UText *)uprv_malloc(sizeof(UText));
if(t2!=NULL) { if(t2!=NULL) {
*t2=*t; *t2=*t;
@ -1114,6 +1276,8 @@ unistrTextClone(const UText *t) {
} }
} }
return t2; return t2;
#endif
return NULL;
} }
static int32_t U_CALLCONV static int32_t U_CALLCONV
@ -1129,31 +1293,37 @@ unistrTextLength(UText *t) {
return ((const UnicodeString *)t->context)->length(); return ((const UnicodeString *)t->context)->length();
} }
static int32_t U_CALLCONV
unistrTextAccess(UText *t, int32_t index, UBool forward, UTextChunk *chunk) {
const UnicodeString *us=(const UnicodeString *)t->context;
int32_t length=us->length();
if (forward) { static UBool U_CALLCONV
if (index<0 || index>=length) { unistrTextAccess(UText *ut, int32_t index, UBool forward, UTextChunk *chunk) {
// Forward iteration. Character after index position must exist. const UnicodeString *us = (const UnicodeString *)ut->context;
return -1; int32_t length = us->length();
}
} else { if (chunk->limit != length) {
if (index<=0 || index>length) { // This chunk is not yet set up. Do it now.
// Reverse iteration. Character before index position must exist. chunk->contents=us->getBuffer();
return -1; chunk->length=length;
} chunk->start=0;
chunk->limit=length;
chunk->nonUTF16Indexes=FALSE;
} }
// pin the requested index to the bounds of the string,
// and set current iteration position.
if (index<0) {
index = 0;
} else if (index>length) {
index = length;
}
chunk->offset = index;
chunk->contents=us->getBuffer(); // Check whether request is at the start or end
chunk->length=length; UBool retVal = (forward && index<length) || (!forward && index>0);
chunk->start=0; return retVal;
chunk->limit=length;
chunk->nonUTF16Indexes=FALSE;
return index; // chunkOffset corresponding to index
} }
static int32_t U_CALLCONV static int32_t U_CALLCONV
unistrTextExtract(UText *t, unistrTextExtract(UText *t,
int32_t start, int32_t limit, int32_t start, int32_t limit,
@ -1188,7 +1358,6 @@ static int32_t U_CALLCONV
unistrTextReplace(UText *t, unistrTextReplace(UText *t,
int32_t start, int32_t limit, int32_t start, int32_t limit,
const UChar *src, int32_t length, const UChar *src, int32_t length,
UTextChunk *chunk,
UErrorCode *pErrorCode) { UErrorCode *pErrorCode) {
UnicodeString *us=(UnicodeString *)t->context; UnicodeString *us=(UnicodeString *)t->context;
const UChar *oldBuffer = NULL; const UChar *oldBuffer = NULL;
@ -1205,16 +1374,11 @@ unistrTextReplace(UText *t,
*pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR; *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
return 0; return 0;
} }
// prepare
if(chunk!=NULL) {
oldBuffer=us->getBuffer(); // for chunk invalidation
}
// replace // replace
us->replace(start, limit-start, src, length); us->replace(start, limit-start, src, length);
// post-processing
if(chunk!=NULL && oldBuffer!=us->getBuffer()) { // TODO: update chunk, set our iteration position.
chunk->contents=NULL;
}
return us->length()-oldLength; return us->length()-oldLength;
} }
@ -1223,7 +1387,6 @@ unistrTextCopy(UText *t,
int32_t start, int32_t limit, int32_t start, int32_t limit,
int32_t destIndex, int32_t destIndex,
UBool move, UBool move,
UTextChunk *chunk,
UErrorCode *pErrorCode) { UErrorCode *pErrorCode) {
UnicodeString *us=(UnicodeString *)t->context; UnicodeString *us=(UnicodeString *)t->context;
const UChar *oldBuffer = NULL; const UChar *oldBuffer = NULL;
@ -1239,9 +1402,6 @@ unistrTextCopy(UText *t,
*pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR; *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
return; return;
} }
if(chunk!=NULL) {
oldBuffer=us->getBuffer(); // for chunk invalidation
}
if(move) { if(move) {
// move: copy to destIndex, then replace original with nothing // move: copy to destIndex, then replace original with nothing
int32_t segLength=limit-start; int32_t segLength=limit-start;
@ -1254,9 +1414,7 @@ unistrTextCopy(UText *t,
// copy // copy
us->copy(start, limit, destIndex); us->copy(start, limit, destIndex);
} }
if(chunk!=NULL && oldBuffer!=us->getBuffer()) { // TODO: update chunk description, set iteration position.
chunk->contents=NULL;
}
} }
U_CDECL_END U_CDECL_END

View File

@ -100,7 +100,8 @@ _uErrorName[U_STANDARD_ERROR_LIMIT]={
"U_INVARIANT_CONVERSION_ERROR", "U_INVARIANT_CONVERSION_ERROR",
"U_INVALID_STATE_ERROR", "U_INVALID_STATE_ERROR",
"U_COLLATOR_VERSION_MISMATCH", "U_COLLATOR_VERSION_MISMATCH",
"U_USELESS_COLLATOR_ERROR" "U_USELESS_COLLATOR_ERROR",
"U_NO_WRITE_PERMISSION"
}; };
static const char * const static const char * const
_uFmtErrorName[U_FMT_PARSE_ERROR_LIMIT - U_FMT_PARSE_ERROR_START] = { _uFmtErrorName[U_FMT_PARSE_ERROR_LIMIT - U_FMT_PARSE_ERROR_START] = {

View File

@ -151,7 +151,6 @@ void UTextTest::TestAccess(const UnicodeString &us, UText *ut, int cpCount, m *c
// Iterate forwards, verify that we get the correct code points // Iterate forwards, verify that we get the correct code points
// at the correct native offsets. // at the correct native offsets.
// //
UTextIterator it(ut);
int i = 0; int i = 0;
int index; int index;
int expectedIndex = 0; int expectedIndex = 0;
@ -160,39 +159,54 @@ void UTextTest::TestAccess(const UnicodeString &us, UText *ut, int cpCount, m *c
UChar32 foundC; UChar32 foundC;
int32_t len; int32_t len;
UTextIterator uti(ut);
for (i=0; i<cpCount; i++) { for (i=0; i<cpCount; i++) {
expectedIndex = cpMap[i].nativeIdx; expectedIndex = cpMap[i].nativeIdx;
foundIndex = uti.getIndex(); foundIndex = utext_getIndex(ut);
TEST_ASSERT(expectedIndex == foundIndex); TEST_ASSERT(expectedIndex == foundIndex);
expectedC = cpMap[i].cp; expectedC = cpMap[i].cp;
foundC = uti.next32(); foundC = utext_next32(ut);
TEST_ASSERT(expectedC == foundC); TEST_ASSERT(expectedC == foundC);
if (gFailed) { if (gFailed) {
return; return;
} }
} }
foundC = uti.next32(); foundC = utext_next32(ut);
TEST_ASSERT(foundC == U_SENTINEL); TEST_ASSERT(foundC == U_SENTINEL);
// Repeat above, using macros
utext_setIndex(ut, 0);
for (i=0; i<cpCount; i++) {
expectedIndex = cpMap[i].nativeIdx;
foundIndex = utext_getIndex(ut);
TEST_ASSERT(expectedIndex == foundIndex);
expectedC = cpMap[i].cp;
foundC = UTEXT_NEXT32(ut);
TEST_ASSERT(expectedC == foundC);
if (gFailed) {
return;
}
}
foundC = utext_next32(ut);
TEST_ASSERT(foundC == U_SENTINEL);
// //
// Forward iteration (above) should have left index at the // Forward iteration (above) should have left index at the
// end of the input, which should == length(). // end of the input, which should == length().
// //
len = uti.length(); len = utext_length(ut);
foundIndex = uti.getIndex(); foundIndex = utext_getIndex(ut);
TEST_ASSERT(len == foundIndex); TEST_ASSERT(len == foundIndex);
// //
// Iterate backwards over entire test string // Iterate backwards over entire test string
// //
len = uti.getIndex(); len = utext_getIndex(ut);
uti.setIndex(len); utext_setIndex(ut, len);
for (i=cpCount-1; i>=0; i--) { for (i=cpCount-1; i>=0; i--) {
expectedC = cpMap[i].cp; expectedC = cpMap[i].cp;
expectedIndex = cpMap[i].nativeIdx; expectedIndex = cpMap[i].nativeIdx;
foundC = uti.previous32(); foundC = utext_previous32(ut);
foundIndex = uti.getIndex(); foundIndex = utext_getIndex(ut);
TEST_ASSERT(expectedIndex == foundIndex); TEST_ASSERT(expectedIndex == foundIndex);
TEST_ASSERT(expectedC == foundC); TEST_ASSERT(expectedC == foundC);
if (gFailed) { if (gFailed) {
@ -204,12 +218,12 @@ void UTextTest::TestAccess(const UnicodeString &us, UText *ut, int cpCount, m *c
// Backwards iteration, above, should have left our iterator // Backwards iteration, above, should have left our iterator
// position at zero, and continued backwards iterationshould fail. // position at zero, and continued backwards iterationshould fail.
// //
foundIndex = uti.getIndex(); foundIndex = utext_getIndex(ut);
TEST_ASSERT(foundIndex == 0); TEST_ASSERT(foundIndex == 0);
foundC = uti.previous32(); foundC = utext_previous32(ut);
TEST_ASSERT(foundC == U_SENTINEL); TEST_ASSERT(foundC == U_SENTINEL);
foundIndex = uti.getIndex(); foundIndex = utext_getIndex(ut);
TEST_ASSERT(foundIndex == 0); TEST_ASSERT(foundIndex == 0);
if (gFailed) { if (gFailed) {
return; return;
@ -223,7 +237,7 @@ void UTextTest::TestAccess(const UnicodeString &us, UText *ut, int cpCount, m *c
cpIndex = (cpIndex + 9973) % cpCount; cpIndex = (cpIndex + 9973) % cpCount;
index = cpMap[cpIndex].nativeIdx; index = cpMap[cpIndex].nativeIdx;
expectedC = cpMap[cpIndex].cp; expectedC = cpMap[cpIndex].cp;
foundC = uti.next32From(index); foundC = utext_next32From(ut, index);
TEST_ASSERT(expectedC == foundC); TEST_ASSERT(expectedC == foundC);
TEST_ASSERT(expectedIndex == foundIndex); TEST_ASSERT(expectedIndex == foundIndex);
if (gFailed) { if (gFailed) {
@ -236,7 +250,7 @@ void UTextTest::TestAccess(const UnicodeString &us, UText *ut, int cpCount, m *c
cpIndex = (cpIndex + 9973) % cpCount; cpIndex = (cpIndex + 9973) % cpCount;
index = cpMap[cpIndex+1].nativeIdx; index = cpMap[cpIndex+1].nativeIdx;
expectedC = cpMap[cpIndex].cp; expectedC = cpMap[cpIndex].cp;
foundC = uti.previous32From(index); foundC = utext_previous32From(ut, index);
TEST_ASSERT(expectedC == foundC); TEST_ASSERT(expectedC == foundC);
TEST_ASSERT(expectedIndex == foundIndex); TEST_ASSERT(expectedIndex == foundIndex);
if (gFailed) { if (gFailed) {
@ -249,42 +263,42 @@ void UTextTest::TestAccess(const UnicodeString &us, UText *ut, int cpCount, m *c
// //
// Walk through frontwards, incrementing by one // Walk through frontwards, incrementing by one
uti.setIndex(0); utext_setIndex(ut, 0);
for (i=1; i<=cpCount; i++) { for (i=1; i<=cpCount; i++) {
uti.moveIndex(1); utext_moveIndex(ut, 1);
index = uti.getIndex(); index = utext_getIndex(ut);
expectedIndex = cpMap[i].nativeIdx; expectedIndex = cpMap[i].nativeIdx;
TEST_ASSERT(expectedIndex == index); TEST_ASSERT(expectedIndex == index);
} }
// Walk through frontwards, incrementing by two // Walk through frontwards, incrementing by two
uti.setIndex(0); utext_setIndex(ut, 0);
for (i=2; i<cpCount; i+=2) { for (i=2; i<cpCount; i+=2) {
uti.moveIndex(2); utext_moveIndex(ut, 2);
index = uti.getIndex(); index = utext_getIndex(ut);
expectedIndex = cpMap[i].nativeIdx; expectedIndex = cpMap[i].nativeIdx;
TEST_ASSERT(expectedIndex == index); TEST_ASSERT(expectedIndex == index);
} }
// walk through the string backwards, decrementing by one. // walk through the string backwards, decrementing by one.
i = cpMap[cpCount].nativeIdx; i = cpMap[cpCount].nativeIdx;
uti.setIndex(i); utext_setIndex(ut, i);
for (i=cpCount; i>=0; i--) { for (i=cpCount; i>=0; i--) {
expectedIndex = cpMap[i].nativeIdx; expectedIndex = cpMap[i].nativeIdx;
index = uti.getIndex(); index = utext_getIndex(ut);
TEST_ASSERT(expectedIndex == index); TEST_ASSERT(expectedIndex == index);
uti.moveIndex(-1); utext_moveIndex(ut, -1);
} }
// walk through backwards, decrementing by three // walk through backwards, decrementing by three
i = cpMap[cpCount].nativeIdx; i = cpMap[cpCount].nativeIdx;
uti.setIndex(i); utext_setIndex(ut, i);
for (i=cpCount; i>=0; i-=3) { for (i=cpCount; i>=0; i-=3) {
expectedIndex = cpMap[i].nativeIdx; expectedIndex = cpMap[i].nativeIdx;
index = uti.getIndex(); index = utext_getIndex(ut);
TEST_ASSERT(expectedIndex == index); TEST_ASSERT(expectedIndex == index);
uti.moveIndex(-3); utext_moveIndex(ut, -3);
} }
@ -295,20 +309,20 @@ void UTextTest::TestAccess(const UnicodeString &us, UText *ut, int cpCount, m *c
UChar *buf = new UChar[bufSize]; UChar *buf = new UChar[bufSize];
status = U_ZERO_ERROR; status = U_ZERO_ERROR;
expectedLen = us.length(); expectedLen = us.length();
len = ut->extract(ut, 0, utlen, buf, bufSize, &status); len = utext_extract(ut, 0, utlen, buf, bufSize, &status);
TEST_SUCCESS(status); TEST_SUCCESS(status);
TEST_ASSERT(len == expectedLen); TEST_ASSERT(len == expectedLen);
int compareResult = us.compare(buf, -1); int compareResult = us.compare(buf, -1);
TEST_ASSERT(compareResult == 0); TEST_ASSERT(compareResult == 0);
status = U_ZERO_ERROR; status = U_ZERO_ERROR;
len = ut->extract(ut, 0, utlen, NULL, 0, &status); len = utext_extract(ut, 0, utlen, NULL, 0, &status);
TEST_ASSERT(status == U_BUFFER_OVERFLOW_ERROR) TEST_ASSERT(status == U_BUFFER_OVERFLOW_ERROR)
TEST_ASSERT(len == expectedLen); TEST_ASSERT(len == expectedLen);
status = U_ZERO_ERROR; status = U_ZERO_ERROR;
u_memset(buf, 0x5555, bufSize); u_memset(buf, 0x5555, bufSize);
len = ut->extract(ut, 0, utlen, buf, 1, &status); len = utext_extract(ut, 0, utlen, buf, 1, &status);
if (us.length() == 0) { if (us.length() == 0) {
TEST_SUCCESS(status); TEST_SUCCESS(status);
TEST_ASSERT(buf[0] == 0); TEST_ASSERT(buf[0] == 0);