// © 2016 and later: Unicode, Inc. and others. // License & terms of use: http://www.unicode.org/copyright.html /* ********************************************************************** * Copyright (C) 2001-2012, International Business Machines * Corporation and others. All Rights Reserved. ********************************************************************** * Date Name Description * 07/26/01 aliu Creation. ********************************************************************** */ #include "unicode/utypes.h" #if !UCONFIG_NO_TRANSLITERATION #include "quant.h" #include "unicode/unistr.h" #include "util.h" U_NAMESPACE_BEGIN UOBJECT_DEFINE_RTTI_IMPLEMENTATION(Quantifier) Quantifier::Quantifier(UnicodeFunctor *adoptedMatcher, uint32_t _minCount, uint32_t _maxCount) { // assert(adopted != 0); // assert(minCount <= maxCount); matcher = adoptedMatcher; this->minCount = _minCount; this->maxCount = _maxCount; } Quantifier::Quantifier(const Quantifier& o) : UnicodeFunctor(o), UnicodeMatcher(o), matcher(o.matcher->clone()), minCount(o.minCount), maxCount(o.maxCount) { } Quantifier::~Quantifier() { delete matcher; } /** * Implement UnicodeFunctor */ UnicodeFunctor* Quantifier::clone() const { return new Quantifier(*this); } /** * UnicodeFunctor API. Cast 'this' to a UnicodeMatcher* pointer * and return the pointer. */ UnicodeMatcher* Quantifier::toMatcher() const { Quantifier *nonconst_this = const_cast<Quantifier *>(this); UnicodeMatcher *nonconst_base = static_cast<UnicodeMatcher *>(nonconst_this); return nonconst_base; } UMatchDegree Quantifier::matches(const Replaceable& text, int32_t& offset, int32_t limit, UBool incremental) { int32_t start = offset; uint32_t count = 0; while (count < maxCount) { int32_t pos = offset; UMatchDegree m = matcher->toMatcher()->matches(text, offset, limit, incremental); if (m == U_MATCH) { ++count; if (pos == offset) { // If offset has not moved we have a zero-width match. // Don't keep matching it infinitely. break; } } else if (incremental && m == U_PARTIAL_MATCH) { return U_PARTIAL_MATCH; } else { break; } } if (incremental && offset == limit) { return U_PARTIAL_MATCH; } if (count >= minCount) { return U_MATCH; } offset = start; return U_MISMATCH; } /** * Implement UnicodeMatcher */ UnicodeString& Quantifier::toPattern(UnicodeString& result, UBool escapeUnprintable) const { result.truncate(0); matcher->toMatcher()->toPattern(result, escapeUnprintable); if (minCount == 0) { if (maxCount == 1) { return result.append((UChar)63); /*?*/ } else if (maxCount == MAX) { return result.append((UChar)42); /***/ } // else fall through } else if (minCount == 1 && maxCount == MAX) { return result.append((UChar)43); /*+*/ } result.append((UChar)123); /*{*/ ICU_Utility::appendNumber(result, minCount); result.append((UChar)44); /*,*/ if (maxCount != MAX) { ICU_Utility::appendNumber(result, maxCount); } result.append((UChar)125); /*}*/ return result; } /** * Implement UnicodeMatcher */ UBool Quantifier::matchesIndexValue(uint8_t v) const { return (minCount == 0) || matcher->toMatcher()->matchesIndexValue(v); } /** * Implement UnicodeMatcher */ void Quantifier::addMatchSetTo(UnicodeSet& toUnionTo) const { if (maxCount > 0) { matcher->toMatcher()->addMatchSetTo(toUnionTo); } } /** * Implement UnicodeFunctor */ void Quantifier::setData(const TransliterationRuleData* d) { matcher->setData(d); } U_NAMESPACE_END #endif /* #if !UCONFIG_NO_TRANSLITERATION */ //eof