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