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