| // © 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 |
| */ |
| Quantifier* 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 |