2 ******************************************************************************
\r
3 * Copyright (C) 2007, International Business Machines Corporation and *
\r
4 * others. All Rights Reserved. *
\r
5 ******************************************************************************
\r
8 package com.ibm.icu.impl.duration.impl;
\r
10 import java.util.Locale;
\r
12 public class Utils {
\r
13 public static final Locale localeFromString(String s) {
\r
14 String language = s;
\r
16 String variant = "";
\r
18 int x = language.indexOf("_");
\r
20 region = language.substring(x+1);
\r
21 language = language.substring(0, x);
\r
23 x = region.indexOf("_");
\r
25 variant = region.substring(x+1);
\r
26 region = region.substring(0, x);
\r
28 return new Locale(language, region, variant);
\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
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
52 public static String chineseNumber(long n, ChineseDigits zh) {
\r
58 return String.valueOf(zh.liang);
\r
60 return String.valueOf(zh.digits[(int)n]);
\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
67 // first, generate all the digits in place
\r
68 // convert runs of zeros into a single zero, but keep places
\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
73 for (int i = digits.length, u = -1, l = -1; --i >= 0;) {
\r
76 buf[--x] = zh.levels[l];
\r
82 buf[--x] = zh.units[u++];
\r
88 int d = digits[i] - '0';
\r
90 if (x < buf.length-1 && u != 0) {
\r
93 if (inZero || forcedZero) {
\r
96 buf[--x] = zh.digits[0];
\r
98 forcedZero = u == 1;
\r
102 buf[--x] = zh.digits[d];
\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
110 boolean last = true;
\r
111 int i = buf.length - 3;
\r
113 if (buf[i] == '0') {
\r
120 i = buf.length - 7;
\r
122 if (buf[i] == zh.digits[0] && !last) {
\r
129 // remove levels for empty blocks
\r
130 if (n >= 100000000) {
\r
131 i = buf.length - 8;
\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
141 if (buf[i+1] != '*' && buf[i+1] != zh.digits[0]) {
\r
142 buf[i] = zh.digits[0];
\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
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
166 // now, compress out the '*'
\r
168 for (int r = x; r < buf.length; ++r) {
\r
169 if (buf[r] != '*') {
\r
173 return new String(buf, x, w-x);
\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
186 public static class ChineseDigits {
\r
187 final char[] digits;
\r
188 final char[] units;
\r
189 final char[] levels;
\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
201 public static final ChineseDigits DEBUG =
\r
202 new ChineseDigits("0123456789s", "sbq", "WYZ", 'L', false);
\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
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
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