|  | /* | 
|  | ********************************************************************** | 
|  | *   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; | 
|  | } | 
|  |  | 
|  |  | 
|  |  |