diff options
author | Tom Tromey <tromey@cygnus.com> | 1999-04-26 15:34:44 +0000 |
---|---|---|
committer | Tom Tromey <tromey@gcc.gnu.org> | 1999-04-26 15:34:44 +0000 |
commit | 3cc26081445329aec4d4711d69c0d86e05af841b (patch) | |
tree | a49553afea7d22437a2921c9b7915e6152eb4206 /libjava | |
parent | d5d9a8b6c3dce9425129aa7ee9bd5ab69ae27c2a (diff) | |
download | gcc-3cc26081445329aec4d4711d69c0d86e05af841b.zip gcc-3cc26081445329aec4d4711d69c0d86e05af841b.tar.gz gcc-3cc26081445329aec4d4711d69c0d86e05af841b.tar.bz2 |
GregorianCalendar.java (setDefaultTime): New method.
* java/util/GregorianCalendar.java (setDefaultTime): New method.
(GregorianCalendar): Use it in all constructors.
* java/util/Calendar.java (Calendar): Changed argument name to
`zone' to match code.
* gnu/gcj/text/LocaleData_en.java: Added collatorRule element.
* java/text/CollationKey.java: New file.
* java/text/CollationElementIterator.java: New file.
* java/text/Collator.java: New file.
* java/text/RuleBasedCollator.java: New file.
From-SVN: r26654
Diffstat (limited to 'libjava')
-rw-r--r-- | libjava/ChangeLog | 11 | ||||
-rw-r--r-- | libjava/gnu/gcj/text/LocaleData_en.java | 8 | ||||
-rw-r--r-- | libjava/java/text/CollationElementIterator.java | 75 | ||||
-rw-r--r-- | libjava/java/text/CollationKey.java | 104 | ||||
-rw-r--r-- | libjava/java/text/Collator.java | 130 | ||||
-rw-r--r-- | libjava/java/text/RuleBasedCollator.java | 361 | ||||
-rw-r--r-- | libjava/java/util/Calendar.java | 2 | ||||
-rw-r--r-- | libjava/java/util/GregorianCalendar.java | 9 |
8 files changed, 698 insertions, 2 deletions
diff --git a/libjava/ChangeLog b/libjava/ChangeLog index b320d0c..af7aa2e 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -1,5 +1,16 @@ 1999-04-26 Tom Tromey <tromey@cygnus.com> + * java/util/GregorianCalendar.java (setDefaultTime): New method. + (GregorianCalendar): Use it in all constructors. + * java/util/Calendar.java (Calendar): Changed argument name to + `zone' to match code. + + * gnu/gcj/text/LocaleData_en.java: Added collatorRule element. + * java/text/CollationKey.java: New file. + * java/text/CollationElementIterator.java: New file. + * java/text/Collator.java: New file. + * java/text/RuleBasedCollator.java: New file. + * Makefile.in: Rebuilt. * Makefile.am (jv_convert_LDFLAGS): Added -nodefaultlibs. (jv_convert_LDADD): Explicltly add -lm -lc. diff --git a/libjava/gnu/gcj/text/LocaleData_en.java b/libjava/gnu/gcj/text/LocaleData_en.java index df5a0de..1286e8a 100644 --- a/libjava/gnu/gcj/text/LocaleData_en.java +++ b/libjava/gnu/gcj/text/LocaleData_en.java @@ -65,7 +65,13 @@ public final class LocaleData_en extends ListResourceBundle { "months", monthsDefault }, { "shortMonths", shortMonthsDefault }, { "shortWeekdays", shortWeekdaysDefault }, - { "weekdays", weekdaysDefault } + { "weekdays", weekdaysDefault }, + + // For RuleBasedCollator. + // FIXME: this is nowhere near complete. + // In particular we must mark accents as ignorable, + // and probably other things as well. + { "collatorRule", "0 < 1 < 2 < 3 < 4 < 5 < 6 < 7 < 8 < 9 < a,A < b,B < c,C < d,D < e,E < f,F < g,G < h,H < i,I < j,J < k,K < l,L < m,M < n,N < o,O < p,P < q,Q < r,R < s,S < t,T < u,U < v,V < w,W < x,X < y,Y < z,Z" } }; protected Object[][] getContents () diff --git a/libjava/java/text/CollationElementIterator.java b/libjava/java/text/CollationElementIterator.java new file mode 100644 index 0000000..a654629 --- /dev/null +++ b/libjava/java/text/CollationElementIterator.java @@ -0,0 +1,75 @@ +// CollationElementIterator.java - Iterate over decomposed characters. + +/* Copyright (C) 1999 Cygnus Solutions + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +package java.text; + +/** + * @author Tom Tromey <tromey@cygnus.com> + * @date March 25, 1999 + */ +/* Written using "Java Class Libraries", 2nd edition, plus online + * API docs for JDK 1.2 from http://www.javasoft.com. + * Status: Believed complete and correct to JDK 1.1. + */ + +public final class CollationElementIterator +{ + public static final int NULLORDER = 0xffffffff; + + public int next () + { + if (index == text.length()) + return NULLORDER; + return RuleBasedCollator.ceiNext(this); + } + + // This one returns int while the others return short. + public static final int primaryOrder (int order) + { + // From the JDK 1.2 spec. + return order >>> 16; + } + + public void reset () + { + index = 0; + } + + public static final short secondaryOrder (int order) + { + // From the JDK 1.2 spec. + return (order >>> 8) & 255; + } + + public static final short tertiaryOrder (int order) + { + // From the JDK 1.2 spec. + return order & 255; + } + + // Non-public constructor. + CollationElementIterator (String text) + { + this.text = text; + this.index = 0; + this.lookahead_set = false; + this.lookahead = 0; + } + + // Text over which we iterate. + String text; + + // Index of next character to examine in TEXT. + int index; + + // A piece of lookahead. + boolean lookahead_set; + int lookahead; +} diff --git a/libjava/java/text/CollationKey.java b/libjava/java/text/CollationKey.java new file mode 100644 index 0000000..05a9932 --- /dev/null +++ b/libjava/java/text/CollationKey.java @@ -0,0 +1,104 @@ +// CollationKey.java - Sort key for locale-sensitive String. + +/* Copyright (C) 1999 Cygnus Solutions + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +package java.text; + +/** + * @author Tom Tromey <tromey@cygnus.com> + * @date March 25, 1999 + */ +/* Written using "Java Class Libraries", 2nd edition, plus online + * API docs for JDK 1.2 from http://www.javasoft.com. + * Status: Believed complete and correct. + */ + +public final class CollationKey +{ + public int compareTo (CollationKey target) + { + int max = Math.min(key.length, target.key.length); + + for (int i = 0; i < max; ++i) + { + if (key[i] != target.key[i]) + return key[i] - target.key[i]; + } + + return key.length - target.key.length; + } + + public boolean equals (Object obj) + { + if (! (obj instanceof CollationKey)) + return false; + + CollationKey ck = (CollationKey) obj; + + if (key.length != ck.key.length) + return false; + + for (int i = 0; i < key.length; ++i) + if (key[i] != ck.key[i]) + return false; + + return true; + } + + public String getSourceString () + { + return originalText; + } + + public int hashCode () + { + // We just follow BitSet instead of thinking up something new. + long h = originalText.hashCode(); + for (int i = key.length - 1; i >= 0; --i) + h ^= key[i] * (i + 1); + return (int) ((h >> 32) ^ h); + } + + public byte[] toByteArray () + { + byte[] r = new byte[4 * key.length]; + int off = 0; + for (int i = 0; i < key.length; ++i) + { + r[off++] = (byte) ((key[i] >>> 24) & 255); + r[off++] = (byte) ((key[i] >>> 16) & 255); + r[off++] = (byte) ((key[i] >>> 8) & 255); + r[off++] = (byte) ((key[i] ) & 255); + } + return r; + } + + CollationKey (CollationElementIterator iter, String originalText, + int strength) + { + this.originalText = originalText; + + // Compute size of required array. + int size = 0; + while (RuleBasedCollator.next(iter, strength) + != CollationElementIterator.NULLORDER) + ++size; + + iter.reset(); + key = new int[size]; + for (int i = 0; i < size; i++) + key[i] = RuleBasedCollator.next(iter, strength); + } + + // Original string. + private String originalText; + + // Collation key. + private int[] key; +} diff --git a/libjava/java/text/Collator.java b/libjava/java/text/Collator.java new file mode 100644 index 0000000..ad7a5ca --- /dev/null +++ b/libjava/java/text/Collator.java @@ -0,0 +1,130 @@ +// Collator.java - Locale-sensitive string comparison. + +/* Copyright (C) 1999 Cygnus Solutions + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +package java.text; + +import java.io.Serializable; +import java.util.Locale; +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +/** + * @author Tom Tromey <tromey@cygnus.com> + * @date March 18, 1999 + */ +/* Written using "Java Class Libraries", 2nd edition, plus online + * API docs for JDK 1.2 from http://www.javasoft.com. + * Status: Mostly complete, but parts stubbed out. Look for FIXME. + */ + +public abstract class Collator implements Cloneable, Serializable +{ + public static final int NO_DECOMPOSITION = 0; + public static final int CANONCIAL_DECOMPOSITION = 1; + public static final int FULL_DECOMPOSITION = 2; + + public static final int PRIMARY = 0; + public static final int SECONDARY = 1; + public static final int TERTIARY = 2; + public static final int IDENTICAL = 3; + + protected Collator () + { + strength = TERTIARY; + decmp = CANONCIAL_DECOMPOSITION; + } + + public abstract int compare (String source, String target); + + public boolean equals (Object obj) + { + if (! (obj instanceof Collator)) + return false; + Collator c = (Collator) obj; + return decmp == c.decmp && strength == c.strength; + } + + public boolean equals (String source, String target) + { + return compare (source, target) == 0; + } + + public static synchronized Locale[] getAvailableLocales () + { + // FIXME. + return null; + } + + public abstract CollationKey getCollationKey (String source); + + public synchronized int getDecomposition () + { + return decmp; + } + + public static Collator getInstance () + { + return getInstance (Locale.getDefault()); + } + + public static Collator getInstance (Locale loc) + { + ResourceBundle res; + String pattern; + try + { + res = ResourceBundle.getBundle("gnu.gcj.text.LocaleData", loc); + pattern = res.getString("collatorRule"); + } + catch (MissingResourceException x) + { + return null; + } + try + { + return new RuleBasedCollator (pattern); + } + catch (ParseException x) + { + return null; + } + } + + public synchronized int getStrength () + { + return strength; + } + + public abstract int hashCode (); + + public synchronized void setDecomposition (int mode) + { + if (mode != NO_DECOMPOSITION + && mode != CANONCIAL_DECOMPOSITION + && mode != FULL_DECOMPOSITION) + throw new IllegalArgumentException (); + decmp = mode; + } + + public synchronized void setStrength (int strength) + { + if (strength != PRIMARY && strength != SECONDARY + && strength != TERTIARY && strength != IDENTICAL) + throw new IllegalArgumentException (); + this.strength = strength; + } + + // Decompose a single character and append results to the buffer. + protected native final void decomposeCharacter (char c, StringBuffer buf); + + // These names are fixed by the serialization spec. + protected int decmp; + protected int strength; +} diff --git a/libjava/java/text/RuleBasedCollator.java b/libjava/java/text/RuleBasedCollator.java new file mode 100644 index 0000000..18046ad --- /dev/null +++ b/libjava/java/text/RuleBasedCollator.java @@ -0,0 +1,361 @@ +// RuleBasedCollator.java - Concrete class for locale-based string compare. + +/* Copyright (C) 1999 Cygnus Solutions + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +package java.text; + +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Vector; + +/** + * @author Tom Tromey <tromey@cygnus.com> + * @date March 25, 1999 + */ +/* Written using "Java Class Libraries", 2nd edition, plus online + * API docs for JDK 1.2 from http://www.javasoft.com. + * Status: Believed complete and correct + */ + +class RBCElement +{ + String key; + char relation; + + RBCElement (String key, char relation) + { + this.key = key; + this.relation = relation; + } +} + +public class RuleBasedCollator extends Collator +{ + public Object clone () + { + return new RuleBasedCollator (this); + } + + // A helper for CollationElementIterator.next(). + static int ceiNext (CollationElementIterator cei) + { + if (cei.lookahead_set) + { + cei.lookahead_set = false; + return cei.lookahead; + } + + int save = cei.index; + int max = cei.text.length(); + String s = null; + + // It is possible to have a case where `abc' has a mapping, but + // neither `ab' nor `abd' do. In this case we must treat `abd' as + // nothing special. + boolean found = false; + + int i; + for (i = save; i < max; ++i) + { + s = cei.text.substring(save, i); + if (prefixes.get(s) == null) + break; + found = true; + } + // Assume s != null. + + Object obj = map.get(s); + // The special case. + while (found && obj == null && s.length() > 1) + { + --i; + s = cei.text.substring(save, i); + obj = map.get(s); + } + + // Update state. + cei.index = i; + + if (obj == null) + { + // This idea, and the values, come from JDK. + // assert (s.length() == 1) + cei.lookahead_set = true; + cei.lookahead = s.charAt(0) << 8; + return 0x7fff << 16; + } + + return ((Integer) obj).intValue(); + } + + // A helper for compareTo() that returns the next character that has + // a nonzero ordering at the indicated strength. This is also used + // in CollationKey. + static final int next (CollationElementIterator iter, int strength) + { + while (true) + { + int os = iter.next(); + if (os == CollationElementIterator.NULLORDER) + return os; + int c = 0; + switch (strength) + { + case PRIMARY: + c |= CollationElementIterator.primaryOrder(os); + /* Fall through. */ + case SECONDARY: + c |= CollationElementIterator.secondaryOrder(os); + /* Fall through. */ + case TERTIARY: + c |= CollationElementIterator.tertiaryOrder(os); + break; + case IDENTICAL: + c = os; + } + if (c != 0) + return c; + } + } + + public int compare (String source, String target) + { + CollationElementIterator cs, ct; + + cs = new CollationElementIterator (source); + ct = new CollationElementIterator (target); + + while (true) + { + int os = next (cs, strength); + int ot = next (ct, strength); + + if (os == CollationElementIterator.NULLORDER + && ot == CollationElementIterator.NULLORDER) + break; + else if (os == CollationElementIterator.NULLORDER) + return 1; + else if (ot == CollationElementIterator.NULLORDER) + return -1; + + if (os != ot) + return os - ot; + } + + return 0; + } + + public boolean equals (Object obj) + { + if (! (obj instanceof RuleBasedCollator) || ! super.equals(obj)) + return false; + RuleBasedCollator rbc = (RuleBasedCollator) obj; + // FIXME: this is probably wrong. Instead we should compare maps + // directly. + return (frenchAccents == rbc.frenchAccents + && rules.equals(rbc.rules)); + } + + public CollationElementIterator getCollationElementIterator (String source) + { + StringBuffer expand = new StringBuffer (source.length()); + int max = source.length(); + for (int i = 0; i < max; ++i) + decomposeCharacter (source.charAt(i), expand); + return new CollationElementIterator (expand.toString()); + } + + public CollationKey getCollationKey (String source) + { + return new CollationKey (getCollationElementIterator (source), source, + strength); + } + + public String getRules () + { + return rules; + } + + public int hashCode () + { + return (frenchAccents ? 1231 : 1237 + ^ rules.hashCode() + ^ map.hashCode() + ^ prefixes.hashCode()); + } + + private final boolean is_special (char c) + { + // Rules from JCL book. + return ((c >= 0x0009 && c <= 0x000d) + || (c >= 0x0020 && c <= 0x002f) + || (c >= 0x003a && c <= 0x0040) + || (c >= 0x005b && c <= 0x0060) + || (c >= 0x007b && c <= 0x007e)); + } + + private final int text_argument (String rules, int index, + StringBuffer result) + { + result.setLength(0); + int len = rules.length(); + while (index < len) + { + char c = rules.charAt(index); + if (c == '\'' && index + 2 < len + && rules.charAt(index + 2) == '\'' + && is_special (rules.charAt(index + 1))) + index += 2; + else if (is_special (c) || Character.isWhitespace(c)) + return index; + result.append(c); + ++index; + } + return index; + } + + public RuleBasedCollator (String rules) throws ParseException + { + this.rules = rules; + this.frenchAccents = false; + + // We keep each rule in order in a vector. At the end we traverse + // the vector and compute collation values from it. + int insertion_index = 0; + Vector vec = new Vector (); + + StringBuffer argument = new StringBuffer (); + + int len = rules.length(); + for (int index = 0; index < len; ++index) + { + char c = rules.charAt(index); + + // Just skip whitespace. + if (Character.isWhitespace(c)) + continue; + + // Modifier. + if (c == '@') + { + frenchAccents = true; + continue; + } + + // Check for relation or reset operator. + if (! (c == '<' || c == ';' || c == ',' || c == '=' || c == '&')) + throw new ParseException ("invalid character", index); + + ++index; + while (index < len) + { + if (! Character.isWhitespace(rules.charAt(index))) + break; + ++index; + } + if (index == len) + throw new ParseException ("missing argument", index); + + int save = index; + index = text_argument (rules, index, argument); + if (argument.length() == 0) + throw new ParseException ("invalid character", save); + String arg = argument.toString(); + int item_index = vec.indexOf(arg); + if (c != '&') + { + // If the argument already appears in the vector, then we + // must remove it in order to re-order. + if (item_index != -1) + { + vec.removeElementAt(item_index); + if (insertion_index >= item_index) + --insertion_index; + } + RBCElement r = new RBCElement (arg, c); + vec.insertElementAt(r, insertion_index); + ++insertion_index; + } + else + { + // Reset. + if (item_index == -1) + throw + new ParseException ("argument to reset not previously seen", + save); + insertion_index = item_index + 1; + } + + // Ugly: in this case the resulting INDEX comes from + // text_argument, which returns the index of the next + // character we should examine. + --index; + } + + // Now construct a hash table that maps strings onto their + // collation values. + int primary = 0; + int secondary = 0; + int tertiary = 0; + this.map = new Hashtable (); + this.prefixes = new Hashtable (); + Enumeration e = vec.elements(); + while (e.hasMoreElements()) + { + RBCElement r = (RBCElement) e.nextElement(); + switch (r.relation) + { + case '<': + ++primary; + secondary = 0; + tertiary = 0; + break; + case ';': + ++secondary; + tertiary = 0; + break; + case ',': + ++tertiary; + break; + case '=': + break; + } + // This must match CollationElementIterator. + map.put(r.key, new Integer (primary << 16 + | secondary << 8 | tertiary)); + + // Make a map of all lookaheads we might need. + for (int i = r.key.length() - 1; i >= 1; --i) + prefixes.put(r.key.substring(0, i), Boolean.TRUE); + } + } + + // This is a helper for clone. + private RuleBasedCollator (RuleBasedCollator other) + { + frenchAccents = other.frenchAccents; + rules = other.rules; + decmp = other.decmp; + strength = other.strength; + map = other.map; + prefixes = other.prefixes; + } + + // True if we are using French-style accent ordering. + private boolean frenchAccents; + + // It's easier to just save the rules than to try to recreate them. + private String rules; + + // This maps strings onto collation values. + private Hashtable map; + // An entry in this hash means that more lookahead is required for + // the prefix string. + private Hashtable prefixes; +} diff --git a/libjava/java/util/Calendar.java b/libjava/java/util/Calendar.java index 8649adf..f4806a3 100644 --- a/libjava/java/util/Calendar.java +++ b/libjava/java/util/Calendar.java @@ -88,7 +88,7 @@ public abstract class Calendar implements java.io.Serializable, Cloneable this (null, null); } - protected Calendar (TimeZone tx, Locale loc) + protected Calendar (TimeZone zone, Locale loc) { fields = new int[FIELD_COUNT]; isSet = new boolean[FIELD_COUNT]; diff --git a/libjava/java/util/GregorianCalendar.java b/libjava/java/util/GregorianCalendar.java index d20c06e..26a9814 100644 --- a/libjava/java/util/GregorianCalendar.java +++ b/libjava/java/util/GregorianCalendar.java @@ -107,11 +107,13 @@ public class GregorianCalendar extends Calendar { public GregorianCalendar (TimeZone zone, Locale locale) { super (zone, locale); + setDefaultTime (); } public GregorianCalendar (int year, int month, int date) { this((TimeZone) null); + setDefaultTime (); set (year, month, date); } @@ -119,6 +121,7 @@ public class GregorianCalendar extends Calendar { int hour, int minute) { this((TimeZone) null); + setDefaultTime (); set (year, month, date, hour, minute); } @@ -126,9 +129,15 @@ public class GregorianCalendar extends Calendar { int hour, int minute, int second) { this((TimeZone) null); + setDefaultTime (); set (year, month, date, hour, minute, second); } + private final void setDefaultTime () + { + setTimeInMillis (System.currentTimeMillis()); + } + public int getMinimum(int calfield) { return mins[calfield]; } public int getGreatestMinimum(int calfield) { return mins[calfield]; } public int getMaximum(int calfield) { return maxs[calfield]; } |