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