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