]>
Commit | Line | Data |
---|---|---|
0f5d89e8 A |
1 | // © 2018 and later: Unicode, Inc. and others. |
2 | // License & terms of use: http://www.unicode.org/copyright.html | |
3 | ||
4 | #include "unicode/utypes.h" | |
5 | ||
6 | #if !UCONFIG_NO_FORMATTING | |
7 | ||
8 | // Allow implicit conversion from char16_t* to UnicodeString for this file: | |
9 | // Helpful in toString methods and elsewhere. | |
10 | #define UNISTR_FROM_STRING_EXPLICIT | |
11 | ||
12 | #include "numparse_types.h" | |
13 | #include "numparse_symbols.h" | |
14 | #include "numparse_utils.h" | |
15 | ||
16 | using namespace icu; | |
17 | using namespace icu::numparse; | |
18 | using namespace icu::numparse::impl; | |
19 | ||
20 | ||
21 | SymbolMatcher::SymbolMatcher(const UnicodeString& symbolString, unisets::Key key) { | |
22 | fUniSet = unisets::get(key); | |
23 | if (fUniSet->contains(symbolString)) { | |
24 | fString.setToBogus(); | |
25 | } else { | |
26 | fString = symbolString; | |
27 | } | |
28 | } | |
29 | ||
30 | const UnicodeSet* SymbolMatcher::getSet() const { | |
31 | return fUniSet; | |
32 | } | |
33 | ||
34 | bool SymbolMatcher::match(StringSegment& segment, ParsedNumber& result, UErrorCode&) const { | |
35 | // Smoke test first; this matcher might be disabled. | |
36 | if (isDisabled(result)) { | |
37 | return false; | |
38 | } | |
39 | ||
40 | // Test the string first in order to consume trailing chars greedily. | |
41 | int overlap = 0; | |
42 | if (!fString.isEmpty()) { | |
43 | overlap = segment.getCommonPrefixLength(fString); | |
44 | if (overlap == fString.length()) { | |
45 | segment.adjustOffset(fString.length()); | |
46 | accept(segment, result); | |
47 | return false; | |
48 | } | |
49 | } | |
50 | ||
51 | int cp = segment.getCodePoint(); | |
52 | if (cp != -1 && fUniSet->contains(cp)) { | |
53 | segment.adjustOffset(U16_LENGTH(cp)); | |
54 | accept(segment, result); | |
55 | return false; | |
56 | } | |
57 | ||
58 | return overlap == segment.length(); | |
59 | } | |
60 | ||
61 | bool SymbolMatcher::smokeTest(const StringSegment& segment) const { | |
62 | return segment.startsWith(*fUniSet) || segment.startsWith(fString); | |
63 | } | |
64 | ||
65 | UnicodeString SymbolMatcher::toString() const { | |
66 | // TODO: Customize output for each symbol | |
67 | return u"<Symbol>"; | |
68 | } | |
69 | ||
70 | ||
71 | IgnorablesMatcher::IgnorablesMatcher(unisets::Key key) | |
72 | : SymbolMatcher({}, key) { | |
73 | } | |
74 | ||
75 | bool IgnorablesMatcher::isFlexible() const { | |
76 | return true; | |
77 | } | |
78 | ||
79 | UnicodeString IgnorablesMatcher::toString() const { | |
80 | return u"<Ignorables>"; | |
81 | } | |
82 | ||
83 | bool IgnorablesMatcher::isDisabled(const ParsedNumber&) const { | |
84 | return false; | |
85 | } | |
86 | ||
87 | void IgnorablesMatcher::accept(StringSegment&, ParsedNumber&) const { | |
88 | // No-op | |
89 | } | |
90 | ||
91 | ||
92 | InfinityMatcher::InfinityMatcher(const DecimalFormatSymbols& dfs) | |
93 | : SymbolMatcher(dfs.getConstSymbol(DecimalFormatSymbols::kInfinitySymbol), unisets::INFINITY_KEY) { | |
94 | } | |
95 | ||
96 | bool InfinityMatcher::isDisabled(const ParsedNumber& result) const { | |
97 | return 0 != (result.flags & FLAG_INFINITY); | |
98 | } | |
99 | ||
100 | void InfinityMatcher::accept(StringSegment& segment, ParsedNumber& result) const { | |
101 | result.flags |= FLAG_INFINITY; | |
102 | result.setCharsConsumed(segment); | |
103 | } | |
104 | ||
105 | ||
106 | MinusSignMatcher::MinusSignMatcher(const DecimalFormatSymbols& dfs, bool allowTrailing) | |
107 | : SymbolMatcher(dfs.getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol), unisets::MINUS_SIGN), | |
108 | fAllowTrailing(allowTrailing) { | |
109 | } | |
110 | ||
111 | bool MinusSignMatcher::isDisabled(const ParsedNumber& result) const { | |
112 | return !fAllowTrailing && result.seenNumber(); | |
113 | } | |
114 | ||
115 | void MinusSignMatcher::accept(StringSegment& segment, ParsedNumber& result) const { | |
116 | result.flags |= FLAG_NEGATIVE; | |
117 | result.setCharsConsumed(segment); | |
118 | } | |
119 | ||
120 | ||
121 | NanMatcher::NanMatcher(const DecimalFormatSymbols& dfs) | |
122 | : SymbolMatcher(dfs.getConstSymbol(DecimalFormatSymbols::kNaNSymbol), unisets::EMPTY) { | |
123 | } | |
124 | ||
125 | bool NanMatcher::isDisabled(const ParsedNumber& result) const { | |
126 | return result.seenNumber(); | |
127 | } | |
128 | ||
129 | void NanMatcher::accept(StringSegment& segment, ParsedNumber& result) const { | |
130 | result.flags |= FLAG_NAN; | |
131 | result.setCharsConsumed(segment); | |
132 | } | |
133 | ||
134 | ||
135 | PaddingMatcher::PaddingMatcher(const UnicodeString& padString) | |
136 | : SymbolMatcher(padString, unisets::EMPTY) {} | |
137 | ||
138 | bool PaddingMatcher::isFlexible() const { | |
139 | return true; | |
140 | } | |
141 | ||
142 | bool PaddingMatcher::isDisabled(const ParsedNumber&) const { | |
143 | return false; | |
144 | } | |
145 | ||
146 | void PaddingMatcher::accept(StringSegment&, ParsedNumber&) const { | |
147 | // No-op | |
148 | } | |
149 | ||
150 | ||
151 | PercentMatcher::PercentMatcher(const DecimalFormatSymbols& dfs) | |
152 | : SymbolMatcher(dfs.getConstSymbol(DecimalFormatSymbols::kPercentSymbol), unisets::PERCENT_SIGN) { | |
153 | } | |
154 | ||
155 | bool PercentMatcher::isDisabled(const ParsedNumber& result) const { | |
156 | return 0 != (result.flags & FLAG_PERCENT); | |
157 | } | |
158 | ||
159 | void PercentMatcher::accept(StringSegment& segment, ParsedNumber& result) const { | |
160 | result.flags |= FLAG_PERCENT; | |
161 | result.setCharsConsumed(segment); | |
162 | } | |
163 | ||
164 | ||
165 | PermilleMatcher::PermilleMatcher(const DecimalFormatSymbols& dfs) | |
166 | : SymbolMatcher(dfs.getConstSymbol(DecimalFormatSymbols::kPerMillSymbol), unisets::PERMILLE_SIGN) { | |
167 | } | |
168 | ||
169 | bool PermilleMatcher::isDisabled(const ParsedNumber& result) const { | |
170 | return 0 != (result.flags & FLAG_PERMILLE); | |
171 | } | |
172 | ||
173 | void PermilleMatcher::accept(StringSegment& segment, ParsedNumber& result) const { | |
174 | result.flags |= FLAG_PERMILLE; | |
175 | result.setCharsConsumed(segment); | |
176 | } | |
177 | ||
178 | ||
179 | PlusSignMatcher::PlusSignMatcher(const DecimalFormatSymbols& dfs, bool allowTrailing) | |
180 | : SymbolMatcher(dfs.getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol), unisets::PLUS_SIGN), | |
181 | fAllowTrailing(allowTrailing) { | |
182 | } | |
183 | ||
184 | bool PlusSignMatcher::isDisabled(const ParsedNumber& result) const { | |
185 | return !fAllowTrailing && result.seenNumber(); | |
186 | } | |
187 | ||
188 | void PlusSignMatcher::accept(StringSegment& segment, ParsedNumber& result) const { | |
189 | result.setCharsConsumed(segment); | |
190 | } | |
191 | ||
192 | ||
193 | #endif /* #if !UCONFIG_NO_FORMATTING */ |