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