summaryrefslogtreecommitdiff
path: root/icu4j/main/core/src/main/java/com/ibm/icu/impl/number/SimpleModifier.java
blob: ca77e489bef5154d47c284fff0eb83162c8c5803 (plain)
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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
// © 2017 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
package com.ibm.icu.impl.number;

import java.text.Format.Field;

import com.ibm.icu.impl.FormattedStringBuilder;
import com.ibm.icu.impl.SimpleFormatterImpl;
import com.ibm.icu.impl.number.range.PrefixInfixSuffixLengthHelper;
import com.ibm.icu.util.ICUException;

/**
 * The second primary implementation of {@link Modifier}, this one consuming a
 * {@link com.ibm.icu.text.SimpleFormatter} pattern.
 */
public class SimpleModifier implements Modifier {
    private final String compiledPattern;
    private final Field field;
    private final boolean strong;

    // Parameters: used for number range formatting
    private final Parameters parameters;

    /** TODO: This is copied from SimpleFormatterImpl. */
    private static final int ARG_NUM_LIMIT = 0x100;

    /** Creates a modifier that uses the SimpleFormatter string formats. */
    public SimpleModifier(String compiledPattern, Field field, boolean strong) {
        this(compiledPattern, field, strong, null);
    }

    /** Creates a modifier that uses the SimpleFormatter string formats. */
    public SimpleModifier(String compiledPattern, Field field, boolean strong, Parameters parameters) {
        assert compiledPattern != null;
        this.compiledPattern = compiledPattern;
        this.field = field;
        this.strong = strong;
        this.parameters = parameters;
    }

    @Override
    public int apply(FormattedStringBuilder output, int leftIndex, int rightIndex) {
        return SimpleFormatterImpl.formatPrefixSuffix(compiledPattern, field, leftIndex, rightIndex, output);
    }

    @Override
    public int getPrefixLength() {
        return SimpleFormatterImpl.getPrefixLength(compiledPattern);
    }

    @Override
    public int getCodePointCount() {
        return SimpleFormatterImpl.getLength(compiledPattern, true);
    }

    @Override
    public boolean isStrong() {
        return strong;
    }

    @Override
    public boolean containsField(Field field) {
        // This method is not currently used.
        assert false;
        return false;
    }

    @Override
    public Parameters getParameters() {
        return parameters;
    }

    @Override
    public boolean semanticallyEquivalent(Modifier other) {
        if (!(other instanceof SimpleModifier)) {
            return false;
        }
        SimpleModifier _other = (SimpleModifier) other;
        if (parameters != null && _other.parameters != null && parameters.obj == _other.parameters.obj) {
            return true;
        }
        return compiledPattern.equals(_other.compiledPattern) && field == _other.field && strong == _other.strong;
    }

    /**
     * TODO: Like above, this belongs with the rest of the SimpleFormatterImpl code.
     * I put it here so that the SimpleFormatter uses in FormattedStringBuilder are near each other.
     *
     * <p>
     * Applies the compiled two-argument pattern to the FormattedStringBuilder.
     *
     * <p>
     * This method is optimized for the case where the prefix and suffix are often empty, such as
     * in the range pattern like "{0}-{1}".
     */
    public static void formatTwoArgPattern(String compiledPattern, FormattedStringBuilder result, int index, PrefixInfixSuffixLengthHelper h,
            Field field) {
        int argLimit = SimpleFormatterImpl.getArgumentLimit(compiledPattern);
        if (argLimit != 2) {
            throw new ICUException();
        }
        int offset = 1; // offset into compiledPattern
        int length = 0; // chars added to result

        int prefixLength = compiledPattern.charAt(offset);
        offset++;
        if (prefixLength < ARG_NUM_LIMIT) {
            // No prefix
            prefixLength = 0;
        } else {
            prefixLength -= ARG_NUM_LIMIT;
            result.insert(index + length, compiledPattern, offset, offset + prefixLength, field);
            offset += prefixLength;
            length += prefixLength;
            offset++;
        }

        int infixLength = compiledPattern.charAt(offset);
        offset++;
        if (infixLength < ARG_NUM_LIMIT) {
            // No infix
            infixLength = 0;
        } else {
            infixLength -= ARG_NUM_LIMIT;
            result.insert(index + length, compiledPattern, offset, offset + infixLength, field);
            offset += infixLength;
            length += infixLength;
            offset++;
        }

        int suffixLength;
        if (offset == compiledPattern.length()) {
            // No suffix
            suffixLength = 0;
        } else {
            suffixLength = compiledPattern.charAt(offset) -  ARG_NUM_LIMIT;
            offset++;
            result.insert(index + length, compiledPattern, offset, offset + suffixLength, field);
            length += suffixLength;
        }

        h.lengthPrefix = prefixLength;
        h.lengthInfix = infixLength;
        h.lengthSuffix = suffixLength;
    }
}