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