12e5b6d6dSopenharmony_ci// © 2016 and later: Unicode, Inc. and others.
22e5b6d6dSopenharmony_ci// License & terms of use: http://www.unicode.org/copyright.html
32e5b6d6dSopenharmony_ci/*
42e5b6d6dSopenharmony_ci**********************************************************************
52e5b6d6dSopenharmony_ci*   Copyright (C) 2001-2014 IBM and others. All rights reserved.
62e5b6d6dSopenharmony_ci**********************************************************************
72e5b6d6dSopenharmony_ci*   Date        Name        Description
82e5b6d6dSopenharmony_ci*  03/22/2000   helena      Creation.
92e5b6d6dSopenharmony_ci**********************************************************************
102e5b6d6dSopenharmony_ci*/
112e5b6d6dSopenharmony_ci
122e5b6d6dSopenharmony_ci#include "unicode/utypes.h"
132e5b6d6dSopenharmony_ci
142e5b6d6dSopenharmony_ci#if !UCONFIG_NO_COLLATION && !UCONFIG_NO_BREAK_ITERATION
152e5b6d6dSopenharmony_ci
162e5b6d6dSopenharmony_ci#include "unicode/stsearch.h"
172e5b6d6dSopenharmony_ci#include "usrchimp.h"
182e5b6d6dSopenharmony_ci#include "cmemory.h"
192e5b6d6dSopenharmony_ci
202e5b6d6dSopenharmony_ciU_NAMESPACE_BEGIN
212e5b6d6dSopenharmony_ci
222e5b6d6dSopenharmony_ciUOBJECT_DEFINE_RTTI_IMPLEMENTATION(StringSearch)
232e5b6d6dSopenharmony_ci
242e5b6d6dSopenharmony_ci// public constructors and destructors -----------------------------------
252e5b6d6dSopenharmony_ci
262e5b6d6dSopenharmony_ciStringSearch::StringSearch(const UnicodeString &pattern,
272e5b6d6dSopenharmony_ci                           const UnicodeString &text,
282e5b6d6dSopenharmony_ci                           const Locale        &locale,
292e5b6d6dSopenharmony_ci                                 BreakIterator *breakiter,
302e5b6d6dSopenharmony_ci                                 UErrorCode    &status) :
312e5b6d6dSopenharmony_ci                           SearchIterator(text, breakiter),
322e5b6d6dSopenharmony_ci                           m_pattern_(pattern)
332e5b6d6dSopenharmony_ci{
342e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
352e5b6d6dSopenharmony_ci        m_strsrch_ = NULL;
362e5b6d6dSopenharmony_ci        return;
372e5b6d6dSopenharmony_ci    }
382e5b6d6dSopenharmony_ci
392e5b6d6dSopenharmony_ci    m_strsrch_ = usearch_open(m_pattern_.getBuffer(), m_pattern_.length(),
402e5b6d6dSopenharmony_ci                              m_text_.getBuffer(), m_text_.length(),
412e5b6d6dSopenharmony_ci                              locale.getName(), (UBreakIterator *)breakiter,
422e5b6d6dSopenharmony_ci                              &status);
432e5b6d6dSopenharmony_ci    uprv_free(m_search_);
442e5b6d6dSopenharmony_ci    m_search_ = NULL;
452e5b6d6dSopenharmony_ci
462e5b6d6dSopenharmony_ci    if (U_SUCCESS(status)) {
472e5b6d6dSopenharmony_ci        // m_search_ has been created by the base SearchIterator class
482e5b6d6dSopenharmony_ci        m_search_        = m_strsrch_->search;
492e5b6d6dSopenharmony_ci    }
502e5b6d6dSopenharmony_ci}
512e5b6d6dSopenharmony_ci
522e5b6d6dSopenharmony_ciStringSearch::StringSearch(const UnicodeString     &pattern,
532e5b6d6dSopenharmony_ci                           const UnicodeString     &text,
542e5b6d6dSopenharmony_ci                                 RuleBasedCollator *coll,
552e5b6d6dSopenharmony_ci                                 BreakIterator     *breakiter,
562e5b6d6dSopenharmony_ci                                 UErrorCode        &status) :
572e5b6d6dSopenharmony_ci                           SearchIterator(text, breakiter),
582e5b6d6dSopenharmony_ci                           m_pattern_(pattern)
592e5b6d6dSopenharmony_ci{
602e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
612e5b6d6dSopenharmony_ci        m_strsrch_ = NULL;
622e5b6d6dSopenharmony_ci        return;
632e5b6d6dSopenharmony_ci    }
642e5b6d6dSopenharmony_ci    if (coll == NULL) {
652e5b6d6dSopenharmony_ci        status     = U_ILLEGAL_ARGUMENT_ERROR;
662e5b6d6dSopenharmony_ci        m_strsrch_ = NULL;
672e5b6d6dSopenharmony_ci        return;
682e5b6d6dSopenharmony_ci    }
692e5b6d6dSopenharmony_ci    m_strsrch_ = usearch_openFromCollator(m_pattern_.getBuffer(),
702e5b6d6dSopenharmony_ci                                          m_pattern_.length(),
712e5b6d6dSopenharmony_ci                                          m_text_.getBuffer(),
722e5b6d6dSopenharmony_ci                                          m_text_.length(), coll->toUCollator(),
732e5b6d6dSopenharmony_ci                                          (UBreakIterator *)breakiter,
742e5b6d6dSopenharmony_ci                                          &status);
752e5b6d6dSopenharmony_ci    uprv_free(m_search_);
762e5b6d6dSopenharmony_ci    m_search_ = NULL;
772e5b6d6dSopenharmony_ci
782e5b6d6dSopenharmony_ci    if (U_SUCCESS(status)) {
792e5b6d6dSopenharmony_ci        // m_search_ has been created by the base SearchIterator class
802e5b6d6dSopenharmony_ci        m_search_ = m_strsrch_->search;
812e5b6d6dSopenharmony_ci    }
822e5b6d6dSopenharmony_ci}
832e5b6d6dSopenharmony_ci
842e5b6d6dSopenharmony_ciStringSearch::StringSearch(const UnicodeString     &pattern,
852e5b6d6dSopenharmony_ci                                 CharacterIterator &text,
862e5b6d6dSopenharmony_ci                           const Locale            &locale,
872e5b6d6dSopenharmony_ci                                 BreakIterator     *breakiter,
882e5b6d6dSopenharmony_ci                                 UErrorCode        &status) :
892e5b6d6dSopenharmony_ci                           SearchIterator(text, breakiter),
902e5b6d6dSopenharmony_ci                           m_pattern_(pattern)
912e5b6d6dSopenharmony_ci{
922e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
932e5b6d6dSopenharmony_ci        m_strsrch_ = NULL;
942e5b6d6dSopenharmony_ci        return;
952e5b6d6dSopenharmony_ci    }
962e5b6d6dSopenharmony_ci    m_strsrch_ = usearch_open(m_pattern_.getBuffer(), m_pattern_.length(),
972e5b6d6dSopenharmony_ci                              m_text_.getBuffer(), m_text_.length(),
982e5b6d6dSopenharmony_ci                              locale.getName(), (UBreakIterator *)breakiter,
992e5b6d6dSopenharmony_ci                              &status);
1002e5b6d6dSopenharmony_ci    uprv_free(m_search_);
1012e5b6d6dSopenharmony_ci    m_search_ = NULL;
1022e5b6d6dSopenharmony_ci
1032e5b6d6dSopenharmony_ci    if (U_SUCCESS(status)) {
1042e5b6d6dSopenharmony_ci        // m_search_ has been created by the base SearchIterator class
1052e5b6d6dSopenharmony_ci        m_search_ = m_strsrch_->search;
1062e5b6d6dSopenharmony_ci    }
1072e5b6d6dSopenharmony_ci}
1082e5b6d6dSopenharmony_ci
1092e5b6d6dSopenharmony_ciStringSearch::StringSearch(const UnicodeString     &pattern,
1102e5b6d6dSopenharmony_ci                                 CharacterIterator &text,
1112e5b6d6dSopenharmony_ci                                 RuleBasedCollator *coll,
1122e5b6d6dSopenharmony_ci                                 BreakIterator     *breakiter,
1132e5b6d6dSopenharmony_ci                                 UErrorCode        &status) :
1142e5b6d6dSopenharmony_ci                           SearchIterator(text, breakiter),
1152e5b6d6dSopenharmony_ci                           m_pattern_(pattern)
1162e5b6d6dSopenharmony_ci{
1172e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
1182e5b6d6dSopenharmony_ci        m_strsrch_ = NULL;
1192e5b6d6dSopenharmony_ci        return;
1202e5b6d6dSopenharmony_ci    }
1212e5b6d6dSopenharmony_ci    if (coll == NULL) {
1222e5b6d6dSopenharmony_ci        status     = U_ILLEGAL_ARGUMENT_ERROR;
1232e5b6d6dSopenharmony_ci        m_strsrch_ = NULL;
1242e5b6d6dSopenharmony_ci        return;
1252e5b6d6dSopenharmony_ci    }
1262e5b6d6dSopenharmony_ci    m_strsrch_ = usearch_openFromCollator(m_pattern_.getBuffer(),
1272e5b6d6dSopenharmony_ci                                          m_pattern_.length(),
1282e5b6d6dSopenharmony_ci                                          m_text_.getBuffer(),
1292e5b6d6dSopenharmony_ci                                          m_text_.length(), coll->toUCollator(),
1302e5b6d6dSopenharmony_ci                                          (UBreakIterator *)breakiter,
1312e5b6d6dSopenharmony_ci                                          &status);
1322e5b6d6dSopenharmony_ci    uprv_free(m_search_);
1332e5b6d6dSopenharmony_ci    m_search_ = NULL;
1342e5b6d6dSopenharmony_ci
1352e5b6d6dSopenharmony_ci    if (U_SUCCESS(status)) {
1362e5b6d6dSopenharmony_ci        // m_search_ has been created by the base SearchIterator class
1372e5b6d6dSopenharmony_ci        m_search_ = m_strsrch_->search;
1382e5b6d6dSopenharmony_ci    }
1392e5b6d6dSopenharmony_ci}
1402e5b6d6dSopenharmony_ci
1412e5b6d6dSopenharmony_ciStringSearch::StringSearch(const StringSearch &that) :
1422e5b6d6dSopenharmony_ci                       SearchIterator(that.m_text_, that.m_breakiterator_),
1432e5b6d6dSopenharmony_ci                       m_pattern_(that.m_pattern_)
1442e5b6d6dSopenharmony_ci{
1452e5b6d6dSopenharmony_ci    UErrorCode status = U_ZERO_ERROR;
1462e5b6d6dSopenharmony_ci
1472e5b6d6dSopenharmony_ci    // Free m_search_ from the superclass
1482e5b6d6dSopenharmony_ci    uprv_free(m_search_);
1492e5b6d6dSopenharmony_ci    m_search_ = NULL;
1502e5b6d6dSopenharmony_ci
1512e5b6d6dSopenharmony_ci    if (that.m_strsrch_ == NULL) {
1522e5b6d6dSopenharmony_ci        // This was not a good copy
1532e5b6d6dSopenharmony_ci        m_strsrch_ = NULL;
1542e5b6d6dSopenharmony_ci    }
1552e5b6d6dSopenharmony_ci    else {
1562e5b6d6dSopenharmony_ci        // Make a deep copy
1572e5b6d6dSopenharmony_ci        m_strsrch_ = usearch_openFromCollator(m_pattern_.getBuffer(),
1582e5b6d6dSopenharmony_ci                                              m_pattern_.length(),
1592e5b6d6dSopenharmony_ci                                              m_text_.getBuffer(),
1602e5b6d6dSopenharmony_ci                                              m_text_.length(),
1612e5b6d6dSopenharmony_ci                                              that.m_strsrch_->collator,
1622e5b6d6dSopenharmony_ci                                             (UBreakIterator *)that.m_breakiterator_,
1632e5b6d6dSopenharmony_ci                                              &status);
1642e5b6d6dSopenharmony_ci        if (U_SUCCESS(status)) {
1652e5b6d6dSopenharmony_ci            // m_search_ has been created by the base SearchIterator class
1662e5b6d6dSopenharmony_ci            m_search_        = m_strsrch_->search;
1672e5b6d6dSopenharmony_ci        }
1682e5b6d6dSopenharmony_ci    }
1692e5b6d6dSopenharmony_ci}
1702e5b6d6dSopenharmony_ci
1712e5b6d6dSopenharmony_ciStringSearch::~StringSearch()
1722e5b6d6dSopenharmony_ci{
1732e5b6d6dSopenharmony_ci    if (m_strsrch_ != NULL) {
1742e5b6d6dSopenharmony_ci        usearch_close(m_strsrch_);
1752e5b6d6dSopenharmony_ci        m_search_ = NULL;
1762e5b6d6dSopenharmony_ci    }
1772e5b6d6dSopenharmony_ci}
1782e5b6d6dSopenharmony_ci
1792e5b6d6dSopenharmony_ciStringSearch *
1802e5b6d6dSopenharmony_ciStringSearch::clone() const {
1812e5b6d6dSopenharmony_ci    return new StringSearch(*this);
1822e5b6d6dSopenharmony_ci}
1832e5b6d6dSopenharmony_ci
1842e5b6d6dSopenharmony_ci// operator overloading ---------------------------------------------
1852e5b6d6dSopenharmony_ciStringSearch & StringSearch::operator=(const StringSearch &that)
1862e5b6d6dSopenharmony_ci{
1872e5b6d6dSopenharmony_ci    if (this != &that) {
1882e5b6d6dSopenharmony_ci        UErrorCode status = U_ZERO_ERROR;
1892e5b6d6dSopenharmony_ci        m_text_          = that.m_text_;
1902e5b6d6dSopenharmony_ci        m_breakiterator_ = that.m_breakiterator_;
1912e5b6d6dSopenharmony_ci        m_pattern_       = that.m_pattern_;
1922e5b6d6dSopenharmony_ci        // all m_search_ in the parent class is linked up with m_strsrch_
1932e5b6d6dSopenharmony_ci        usearch_close(m_strsrch_);
1942e5b6d6dSopenharmony_ci        m_strsrch_ = usearch_openFromCollator(m_pattern_.getBuffer(),
1952e5b6d6dSopenharmony_ci                                              m_pattern_.length(),
1962e5b6d6dSopenharmony_ci                                              m_text_.getBuffer(),
1972e5b6d6dSopenharmony_ci                                              m_text_.length(),
1982e5b6d6dSopenharmony_ci                                              that.m_strsrch_->collator,
1992e5b6d6dSopenharmony_ci                                              NULL, &status);
2002e5b6d6dSopenharmony_ci        // Check null pointer
2012e5b6d6dSopenharmony_ci        if (m_strsrch_ != NULL) {
2022e5b6d6dSopenharmony_ci            m_search_ = m_strsrch_->search;
2032e5b6d6dSopenharmony_ci        }
2042e5b6d6dSopenharmony_ci    }
2052e5b6d6dSopenharmony_ci    return *this;
2062e5b6d6dSopenharmony_ci}
2072e5b6d6dSopenharmony_ci
2082e5b6d6dSopenharmony_cibool StringSearch::operator==(const SearchIterator &that) const
2092e5b6d6dSopenharmony_ci{
2102e5b6d6dSopenharmony_ci    if (this == &that) {
2112e5b6d6dSopenharmony_ci        return true;
2122e5b6d6dSopenharmony_ci    }
2132e5b6d6dSopenharmony_ci    if (SearchIterator::operator ==(that)) {
2142e5b6d6dSopenharmony_ci        StringSearch &thatsrch = (StringSearch &)that;
2152e5b6d6dSopenharmony_ci        return (this->m_pattern_ == thatsrch.m_pattern_ &&
2162e5b6d6dSopenharmony_ci                this->m_strsrch_->collator == thatsrch.m_strsrch_->collator);
2172e5b6d6dSopenharmony_ci    }
2182e5b6d6dSopenharmony_ci    return false;
2192e5b6d6dSopenharmony_ci}
2202e5b6d6dSopenharmony_ci
2212e5b6d6dSopenharmony_ci// public get and set methods ----------------------------------------
2222e5b6d6dSopenharmony_ci
2232e5b6d6dSopenharmony_civoid StringSearch::setOffset(int32_t position, UErrorCode &status)
2242e5b6d6dSopenharmony_ci{
2252e5b6d6dSopenharmony_ci    // status checked in usearch_setOffset
2262e5b6d6dSopenharmony_ci    usearch_setOffset(m_strsrch_, position, &status);
2272e5b6d6dSopenharmony_ci}
2282e5b6d6dSopenharmony_ci
2292e5b6d6dSopenharmony_ciint32_t StringSearch::getOffset(void) const
2302e5b6d6dSopenharmony_ci{
2312e5b6d6dSopenharmony_ci    return usearch_getOffset(m_strsrch_);
2322e5b6d6dSopenharmony_ci}
2332e5b6d6dSopenharmony_ci
2342e5b6d6dSopenharmony_civoid StringSearch::setText(const UnicodeString &text, UErrorCode &status)
2352e5b6d6dSopenharmony_ci{
2362e5b6d6dSopenharmony_ci    if (U_SUCCESS(status)) {
2372e5b6d6dSopenharmony_ci        m_text_ = text;
2382e5b6d6dSopenharmony_ci        usearch_setText(m_strsrch_, text.getBuffer(), text.length(), &status);
2392e5b6d6dSopenharmony_ci    }
2402e5b6d6dSopenharmony_ci}
2412e5b6d6dSopenharmony_ci
2422e5b6d6dSopenharmony_civoid StringSearch::setText(CharacterIterator &text, UErrorCode &status)
2432e5b6d6dSopenharmony_ci{
2442e5b6d6dSopenharmony_ci    if (U_SUCCESS(status)) {
2452e5b6d6dSopenharmony_ci        text.getText(m_text_);
2462e5b6d6dSopenharmony_ci        usearch_setText(m_strsrch_, m_text_.getBuffer(), m_text_.length(), &status);
2472e5b6d6dSopenharmony_ci    }
2482e5b6d6dSopenharmony_ci}
2492e5b6d6dSopenharmony_ci
2502e5b6d6dSopenharmony_ciRuleBasedCollator * StringSearch::getCollator() const
2512e5b6d6dSopenharmony_ci{
2522e5b6d6dSopenharmony_ci    // Note the const_cast. It would be cleaner if this const method returned a const collator.
2532e5b6d6dSopenharmony_ci    return RuleBasedCollator::rbcFromUCollator(const_cast<UCollator *>(m_strsrch_->collator));
2542e5b6d6dSopenharmony_ci}
2552e5b6d6dSopenharmony_ci
2562e5b6d6dSopenharmony_civoid StringSearch::setCollator(RuleBasedCollator *coll, UErrorCode &status)
2572e5b6d6dSopenharmony_ci{
2582e5b6d6dSopenharmony_ci    if (U_SUCCESS(status)) {
2592e5b6d6dSopenharmony_ci        usearch_setCollator(m_strsrch_, coll->toUCollator(), &status);
2602e5b6d6dSopenharmony_ci    }
2612e5b6d6dSopenharmony_ci}
2622e5b6d6dSopenharmony_ci
2632e5b6d6dSopenharmony_civoid StringSearch::setPattern(const UnicodeString &pattern,
2642e5b6d6dSopenharmony_ci                                    UErrorCode    &status)
2652e5b6d6dSopenharmony_ci{
2662e5b6d6dSopenharmony_ci    if (U_SUCCESS(status)) {
2672e5b6d6dSopenharmony_ci        m_pattern_ = pattern;
2682e5b6d6dSopenharmony_ci        usearch_setPattern(m_strsrch_, m_pattern_.getBuffer(), m_pattern_.length(),
2692e5b6d6dSopenharmony_ci                           &status);
2702e5b6d6dSopenharmony_ci    }
2712e5b6d6dSopenharmony_ci}
2722e5b6d6dSopenharmony_ci
2732e5b6d6dSopenharmony_ciconst UnicodeString & StringSearch::getPattern() const
2742e5b6d6dSopenharmony_ci{
2752e5b6d6dSopenharmony_ci    return m_pattern_;
2762e5b6d6dSopenharmony_ci}
2772e5b6d6dSopenharmony_ci
2782e5b6d6dSopenharmony_ci// public methods ----------------------------------------------------
2792e5b6d6dSopenharmony_ci
2802e5b6d6dSopenharmony_civoid StringSearch::reset()
2812e5b6d6dSopenharmony_ci{
2822e5b6d6dSopenharmony_ci    usearch_reset(m_strsrch_);
2832e5b6d6dSopenharmony_ci}
2842e5b6d6dSopenharmony_ci
2852e5b6d6dSopenharmony_ciStringSearch * StringSearch::safeClone() const
2862e5b6d6dSopenharmony_ci{
2872e5b6d6dSopenharmony_ci    UErrorCode status = U_ZERO_ERROR;
2882e5b6d6dSopenharmony_ci    StringSearch *result = new StringSearch(m_pattern_, m_text_,
2892e5b6d6dSopenharmony_ci                                            getCollator(),
2902e5b6d6dSopenharmony_ci                                            m_breakiterator_,
2912e5b6d6dSopenharmony_ci                                            status);
2922e5b6d6dSopenharmony_ci    /* test for NULL */
2932e5b6d6dSopenharmony_ci    if (result == 0) {
2942e5b6d6dSopenharmony_ci        status = U_MEMORY_ALLOCATION_ERROR;
2952e5b6d6dSopenharmony_ci        return 0;
2962e5b6d6dSopenharmony_ci    }
2972e5b6d6dSopenharmony_ci    result->setOffset(getOffset(), status);
2982e5b6d6dSopenharmony_ci    result->setMatchStart(m_strsrch_->search->matchedIndex);
2992e5b6d6dSopenharmony_ci    result->setMatchLength(m_strsrch_->search->matchedLength);
3002e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
3012e5b6d6dSopenharmony_ci        return NULL;
3022e5b6d6dSopenharmony_ci    }
3032e5b6d6dSopenharmony_ci    return result;
3042e5b6d6dSopenharmony_ci}
3052e5b6d6dSopenharmony_ci
3062e5b6d6dSopenharmony_ci// protected method -------------------------------------------------
3072e5b6d6dSopenharmony_ci
3082e5b6d6dSopenharmony_ciint32_t StringSearch::handleNext(int32_t position, UErrorCode &status)
3092e5b6d6dSopenharmony_ci{
3102e5b6d6dSopenharmony_ci    // values passed here are already in the pre-shift position
3112e5b6d6dSopenharmony_ci    if (U_SUCCESS(status)) {
3122e5b6d6dSopenharmony_ci        if (m_strsrch_->pattern.cesLength == 0) {
3132e5b6d6dSopenharmony_ci            m_search_->matchedIndex =
3142e5b6d6dSopenharmony_ci                                    m_search_->matchedIndex == USEARCH_DONE ?
3152e5b6d6dSopenharmony_ci                                    getOffset() : m_search_->matchedIndex + 1;
3162e5b6d6dSopenharmony_ci            m_search_->matchedLength = 0;
3172e5b6d6dSopenharmony_ci            ucol_setOffset(m_strsrch_->textIter, m_search_->matchedIndex,
3182e5b6d6dSopenharmony_ci                           &status);
3192e5b6d6dSopenharmony_ci            if (m_search_->matchedIndex == m_search_->textLength) {
3202e5b6d6dSopenharmony_ci                m_search_->matchedIndex = USEARCH_DONE;
3212e5b6d6dSopenharmony_ci            }
3222e5b6d6dSopenharmony_ci        }
3232e5b6d6dSopenharmony_ci        else {
3242e5b6d6dSopenharmony_ci            // looking at usearch.cpp, this part is shifted out to
3252e5b6d6dSopenharmony_ci            // StringSearch instead of SearchIterator because m_strsrch_ is
3262e5b6d6dSopenharmony_ci            // not accessible in SearchIterator
3272e5b6d6dSopenharmony_ci#if 0
3282e5b6d6dSopenharmony_ci            if (position + m_strsrch_->pattern.defaultShiftSize
3292e5b6d6dSopenharmony_ci                > m_search_->textLength) {
3302e5b6d6dSopenharmony_ci                setMatchNotFound();
3312e5b6d6dSopenharmony_ci                return USEARCH_DONE;
3322e5b6d6dSopenharmony_ci            }
3332e5b6d6dSopenharmony_ci#endif
3342e5b6d6dSopenharmony_ci            if (m_search_->matchedLength <= 0) {
3352e5b6d6dSopenharmony_ci                // the flipping direction issue has already been handled
3362e5b6d6dSopenharmony_ci                // in next()
3372e5b6d6dSopenharmony_ci                // for boundary check purposes. this will ensure that the
3382e5b6d6dSopenharmony_ci                // next match will not precede the current offset
3392e5b6d6dSopenharmony_ci                // note search->matchedIndex will always be set to something
3402e5b6d6dSopenharmony_ci                // in the code
3412e5b6d6dSopenharmony_ci                m_search_->matchedIndex = position - 1;
3422e5b6d6dSopenharmony_ci            }
3432e5b6d6dSopenharmony_ci
3442e5b6d6dSopenharmony_ci            ucol_setOffset(m_strsrch_->textIter, position, &status);
3452e5b6d6dSopenharmony_ci
3462e5b6d6dSopenharmony_ci#if 0
3472e5b6d6dSopenharmony_ci            for (;;) {
3482e5b6d6dSopenharmony_ci                if (m_search_->isCanonicalMatch) {
3492e5b6d6dSopenharmony_ci                    // can't use exact here since extra accents are allowed.
3502e5b6d6dSopenharmony_ci                    usearch_handleNextCanonical(m_strsrch_, &status);
3512e5b6d6dSopenharmony_ci                }
3522e5b6d6dSopenharmony_ci                else {
3532e5b6d6dSopenharmony_ci                    usearch_handleNextExact(m_strsrch_, &status);
3542e5b6d6dSopenharmony_ci                }
3552e5b6d6dSopenharmony_ci                if (U_FAILURE(status)) {
3562e5b6d6dSopenharmony_ci                    return USEARCH_DONE;
3572e5b6d6dSopenharmony_ci                }
3582e5b6d6dSopenharmony_ci                if (m_breakiterator_ == NULL
3592e5b6d6dSopenharmony_ci#if !UCONFIG_NO_BREAK_ITERATION
3602e5b6d6dSopenharmony_ci                    ||
3612e5b6d6dSopenharmony_ci                    m_search_->matchedIndex == USEARCH_DONE ||
3622e5b6d6dSopenharmony_ci                    (m_breakiterator_->isBoundary(m_search_->matchedIndex) &&
3632e5b6d6dSopenharmony_ci                     m_breakiterator_->isBoundary(m_search_->matchedIndex +
3642e5b6d6dSopenharmony_ci                                                  m_search_->matchedLength))
3652e5b6d6dSopenharmony_ci#endif
3662e5b6d6dSopenharmony_ci                ) {
3672e5b6d6dSopenharmony_ci                    if (m_search_->matchedIndex == USEARCH_DONE) {
3682e5b6d6dSopenharmony_ci                        ucol_setOffset(m_strsrch_->textIter,
3692e5b6d6dSopenharmony_ci                                       m_search_->textLength, &status);
3702e5b6d6dSopenharmony_ci                    }
3712e5b6d6dSopenharmony_ci                    else {
3722e5b6d6dSopenharmony_ci                        ucol_setOffset(m_strsrch_->textIter,
3732e5b6d6dSopenharmony_ci                                       m_search_->matchedIndex, &status);
3742e5b6d6dSopenharmony_ci                    }
3752e5b6d6dSopenharmony_ci                    return m_search_->matchedIndex;
3762e5b6d6dSopenharmony_ci                }
3772e5b6d6dSopenharmony_ci            }
3782e5b6d6dSopenharmony_ci#else
3792e5b6d6dSopenharmony_ci            // if m_strsrch_->breakIter is always the same as m_breakiterator_
3802e5b6d6dSopenharmony_ci            // then we don't need to check the match boundaries here because
3812e5b6d6dSopenharmony_ci            // usearch_handleNextXXX will already have done it.
3822e5b6d6dSopenharmony_ci            if (m_search_->isCanonicalMatch) {
3832e5b6d6dSopenharmony_ci            	// *could* actually use exact here 'cause no extra accents allowed...
3842e5b6d6dSopenharmony_ci            	usearch_handleNextCanonical(m_strsrch_, &status);
3852e5b6d6dSopenharmony_ci            } else {
3862e5b6d6dSopenharmony_ci            	usearch_handleNextExact(m_strsrch_, &status);
3872e5b6d6dSopenharmony_ci            }
3882e5b6d6dSopenharmony_ci
3892e5b6d6dSopenharmony_ci            if (U_FAILURE(status)) {
3902e5b6d6dSopenharmony_ci            	return USEARCH_DONE;
3912e5b6d6dSopenharmony_ci            }
3922e5b6d6dSopenharmony_ci
3932e5b6d6dSopenharmony_ci            if (m_search_->matchedIndex == USEARCH_DONE) {
3942e5b6d6dSopenharmony_ci            	ucol_setOffset(m_strsrch_->textIter, m_search_->textLength, &status);
3952e5b6d6dSopenharmony_ci            } else {
3962e5b6d6dSopenharmony_ci            	ucol_setOffset(m_strsrch_->textIter, m_search_->matchedIndex, &status);
3972e5b6d6dSopenharmony_ci            }
3982e5b6d6dSopenharmony_ci
3992e5b6d6dSopenharmony_ci            return m_search_->matchedIndex;
4002e5b6d6dSopenharmony_ci#endif
4012e5b6d6dSopenharmony_ci        }
4022e5b6d6dSopenharmony_ci    }
4032e5b6d6dSopenharmony_ci    return USEARCH_DONE;
4042e5b6d6dSopenharmony_ci}
4052e5b6d6dSopenharmony_ci
4062e5b6d6dSopenharmony_ciint32_t StringSearch::handlePrev(int32_t position, UErrorCode &status)
4072e5b6d6dSopenharmony_ci{
4082e5b6d6dSopenharmony_ci    // values passed here are already in the pre-shift position
4092e5b6d6dSopenharmony_ci    if (U_SUCCESS(status)) {
4102e5b6d6dSopenharmony_ci        if (m_strsrch_->pattern.cesLength == 0) {
4112e5b6d6dSopenharmony_ci            m_search_->matchedIndex =
4122e5b6d6dSopenharmony_ci                  (m_search_->matchedIndex == USEARCH_DONE ? getOffset() :
4132e5b6d6dSopenharmony_ci                   m_search_->matchedIndex);
4142e5b6d6dSopenharmony_ci            if (m_search_->matchedIndex == 0) {
4152e5b6d6dSopenharmony_ci                setMatchNotFound();
4162e5b6d6dSopenharmony_ci            }
4172e5b6d6dSopenharmony_ci            else {
4182e5b6d6dSopenharmony_ci                m_search_->matchedIndex --;
4192e5b6d6dSopenharmony_ci                ucol_setOffset(m_strsrch_->textIter, m_search_->matchedIndex,
4202e5b6d6dSopenharmony_ci                               &status);
4212e5b6d6dSopenharmony_ci                m_search_->matchedLength = 0;
4222e5b6d6dSopenharmony_ci            }
4232e5b6d6dSopenharmony_ci        }
4242e5b6d6dSopenharmony_ci        else {
4252e5b6d6dSopenharmony_ci            // looking at usearch.cpp, this part is shifted out to
4262e5b6d6dSopenharmony_ci            // StringSearch instead of SearchIterator because m_strsrch_ is
4272e5b6d6dSopenharmony_ci            // not accessible in SearchIterator
4282e5b6d6dSopenharmony_ci#if 0
4292e5b6d6dSopenharmony_ci            if (!m_search_->isOverlap &&
4302e5b6d6dSopenharmony_ci                position - m_strsrch_->pattern.defaultShiftSize < 0) {
4312e5b6d6dSopenharmony_ci                setMatchNotFound();
4322e5b6d6dSopenharmony_ci                return USEARCH_DONE;
4332e5b6d6dSopenharmony_ci            }
4342e5b6d6dSopenharmony_ci
4352e5b6d6dSopenharmony_ci            for (;;) {
4362e5b6d6dSopenharmony_ci                if (m_search_->isCanonicalMatch) {
4372e5b6d6dSopenharmony_ci                    // can't use exact here since extra accents are allowed.
4382e5b6d6dSopenharmony_ci                    usearch_handlePreviousCanonical(m_strsrch_, &status);
4392e5b6d6dSopenharmony_ci                }
4402e5b6d6dSopenharmony_ci                else {
4412e5b6d6dSopenharmony_ci                    usearch_handlePreviousExact(m_strsrch_, &status);
4422e5b6d6dSopenharmony_ci                }
4432e5b6d6dSopenharmony_ci                if (U_FAILURE(status)) {
4442e5b6d6dSopenharmony_ci                    return USEARCH_DONE;
4452e5b6d6dSopenharmony_ci                }
4462e5b6d6dSopenharmony_ci                if (m_breakiterator_ == NULL
4472e5b6d6dSopenharmony_ci#if !UCONFIG_NO_BREAK_ITERATION
4482e5b6d6dSopenharmony_ci                    ||
4492e5b6d6dSopenharmony_ci                    m_search_->matchedIndex == USEARCH_DONE ||
4502e5b6d6dSopenharmony_ci                    (m_breakiterator_->isBoundary(m_search_->matchedIndex) &&
4512e5b6d6dSopenharmony_ci                     m_breakiterator_->isBoundary(m_search_->matchedIndex +
4522e5b6d6dSopenharmony_ci                                                  m_search_->matchedLength))
4532e5b6d6dSopenharmony_ci#endif
4542e5b6d6dSopenharmony_ci                ) {
4552e5b6d6dSopenharmony_ci                    return m_search_->matchedIndex;
4562e5b6d6dSopenharmony_ci                }
4572e5b6d6dSopenharmony_ci            }
4582e5b6d6dSopenharmony_ci#else
4592e5b6d6dSopenharmony_ci            ucol_setOffset(m_strsrch_->textIter, position, &status);
4602e5b6d6dSopenharmony_ci
4612e5b6d6dSopenharmony_ci            if (m_search_->isCanonicalMatch) {
4622e5b6d6dSopenharmony_ci            	// *could* use exact match here since extra accents *not* allowed!
4632e5b6d6dSopenharmony_ci            	usearch_handlePreviousCanonical(m_strsrch_, &status);
4642e5b6d6dSopenharmony_ci            } else {
4652e5b6d6dSopenharmony_ci            	usearch_handlePreviousExact(m_strsrch_, &status);
4662e5b6d6dSopenharmony_ci            }
4672e5b6d6dSopenharmony_ci
4682e5b6d6dSopenharmony_ci            if (U_FAILURE(status)) {
4692e5b6d6dSopenharmony_ci            	return USEARCH_DONE;
4702e5b6d6dSopenharmony_ci            }
4712e5b6d6dSopenharmony_ci
4722e5b6d6dSopenharmony_ci            return m_search_->matchedIndex;
4732e5b6d6dSopenharmony_ci#endif
4742e5b6d6dSopenharmony_ci        }
4752e5b6d6dSopenharmony_ci
4762e5b6d6dSopenharmony_ci        return m_search_->matchedIndex;
4772e5b6d6dSopenharmony_ci    }
4782e5b6d6dSopenharmony_ci    return USEARCH_DONE;
4792e5b6d6dSopenharmony_ci}
4802e5b6d6dSopenharmony_ci
4812e5b6d6dSopenharmony_ciU_NAMESPACE_END
4822e5b6d6dSopenharmony_ci
4832e5b6d6dSopenharmony_ci#endif /* #if !UCONFIG_NO_COLLATION */
484