]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-52_1/main/classes/core/src/com/ibm/icu/impl/duration/impl/Utils.java
Clean up imports.
[Dictionary.git] / jars / icu4j-52_1 / main / classes / core / src / com / ibm / icu / impl / duration / impl / Utils.java
1 /*
2 ******************************************************************************
3 * Copyright (C) 2007-2012, International Business Machines Corporation and   *
4 * others. All Rights Reserved.                                               *
5 ******************************************************************************
6 */
7
8 package com.ibm.icu.impl.duration.impl;
9
10 import java.util.Locale;
11
12 public class Utils {
13   public static final Locale localeFromString(String s) {
14     String language = s;
15     String region = "";
16     String variant = "";
17
18     int x = language.indexOf("_");
19     if (x != -1) {
20       region = language.substring(x+1);
21       language = language.substring(0, x);
22     }
23     x = region.indexOf("_");
24     if (x != -1) {
25       variant = region.substring(x+1);
26       region = region.substring(0, x);
27     }
28     return new Locale(language, region, variant);
29   }
30     /*
31   public static <T> T[] arraycopy(T[] src) {
32     T[] result = (T[])Array.newInstance(src.getClass().getComponentType(), src.length); // can we do this without casting?
33     for (int i = 0; i < src.length; ++i) {
34       result[i] = src[i];
35     }
36     return result;
37   }
38     */
39
40   /**
41    * Interesting features of chinese numbers:
42    * - Each digit is followed by a unit symbol (10's, 100's, 1000's).
43    * - Units repeat in levels of 10,000, there are symbols for each level too (except 1's).
44    * - The digit 2 has a special form before the 10 symbol and at the end of the number.
45    * - If the first digit in the number is 1 and its unit is 10, the 1 is omitted.
46    * - Sequences of 0 digits and their units are replaced by a single 0 and no unit.
47    * - If there are two such sequences of 0 digits in a level (1000's and 10's), the 1000's 0 is also omitted.
48    * - The 1000's 0 is also omitted in alternating levels, such that it is omitted in the rightmost
49    *     level with a 10's 0, or if none, in the rightmost level.
50    * - Level symbols are omitted if all of their units are omitted
51    */
52   public static String chineseNumber(long n, ChineseDigits zh) {
53     if (n < 0) {
54       n = -n;
55     }
56     if (n <= 10) {
57       if (n == 2) {
58         return String.valueOf(zh.liang);
59       }
60       return String.valueOf(zh.digits[(int)n]);
61     }
62
63     // 9223372036854775807
64     char[] buf = new char[40]; // as long as we get, and actually we can't get this high, no units past zhao
65     char[] digits = String.valueOf(n).toCharArray();
66
67     // first, generate all the digits in place
68     // convert runs of zeros into a single zero, but keep places
69     // 
70     boolean inZero = true; // true if we should zap zeros in this block, resets at start of block
71     boolean forcedZero = false; // true if we have a 0 in tens's place
72     int x = buf.length;
73     for (int i = digits.length, u = -1, l = -1; --i >= 0;) {
74       if (u == -1) {
75         if (l != -1) {
76           buf[--x] = zh.levels[l];
77           inZero = true;
78           forcedZero = false;
79         }
80         ++u;
81       } else {
82         buf[--x] = zh.units[u++];
83         if (u == 3) {
84           u = -1;
85           ++l;
86         }
87       }
88       int d = digits[i] - '0';
89       if (d == 0) {
90         if (x < buf.length-1 && u != 0) {
91           buf[x] = '*';
92         }
93         if (inZero || forcedZero) {
94           buf[--x] = '*';
95         } else {
96           buf[--x] = zh.digits[0];
97           inZero = true;
98           forcedZero = u == 1;
99         }
100       } else {
101         inZero = false;
102         buf[--x] = zh.digits[d];
103       }
104     }
105
106     // scanning from right, find first required 'ling'
107     // we only care if n > 101,0000 as this is the first case where
108     // it might shift.  remove optional lings in alternating blocks.
109     if (n > 1000000) {
110       boolean last = true;
111       int i = buf.length - 3;
112       do {
113         if (buf[i] == '0') {
114           break;
115         }
116         i -= 8;
117         last = !last;
118       } while (i > x);
119
120       i = buf.length - 7;
121       do {
122         if (buf[i] == zh.digits[0] && !last) {
123           buf[i] = '*';
124         }
125         i -= 8;
126         last = !last;
127       } while (i > x);
128
129       // remove levels for empty blocks
130       if (n >= 100000000) {
131         i = buf.length - 8;
132         do {
133           boolean empty = true;
134           for (int j = i-1, e = Math.max(x-1, i-8); j > e; --j) {
135             if (buf[j] != '*') {
136               empty = false;
137               break;
138             }
139           }
140           if (empty) {
141             if (buf[i+1] != '*' && buf[i+1] != zh.digits[0]) {
142               buf[i] = zh.digits[0];
143             } else {
144               buf[i] = '*';
145             }
146           }
147           i -= 8;
148         } while (i > x);
149       }          
150     }
151
152     // replace er by liang except before or after shi or after ling
153     for (int i = x; i < buf.length; ++i) {
154       if (buf[i] != zh.digits[2]) continue;
155       if (i < buf.length - 1 && buf[i+1] == zh.units[0]) continue;
156       if (i > x && (buf[i-1] == zh.units[0] || buf[i-1] == zh.digits[0] || buf[i-1] == '*')) continue;
157
158       buf[i] = zh.liang;
159     }
160     
161     // eliminate leading 1 if following unit is shi
162     if (buf[x] == zh.digits[1] && (zh.ko || buf[x+1] == zh.units[0])) {
163       ++x;
164     }
165
166     // now, compress out the '*'
167     int w = x;
168     for (int r = x; r < buf.length; ++r) {
169       if (buf[r] != '*') {
170         buf[w++] = buf[r];
171       }
172     }
173     return new String(buf, x, w-x);
174   }
175
176 //  public static void main(String[] args) {
177 //    for (int i = 0; i < args.length; ++i) {
178 //      String arg = args[i];
179 //      System.out.print(arg);
180 //      System.out.print(" > ");
181 //      long n = Long.parseLong(arg);
182 //      System.out.println(chineseNumber(n, ChineseDigits.DEBUG));
183 //    }
184 //  }
185
186   public static class ChineseDigits {
187     final char[] digits;
188     final char[] units;
189     final char[] levels;
190     final char liang;
191     final boolean ko;
192
193     ChineseDigits(String digits, String units, String levels, char liang, boolean ko) {
194       this.digits = digits.toCharArray();
195       this.units = units.toCharArray();
196       this.levels = levels.toCharArray();
197       this.liang = liang;
198       this.ko = ko;
199     }
200
201     public static final ChineseDigits DEBUG = 
202       new ChineseDigits("0123456789s", "sbq", "WYZ", 'L', false);
203
204     public static final ChineseDigits TRADITIONAL = 
205       new ChineseDigits("\u96f6\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d\u5341", // to shi
206                         "\u5341\u767e\u5343", // shi, bai, qian
207                         "\u842c\u5104\u5146", // wan, yi, zhao
208                         '\u5169', false); // liang
209
210     public static final ChineseDigits SIMPLIFIED = 
211       new ChineseDigits("\u96f6\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d\u5341", // to shi
212                         "\u5341\u767e\u5343", // shi, bai, qian
213                         "\u4e07\u4ebf\u5146", // wan, yi, zhao
214                         '\u4e24', false); // liang
215     
216     // no 1 before first unit no matter what it is
217     // not sure if there are 'ling' units
218     public static final ChineseDigits KOREAN =
219       new ChineseDigits("\uc601\uc77c\uc774\uc0bc\uc0ac\uc624\uc721\uce60\ud314\uad6c\uc2ed", // to ten
220                         "\uc2ed\ubc31\ucc9c", // 10, 100, 1000
221                         "\ub9cc\uc5b5?", // 10^4, 10^8, 10^12
222                         '\uc774', true);
223   }
224 }