1 /* 2 ********************************************************************** 3 * Copyright (C) 2001-2012, 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 Quantifier *nonconst_this = const_cast<Quantifier *>(this); 58 UnicodeMatcher *nonconst_base = static_cast<UnicodeMatcher *>(nonconst_this); 59 60 return nonconst_base; 61 } 62 63 UMatchDegree Quantifier::matches(const Replaceable& text, 64 int32_t& offset, 65 int32_t limit, 66 UBool incremental) { 67 int32_t start = offset; 68 uint32_t count = 0; 69 while (count < maxCount) { 70 int32_t pos = offset; 71 UMatchDegree m = matcher->toMatcher()->matches(text, offset, limit, incremental); 72 if (m == U_MATCH) { 73 ++count; 74 if (pos == offset) { 75 // If offset has not moved we have a zero-width match. 76 // Don't keep matching it infinitely. 77 break; 78 } 79 } else if (incremental && m == U_PARTIAL_MATCH) { 80 return U_PARTIAL_MATCH; 81 } else { 82 break; 83 } 84 } 85 if (incremental && offset == limit) { 86 return U_PARTIAL_MATCH; 87 } 88 if (count >= minCount) { 89 return U_MATCH; 90 } 91 offset = start; 92 return U_MISMATCH; 93 } 94 95 /** 96 * Implement UnicodeMatcher 97 */ 98 UnicodeString& Quantifier::toPattern(UnicodeString& result, 99 UBool escapeUnprintable) const { 100 result.truncate(0); 101 matcher->toMatcher()->toPattern(result, escapeUnprintable); 102 if (minCount == 0) { 103 if (maxCount == 1) { 104 return result.append((UChar)63); /*?*/ 105 } else if (maxCount == MAX) { 106 return result.append((UChar)42); /***/ 107 } 108 // else fall through 109 } else if (minCount == 1 && maxCount == MAX) { 110 return result.append((UChar)43); /*+*/ 111 } 112 result.append((UChar)123); /*{*/ 113 ICU_Utility::appendNumber(result, minCount); 114 result.append((UChar)44); /*,*/ 115 if (maxCount != MAX) { 116 ICU_Utility::appendNumber(result, maxCount); 117 } 118 result.append((UChar)125); /*}*/ 119 return result; 120 } 121 122 /** 123 * Implement UnicodeMatcher 124 */ 125 UBool Quantifier::matchesIndexValue(uint8_t v) const { 126 return (minCount == 0) || matcher->toMatcher()->matchesIndexValue(v); 127 } 128 129 /** 130 * Implement UnicodeMatcher 131 */ 132 void Quantifier::addMatchSetTo(UnicodeSet& toUnionTo) const { 133 if (maxCount > 0) { 134 matcher->toMatcher()->addMatchSetTo(toUnionTo); 135 } 136 } 137 138 /** 139 * Implement UnicodeFunctor 140 */ 141 void Quantifier::setData(const TransliterationRuleData* d) { 142 matcher->setData(d); 143 } 144 145 U_NAMESPACE_END 146 147 #endif /* #if !UCONFIG_NO_TRANSLITERATION */ 148 149 //eof 150