natString.cc: Include Locale.h.

* java/lang/natString.cc: Include Locale.h.
	(toUpperCase): Added `locale' argument.  Handle locale
	sensitivity.
	(toLowerCase): Added `locale' argument.  Handle locale
	sensitivity.
	(ESSET, CAPITAL_S, SMALL_I, CAPITAL_I_WITH_DOT, SMALL_DOTLESS_I,
	CAPITAL_I): New defines.
	* java/lang/String.java (CASE_INSENSITIVE_ORDER): Now public and
	final.
	Import Locale.
	(toUpperCase, toLowerCase): New methods.  Variants which accept
	locale now native.

	* java/lang/ExceptionInInitializerError.java (printStackTrace):
	New methods.

	* java/util/PropertyPermission.java: Re-merged from Classpath.

	* java/text/RuleBasedCollator.java (getCollationElementIterator):
	New method.
	* java/text/StringCharacterIterator.java: Reindented.
	(setText): New method.

From-SVN: r37539
This commit is contained in:
Tom Tromey 2000-11-18 02:29:13 +00:00 committed by Tom Tromey
parent c5f651bf3f
commit 9839499072
7 changed files with 327 additions and 159 deletions

View file

@ -1,3 +1,28 @@
2000-11-17 Tom Tromey <tromey@cygnus.com>
* java/lang/natString.cc: Include Locale.h.
(toUpperCase): Added `locale' argument. Handle locale
sensitivity.
(toLowerCase): Added `locale' argument. Handle locale
sensitivity.
(ESSET, CAPITAL_S, SMALL_I, CAPITAL_I_WITH_DOT, SMALL_DOTLESS_I,
CAPITAL_I): New defines.
* java/lang/String.java (CASE_INSENSITIVE_ORDER): Now public and
final.
Import Locale.
(toUpperCase, toLowerCase): New methods. Variants which accept
locale now native.
* java/lang/ExceptionInInitializerError.java (printStackTrace):
New methods.
* java/util/PropertyPermission.java: Re-merged from Classpath.
* java/text/RuleBasedCollator.java (getCollationElementIterator):
New method.
* java/text/StringCharacterIterator.java: Reindented.
(setText): New method.
2000-11-17 Mark Wielaar <mark@klomp.org> 2000-11-17 Mark Wielaar <mark@klomp.org>
Merge with Classpath (changes by Bryce McKinlay) Merge with Classpath (changes by Bryce McKinlay)

View file

@ -1,6 +1,6 @@
// ExceptionInInitializerError.java // ExceptionInInitializerError.java
/* Copyright (C) 1998, 1999 Free Software Foundation /* Copyright (C) 1998, 1999, 2000 Free Software Foundation
This file is part of libgcj. This file is part of libgcj.
@ -9,6 +9,8 @@ Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */ details. */
package java.lang; package java.lang;
import java.io.PrintStream;
import java.io.PrintWriter;
/** /**
* @author Tom Tromey <tromey@cygnus.com> * @author Tom Tromey <tromey@cygnus.com>
@ -45,6 +47,21 @@ public class ExceptionInInitializerError extends LinkageError
return exception; return exception;
} }
public void printStackTrace ()
{
exception.printStackTrace ();
}
public void printStackTrace (PrintStream ps)
{
exception.printStackTrace (ps);
}
public void printStackTrace (PrintWriter pw)
{
exception.printStackTrace (pw);
}
// The exception that caused this error. // The exception that caused this error.
private Throwable exception; private Throwable exception;
} }

View file

@ -11,6 +11,7 @@ import java.io.UnsupportedEncodingException;
import java.io.Serializable; import java.io.Serializable;
import java.lang.Comparable; import java.lang.Comparable;
import java.util.Comparator; import java.util.Comparator;
import java.util.Locale;
/** /**
* @author Per Bothner <bothner@cygnus.com> * @author Per Bothner <bothner@cygnus.com>
@ -31,13 +32,13 @@ public final class String implements Serializable, Comparable
// but it will avoid showing up as a discrepancy when comparing SUIDs. // but it will avoid showing up as a discrepancy when comparing SUIDs.
private static final long serialVersionUID = -6849794470754667710L; private static final long serialVersionUID = -6849794470754667710L;
static Comparator CASE_INSENSITIVE_ORDER = new Comparator() public static final Comparator CASE_INSENSITIVE_ORDER = new Comparator()
{
public int compare (Object o1, Object o2)
{ {
public int compare (Object o1, Object o2) return ((String) o1).compareToIgnoreCase ((String) o2);
{ }
return ((String) o1).compareToIgnoreCase ((String) o2); };
}
};
public String () public String ()
{ {
@ -276,9 +277,26 @@ public final class String implements Serializable, Comparable
public native String replace (char oldChar, char newChar); public native String replace (char oldChar, char newChar);
public native String toLowerCase (); public native String toLowerCase (Locale locale);
public native String toUpperCase (Locale locale);
public native String toUpperCase (); public String toLowerCase ()
{
// The JDK is a bit confused about what to do here. If we pass in
// the default Locale then special Locale handling might be
// invoked. However, the docs also say that Character.toLowerCase
// rules here. We go with the latter.
return toLowerCase (null);
}
public String toUpperCase ()
{
// The JDK is a bit confused about what to do here. If we pass in
// the default Locale then special Locale handling might be
// invoked. However, the docs also say that Character.toLowerCase
// rules here. We go with the latter.
return toUpperCase (null);
}
public native String trim (); public native String trim ();

View file

@ -24,6 +24,7 @@ details. */
#include <java/io/OutputStreamWriter.h> #include <java/io/OutputStreamWriter.h>
#include <java/io/ByteArrayInputStream.h> #include <java/io/ByteArrayInputStream.h>
#include <java/io/InputStreamReader.h> #include <java/io/InputStreamReader.h>
#include <java/util/Locale.h>
#include <gnu/gcj/convert/UnicodeToBytes.h> #include <gnu/gcj/convert/UnicodeToBytes.h>
#include <gnu/gcj/convert/BytesToUnicode.h> #include <gnu/gcj/convert/BytesToUnicode.h>
#include <jvm.h> #include <jvm.h>
@ -33,6 +34,14 @@ static int strhash_count = 0; /* Number of slots used in strhash. */
static int strhash_size = 0; /* Number of slots available in strhash. static int strhash_size = 0; /* Number of slots available in strhash.
* Assumed be power of 2! */ * Assumed be power of 2! */
// Some defines used by toUpperCase / toLowerCase.
#define ESSET 0x00df
#define CAPITAL_S 0x0053
#define SMALL_I 0x0069
#define CAPITAL_I_WITH_DOT 0x0130
#define SMALL_DOTLESS_I 0x0131
#define CAPITAL_I 0x0049
#define DELETED_STRING ((jstring)(~0)) #define DELETED_STRING ((jstring)(~0))
#define SET_STRING_IS_INTERNED(STR) /* nothing */ #define SET_STRING_IS_INTERNED(STR) /* nothing */
@ -755,16 +764,32 @@ java::lang::String::replace (jchar oldChar, jchar newChar)
} }
jstring jstring
java::lang::String::toLowerCase () java::lang::String::toLowerCase (java::util::Locale *locale)
{ {
jint i; jint i;
jchar* chrs = JvGetStringChars(this); jchar* chrs = JvGetStringChars(this);
jchar ch; jchar ch;
bool handle_tr = false;
if (locale != NULL)
{
String *lang = locale->getLanguage ();
if (lang->length () == 2
&& lang->charAt (0) == 't'
&& lang->charAt (1) == 'r')
handle_tr = true;
}
for (i = 0; ; i++) for (i = 0; ; i++)
{ {
if (i == count) if (i == count)
return this; return this;
jchar origChar = chrs[i]; jchar origChar = chrs[i];
if (handle_tr && (origChar == CAPITAL_I
|| origChar == CAPITAL_I_WITH_DOT))
break;
ch = java::lang::Character::toLowerCase(origChar); ch = java::lang::Character::toLowerCase(origChar);
if (ch != origChar) if (ch != origChar)
break; break;
@ -776,34 +801,80 @@ java::lang::String::toLowerCase ()
*dPtr++ = ch; i++; *dPtr++ = ch; i++;
for (; i < count; i++) for (; i < count; i++)
{ {
*dPtr++ = java::lang::Character::toLowerCase(chrs[i]); if (handle_tr && chrs[i] == CAPITAL_I)
*dPtr++ = SMALL_DOTLESS_I;
else if (handle_tr && chrs[i] == CAPITAL_I_WITH_DOT)
*dPtr++ = SMALL_I;
else
*dPtr++ = java::lang::Character::toLowerCase(chrs[i]);
} }
return result; return result;
} }
jstring jstring
java::lang::String::toUpperCase () java::lang::String::toUpperCase (java::util::Locale *locale)
{ {
jint i; jint i;
jchar* chrs = JvGetStringChars(this); jchar* chrs = JvGetStringChars(this);
jchar ch; jchar ch;
// When handling a specific locale there might be special rules.
// Currently all existing rules are simply handled inline, as there
// are only two and they are documented in the online 1.2 docs.
bool handle_esset = locale != NULL;
bool handle_tr = false;
if (locale != NULL)
{
String *lang = locale->getLanguage ();
if (lang->length () == 2
&& lang->charAt (0) == 't'
&& lang->charAt (1) == 'r')
handle_tr = true;
}
int new_count = count;
bool new_string = false;
for (i = 0; ; i++) for (i = 0; ; i++)
{ {
if (i == count) if (i == count)
return this; break;
jchar origChar = chrs[i]; jchar origChar = chrs[i];
ch = java::lang::Character::toUpperCase(origChar);
if (ch != origChar) if (handle_esset && origChar == ESSET)
{
++new_count;
new_string = true;
}
else if (handle_tr && (origChar == SMALL_I
|| origChar == SMALL_DOTLESS_I))
new_string = true;
else
{
ch = java::lang::Character::toUpperCase(origChar);
if (ch != origChar)
new_string = true;
}
if (new_string && ! handle_esset)
break; break;
} }
jstring result = JvAllocString(count); if (! new_string)
return this;
jstring result = JvAllocString(new_count);
jchar *dPtr = JvGetStringChars (result); jchar *dPtr = JvGetStringChars (result);
for (int j = 0; j < i; j++) for (i = 0; i < count; i++)
*dPtr++ = chrs[j];
*dPtr++ = ch; i++;
for (; i < count; i++)
{ {
*dPtr++ = java::lang::Character::toUpperCase(chrs[i]); if (handle_esset && chrs[i] == ESSET)
{
*dPtr++ = CAPITAL_S;
*dPtr++ = CAPITAL_S;
}
else if (handle_tr && chrs[i] == SMALL_I)
*dPtr++ = CAPITAL_I_WITH_DOT;
else if (handle_tr && chrs[i] == SMALL_DOTLESS_I)
*dPtr++ = CAPITAL_I;
else
*dPtr++ = java::lang::Character::toUpperCase(chrs[i]);
} }
return result; return result;
} }

View file

@ -176,6 +176,17 @@ public class RuleBasedCollator extends Collator
return new CollationElementIterator (expand.toString(), this); return new CollationElementIterator (expand.toString(), this);
} }
public CollationElementIterator getCollationElementIterator (CharacterIterator source)
{
StringBuffer expand = new StringBuffer ();
for (char c = source.first ();
c != CharacterIterator.DONE;
c = source.next ())
decomposeCharacter (c, expand);
return new CollationElementIterator (expand.toString(), this);
}
public CollationKey getCollationKey (String source) public CollationKey getCollationKey (String source)
{ {
return new CollationKey (getCollationElementIterator (source), source, return new CollationKey (getCollationElementIterator (source), source,

View file

@ -22,108 +22,121 @@ package java.text;
public final class StringCharacterIterator implements CharacterIterator public final class StringCharacterIterator implements CharacterIterator
{ {
public Object clone () public Object clone ()
{ {
return (Object) new StringCharacterIterator (text, begin, end, pos); return (Object) new StringCharacterIterator (text, begin, end, pos);
} }
public char current () public char current ()
{ {
// This follows JDK 1.2 semantics and not 1.1 semantics. // This follows JDK 1.2 semantics and not 1.1 semantics.
// In 1.1 we would throw an exception if begin==end. // In 1.1 we would throw an exception if begin==end.
return (pos < end) ? text.charAt(pos) : CharacterIterator.DONE; return (pos < end) ? text.charAt(pos) : CharacterIterator.DONE;
} }
public boolean equals (Object obj) public boolean equals (Object obj)
{ {
if (! (obj instanceof StringCharacterIterator)) if (! (obj instanceof StringCharacterIterator))
return false; return false;
StringCharacterIterator sci = (StringCharacterIterator) obj; StringCharacterIterator sci = (StringCharacterIterator) obj;
// The spec says "the same text". We take this to mean equals, // The spec says "the same text". We take this to mean equals,
// not ==. // not ==.
return (pos == sci.pos return (pos == sci.pos
&& begin == sci.begin && begin == sci.begin
&& end == sci.end && end == sci.end
&& text.equals(sci.text)); && text.equals(sci.text));
} }
public char first () public char first ()
{ {
pos = begin; pos = begin;
return current (); return current ();
} }
public int getBeginIndex () public int getBeginIndex ()
{ {
return begin; return begin;
} }
public int getEndIndex () public int getEndIndex ()
{ {
return end; return end;
} }
public int getIndex () public int getIndex ()
{ {
return pos; return pos;
} }
public int hashCode () public int hashCode ()
{ {
// FIXME: this is a terrible hash code. Find a better one. // FIXME: this is a terrible hash code. Find a better one.
return text.hashCode() + pos + begin + end; return text.hashCode() + pos + begin + end;
} }
public char last () public char last ()
{ {
pos = end; pos = end;
return current (); return current ();
} }
public char next () public char next ()
{ {
if (pos == end) if (pos == end)
return CharacterIterator.DONE; return CharacterIterator.DONE;
++pos; ++pos;
return current (); return current ();
} }
public char previous () public char previous ()
{ {
if (pos == begin) if (pos == begin)
return CharacterIterator.DONE; return CharacterIterator.DONE;
--pos; --pos;
return current (); return current ();
} }
public char setIndex (int idx) public char setIndex (int idx)
{ {
// In 1.1 we would throw an error if `idx == end'. // In 1.1 we would throw an error if `idx == end'.
if (idx < begin || idx > end) if (idx < begin || idx > end)
throw new IllegalArgumentException (); throw new IllegalArgumentException ();
pos = idx; pos = idx;
return current (); return current ();
} }
public StringCharacterIterator (String text) public StringCharacterIterator (String text)
{ {
this (text, 0, text.length(), 0); this (text, 0, text.length(), 0);
} }
public StringCharacterIterator (String text, int pos)
{
this (text, 0, text.length(), pos);
}
public StringCharacterIterator (String text, int begin, int end, int pos)
{
if (begin < 0 || begin > end || end > text.length()
// In 1.1 we would also throw if `pos == end'.
|| pos < begin || pos > end)
throw new IllegalArgumentException ();
this.text = text; public StringCharacterIterator (String text, int pos)
this.begin = begin; {
this.end = end; this (text, 0, text.length(), pos);
this.pos = pos; }
}
public StringCharacterIterator (String text, int begin, int end, int pos)
{
if (begin < 0 || begin > end || end > text.length()
// In 1.1 we would also throw if `pos == end'.
|| pos < begin || pos > end)
throw new IllegalArgumentException ();
this.text = text;
this.begin = begin;
this.end = end;
this.pos = pos;
}
// The online 1.2 docs say that this is "package visible" in the
// method description, but they also say it is public. We choose
// the latter for compatibility with the actual implementation.
public void setText (String text)
{
this.text = text;
this.begin = 0;
this.end = text.length ();
this.pos = 0;
}
// String to iterate over. // String to iterate over.
private String text; private String text;

View file

@ -1,5 +1,5 @@
/* java.util.PropertyPermission /* java.util.PropertyPermission
Copyright (C) 1999 Free Software Foundation, Inc. Copyright (C) 1999, 2000 Free Software Foundation, Inc.
This file is part of GNU Classpath. This file is part of GNU Classpath.
@ -68,11 +68,11 @@ public final class PropertyPermission extends BasicPermission
private static final long serialVersionUID = 885438825399942851L; private static final long serialVersionUID = 885438825399942851L;
private static final int READ = 1; private static final int READ = 1;
private static final int WRITE = 2; private static final int WRITE = 2;
private transient int actions; private transient int actions;
private static String actionStrings[] = private static final String actionStrings[] =
{ {
"", "read", "write", "read,write" "", "read", "write", "read,write"
}; };
@ -109,7 +109,7 @@ public final class PropertyPermission extends BasicPermission
else if ("write".equals(anAction)) else if ("write".equals(anAction))
this.actions |= WRITE; this.actions |= WRITE;
else else
throw new IllegalArgumentException("illegal action "+anAction); throw new IllegalArgumentException("illegal action " + anAction);
} }
} }
@ -150,6 +150,20 @@ public final class PropertyPermission extends BasicPermission
return actionStrings[actions]; return actionStrings[actions];
} }
/**
* Check to see whether this object is the same as another
* PropertyPermission object.
*
* @param obj The other object
*/
public boolean equals (Object obj)
{
if (! (obj instanceof PropertyPermission))
return false;
PropertyPermission p = (PropertyPermission) obj;
return actions == p.actions && super.equals (p);
}
/** /**
* Reads an object from the stream. This converts the external to the * Reads an object from the stream. This converts the external to the
* internal representation. * internal representation.
@ -165,8 +179,7 @@ public final class PropertyPermission extends BasicPermission
* Writes an object to the stream. This converts the internal to the * Writes an object to the stream. This converts the internal to the
* external representation. * external representation.
*/ */
private void writeObject(ObjectOutputStream s) private void writeObject(ObjectOutputStream s) throws IOException
throws IOException
{ {
ObjectOutputStream.PutField fields = s.putFields(); ObjectOutputStream.PutField fields = s.putFields();
fields.put("actions", getActions()); fields.put("actions", getActions());
@ -181,58 +194,58 @@ public final class PropertyPermission extends BasicPermission
public PermissionCollection newPermissionCollection() public PermissionCollection newPermissionCollection()
{ {
return new PermissionCollection() return new PermissionCollection()
{
Hashtable permissions = new Hashtable();
int allActions = 0;
public void add(Permission permission)
{ {
Hashtable permissions = new Hashtable(); if (isReadOnly())
int allActions = 0; throw new IllegalStateException("readonly");
public void add(Permission permission) // also check that permission is of correct type.
PropertyPermission pp = (PropertyPermission) permission;
String name = pp.getName();
if (name.equals("*"))
allActions |= pp.actions;
permissions.put(name, pp);
}
public boolean implies(Permission permission)
{
if (!(permission instanceof PropertyPermission))
return false;
PropertyPermission toImply = (PropertyPermission) permission;
if ((toImply.actions & ~allActions) == 0)
return true;
String name = toImply.getName();
if (name.equals("*"))
return false;
int prefixLength = name.length();
if (name.endsWith("*"))
prefixLength -= 2;
while (true)
{ {
if (isReadOnly()) PropertyPermission forName =
throw new IllegalStateException("readonly"); (PropertyPermission) permissions.get(name);
if (forName != null && (toImply.actions & ~forName.actions) == 0)
// also check that permission is of correct type.
PropertyPermission pp = (PropertyPermission) permission;
String name = pp.getName();
if (name.equals("*"))
allActions |= pp.actions;
permissions.put(name, pp);
}
public boolean implies(Permission permission)
{
if (!(permission instanceof PropertyPermission))
return false;
PropertyPermission toImply = (PropertyPermission) permission;
if ((toImply.actions & ~allActions) == 0)
return true; return true;
String name = toImply.getName(); prefixLength = name.lastIndexOf('.', prefixLength);
if (name.equals("*")) if (prefixLength < 0)
return false; return false;
name = name.substring(0, prefixLength + 1) + '*';
int prefixLength = name.length();
if (name.endsWith("*"))
prefixLength -= 2;
while (true) {
PropertyPermission forName =
(PropertyPermission) permissions.get(name);
if (forName != null
&& (toImply.actions & ~forName.actions) == 0)
return true;
prefixLength = name.lastIndexOf('.', prefixLength);
if (prefixLength < 0)
return false;
name = name.substring(0, prefixLength + 1) + '*';
}
} }
}
public Enumeration elements() public Enumeration elements()
{ {
return permissions.elements(); return permissions.elements();
} }
}; };
} }
} }