• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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