1 /* 2 ********************************************************************** 3 * Copyright (C) 2001-2008, International Business Machines 4 * Corporation and others. All Rights Reserved. 5 ********************************************************************** 6 * Date Name Description 7 * 07/26/01 aliu Creation. 8 ********************************************************************** 9 */ 10 11 #include "unicode/utypes.h" 12 13 #if !UCONFIG_NO_TRANSLITERATION 14 15 #include "quant.h" 16 #include "unicode/unistr.h" 17 #include "util.h" 18 19 U_NAMESPACE_BEGIN 20 21 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(Quantifier) 22 23 Quantifier::Quantifier(UnicodeFunctor *adoptedMatcher, 24 uint32_t _minCount, uint32_t _maxCount) { 25 // assert(adopted != 0); 26 // assert(minCount <= maxCount); 27 matcher = adoptedMatcher; 28 this->minCount = _minCount; 29 this->maxCount = _maxCount; 30 } 31 32 Quantifier::Quantifier(const Quantifier& o) : 33 UnicodeFunctor(o), 34 UnicodeMatcher(o), 35 matcher(o.matcher->clone()), 36 minCount(o.minCount), 37 maxCount(o.maxCount) 38 { 39 } 40 41 Quantifier::~Quantifier() { 42 delete matcher; 43 } 44 45 /** 46 * Implement UnicodeFunctor 47 */ 48 UnicodeFunctor* Quantifier::clone() const { 49 return new Quantifier(*this); 50 } 51 52 /** 53 * UnicodeFunctor API. Cast 'this' to a UnicodeMatcher* pointer 54 * and return the pointer. 55 */ 56 UnicodeMatcher* Quantifier::toMatcher() const { 57 return (UnicodeMatcher*) this; 58 } 59 60 UMatchDegree Quantifier::matches(const Replaceable& text, 61 int32_t& offset, 62 int32_t limit, 63 UBool incremental) { 64 int32_t start = offset; 65 uint32_t count = 0; 66 while (count < maxCount) { 67 int32_t pos = offset; 68 UMatchDegree m = matcher->toMatcher()->matches(text, offset, limit, incremental); 69 if (m == U_MATCH) { 70 ++count; 71 if (pos == offset) { 72 // If offset has not moved we have a zero-width match. 73 // Don't keep matching it infinitely. 74 break; 75 } 76 } else if (incremental && m == U_PARTIAL_MATCH) { 77 return U_PARTIAL_MATCH; 78 } else { 79 break; 80 } 81 } 82 if (incremental && offset == limit) { 83 return U_PARTIAL_MATCH; 84 } 85 if (count >= minCount) { 86 return U_MATCH; 87 } 88 offset = start; 89 return U_MISMATCH; 90 } 91 92 /** 93 * Implement UnicodeMatcher 94 */ 95 UnicodeString& Quantifier::toPattern(UnicodeString& result, 96 UBool escapeUnprintable) const { 97 result.truncate(0); 98 matcher->toMatcher()->toPattern(result, escapeUnprintable); 99 if (minCount == 0) { 100 if (maxCount == 1) { 101 return result.append((UChar)63); /*?*/ 102 } else if (maxCount == MAX) { 103 return result.append((UChar)42); /***/ 104 } 105 // else fall through 106 } else if (minCount == 1 && maxCount == MAX) { 107 return result.append((UChar)43); /*+*/ 108 } 109 result.append((UChar)123); /*{*/ 110 ICU_Utility::appendNumber(result, minCount); 111 result.append((UChar)44); /*,*/ 112 if (maxCount != MAX) { 113 ICU_Utility::appendNumber(result, maxCount); 114 } 115 result.append((UChar)125); /*}*/ 116 return result; 117 } 118 119 /** 120 * Implement UnicodeMatcher 121 */ 122 UBool Quantifier::matchesIndexValue(uint8_t v) const { 123 return (minCount == 0) || matcher->toMatcher()->matchesIndexValue(v); 124 } 125 126 /** 127 * Implement UnicodeMatcher 128 */ 129 void Quantifier::addMatchSetTo(UnicodeSet& toUnionTo) const { 130 if (maxCount > 0) { 131 matcher->toMatcher()->addMatchSetTo(toUnionTo); 132 } 133 } 134 135 /** 136 * Implement UnicodeFunctor 137 */ 138 void Quantifier::setData(const TransliterationRuleData* d) { 139 matcher->setData(d); 140 } 141 142 U_NAMESPACE_END 143 144 #endif /* #if !UCONFIG_NO_TRANSLITERATION */ 145 146 //eof 147