• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GENERATED SOURCE. DO NOT MODIFY. */
2 // © 2017 and later: Unicode, Inc. and others.
3 // License & terms of use: http://www.unicode.org/copyright.html
4 package android.icu.number;
5 
6 import java.math.BigInteger;
7 import java.text.Format;
8 import java.util.Objects;
9 import java.util.concurrent.atomic.AtomicLongFieldUpdater;
10 
11 import android.icu.impl.FormattedStringBuilder;
12 import android.icu.impl.StandardPlural;
13 import android.icu.impl.number.DecimalQuantity;
14 import android.icu.impl.number.DecimalQuantity_DualStorageBCD;
15 import android.icu.impl.number.LocalizedNumberFormatterAsFormat;
16 import android.icu.impl.number.MacroProps;
17 import android.icu.impl.number.MicroProps;
18 import android.icu.math.BigDecimal;
19 import android.icu.util.CurrencyAmount;
20 import android.icu.util.Measure;
21 import android.icu.util.MeasureUnit;
22 
23 /**
24  * A NumberFormatter that has a locale associated with it; this means .format() methods are available.
25  *
26  * Instances of this class are immutable and thread-safe.
27  *
28  * @see NumberFormatter
29  * @see NumberFormatter
30  */
31 public class LocalizedNumberFormatter extends NumberFormatterSettings<LocalizedNumberFormatter> {
32 
33     static final AtomicLongFieldUpdater<LocalizedNumberFormatter> callCount = AtomicLongFieldUpdater
34             .newUpdater(LocalizedNumberFormatter.class, "callCountInternal");
35 
36     volatile long callCountInternal; // do not access directly; use callCount instead
37     volatile LocalizedNumberFormatter savedWithUnit;
38     volatile NumberFormatterImpl compiled;
39 
LocalizedNumberFormatter(NumberFormatterSettings<?> parent, int key, Object value)40     LocalizedNumberFormatter(NumberFormatterSettings<?> parent, int key, Object value) {
41         super(parent, key, value);
42     }
43 
44     /**
45      * Format the given byte, short, int, or long to a string using the settings specified in the
46      * NumberFormatter fluent setting chain.
47      *
48      * @param input
49      *            The number to format.
50      * @return A FormattedNumber object; call .toString() to get the string.
51      * @see NumberFormatter
52      */
format(long input)53     public FormattedNumber format(long input) {
54         return format(new DecimalQuantity_DualStorageBCD(input));
55     }
56 
57     /**
58      * Format the given float or double to a string using the settings specified in the NumberFormatter
59      * fluent setting chain.
60      *
61      * @param input
62      *            The number to format.
63      * @return A FormattedNumber object; call .toString() to get the string.
64      * @see NumberFormatter
65      */
format(double input)66     public FormattedNumber format(double input) {
67         return format(new DecimalQuantity_DualStorageBCD(input));
68     }
69 
70     /**
71      * Format the given {@link BigInteger}, {@link BigDecimal}, or other {@link Number} to a string using
72      * the settings specified in the NumberFormatter fluent setting chain.
73      *
74      * @param input
75      *            The number to format.
76      * @return A FormattedNumber object; call .toString() to get the string.
77      * @see NumberFormatter
78      */
format(Number input)79     public FormattedNumber format(Number input) {
80         return format(new DecimalQuantity_DualStorageBCD(input));
81     }
82 
83     /**
84      * Format the given {@link Measure} or {@link CurrencyAmount} to a string using the settings
85      * specified in the NumberFormatter fluent setting chain.
86      *
87      * <p>
88      * The unit specified here overrides any unit that may have been specified in the setter chain. This
89      * method is intended for cases when each input to the number formatter has a different unit.
90      *
91      * @param input
92      *            The number to format.
93      * @return A FormattedNumber object; call .toString() to get the string.
94      * @see NumberFormatter
95      */
format(Measure input)96     public FormattedNumber format(Measure input) {
97         DecimalQuantity fq = new DecimalQuantity_DualStorageBCD(input.getNumber());
98         MeasureUnit unit = input.getUnit();
99         FormattedStringBuilder string = new FormattedStringBuilder();
100         MicroProps micros = formatImpl(fq, unit, string);
101         return new FormattedNumber(string, fq, micros.outputUnit, micros.gender);
102     }
103 
104     /**
105      * Creates a representation of this LocalizedNumberFormat as a {@link java.text.Format}, enabling the
106      * use of this number formatter with APIs that need an object of that type, such as MessageFormat.
107      * <p>
108      * This API is not intended to be used other than for enabling API compatibility. The {@link #format}
109      * methods should normally be used when formatting numbers, not the Format object returned by this
110      * method.
111      *
112      * @return A Format wrapping this LocalizedNumberFormatter.
113      * @see NumberFormatter
114      */
toFormat()115     public Format toFormat() {
116         return new LocalizedNumberFormatterAsFormat(this, resolve().loc);
117     }
118 
119     /**
120      * Disassociate the locale from this formatter.
121      *
122      * @return The fluent chain.
123      */
124     @android.annotation.FlaggedApi(com.android.icu.Flags.FLAG_ICU_25Q2_API)
withoutLocale()125     public UnlocalizedNumberFormatter withoutLocale() {
126         return new UnlocalizedNumberFormatter(this, KEY_LOCALE, null);
127     }
128 
129     /**
130      *  Helper method that creates a FormattedStringBuilder and formats.
131      */
format(DecimalQuantity fq)132     private FormattedNumber format(DecimalQuantity fq) {
133         FormattedStringBuilder string = new FormattedStringBuilder();
134         MicroProps micros = formatImpl(fq, string);
135         return new FormattedNumber(string, fq, micros.outputUnit, micros.gender);
136     }
137 
138     /**
139      * This is the core entrypoint to the number formatting pipeline. It performs self-regulation: a
140      * static code path for the first few calls, and compiling a more efficient data structure if called
141      * repeatedly.
142      *
143      * <p>
144      * This function is very hot, being called in every call to the number formatting pipeline.
145      *
146      * @param fq
147      *            The quantity to be formatted.
148      * @param string
149      *            The string builder into which to insert the result.
150      *
151      * @deprecated ICU 60 This API is ICU internal only.
152      * @hide draft / provisional / internal are hidden on Android
153      */
154     @Deprecated
formatImpl(DecimalQuantity fq, FormattedStringBuilder string)155     public MicroProps formatImpl(DecimalQuantity fq, FormattedStringBuilder string) {
156         if (computeCompiled()) {
157             return compiled.format(fq, string);
158         }
159         return NumberFormatterImpl.formatStatic(resolve(), fq, string);
160     }
161 
162     /**
163      * Version of above for unit override.
164      *
165      * @deprecated ICU 67 This API is ICU internal only.
166      * @hide draft / provisional / internal are hidden on Android
167      */
168     @Deprecated
formatImpl(DecimalQuantity fq, MeasureUnit unit, FormattedStringBuilder string)169     public MicroProps formatImpl(DecimalQuantity fq, MeasureUnit unit, FormattedStringBuilder string) {
170         // Use this formatter if possible
171         if (Objects.equals(resolve().unit, unit)) {
172             return formatImpl(fq, string);
173 
174         }
175         // This mechanism saves the previously used unit, so if the user calls this method with the
176         // same unit multiple times in a row, they get a more efficient code path.
177         LocalizedNumberFormatter withUnit = savedWithUnit;
178         if (withUnit == null || !Objects.equals(withUnit.resolve().unit, unit)) {
179             withUnit = new LocalizedNumberFormatter(this, KEY_UNIT, unit);
180             savedWithUnit = withUnit;
181         }
182         return withUnit.formatImpl(fq, string);
183     }
184 
185     /**
186      * @deprecated This API is ICU internal only. Use {@link FormattedNumber#nextPosition}
187      *             for related functionality.
188      * @hide draft / provisional / internal are hidden on Android
189      */
190     @Deprecated
getAffixImpl(boolean isPrefix, boolean isNegative)191     public String getAffixImpl(boolean isPrefix, boolean isNegative) {
192         FormattedStringBuilder string = new FormattedStringBuilder();
193         byte signum = (byte) (isNegative ? -1 : 1);
194         // Always return affixes for plural form OTHER.
195         StandardPlural plural = StandardPlural.OTHER;
196         int prefixLength;
197         if (computeCompiled()) {
198             prefixLength = compiled.getPrefixSuffix(signum, plural, string);
199         } else {
200             prefixLength = NumberFormatterImpl.getPrefixSuffixStatic(resolve(), signum, plural, string);
201         }
202         if (isPrefix) {
203             return string.subSequence(0, prefixLength).toString();
204         } else {
205             return string.subSequence(prefixLength, string.length()).toString();
206         }
207     }
208 
computeCompiled()209     private boolean computeCompiled() {
210         MacroProps macros = resolve();
211         // NOTE: In Java, the atomic increment logic is slightly different than ICU4C.
212         // It seems to be more efficient to make just one function call instead of two.
213         // Further benchmarking is required.
214         long currentCount = callCount.incrementAndGet(this);
215         if (currentCount == macros.threshold.longValue()) {
216             compiled = new NumberFormatterImpl(macros);
217             return true;
218         } else if (compiled != null) {
219             return true;
220         } else {
221             return false;
222         }
223     }
224 
225     @Override
create(int key, Object value)226     LocalizedNumberFormatter create(int key, Object value) {
227         return new LocalizedNumberFormatter(this, key, value);
228     }
229 }
230