GregorianCalendar.java (setDefaultTime): New method.
authorTom Tromey <tromey@cygnus.com>
Mon, 26 Apr 1999 15:34:44 +0000 (15:34 +0000)
committerTom Tromey <tromey@gcc.gnu.org>
Mon, 26 Apr 1999 15:34:44 +0000 (15:34 +0000)
* 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

libjava/ChangeLog
libjava/gnu/gcj/text/LocaleData_en.java
libjava/java/text/CollationElementIterator.java [new file with mode: 0644]
libjava/java/text/CollationKey.java [new file with mode: 0644]
libjava/java/text/Collator.java [new file with mode: 0644]
libjava/java/text/RuleBasedCollator.java [new file with mode: 0644]
libjava/java/util/Calendar.java
libjava/java/util/GregorianCalendar.java

index b320d0ce5512247336e9b481e3e2c320978964e7..af7aa2e1148b44b3127db0391eb4450d1a25d0d1 100644 (file)
@@ -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.
index df5a0de8a403d4cebe1897b059525913a025ffc0..1286e8af3ef2fd95288b119de8d8b0abc9abeba8 100644 (file)
@@ -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 (file)
index 0000000..a654629
--- /dev/null
@@ -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 (file)
index 0000000..05a9932
--- /dev/null
@@ -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 (file)
index 0000000..ad7a5ca
--- /dev/null
@@ -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 (file)
index 0000000..18046ad
--- /dev/null
@@ -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;
+}
index 8649adf600dec0dd9cfdd613b00dea3a24c91af1..f4806a35bdc2e1335244d615eb7cd45b8588567e 100644 (file)
@@ -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];
index d20c06ef8252e58afe085b5d1ab6ea5f0c099d1b..26a9814fc8cb8ac7befefb464cc20a591378d349 100644 (file)
@@ -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]; }