aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/icu/i18n/numparse_compositions.cpp
blob: f343b5a043928f23821767c0bea5f21b9c8ecaf5 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
// © 2018 and later: Unicode, Inc. and others. 
// License & terms of use: http://www.unicode.org/copyright.html 
 
#include "unicode/utypes.h" 
 
#if !UCONFIG_NO_FORMATTING 
 
// Allow implicit conversion from char16_t* to UnicodeString for this file: 
// Helpful in toString methods and elsewhere. 
#define UNISTR_FROM_STRING_EXPLICIT 
 
#include "numparse_types.h" 
#include "numparse_compositions.h" 
#include "string_segment.h" 
#include "unicode/uniset.h" 
 
using namespace icu; 
using namespace icu::numparse; 
using namespace icu::numparse::impl; 
 
 
bool SeriesMatcher::match(StringSegment& segment, ParsedNumber& result, UErrorCode& status) const { 
    ParsedNumber backup(result); 
 
    int32_t initialOffset = segment.getOffset(); 
    bool maybeMore = true; 
    for (auto* it = begin(); it < end();) { 
        const NumberParseMatcher* matcher = *it; 
        int matcherOffset = segment.getOffset(); 
        if (segment.length() != 0) { 
            maybeMore = matcher->match(segment, result, status); 
        } else { 
            // Nothing for this matcher to match; ask for more. 
            maybeMore = true; 
        } 
 
        bool success = (segment.getOffset() != matcherOffset); 
        bool isFlexible = matcher->isFlexible(); 
        if (success && isFlexible) { 
            // Match succeeded, and this is a flexible matcher. Re-run it. 
        } else if (success) { 
            // Match succeeded, and this is NOT a flexible matcher. Proceed to the next matcher. 
            it++; 
            // Small hack: if there is another matcher coming, do not accept trailing weak chars. 
            // Needed for proper handling of currency spacing. 
            if (it < end() && segment.getOffset() != result.charEnd && result.charEnd > matcherOffset) { 
                segment.setOffset(result.charEnd); 
            } 
        } else if (isFlexible) { 
            // Match failed, and this is a flexible matcher. Try again with the next matcher. 
            it++; 
        } else { 
            // Match failed, and this is NOT a flexible matcher. Exit. 
            segment.setOffset(initialOffset); 
            result = backup; 
            return maybeMore; 
        } 
    } 
 
    // All matchers in the series succeeded. 
    return maybeMore; 
} 
 
bool SeriesMatcher::smokeTest(const StringSegment& segment) const { 
    // NOTE: The range-based for loop calls the virtual begin() and end() methods. 
    // NOTE: We only want the first element. Use the for loop for boundary checking. 
    for (auto& matcher : *this) { 
        // SeriesMatchers are never allowed to start with a Flexible matcher. 
        U_ASSERT(!matcher->isFlexible()); 
        return matcher->smokeTest(segment); 
    } 
    return false; 
} 
 
void SeriesMatcher::postProcess(ParsedNumber& result) const { 
    // NOTE: The range-based for loop calls the virtual begin() and end() methods. 
    for (auto* matcher : *this) { 
        matcher->postProcess(result); 
    } 
} 
 
 
ArraySeriesMatcher::ArraySeriesMatcher() 
        : fMatchersLen(0) { 
} 
 
ArraySeriesMatcher::ArraySeriesMatcher(MatcherArray& matchers, int32_t matchersLen) 
        : fMatchers(std::move(matchers)), fMatchersLen(matchersLen) { 
} 
 
int32_t ArraySeriesMatcher::length() const { 
    return fMatchersLen; 
} 
 
const NumberParseMatcher* const* ArraySeriesMatcher::begin() const { 
    return fMatchers.getAlias(); 
} 
 
const NumberParseMatcher* const* ArraySeriesMatcher::end() const { 
    return fMatchers.getAlias() + fMatchersLen; 
} 
 
UnicodeString ArraySeriesMatcher::toString() const { 
    return u"<ArraySeries>"; 
} 
 
 
#endif /* #if !UCONFIG_NO_FORMATTING */