1 /* GENERATED SOURCE. DO NOT MODIFY. */ 2 // © 2016 and later: Unicode, Inc. and others. 3 // License & terms of use: http://www.unicode.org/copyright.html#License 4 /* 5 ******************************************************************************* 6 * Copyright (C) 2007-2016, International Business Machines 7 * Corporation and others. All Rights Reserved. 8 ******************************************************************************* 9 */ 10 package ohos.global.icu.impl; 11 12 import java.io.IOException; 13 import java.io.ObjectInputStream; 14 import java.math.BigInteger; 15 import java.text.FieldPosition; 16 import java.text.ParsePosition; 17 import java.util.Arrays; 18 import java.util.MissingResourceException; 19 20 import ohos.global.icu.lang.UCharacter; 21 import ohos.global.icu.math.BigDecimal; 22 import ohos.global.icu.text.NumberFormat; 23 import ohos.global.icu.util.ULocale; 24 import ohos.global.icu.util.UResourceBundle; 25 26 /* 27 * NumberFormat implementation dedicated/optimized for DateFormat, 28 * used by SimpleDateFormat implementation. 29 * This class is not thread-safe. 30 */ 31 /** 32 * @hide exposed on OHOS 33 */ 34 public final class DateNumberFormat extends NumberFormat { 35 36 private static final long serialVersionUID = -6315692826916346953L; 37 38 private char[] digits; 39 private char zeroDigit; // For backwards compatibility 40 private char minusSign; 41 private boolean positiveOnly = false; 42 43 private static final int DECIMAL_BUF_SIZE = 20; // 20 digits is good enough to store Long.MAX_VALUE 44 private transient char[] decimalBuf = new char[DECIMAL_BUF_SIZE]; 45 46 private static SimpleCache<ULocale, char[]> CACHE = new SimpleCache<ULocale, char[]>(); 47 48 private int maxIntDigits; 49 private int minIntDigits; 50 DateNumberFormat(ULocale loc, String digitString, String nsName)51 public DateNumberFormat(ULocale loc, String digitString, String nsName) { 52 if (digitString.length() > 10) { 53 throw new UnsupportedOperationException("DateNumberFormat does not support digits out of BMP."); 54 } 55 initialize(loc,digitString,nsName); 56 } 57 DateNumberFormat(ULocale loc, char zeroDigit, String nsName)58 public DateNumberFormat(ULocale loc, char zeroDigit, String nsName) { 59 StringBuffer buf = new StringBuffer(); 60 for ( int i = 0 ; i < 10 ; i++ ) { 61 buf.append((char)(zeroDigit+i)); 62 } 63 initialize(loc,buf.toString(),nsName); 64 } 65 initialize(ULocale loc,String digitString,String nsName)66 private void initialize(ULocale loc,String digitString,String nsName) { 67 char[] elems = CACHE.get(loc); 68 if (elems == null) { 69 // Missed cache 70 String minusString; 71 ICUResourceBundle rb = (ICUResourceBundle)UResourceBundle.getBundleInstance(ICUData.ICU_BASE_NAME, loc); 72 try { 73 minusString = rb.getStringWithFallback("NumberElements/"+nsName+"/symbols/minusSign"); 74 } catch (MissingResourceException ex) { 75 if ( !nsName.equals("latn") ) { 76 try { 77 minusString = rb.getStringWithFallback("NumberElements/latn/symbols/minusSign"); 78 } catch (MissingResourceException ex1) { 79 minusString = "-"; 80 } 81 } else { 82 minusString = "-"; 83 } 84 } 85 elems = new char[11]; 86 for ( int i = 0 ; i < 10 ; i++ ) { 87 elems[i] = digitString.charAt(i); 88 } 89 elems[10] = minusString.charAt(0); 90 CACHE.put(loc, elems); 91 } 92 93 digits = new char[10]; 94 System.arraycopy(elems, 0, digits, 0, 10); 95 zeroDigit = digits[0]; 96 97 minusSign = elems[10]; 98 } 99 100 @Override setMaximumIntegerDigits(int newValue)101 public void setMaximumIntegerDigits(int newValue) { 102 maxIntDigits = newValue; 103 } 104 105 @Override getMaximumIntegerDigits()106 public int getMaximumIntegerDigits() { 107 return maxIntDigits; 108 } 109 110 @Override setMinimumIntegerDigits(int newValue)111 public void setMinimumIntegerDigits(int newValue) { 112 minIntDigits = newValue; 113 } 114 115 @Override getMinimumIntegerDigits()116 public int getMinimumIntegerDigits() { 117 return minIntDigits; 118 } 119 120 /* For supporting SimpleDateFormat.parseInt */ setParsePositiveOnly(boolean isPositiveOnly)121 public void setParsePositiveOnly(boolean isPositiveOnly) { 122 positiveOnly = isPositiveOnly; 123 } 124 getZeroDigit()125 public char getZeroDigit() { 126 return zeroDigit; 127 } 128 setZeroDigit(char zero)129 public void setZeroDigit(char zero) { 130 zeroDigit = zero; 131 if (digits == null) { 132 digits = new char[10]; 133 } 134 digits[0] = zero; 135 for ( int i = 1 ; i < 10 ; i++ ) { 136 digits[i] = (char)(zero+i); 137 } 138 } 139 getDigits()140 public char[] getDigits() { 141 return digits.clone(); 142 } 143 144 @Override format(double number, StringBuffer toAppendTo, FieldPosition pos)145 public StringBuffer format(double number, StringBuffer toAppendTo, 146 FieldPosition pos) { 147 throw new UnsupportedOperationException("StringBuffer format(double, StringBuffer, FieldPostion) is not implemented"); 148 } 149 150 @Override format(long numberL, StringBuffer toAppendTo, FieldPosition pos)151 public StringBuffer format(long numberL, StringBuffer toAppendTo, 152 FieldPosition pos) { 153 154 if (numberL < 0) { 155 // negative 156 toAppendTo.append(minusSign); 157 numberL = -numberL; 158 } 159 160 // Note: NumberFormat used by DateFormat only uses int numbers. 161 // Remainder operation on 32bit platform using long is significantly slower 162 // than int. So, this method casts long number into int. 163 int number = (int)numberL; 164 165 int limit = decimalBuf.length < maxIntDigits ? decimalBuf.length : maxIntDigits; 166 int index = limit - 1; 167 while (true) { 168 decimalBuf[index] = digits[(number % 10)]; 169 number /= 10; 170 if (index == 0 || number == 0) { 171 break; 172 } 173 index--; 174 } 175 int padding = minIntDigits - (limit - index); 176 for (; padding > 0; padding--) { 177 decimalBuf[--index] = digits[0]; 178 } 179 int length = limit - index; 180 toAppendTo.append(decimalBuf, index, length); 181 pos.setBeginIndex(0); 182 if (pos.getField() == NumberFormat.INTEGER_FIELD) { 183 pos.setEndIndex(length); 184 } else { 185 pos.setEndIndex(0); 186 } 187 return toAppendTo; 188 } 189 190 @Override format(BigInteger number, StringBuffer toAppendTo, FieldPosition pos)191 public StringBuffer format(BigInteger number, StringBuffer toAppendTo, 192 FieldPosition pos) { 193 throw new UnsupportedOperationException("StringBuffer format(BigInteger, StringBuffer, FieldPostion) is not implemented"); 194 } 195 196 @Override format(java.math.BigDecimal number, StringBuffer toAppendTo, FieldPosition pos)197 public StringBuffer format(java.math.BigDecimal number, StringBuffer toAppendTo, 198 FieldPosition pos) { 199 throw new UnsupportedOperationException("StringBuffer format(BigDecimal, StringBuffer, FieldPostion) is not implemented"); 200 } 201 202 @Override format(BigDecimal number, StringBuffer toAppendTo, FieldPosition pos)203 public StringBuffer format(BigDecimal number, 204 StringBuffer toAppendTo, FieldPosition pos) { 205 throw new UnsupportedOperationException("StringBuffer format(BigDecimal, StringBuffer, FieldPostion) is not implemented"); 206 } 207 208 /* 209 * Note: This method only parse integer numbers which can be represented by long 210 */ 211 private static final long PARSE_THRESHOLD = 922337203685477579L; // (Long.MAX_VALUE / 10) - 1 212 213 @Override parse(String text, ParsePosition parsePosition)214 public Number parse(String text, ParsePosition parsePosition) { 215 long num = 0; 216 boolean sawNumber = false; 217 boolean negative = false; 218 int base = parsePosition.getIndex(); 219 int offset = 0; 220 for (; base + offset < text.length(); offset++) { 221 char ch = text.charAt(base + offset); 222 if (offset == 0 && ch == minusSign) { 223 if (positiveOnly) { 224 break; 225 } 226 negative = true; 227 } else { 228 int digit = ch - digits[0]; 229 if (digit < 0 || 9 < digit) { 230 digit = UCharacter.digit(ch); 231 } 232 if (digit < 0 || 9 < digit) { 233 for ( digit = 0 ; digit < 10 ; digit++ ) { 234 if ( ch == digits[digit]) { 235 break; 236 } 237 } 238 } 239 if (0 <= digit && digit <= 9 && num < PARSE_THRESHOLD) { 240 sawNumber = true; 241 num = num * 10 + digit; 242 } else { 243 break; 244 } 245 } 246 } 247 Number result = null; 248 if (sawNumber) { 249 num = negative ? num * (-1) : num; 250 result = Long.valueOf(num); 251 parsePosition.setIndex(base + offset); 252 } 253 return result; 254 } 255 256 @Override equals(Object obj)257 public boolean equals(Object obj) { 258 if (obj == null || !super.equals(obj) || !(obj instanceof DateNumberFormat)) { 259 return false; 260 } 261 DateNumberFormat other = (DateNumberFormat)obj; 262 return (this.maxIntDigits == other.maxIntDigits 263 && this.minIntDigits == other.minIntDigits 264 && this.minusSign == other.minusSign 265 && this.positiveOnly == other.positiveOnly 266 && Arrays.equals(this.digits, other.digits)); 267 } 268 269 @Override hashCode()270 public int hashCode() { 271 return super.hashCode(); 272 } 273 readObject(ObjectInputStream stream)274 private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { 275 stream.defaultReadObject(); 276 if (digits == null) { 277 setZeroDigit(zeroDigit); 278 } 279 // re-allocate the work buffer 280 decimalBuf = new char[DECIMAL_BUF_SIZE]; 281 } 282 283 @Override clone()284 public Object clone() { 285 DateNumberFormat dnfmt = (DateNumberFormat)super.clone(); 286 dnfmt.digits = this.digits.clone(); 287 dnfmt.decimalBuf = new char[DECIMAL_BUF_SIZE]; 288 return dnfmt; 289 } 290 } 291 292 //eof 293