blob: 5f04004dccdd1466c534910df33317b33c0580c2 [file] [log] [blame]
/*
**********************************************************************
* Copyright (C) 1999-2000 IBM and others. All rights reserved.
**********************************************************************
* Date Name Description
* 03/22/2000 helena Creation.
**********************************************************************
*/
#include "unicode/brkiter.h"
#include "unicode/schriter.h"
#include "srchiter.h"
int32_t const SearchIterator::DONE = -1;
int32_t const SearchIterator::BEFORE = -2;
SearchIterator::SearchIterator(void) :
index(0),
length(0),
target(0),
backward(FALSE), /* going forward */
breaker(NULL),
overlap(TRUE)
{
UErrorCode status = U_ZERO_ERROR;
this->breaker = BreakIterator::createCharacterInstance(Locale::getDefault(), status);
if (U_FAILURE(status)) return;
}
SearchIterator::SearchIterator(CharacterIterator* target,
BreakIterator* breaker) :
index(0),
length(0),
target(0),
backward(FALSE), /* going forward */
breaker(NULL),
overlap(TRUE)
{
this->target = target;
this->breaker = breaker;
this->breaker->adoptText(this->target);
index = this->target->startIndex();
length = 0;
}
SearchIterator::SearchIterator(const SearchIterator& other) :
length(other.length),
target(0),
backward(other.backward), /* going forward */
breaker(NULL),
overlap(other.overlap)
{
index = other.target->startIndex();
this->target = other.target->clone();
this->breaker = ((BreakIterator&)other.breaker).clone();
this->breaker->adoptText(this->target);
}
SearchIterator::~SearchIterator()
{
// deletion of breaker will delete target
if (breaker != NULL) {
delete breaker;
breaker = 0;
}
}
UBool SearchIterator::operator == (const SearchIterator& that) const
{
if (this == &that) return TRUE;
if (*that.breaker != *breaker) return FALSE;
else if (*that.target != *target) return FALSE;
else if (that.backward != backward) return FALSE;
else if (that.index != index) return FALSE;
else if (that.length != length) return FALSE;
else if (that.overlap != overlap) return FALSE;
else return TRUE;
}
int32_t SearchIterator::first(void)
{
setIndex(SearchIterator::BEFORE);
return next();
}
int32_t SearchIterator::following(int32_t pos)
{
setIndex(pos);
return next();
}
int32_t SearchIterator::last(void)
{
setIndex(SearchIterator::DONE);
return previous();
}
int32_t SearchIterator::preceding(int32_t pos)
{
setIndex(pos);
return previous();
}
int32_t SearchIterator::next(void)
{
if (index == SearchIterator::BEFORE){
// Starting at the beginning of the text
index = target->startIndex();
} else if (index == SearchIterator::DONE) {
return SearchIterator::DONE;
} else if (length > 0) {
// Finding the next match after a previous one
index += overlap ? 1 : length;
}
index -= 1;
backward = FALSE;
do {
UErrorCode status = U_ZERO_ERROR;
length = 0;
index = handleNext(index + 1, status);
if (U_FAILURE(status))
{
return SearchIterator::DONE;
}
} while (index != SearchIterator::DONE && !isBreakUnit(index, index+length));
return index;
}
int32_t SearchIterator::previous(void)
{
if (index == SearchIterator::DONE) {
index = target->endIndex();
} else if (index == SearchIterator::BEFORE) {
return SearchIterator::DONE;
} else if (length > 0) {
// Finding the previous match before a following one
index = overlap ? index + length - 1 : index;
}
index += 1;
backward = TRUE;
do {
UErrorCode status = U_ZERO_ERROR;
length = 0;
index = handlePrev(index - 1, status);
if (U_FAILURE(status))
{
return SearchIterator::DONE;
}
} while (index != SearchIterator::DONE && !isBreakUnit(index, index+length));
if (index == SearchIterator::DONE) {
index = SearchIterator::BEFORE;
}
return getIndex();
}
int32_t SearchIterator::getIndex() const
{
return index == SearchIterator::BEFORE ? SearchIterator::DONE : index;
}
void SearchIterator::setOverlapping(UBool allowOverlap)
{
overlap = allowOverlap;
}
UBool SearchIterator::isOverlapping(void) const
{
return overlap;
}
int32_t SearchIterator::getMatchLength(void) const
{
return length;
}
void SearchIterator::reset(void)
{
length = 0;
if (backward == FALSE) {
index = 0;
target->setToStart();
breaker->first();
} else {
index = SearchIterator::DONE;
target->setToEnd();
breaker->last();
}
overlap = TRUE;
}
void SearchIterator::setBreakIterator(const BreakIterator* iterator)
{
CharacterIterator *buffer = target->clone();
delete breaker;
breaker = iterator->clone();
breaker->adoptText(buffer);
}
const BreakIterator& SearchIterator::getBreakIterator(void) const
{
return *breaker;
}
void SearchIterator::setTarget(const UnicodeString& newText)
{
if (target != NULL && target->getDynamicClassID()
== StringCharacterIterator::getStaticClassID()) {
((StringCharacterIterator*)target)->setText(newText);
}
else {
delete target;
target = new StringCharacterIterator(newText);
target->first();
breaker->adoptText(target);
}
}
void SearchIterator::adoptTarget(CharacterIterator* iterator) {
target = iterator;
breaker->adoptText(target);
setIndex(SearchIterator::BEFORE);
}
const CharacterIterator& SearchIterator::getTarget(void) const
{
SearchIterator* nonConstThis = (SearchIterator*)this;
// The iterator is initialized pointing to no text at all, so if this
// function is called while we're in that state, we have to fudge an
// an iterator to return.
if (nonConstThis->target == NULL)
nonConstThis->target = new StringCharacterIterator("");
return *nonConstThis->target;
}
void SearchIterator::getMatchedText(UnicodeString& result)
{
result.remove();
if (length > 0) {
int i = 0;
for (UChar c = target->setIndex(index); i < length; c = target->next(), i++)
{
result += c;
}
}
}
void SearchIterator::setMatchLength(int32_t length)
{
this->length = length;
}
void SearchIterator::setIndex(int32_t pos) {
index = pos;
length = 0;
}
UBool SearchIterator::isBreakUnit(int32_t start,
int32_t end)
{
if (breaker == NULL) {
return TRUE;
}
UBool startBound = breaker->isBoundary(start);
UBool endBound = (end == target->endIndex()) || breaker->isBoundary(end);
return startBound && endBound;
}