int32_t StringSearch::handlePrev(int32_t position, UErrorCode &status) { // values passed here are already in the pre-shift position if (U_SUCCESS(status)) { if (m_strsrch_->pattern.CELength == 0) { m_search_->matchedIndex = (m_search_->matchedIndex == USEARCH_DONE ? getOffset() : m_search_->matchedIndex); if (m_search_->matchedIndex == 0) { setMatchNotFound(); } else { m_search_->matchedIndex --; ucol_setOffset(m_strsrch_->textIter, m_search_->matchedIndex, &status); m_search_->matchedLength = 0; } } else { // looking at usearch.cpp, this part is shifted out to // StringSearch instead of SearchIterator because m_strsrch_ is // not accessible in SearchIterator if (!m_search_->isOverlap && position - m_strsrch_->pattern.defaultShiftSize < 0) { setMatchNotFound(); return USEARCH_DONE; } while (TRUE) { if (m_search_->isCanonicalMatch) { // can't use exact here since extra accents are allowed. usearch_handlePreviousCanonical(m_strsrch_, &status); } else { usearch_handlePreviousExact(m_strsrch_, &status); } if (U_FAILURE(status)) { return USEARCH_DONE; } if (m_breakiterator_ == NULL #if !UCONFIG_NO_BREAK_ITERATION || m_search_->matchedIndex == USEARCH_DONE || (m_breakiterator_->isBoundary(m_search_->matchedIndex) && m_breakiterator_->isBoundary(m_search_->matchedIndex + m_search_->matchedLength)) #endif ) { return m_search_->matchedIndex; } } } return m_search_->matchedIndex; } return USEARCH_DONE; }
void SearchIterator::reset() { UErrorCode status = U_ZERO_ERROR; setMatchNotFound(); setOffset(0, status); m_search_->isOverlap = FALSE; m_search_->isCanonicalMatch = FALSE; m_search_->isForwardSearching = TRUE; m_search_->reset = TRUE; }
int32_t SearchIterator::previous(UErrorCode &status) { if (U_SUCCESS(status)) { int32_t offset; if (m_search_->reset) { offset = m_search_->textLength; m_search_->isForwardSearching = FALSE; m_search_->reset = FALSE; setOffset(offset, status); } else { offset = getOffset(); } int32_t matchindex = m_search_->matchedIndex; if (m_search_->isForwardSearching == TRUE) { // switching direction. // if matchedIndex == USEARCH_DONE, it means that either a // setOffset has been called or that next ran off the text // string. the iterator would have been set to offset textLength if // a match is not found. m_search_->isForwardSearching = FALSE; if (matchindex != USEARCH_DONE) { return matchindex; } } else { if (offset == 0 || matchindex == 0) { // not enough characters to match setMatchNotFound(); return USEARCH_DONE; } } if (matchindex != USEARCH_DONE) { if (m_search_->isOverlap) { matchindex += m_search_->matchedLength - 2; } return handlePrev(matchindex, status); } return handlePrev(offset, status); } return USEARCH_DONE; }
int32_t SearchIterator::next(UErrorCode &status) { if (U_SUCCESS(status)) { int32_t offset = getOffset(); int32_t matchindex = m_search_->matchedIndex; int32_t matchlength = m_search_->matchedLength; m_search_->reset = FALSE; if (m_search_->isForwardSearching == TRUE) { int32_t textlength = m_search_->textLength; if (offset == textlength || matchindex == textlength || (matchindex != USEARCH_DONE && matchindex + matchlength >= textlength)) { // not enough characters to match setMatchNotFound(); return USEARCH_DONE; } } else { // switching direction. // if matchedIndex == USEARCH_DONE, it means that either a // setOffset has been called or that previous ran off the text // string. the iterator would have been set to offset 0 if a // match is not found. m_search_->isForwardSearching = TRUE; if (m_search_->matchedIndex != USEARCH_DONE) { // there's no need to set the collation element iterator // the next call to next will set the offset. return matchindex; } } if (matchlength > 0) { // if matchlength is 0 we are at the start of the iteration if (m_search_->isOverlap) { offset ++; } else { offset += matchlength; } } return handleNext(offset, status); } return USEARCH_DONE; }
int32_t StringSearch::handleNext(int32_t position, UErrorCode &status) { // values passed here are already in the pre-shift position if (U_SUCCESS(status)) { if (m_strsrch_->pattern.CELength == 0) { m_search_->matchedIndex = m_search_->matchedIndex == USEARCH_DONE ? getOffset() : m_search_->matchedIndex + 1; m_search_->matchedLength = 0; ucol_setOffset(m_strsrch_->textIter, m_search_->matchedIndex, &status); if (m_search_->matchedIndex == m_search_->textLength) { m_search_->matchedIndex = USEARCH_DONE; } } else { // looking at usearch.cpp, this part is shifted out to // StringSearch instead of SearchIterator because m_strsrch_ is // not accessible in SearchIterator if (position + m_strsrch_->pattern.defaultShiftSize > m_search_->textLength) { setMatchNotFound(); return USEARCH_DONE; } if (m_search_->matchedLength <= 0) { // the flipping direction issue has already been handled // in next() // for boundary check purposes. this will ensure that the // next match will not preceed the current offset // note search->matchedIndex will always be set to something // in the code m_search_->matchedIndex = position - 1; } ucol_setOffset(m_strsrch_->textIter, position, &status); while (TRUE) { if (m_search_->isCanonicalMatch) { // can't use exact here since extra accents are allowed. usearch_handleNextCanonical(m_strsrch_, &status); } else { usearch_handleNextExact(m_strsrch_, &status); } if (U_FAILURE(status)) { return USEARCH_DONE; } if (m_breakiterator_ == NULL #if !UCONFIG_NO_BREAK_ITERATION || m_search_->matchedIndex == USEARCH_DONE || (m_breakiterator_->isBoundary(m_search_->matchedIndex) && m_breakiterator_->isBoundary(m_search_->matchedIndex + m_search_->matchedLength)) #endif ) { if (m_search_->matchedIndex == USEARCH_DONE) { ucol_setOffset(m_strsrch_->textIter, m_search_->textLength, &status); } else { ucol_setOffset(m_strsrch_->textIter, m_search_->matchedIndex, &status); } return m_search_->matchedIndex; } } } } return USEARCH_DONE; }