* 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
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.
{ "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 ()
--- /dev/null
+// 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;
+}
--- /dev/null
+// 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;
+}
--- /dev/null
+// 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;
+}
--- /dev/null
+// 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;
+}
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];
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);
}
int hour, int minute)
{
this((TimeZone) null);
+ setDefaultTime ();
set (year, month, date, hour, minute);
}
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]; }