Initial revision

From-SVN: r26263
This commit is contained in:
Tom Tromey 1999-04-07 14:42:40 +00:00
parent 140fa895c6
commit ee9dd3721b
370 changed files with 173494 additions and 0 deletions

View file

@ -0,0 +1,183 @@
// BitSet - A vector of bits.
/* Copyright (C) 1998, 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.util;
import java.io.Serializable;
/**
* @author Tom Tromey <tromey@cygnus.com>
* @date October 23, 1998.
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* hashCode algorithm taken from JDK 1.2 docs.
*/
public final class BitSet implements Cloneable, Serializable
{
public void and (BitSet bs)
{
if (bs == null)
throw new NullPointerException ();
int max = Math.min(bits.length, bs.bits.length);
int i;
for (i = 0; i < max; ++i)
bits[i] &= bs.bits[i];
for ( ; i < bits.length; ++i)
bits[i] = 0;
}
public BitSet ()
{
this (64);
}
public BitSet (int nbits)
{
if (nbits < 0)
throw new NegativeArraySizeException ();
int length = nbits / 64;
if (nbits % 64 != 0)
++length;
bits = new long[length];
}
public void clear (int pos)
{
if (pos < 0)
throw new IndexOutOfBoundsException ();
int bit = pos % 64;
int offset = pos / 64;
ensure (offset);
bits[offset] &= ~ (1 << bit);
}
public Object clone ()
{
BitSet bs = new BitSet (bits.length * 64);
System.arraycopy(bits, 0, bs.bits, 0, bits.length);
return bs;
}
public boolean equals (Object obj)
{
if (! (obj instanceof BitSet))
return false;
BitSet bs = (BitSet) obj;
int max = Math.min(bits.length, bs.bits.length);
int i;
for (i = 0; i < max; ++i)
if (bits[i] != bs.bits[i])
return false;
// If one is larger, check to make sure all extra bits are 0.
for (int j = i; j < bits.length; ++j)
if (bits[j] != 0)
return false;
for (int j = i; j < bs.bits.length; ++j)
if (bs.bits[j] != 0)
return false;
return true;
}
public boolean get (int pos)
{
if (pos < 0)
throw new IndexOutOfBoundsException ();
int bit = pos % 64;
int offset = pos / 64;
if (offset >= bits.length)
return false;
return (bits[offset] & (1 << bit)) == 0 ? false : true;
}
public int hashCode ()
{
long h = 1234;
for (int i = bits.length - 1; i >= 0; --i)
h ^= bits[i] * (i + 1);
return (int) ((h >> 32) ^ h);
}
public void or (BitSet bs)
{
if (bs == null)
throw new NullPointerException ();
ensure (bs.bits.length - 1);
int i;
for (i = 0; i < bs.bits.length; ++i)
bits[i] |= bs.bits[i];
}
public void set (int pos)
{
if (pos < 0)
throw new IndexOutOfBoundsException ();
int bit = pos % 64;
int offset = pos / 64;
ensure (offset);
bits[offset] |= 1 << bit;
}
public int size ()
{
return bits.length * 64;
}
public String toString ()
{
StringBuffer result = new StringBuffer ("{");
boolean first = true;
for (int i = 0; i < bits.length; ++i)
{
int bit = 1;
long word = bits[i];
for (int j = 0; j < 64; ++j)
{
if ((word & bit) != 0)
{
if (! first)
result.append(", ");
result.append(64 * i + j);
first = false;
}
bit <<= 1;
}
}
return result.append("}").toString();
}
public void xor (BitSet bs)
{
if (bs == null)
throw new NullPointerException ();
ensure (bs.bits.length - 1);
int i;
for (i = 0; i < bs.bits.length; ++i)
bits[i] ^= bs.bits[i];
}
// Make sure the vector is big enough.
private final void ensure (int lastElt)
{
if (lastElt + 1 > bits.length)
{
long[] nd = new long[lastElt + 1];
System.arraycopy(bits, 0, nd, 0, bits.length);
bits = nd;
}
}
// The actual bits.
private long[] bits;
}

View file

@ -0,0 +1,258 @@
/* Copyright (C) 1998, 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.util;
/**
* @author Per Bothner <bothner@cygnus.com>
* @date October 24, 1998.
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3,
* and "The Java Language Specification", ISBN 0-201-63451-1.
* Status: Unimplemented: getAvailableLocales.
* No Locale knowledge.
*/
public abstract class Calendar implements java.io.Serializable, Cloneable
{
public final static int JANUARY = 0;
public final static int FEBRUARY = 1;
public final static int MARCH = 2;
public final static int APRIL = 3;
public final static int MAY = 4;
public final static int JUNE = 5;
public final static int JULY = 6;
public final static int AUGUST = 7;
public final static int SEPTEMBER = 8;
public final static int OCTOBER = 9;
public final static int NOVEMBER = 10;
public final static int DECEMBER = 11;
public final static int UNDECIMBER = 12;
public final static int SUNDAY = 1;
public final static int MONDAY = 2;
public final static int TUESDAY = 3;
public final static int WEDNESDAY = 4;
public final static int THURSDAY = 5;
public final static int FRIDAY = 6;
public final static int SATURDAY = 7;
public final static int AM = 0;
public final static int PM = 1;
public final static int FIELD_COUNT = 17;
// These constants are not docuemnted, but were determined using
// a simple test program.
public final static int ERA = 0;
public final static int YEAR = 1;
public final static int MONTH = 2;
public final static int WEEK_OF_YEAR = 3;
public final static int WEEK_OF_MONTH = 4;
public final static int DATE = 5;
public final static int DAY_OF_MONTH = 5;
public final static int DAY_OF_YEAR = 6;
public final static int DAY_OF_WEEK = 7;
public final static int DAY_OF_WEEK_IN_MONTH = 8;
public final static int AM_PM = 9;
public final static int HOUR = 10;
public final static int HOUR_OF_DAY = 11;
public final static int MINUTE = 12;
public final static int SECOND = 13;
public final static int MILLISECOND = 14;
public final static int ZONE_OFFSET = 15;
public final static int DST_OFFSET = 16;
// The fields are as specified in Sun's "Serialized Form"
// in the JDK 1.2 beta 4 API specification.
protected boolean areFieldsSet;
protected int[] fields;
private int firstDayOfWeek;
protected boolean[] isSet;
protected boolean isTimeSet;
private boolean lenient;
private int minimalDaysInFirstWeek;
private int nextStamp;
//private int serialVersionOnStream;
protected long time;
private TimeZone zone;
protected Calendar ()
{
this (null, null);
}
protected Calendar (TimeZone tx, Locale loc)
{
fields = new int[FIELD_COUNT];
isSet = new boolean[FIELD_COUNT];
firstDayOfWeek = SUNDAY; // Locale-dependent. FIXME.
this.zone = zone != null ? zone : TimeZone.getDefault();
}
public Object clone ()
{
try
{
return super.clone();
}
catch (CloneNotSupportedException ex)
{
throw new RuntimeException("internal error - "+ex);
}
}
public static Calendar getInstance ()
{
return new GregorianCalendar ();
}
public static Calendar getInstance (TimeZone zone)
{
return new GregorianCalendar (zone);
}
public static Calendar getInstance (Locale locale)
{
return new GregorianCalendar (locale);
}
public static Calendar getInstance (TimeZone zone, Locale locale)
{
return new GregorianCalendar (zone, locale);
}
public boolean isLenient() { return lenient; }
public void setLenient (boolean lenient) { this.lenient = lenient; }
public int getFirstDayOfWeek ()
{
return firstDayOfWeek;
}
public void setFirstDayOfWeek (int value)
{
firstDayOfWeek = value;
}
public int getMinimalDaysInFirstWeek ()
{
return minimalDaysInFirstWeek;
}
public void setMinimalDaysInFirstWeek (int value)
{
minimalDaysInFirstWeek = value;
}
public TimeZone getTimeZone ()
{
return zone;
}
public void setTimeZone (TimeZone tz)
{
zone = tz;
}
abstract public void add(int fld, int amount);
abstract public void roll (int fld, boolean up);
public final void set (int year, int month, int date)
{
set(YEAR, year);
set(MONTH, month);
set(DATE, date);
}
public final void set (int year, int month, int date, int hour, int minute)
{
set(year, month, date);
set(HOUR_OF_DAY, hour);
set(MINUTE, minute);
}
public final void set (int year, int month, int date,
int hour, int minute, int second)
{
set(year, month, date, hour, minute);
set(SECOND, second);
}
public final void set (int fld, int value)
{
fields[fld] = value;
isTimeSet = false;
}
public final void clear (int fld)
{
fields[fld] = 0;
isSet[fld] = false;
areFieldsSet = false;
}
public final void clear ()
{
for (int fld = FIELD_COUNT; --fld >= 0; )
{
fields[fld] = 0;
isSet[fld] = false;
}
areFieldsSet = false;
}
protected void complete()
{
if (!isTimeSet) computeTime();
if (!areFieldsSet) computeFields();
}
protected abstract void computeFields();
protected abstract void computeTime();
protected final int internalGet (int fld) { return fields[fld]; }
public final int get(int fld)
{
complete();
return fields[fld];
}
public abstract boolean after (Object cal);
public abstract boolean before (Object cal);
public abstract boolean equals (Object obj);
protected long getTimeInMillis()
{
if (!isTimeSet) computeTime();
return time;
}
public final Date getTime() { return new Date(getTimeInMillis()); }
public final void setTime (Date date)
{
setTimeInMillis(date.getTime());
}
protected void setTimeInMillis (long millis)
{
time = millis;
isTimeSet = true;
clear();
}
abstract public int getMaximum(int fld);
abstract public int getMinimum(int fld);
abstract public int getGreatestMinimum(int fld);
abstract public int getLeastMaximum(int fld);
public final boolean isSet(int fld) { return isSet[fld]; }
}

View file

@ -0,0 +1,33 @@
/* Copyright (C) 1998, 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.util;
/**
* @author Warren Levy <warrenl@cygnus.com>
* @date September 2, 1998.
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
* Status: Believed complete and correct.
*/
/* Added in JDK 1.2 */
public class ConcurrentModificationException extends RuntimeException
{
public ConcurrentModificationException()
{
super();
}
public ConcurrentModificationException(String msg)
{
super(msg);
}
}

460
libjava/java/util/Date.java Normal file
View file

@ -0,0 +1,460 @@
/* Copyright (C) 1998, 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.util;
import java.text.*;
/**
* @author Per Bothner <bothner@cygnus.com>
* @date October 24, 1998.
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3,
* "The Java Language Specification", ISBN 0-201-63451-1,
* and O'Reilly's "Java in a Nutshell".
* Status: Need to re-write toString().
* Missing: ToGMTString and toLocaleString.
* Serialization spec: Specifies readObject/writeObject.
*/
public class Date implements java.io.Serializable, Cloneable
{
private long millis;
public Date() { millis = System.currentTimeMillis(); }
public Date(long millis) { this.millis = millis; }
public Date(int year, int month, int date, int hours,
int minutes, int seconds)
{
setTime(year, month, date, hours, minutes, seconds);
}
public Date(int year, int month, int date, int hours, int minutes)
{
setTime(year, month, date, hours, minutes, 0);
}
public Date(int year, int month, int date)
{
setTime(year, month, date, 0, 0, 0);
}
public Date (String s) { this(parse(s)); }
private static int skipParens(String string, int offset)
{
int len = string.length();
int p = 0;
int i;
for (i = offset; i < len; ++i)
{
if (string.charAt(i) == '(')
++p;
else if (string.charAt(i) == ')')
{
--p;
if (p == 0)
return i + 1;
// If we've encounted unbalanced parens, just return the
// leftover one as an ordinary character. It will be
// caught later in parsing and cause an
// IllegalArgumentException.
if (p < 0)
return i;
}
}
// Not sure what to do if `p != 0' here.
return i;
}
private static int parseTz(String tok, char sign)
throws IllegalArgumentException
{
int num;
try
{
// parseInt doesn't handle '+' so strip off sign.
num = Integer.parseInt(tok.substring(1));
}
catch (NumberFormatException ex)
{
throw new IllegalArgumentException(tok);
}
// Convert hours to minutes.
if (num < 24)
num *= 60;
else
num = (num / 100) * 60 + num % 100;
return sign == '-' ? -num : num;
}
private static int parseMonth(String tok)
{
// Initialize strings for month names.
// We could possibly use the fields of DateFormatSymbols but that is
// localized and thus might not match the English words specified.
String months[] = { "JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY",
"JUNE", "JULY", "AUGUST", "SEPTEMBER", "OCTOBER",
"NOVEMBER", "DECEMBER" };
int i;
for (i = 0; i < 12; i++)
if (months[i].startsWith(tok))
return i;
// Return -1 if not found.
return -1;
}
private static boolean parseDayOfWeek(String tok)
{
// Initialize strings for days of the week names.
// We could possibly use the fields of DateFormatSymbols but that is
// localized and thus might not match the English words specified.
String daysOfWeek[] = { "SUNDAY", "MONDAY", "TUESDAY", "WEDNESDAY",
"THURSDAY", "FRIDAY", "SATURDAY" };
int i;
for (i = 0; i < 7; i++)
if (daysOfWeek[i].startsWith(tok))
return true;
return false;
}
public static long parse(String string)
{
// Initialize date/time fields before parsing begins.
int year = -1;
int month = -1;
int day = -1;
int hour = -1;
int minute = -1;
int second = -1;
int timezone = 0;
boolean localTimezone = true;
// Trim out any nested stuff in parentheses now to make parsing easier.
StringBuffer buf = new StringBuffer();
int off = 0;
int openParenOffset, tmpMonth;
while ((openParenOffset = string.indexOf('(', off)) >= 0)
{
// Copy part of string leading up to open paren.
buf.append(string.substring(off, openParenOffset));
off = skipParens(string, openParenOffset);
}
buf.append(string.substring(off));
// Make all chars upper case to simplify comparisons later.
// Also ignore commas; treat them as delimiters.
StringTokenizer strtok =
new StringTokenizer(buf.toString().toUpperCase(), " \t\n\r,");
while (strtok.hasMoreTokens())
{
String tok = strtok.nextToken();
char firstch = tok.charAt(0);
if ((firstch == '+' || firstch == '-') && year >= 0)
{
timezone = parseTz(tok, firstch);
localTimezone = false;
}
else if (firstch >= '0' && firstch <= '9')
{
while (tok != null && tok.length() > 0)
{
// A colon or slash may be valid in the number.
// Find the first of these before calling parseInt.
int colon = tok.indexOf(':');
int slash = tok.indexOf('/');
int hyphen = tok.indexOf('-');
// We choose tok.length initially because it makes
// processing simpler.
int punctOffset = tok.length();
if (colon >= 0)
punctOffset = Math.min(punctOffset, colon);
if (slash >= 0)
punctOffset = Math.min(punctOffset, slash);
if (hyphen >= 0)
punctOffset = Math.min(punctOffset, hyphen);
// Following code relies on -1 being the exceptional
// case.
if (punctOffset == tok.length())
punctOffset = -1;
int num;
try
{
num = Integer.parseInt(punctOffset < 0 ? tok :
tok.substring(0, punctOffset));
}
catch (NumberFormatException ex)
{
throw new IllegalArgumentException(tok);
}
// TBD: Spec says year can be followed by a slash. That might
// make sense if using YY/MM/DD formats, but it would fail in
// that format for years <= 70. Also, what about 1900? That
// is interpreted as the year 3800; seems that the comparison
// should be num >= 1900 rather than just > 1900.
// What about a year of 62 - 70? (61 or less could be a (leap)
// second). 70/MM/DD cause an exception but 71/MM/DD is ok
// even though there's no ambiguity in either case.
// For the parse method, the spec as written seems too loose.
// Until shown otherwise, we'll follow the spec as written.
if (num > 70 && (punctOffset < 0 || punctOffset == slash))
year = num > 1900 ? num - 1900 : num;
else if (punctOffset > 0 && punctOffset == colon)
{
if (hour < 0)
hour = num;
else
minute = num;
}
else if (punctOffset > 0 && punctOffset == slash)
{
if (month < 0)
month = num - 1;
else
day = num;
}
else if (hour >= 0 && minute < 0)
minute = num;
else if (minute >= 0 && second < 0)
second = num;
else if (day < 0)
day = num;
else
throw new IllegalArgumentException(tok);
// Advance string if there's more to process in this token.
if (punctOffset < 0 || punctOffset + 1 >= tok.length())
tok = null;
else
tok = tok.substring(punctOffset + 1);
}
}
else if (firstch >= 'A' && firstch <= 'Z')
{
if (tok.equals("AM"))
{
if (hour < 1 || hour > 12)
throw new IllegalArgumentException(tok);
if (hour == 12)
hour = 0;
}
else if (tok.equals("PM"))
{
if (hour < 1 || hour > 12)
throw new IllegalArgumentException(tok);
if (hour < 12)
hour += 12;
}
else if (parseDayOfWeek(tok))
; // Ignore it; throw the token away.
else if (tok.equals("UT") || tok.equals("UTC") || tok.equals("GMT"))
localTimezone = false;
else if (tok.startsWith("UT") || tok.startsWith("GMT"))
{
int signOffset = 3;
if (tok.charAt(1) == 'T' && tok.charAt(2) != 'C')
signOffset = 2;
char sign = tok.charAt(signOffset);
if (sign != '+' && sign != '-')
throw new IllegalArgumentException(tok);
timezone = parseTz(tok.substring(signOffset), sign);
localTimezone = false;
}
else if ((tmpMonth = parseMonth(tok)) >= 0)
month = tmpMonth;
else if (tok.length() == 3 && tok.charAt(2) == 'T')
{
// Convert timezone offset from hours to minutes.
char ch = tok.charAt(0);
if (ch == 'E')
timezone = -5 * 60;
else if (ch == 'C')
timezone = -6 * 60;
else if (ch == 'M')
timezone = -7 * 60;
else if (ch == 'P')
timezone = -8 * 60;
else
throw new IllegalArgumentException(tok);
// Shift 60 minutes for Daylight Savings Time.
if (tok.charAt(1) == 'D')
timezone += 60;
else if (tok.charAt(1) != 'S')
throw new IllegalArgumentException(tok);
localTimezone = false;
}
else
throw new IllegalArgumentException(tok);
}
else
throw new IllegalArgumentException(tok);
}
// Unspecified minutes and seconds should default to 0.
if (minute < 0)
minute = 0;
if (second < 0)
second = 0;
// Throw exception if any other fields have not been recognized and set.
if (year < 0 || month < 0 || day < 0 || hour < 0)
throw new IllegalArgumentException("Missing field");
// Return the time in either local time or relative to GMT as parsed.
// If no time-zone was specified, get the local one (in minutes) and
// convert to milliseconds before adding to the UTC.
return UTC(year, month, day, hour, minute, second) + (localTimezone ?
new Date(year, month, day).getTimezoneOffset() * 60 * 1000:
-timezone * 60 * 1000);
}
public boolean after (Date when) { return this.millis > when.millis; }
public boolean before (Date when) { return this.millis < when.millis; }
public boolean equals(Object obj)
{
return (obj != null && obj instanceof Date
&& ((Date)obj).millis == this.millis);
}
public long getTime() { return millis; }
public int hashCode()
{
return (int)(millis^(millis>>>32));
}
private void setTime(int year, int month, int date,
int hours, int minutes, int seconds)
{
Calendar cal = new GregorianCalendar(year+1900, month, date,
hours, minutes, seconds);
millis = cal.getTimeInMillis();
}
public void setTime(long millis) { this.millis = millis; }
private int getField (int fld)
{
Calendar cal = new GregorianCalendar();
cal.setTime(this);
return cal.get(fld);
}
public int getYear ()
{
return getField(Calendar.YEAR) - 1900;
}
public int getMonth ()
{
return getField(Calendar.MONTH);
}
public int getDate ()
{
return getField(Calendar.DATE);
}
public int getDay ()
{
return getField(Calendar.DAY_OF_WEEK) - 1;
}
public int getHours ()
{
return getField(Calendar.HOUR_OF_DAY);
}
public int getMinutes ()
{
return getField(Calendar.MINUTE);
}
public int getSeconds ()
{
return getField(Calendar.SECOND);
}
private void setField (int fld, int value)
{
Calendar cal = new GregorianCalendar();
cal.setTime(this);
cal.set(fld, value);
millis = cal.getTimeInMillis();
}
public void setYear (int year)
{
setField(Calendar.YEAR, 1900 + year);
}
public void setMonth (int month)
{
setField(Calendar.MONTH, month);
}
public void setDate (int date)
{
setField(Calendar.DATE, date);
}
public void setHours (int hours)
{
setField(Calendar.HOUR_OF_DAY, hours);
}
public void setMinutes (int minutes)
{
setField(Calendar.MINUTE, minutes);
}
public void setSeconds (int seconds)
{
setField(Calendar.SECOND, seconds);
}
public int getTimezoneOffset ()
{
Calendar cal = new GregorianCalendar();
cal.setTime(this);
return - (cal.get(Calendar.ZONE_OFFSET)
+ cal.get(Calendar.DST_OFFSET)/(60*1000));
}
public native String toString ();
// TODO: toLocaleString
// TODO: toGMTString
public static long UTC (int year, int month, int date,
int hours, int minutes, int seconds)
{
GregorianCalendar cal = new GregorianCalendar (TimeZone.zoneGMT);
cal.set(year+1900, month, date, hours, minutes, seconds);
return cal.getTimeInMillis();
}
}

View file

@ -0,0 +1,34 @@
/* Copyright (C) 1998, 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.util;
/**
* @author Warren Levy <warrenl@cygnus.com>
* @date August 31, 1998.
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
* Status: Believed complete and correct
*/
/* The JDK 1.2 beta doc indicates that Dictionary is obsolete and that the
* new java.util.Map interface should be used instead.
*/
public abstract class Dictionary
{
public abstract Enumeration elements();
public abstract Object get(Object key) throws NullPointerException;
public abstract boolean isEmpty();
public abstract Enumeration keys();
public abstract Object put(Object key, Object elem)
throws NullPointerException;
public abstract Object remove(Object key) throws NullPointerException;
public abstract int size();
}

View file

@ -0,0 +1,27 @@
/* Copyright (C) 1998, 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.util;
/**
* @author Warren Levy <warrenl@cygnus.com>
* @date September 2, 1998.
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
* Status: Believed complete and correct.
*/
public class EmptyStackException extends RuntimeException
{
public EmptyStackException()
{
super();
}
}

View file

@ -0,0 +1,24 @@
/* Copyright (C) 1998, 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.util;
/**
* @author Warren Levy <warrenl@cygnus.com>
* @date August 25, 1998.
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1.
* Status: Believed complete and correct
*/
public interface Enumeration
{
public boolean hasMoreElements();
public Object nextElement() throws NoSuchElementException;
}

View file

@ -0,0 +1,24 @@
// EventListener.java - Listen for events from event source.
/* Copyright (C) 1998, 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.util;
/**
* @author Tom Tromey <tromey@cygnus.com>
* @date December 12, 1998
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* Status: Believed complete and correct.
*/
public interface EventListener
{
}

View file

@ -0,0 +1,42 @@
// EventObject.java - Represent events fired by objects.
/* Copyright (C) 1998, 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.util;
/**
* @author Tom Tromey <tromey@cygnus.com>
* @date December 12, 1998
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* Status: Believed complete, but not fully correct.
*/
public class EventObject implements java.io.Serializable
{
public EventObject (Object source)
{
this.source = source;
}
public Object getSource ()
{
return source;
}
public String toString ()
{
// FIXME.
return getSource().toString();
}
// Source of the event.
protected transient Object source;
}

View file

@ -0,0 +1,257 @@
/* Copyright (C) 1998, 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.util;
/**
* @author Per Bothner <bothner@cygnus.com>
* @date October 24, 1998.
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3,
* and "The Java Language Specification", ISBN 0-201-63451-1.
* Status: "leniency" is not handled, and neither is roll-over in
* add and roll. This is partly because of unclear specification.
* hashCode has no spec.
*/
public class GregorianCalendar extends Calendar {
public static final int BC = 0;
public static final int AD = 1;
// The fields are as specified in Sun's "Serialized Form"
// in the JDK 1.2 beta 4 API specification.
// Value from a simple test program (getGregorianChange.getTime()).
long gregorianCutover = -12219292800000L;
private final static int[] mins = {
0 /* ERA */,
1 /* YEAR */,
0 /* MONTH */,
0 /* WEEK_OF_YEAR */,
0 /* WEEK_OF_MONTH */,
1 /* DATE */,
1 /* DAY_OF_YEAR */,
1 /* DAY_OF_WEEK */,
-1 /* DAY_OF_WEEK_IN_MONTH */,
0 /* AM_PM */,
0 /* HOUR */,
0 /* HOUR_OF_DAY */,
0 /* MINUTE */,
0 /* SECOND */,
0 /* MILLISECOND */,
-43200000 /* ZONE_OFFSET */,
0 /* DST_OFFSET */
};
private final static int[] maxs = {
1 /* ERA */,
5000000 /* YEAR */,
11 /* MONTH */,
54 /* WEEK_OF_YEAR */,
6 /* WEEK_OF_MONTH */,
31 /* DATE */,
366 /* DAY_OF_YEAR */,
7 /* DAY_OF_WEEK */,
6 /* DAY_OF_WEEK_IN_MONTH */,
1 /* AM_PM */,
12 /* HOUR */,
23 /* HOUR_OF_DAY */,
59 /* MINUTE */,
59 /* SECOND */,
999 /* MILLISECOND */,
43200000 /* ZONE_OFFSET */,
3600000 /* DST_OFFSET */
};
private final static int[] leastMaximums = {
1 /* ERA */,
5000000 /* YEAR */,
11 /* MONTH */,
53 /* WEEK_OF_YEAR */,
6 /* WEEK_OF_MONTH */,
28 /* DATE */,
365 /* DAY_OF_YEAR */,
7 /* DAY_OF_WEEK */,
4 /* DAY_OF_WEEK_IN_MONTH */,
1 /* AM_PM */,
11 /* HOUR */,
23 /* HOUR_OF_DAY */,
59 /* MINUTE */,
59 /* SECOND */,
999 /* MILLISECOND */,
43200000 /* ZONE_OFFSET */,
3600000 /* DST_OFFSET */
};
public GregorianCalendar ()
{
this(null, null);
}
public GregorianCalendar (TimeZone zone)
{
this (zone, null);
}
public GregorianCalendar (Locale locale)
{
this (null, locale);
}
public GregorianCalendar (TimeZone zone, Locale locale)
{
super (zone, locale);
}
public GregorianCalendar (int year, int month, int date)
{
this((TimeZone) null);
set (year, month, date);
}
public GregorianCalendar (int year, int month, int date,
int hour, int minute)
{
this((TimeZone) null);
set (year, month, date, hour, minute);
}
public GregorianCalendar (int year, int month, int date,
int hour, int minute, int second)
{
this((TimeZone) null);
set (year, month, date, hour, minute, second);
}
public int getMinimum(int calfield) { return mins[calfield]; }
public int getGreatestMinimum(int calfield) { return mins[calfield]; }
public int getMaximum(int calfield) { return maxs[calfield]; }
public int getLeastMaximum(int calfield) { return leastMaximums[calfield]; }
protected native void computeFields();
protected native void computeTime();
public void add (int fld, int amount)
{
if (fld >= ZONE_OFFSET)
throw new IllegalArgumentException("bad field to add");
fields[fld] += amount;
adjust(fld);
}
public void roll (int fld, boolean up)
{
if (fld >= ZONE_OFFSET)
throw new IllegalArgumentException("bad field to roll");
int old = fields[fld];
if (up)
{
fields[fld] = old == getMaximum(fld) ? getMinimum(fld)
: old + 1;
}
else
{
fields[fld] = old == getMinimum(fld) ? getMaximum(fld)
: old - 1;
}
}
private void adjust (int fld)
{
int value = fields[fld];
int radix = maxs[fld] + 1;
switch (fld)
{
case MONTH:
case SECOND:
case MILLISECOND:
if (value >= radix)
{
int next = value / radix;
fields[fld] = value - radix * next;
fields[fld - 1] += next;
adjust(fld - 1);
}
else if (value < 0) // min[fld]
{
int next = (value - radix - 1) / radix;
fields[fld] = value - radix * next;
fields[fld - 1] += next;
adjust(fld - 1);
}
break;
}
}
public final Date getGregorianChange() { return new Date(gregorianCutover); }
public void setGregorianChange (Date date)
{ gregorianCutover = date.getTime(); }
public boolean isLeapYear(int year)
{
if ((year % 4) != 0)
return false;
if ((year % 100) != 0 || (year % 400) == 0)
return true;
// year divisible by 100 but not 400.
GregorianCalendar date = new GregorianCalendar(year, FEBRUARY, 28);
return gregorianCutover < date.getTimeInMillis();
}
public boolean after (Object cal)
{
return cal instanceof Calendar
&& getTimeInMillis() > ((Calendar) cal).getTimeInMillis();
}
public boolean before (Object cal)
{
return cal instanceof Calendar
&& getTimeInMillis() < ((Calendar) cal).getTimeInMillis();
}
public boolean equals (Object obj)
{
if (obj == null || ! (obj instanceof GregorianCalendar))
return false;
GregorianCalendar other = (GregorianCalendar) obj;
for (int i = FIELD_COUNT; --i >= 0; )
{
boolean set = isSet[i];
if (set != other.isSet[i]
|| (set && fields[i] != other.fields[i]))
return false;
}
if (areFieldsSet != other.areFieldsSet
|| isTimeSet != other.isTimeSet
|| (isTimeSet && time != other.time)
|| getFirstDayOfWeek() != other.getFirstDayOfWeek()
|| getMinimalDaysInFirstWeek() != other.getMinimalDaysInFirstWeek()
|| isLenient() != other.isLenient()
|| ! getTimeZone().equals(other.getTimeZone()))
return false;
return true;
}
public int hashCode ()
{
int hashcode = 0;
for (int i = FIELD_COUNT; --i >= 0; )
{
if (isSet[i])
hashcode += 37 * fields[i];
}
if (isTimeSet)
hashcode += 89 * time;
return hashcode;
}
}

View file

@ -0,0 +1,398 @@
/* Copyright (C) 1998, 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.util;
import java.io.Serializable;
/**
* @author Warren Levy <warrenl@cygnus.com>
* @date September 24, 1998.
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
* Status: Believed complete and correct
*/
class HashtableEntry
{
public Object key;
public Object value;
public HashtableEntry nextEntry = null;
public HashtableEntry(Object key, Object value)
{
this.key = key;
this.value = value;
}
}
class HashtableEnumeration implements Enumeration
{
// TBD: Enumeration is not safe if new elements are put in the table as
// this could cause a rehash and we'd completely lose our place. Even
// without a rehash, it is undetermined if a new element added would
// appear in the enumeration. The spec says nothing about this, but
// the "Java Class Libraries" book infers that modifications to the
// hashtable during enumeration causes indeterminate results. Don't do it!
// A safer way would be to make a copy of the table (e.g. into a vector)
// but this is a fair bit more expensive.
private HashtableEntry[] bucket;
private int bucketIndex;
private HashtableEntry elem;
private int enumCount;
private int size;
private boolean values;
public HashtableEnumeration(HashtableEntry[] bkt, int sz, boolean isValues)
{
bucket = bkt;
bucketIndex = -1;
enumCount = 0;
elem = null;
size = sz;
values = isValues;
}
public boolean hasMoreElements()
{
return enumCount < size;
}
public Object nextElement()
{
if (!hasMoreElements())
throw new NoSuchElementException();
// Find next element
if (elem != null) // In the middle of a bucket
elem = elem.nextEntry;
while (elem == null) // Find the next non-empty bucket
elem = bucket[++bucketIndex];
enumCount++;
return values ? elem.value : elem.key;
}
}
// TBD: The algorithm used here closely reflects what is described in
// the "Java Class Libraries" book. The "Java Language Spec" is much
// less specific about the implementation. Because of this freedom
// provided by the actual spec, hash table algorithms should be
// investigated to see if there is a better alternative to this one.
// TODO12:
// public class Hashtable extends Dictionary
// implements Map, Cloneable, Serializable
public class Hashtable extends Dictionary implements Cloneable, Serializable
{
private HashtableEntry bucket[];
private float loadFactor;
private int hsize = 0;
public Hashtable()
{
// The "Java Class Libraries" book (p. 919) says that initial size in this
// case is 101 (a prime number to increase the odds of even distribution).
this(101, 0.75F);
}
public Hashtable(int initialSize)
{
this(initialSize, 0.75F);
}
public Hashtable(int initialSize, float loadFactor)
{
if (initialSize < 0 || loadFactor <= 0.0 || loadFactor > 1.0)
throw new IllegalArgumentException();
bucket = new HashtableEntry[initialSize];
this.loadFactor = loadFactor;
}
// TODO12:
// public Hashtable(Map t)
// {
// }
public synchronized void clear()
{
// Aid the GC by nulling out the entries in the hash table.
for (int i = 0; i < bucket.length; i++)
{
HashtableEntry elem = bucket[i];
bucket[i] = null; // May already be null.
while (elem != null)
{
HashtableEntry next = elem.nextEntry;
elem.nextEntry = null; // May already be null.
elem = next;
}
}
hsize = 0;
}
public synchronized Object clone()
{
// New hashtable will have same initialCapacity and loadFactor.
Hashtable newTable = new Hashtable(bucket.length, loadFactor);
HashtableEntry newElem, prev = null;
for (int i = 0; i < bucket.length; i++)
for (HashtableEntry elem = bucket[i]; elem != null; elem = elem.nextEntry)
{
// An easy but expensive method is newTable.put(elem.key, elem.value);
// Since the hash tables are the same size, the buckets and collisions
// will be the same in the new one, so we can just clone directly.
// This is much cheaper than using put.
newElem = new HashtableEntry(elem.key, elem.value);
if (newTable.bucket[i] == null)
prev = newTable.bucket[i] = newElem;
else
prev = prev.nextEntry = newElem;
}
newTable.hsize = this.hsize;
return newTable;
}
public synchronized boolean contains(Object value) throws NullPointerException
{
// An exception is thrown here according to the JDK 1.2 doc.
if (value == null)
throw new NullPointerException();
for (int i = 0; i < bucket.length; i++)
for (HashtableEntry elem = bucket[i]; elem != null; elem = elem.nextEntry)
if (elem.value.equals(value))
return true;
return false;
}
public synchronized boolean containsKey(Object key)
{
// The Map interface mandates that we throw this.
if (key == null)
throw new NullPointerException ();
for (HashtableEntry elem = bucket[Math.abs(key.hashCode()
% bucket.length)];
elem != null; elem = elem.nextEntry)
if (elem.key.equals(key))
return true;
return false;
}
public synchronized Enumeration elements()
{
return new HashtableEnumeration(bucket, hsize, true);
}
public synchronized Object get(Object key)
{
// The Dictionary interface mandates that get() throw a
// NullPointerException if key is null.
if (key == null)
throw new NullPointerException ();
for (HashtableEntry elem = bucket[Math.abs (key.hashCode()
% bucket.length)];
elem != null; elem = elem.nextEntry)
if (elem.key.equals(key))
return elem.value;
return null;
}
public boolean isEmpty()
{
return this.hsize <= 0;
}
public synchronized Enumeration keys()
{
return new HashtableEnumeration(bucket, hsize, false);
}
public synchronized Object put(Object key, Object value)
throws NullPointerException
{
if (key == null || value == null)
throw new NullPointerException();
HashtableEntry prevElem = null;
final int index = Math.abs(key.hashCode() % bucket.length);
for (HashtableEntry elem = bucket[index]; elem != null;
prevElem = elem, elem = elem.nextEntry)
if (elem.key.equals(key))
{
// Update with the new value and then return the old one.
Object oldVal = elem.value;
elem.value = value;
return oldVal;
}
// At this point, we know we need to add a new element.
HashtableEntry newElem = new HashtableEntry(key, value);
if (bucket[index] == null)
bucket[index] = newElem;
else
prevElem.nextEntry = newElem;
if (++hsize > loadFactor * bucket.length)
rehash();
return null;
}
protected void rehash()
{
// Create a new table which is twice the size (plus one) of the old.
// One is added to make the new array length odd so it thus has at least
// a (small) possibility of being a prime number.
HashtableEntry oldBucket[] = bucket;
bucket = new HashtableEntry[bucket.length * 2 + 1];
// Copy over each entry into the new table
HashtableEntry elem;
for (int i = 0; i < oldBucket.length; i++)
for (elem = oldBucket[i]; elem != null; elem = elem.nextEntry)
{
// Calling put(elem.key, elem.value); would seem like the easy way
// but it is dangerous since put increases 'hsize' and calls rehash!
// This could become infinite recursion under the right
// circumstances. Instead, we'll add the element directly; this is a
// bit more efficient than put since the data is already verified.
final int index = Math.abs(elem.key.hashCode() % bucket.length);
HashtableEntry newElem = new HashtableEntry(elem.key, elem.value);
if (bucket[index] == null)
bucket[index] = newElem;
else
{
// Since this key can't already be in the table, just add this
// in at the top of the bucket.
newElem.nextEntry = bucket[index];
bucket[index] = newElem;
}
}
}
public synchronized Object remove(Object key)
{
// TBD: Hmm, none of the various docs say to throw an exception here.
if (key == null)
return null;
Object retval;
HashtableEntry prevElem = null;
final int index = Math.abs(key.hashCode() % bucket.length);
for (HashtableEntry elem = bucket[index]; elem != null;
prevElem = elem, elem = elem.nextEntry)
if (elem.key.equals(key))
{
retval = elem.value;
if (prevElem == null)
bucket[index] = elem.nextEntry;
else
prevElem.nextEntry = elem.nextEntry;
--hsize;
return retval;
}
return null;
}
public int size()
{
return this.hsize;
}
public synchronized String toString()
{
// Following the Java Lang Spec 21.5.4 (p. 636).
Enumeration keys = keys();
Enumeration values = elements();
// Prepend first element with open bracket
StringBuffer result = new StringBuffer("{");
// add first element if one exists
// TBD: Seems like it is more efficient to catch the exception than
// to call hasMoreElements each time around.
try
{
result.append(keys.nextElement().toString() + "=" +
values.nextElement().toString());
}
catch (NoSuchElementException ex)
{
}
// Prepend subsequent elements with ", "
try
{
while (true)
result.append(", " + keys.nextElement().toString() + "=" +
values.nextElement().toString());
}
catch (NoSuchElementException ex)
{
}
// Append last element with closing bracket
result.append("}");
return result.toString();
}
// TODO12:
// public Set entrySet()
// {
// }
// TODO12:
// public Set keySet()
// {
// }
// Since JDK 1.2:
// This method is identical to contains but is part of the 1.2 Map interface.
// TBD: Should contains return containsValue instead? Depends on which
// will be called more typically.
public synchronized boolean containsValue(Object value)
{
return this.contains(value);
}
// TODO12:
// public boolean equals(Object o)
// {
// }
// TODO12:
// public boolean hashCode()
// {
// }
// TODO12:
// public void putAll(Map t)
// {
// }
// TODO12:
// public Collection values()
// {
// }
}

View file

@ -0,0 +1,52 @@
/* Copyright (C) 1998, 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.util;
/**
* @author Anthony Green <green@cygnus.com>
* @date November 26, 1998.
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3,
* and "The Java Language Specification", ISBN 0-201-63451-1. */
public abstract class ListResourceBundle extends ResourceBundle
{
public final Object handleGetObject(String key)
{
Object a[][] = getContents();
for (int i = 0; i < a.length; i++)
{
if (key.compareTo((String) a[i][0]) == 0)
return a[i][1];
}
throw new MissingResourceException("can't find handle",
getClass().getName(),
key);
}
public Enumeration getKeys()
{
Object a[][] = getContents();
Vector keys = new Vector(a.length);
for (int i = 0; i < a.length; i++)
keys.addElement(a[i][0]);
return keys.elements();
}
protected abstract Object[][] getContents();
public ListResourceBundle()
{
}
}

View file

@ -0,0 +1,125 @@
/* Copyright (C) 1998, 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.util;
/**
* @author Per Bothner <bothner@cygnus.com>
* @date October 24, 1998.
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3,
* and "The Java Language Specification", ISBN 0-201-63451-1.
* Status: None of the getDisplayXXX or getISO3XXX methods are implemented.
*/
public final class Locale implements java.io.Serializable, Cloneable
{
// The fields are as specified in Sun's "Serialized Form"
// in the JDK 1.2 beta 4 API specification.
private String country;
private int hashcode;
private String language;
private String variant;
private static Locale defaultLocale;
// FIXME: many are still missing.
public static final Locale CANADA = new Locale ("en", "CA");
public static final Locale FRANCE = new Locale ("fr", "FR");
public static final Locale JAPAN = new Locale ("ja", "JP");
public static final Locale UK = new Locale ("en", "GB");
public static final Locale US = new Locale ("en", "US");
public Locale (String languageCode, String countryCode)
{
language = languageCode.toLowerCase();
country = countryCode.toUpperCase();
hashcode = languageCode.hashCode() ^ countryCode.hashCode();
}
public Locale (String languageCode, String countryCode,
String variantCode)
{
this (languageCode, countryCode);
variant = variantCode;
hashcode ^= variantCode.hashCode();
}
public Object clone ()
{
return (Object) new Locale (language, country, variant);
}
public boolean equals (Object obj)
{
if (! (obj instanceof Locale))
return false;
Locale loc = (Locale) obj;
if ((language == null && loc.language != null)
|| (country == null && loc.country != null)
|| (variant == null && loc.variant != null))
return false;
return (language.equals(loc.language)
&& country.equals(loc.country)
&& variant.equals(loc.variant));
}
public String getCountry ()
{
return country;
}
public String getLanguage ()
{
return language;
}
public String getVariant ()
{
return variant;
}
public int hashCode ()
{
return hashcode;
}
private static synchronized Locale setDefault()
{
if (defaultLocale != null)
return defaultLocale;
String language = System.getProperty("user.language");
String country = System.getProperty("user.region");
defaultLocale = new Locale (language == null ? "en" : language,
country == null ? "" : country);
return defaultLocale;
}
public static Locale getDefault ()
{
return defaultLocale == null ? setDefault() : defaultLocale;
}
public static void setDefault (Locale newLocale)
{
defaultLocale = newLocale;
}
public String toString ()
{
StringBuffer result = new StringBuffer(20);
result.append(language);
result.append('_');
result.append(country);
if (variant != null && variant.length() > 0)
{
result.append('_');
result.append(variant);
}
return result.toString();
}
}

View file

@ -0,0 +1,43 @@
/* Copyright (C) 1998, 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.util;
/**
* @author Warren Levy <warrenl@cygnus.com>
* @date September 2, 1998.
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
* Status: Believed complete and correct.
*/
public class MissingResourceException extends RuntimeException
{
private String className;
private String key;
public MissingResourceException(String msg, String cName, String k)
{
super(msg);
className = cName;
key = k;
}
public String getClassName()
{
return className;
}
public String getKey()
{
return key;
}
}

View file

@ -0,0 +1,32 @@
/* Copyright (C) 1998, 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.util;
/**
* @author Warren Levy <warrenl@cygnus.com>
* @date September 2, 1998.
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
* Status: Believed complete and correct.
*/
public class NoSuchElementException extends RuntimeException
{
public NoSuchElementException()
{
super();
}
public NoSuchElementException(String msg)
{
super(msg);
}
}

View file

@ -0,0 +1,98 @@
/* Copyright (C) 1998, 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.util;
/**
* @author Warren Levy <warrenl@cygnus.com>
* @date September 2, 1998.
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
* Status: Believed complete and correct.
*/
public class Observable
{
/* tracks whether this object has changed */
private boolean changed;
/* list of the Observers registered as interested in this Observable */
private Vector observerVec;
/* TBD: This might be better implemented as an Observer[]
* but that would mean writing more code rather than making use of
* the existing Vector class (this also implies a larger text code
* space in resulting executables). The tradeoff is one of speed
* (manipulating the Observer[] directly) vs. size/reuse. In the future,
* we may decide to make the tradeoff and reimplement with an Observer[].
*/
public Observable()
{
changed = false;
observerVec = new Vector();
}
public synchronized void addObserver(Observer obs)
{
// JDK 1.2 spec says not to add this if it is already there
if (!observerVec.contains(obs))
observerVec.addElement(obs);
}
protected synchronized void clearChanged()
{
changed = false;
}
public synchronized int countObservers()
{
return observerVec.size();
}
public synchronized void deleteObserver(Observer obs)
{
observerVec.removeElement(obs);
}
public synchronized void deleteObservers()
{
observerVec.removeAllElements();
}
public synchronized boolean hasChanged()
{
return changed;
}
public void notifyObservers()
{
notifyObservers(null);
}
public void notifyObservers(Object arg)
{
if (changed)
{
/* The JDK 1.2 spec states that though the order of notification
* is unspecified in subclasses, in Observable it is in the order
* of registration.
*/
for (int i = 0, numObs = observerVec.size(); i < numObs; i++)
((Observer) (observerVec.elementAt(i))).update(this, arg);
changed = false;
}
}
protected synchronized void setChanged()
{
changed = true;
}
}

View file

@ -0,0 +1,24 @@
/* Copyright (C) 1998, 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.util;
/**
* @author Warren Levy <warrenl@cygnus.com>
* @date August 25, 1998.
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
* Status: Believed complete and correct
*/
public interface Observer
{
public void update(Observable observed, Object arg);
}

View file

@ -0,0 +1,376 @@
// Properties - Property list representation.
/* Copyright (C) 1998, 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.util;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.PushbackReader;
/**
* @author Tom Tromey <tromey@cygnus.com>
* @date October 26, 1998.
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* Status: Complete to JDK 1.1.
*/
public class Properties extends Hashtable
{
protected Properties defaults;
public String getProperty (String propName)
{
return getProperty (propName, null);
}
public String getProperty (String propName, String defVal)
{
String r = (String) get (propName);
if (r == null)
{
if (defaults != null)
r = defaults.getProperty(propName, defVal);
else
r = defVal;
}
return r;
}
public void list (PrintStream out)
{
Enumeration e = propertyNames ();
while (e.hasMoreElements())
{
String key = (String) e.nextElement();
String value = getProperty(key);
if (value != null)
{
if (value.length() > 40)
{
// JDK compatibility.
value = value.substring(0, 37) + "...";
}
out.print(key);
out.print("=");
out.println(value);
}
}
}
public void list (PrintWriter writer)
{
Enumeration e = propertyNames ();
while (e.hasMoreElements())
{
String key = (String) e.nextElement();
String value = getProperty(key);
if (value != null)
{
if (value.length() > 40)
{
// JDK compatibility.
value = value.substring(0, 37) + "...";
}
writer.print(key);
writer.print("=");
writer.println(value);
}
}
}
private final boolean skip_ws (PushbackReader reader) throws IOException
{
while (true)
{
int c = reader.read();
if (c == -1)
return false;
// FIXME: we use our own definition of whitespace.
// Character.isWhitespace includes newlines, which we don't
// want. Character.isSpaceChar doesn't include \t.
if (c == ' ' || c == '\t')
{
reader.unread(c);
return true;
}
}
}
// Note: this method needs to be rewritten for JDK 1.2.
// We rather arbitrarily decide that an EOF in the middle of a line
// means that the whole line should be ignored. The spec doesn't
// specifically address this, but this interpretation seems valid.
public synchronized void load (InputStream in) throws IOException
{
PushbackReader reader = new PushbackReader (new InputStreamReader (in));
StringBuffer key = new StringBuffer ();
StringBuffer value = new StringBuffer ();
nextLine:
while (true)
{
key.setLength(0);
value.setLength(0);
// Skip leading whitespace.
if (! skip_ws (reader))
return;
// Read key until key terminator.
boolean first_char = true;
int c;
while (true)
{
c = reader.read();
if (c == -1)
return;
if (c == '\\')
{
first_char = false;
c = reader.read();
if (c == -1)
return;
}
// If we found a comment, just read to end of line and
// then keep going.
if (first_char == true && (c == '#' || c == '!'))
{
while (c != -1 && c != '\r' && c != '\n')
c = reader.read();
if (c == -1)
return;
continue nextLine;
}
if (c == '\r' || c == '\n')
{
if (first_char)
continue nextLine;
reader.unread(c);
break;
}
// FIXME: again, our own definitino of whitespace.
if (c == ' ' || c == '\t' || c == ':' || c == '=')
break;
first_char = false;
key.append(c);
}
// Found end of key. Skip whitespace. If the terminator
// was whitespace, also skip a single instance of a "real"
// terminator, and then more whitespace.
if (! skip_ws (reader))
return;
if (c != ':' && c != '=')
{
c = reader.read();
if (c == -1)
return;
if (c == ':' || c == '=')
{
// Skip more whitespace.
if (! skip_ws (reader))
return;
}
else
reader.unread(c);
}
// Now read the value.
while (true)
{
c = reader.read();
if (c == -1)
return;
if (c == '\r' || c == '\n')
break;
if (c == '\\')
{
c = reader.read();
switch (c)
{
case -1:
return;
case 't':
c = '\t';
break;
case 'r':
c = '\r';
break;
case 'n':
c = '\n';
break;
case 'u':
c = 0;
for (int i = 0; i < 4; ++i)
{
int x = reader.read();
if (x == -1)
return;
int d = Character.digit((char) x, 16);
// FIXME: what to do here? We call it an
// error.
if (d == -1)
throw new IOException ();
c <<= 4;
c |= d;
}
break;
default:
// Nothing.
}
}
else
value.append(c);
}
put (key.toString(), value.toString());
}
}
public Properties ()
{
defaults = null;
}
public Properties (Properties defs)
{
defaults = defs;
}
private final void addHashEntries (Hashtable base)
{
if (defaults != null)
defaults.addHashEntries(base);
Enumeration keys = keys ();
while (keys.hasMoreElements())
base.put(keys.nextElement(), base);
}
public Enumeration propertyNames ()
{
// We make a new Hashtable that holds all the keys. Then we
// return an enumeration for this hash. We do this because we
// don't want modifications to be reflected in the enumeration
// (per JCL), and because there doesn't seem to be a
// particularly better way to ensure that duplicates are
// ignored.
Hashtable t = new Hashtable ();
addHashEntries (t);
return t.keys();
}
public synchronized void save (OutputStream out, String comment)
{
// Use a buffer because writing a single string through
// OutputStreamWriter is fairly expensive.
BufferedWriter output
= new BufferedWriter (new OutputStreamWriter (out));
String newline = System.getProperty("line.separator");
try
{
if (comment != null)
{
// FIXME: what if COMMENT contains newlines?
output.write("#");
output.write(comment);
output.write(newline);
}
output.write("# ");
output.write(new Date().toString());
output.write(newline);
Enumeration keys = keys ();
while (keys.hasMoreElements())
{
String key = (String) keys.nextElement();
String value = (String) get (key);
// FIXME: JCL says that the key can contain many Unicode
// characters. But it also doesn't say we should encode
// it in any way.
// FIXME: if key contains ':', '=', or whitespace, must
// quote it here.
output.write(key);
output.write("=");
boolean leading = true;
for (int i = 0; i < value.length(); ++i)
{
boolean new_lead = false;
char c = value.charAt(i);
switch (c)
{
case '\n':
output.write("\\n");
break;
case '\r':
output.write("\\r");
break;
case '\t':
output.write("\\t");
break;
case '\\':
output.write("\\\\");
break;
case '#':
case '!':
case '=':
case ':':
output.write("\\");
output.write(c);
break;
case ' ':
new_lead = leading;
if (leading)
output.write("\\");
output.write(c);
break;
default:
if (c < '\u0020' || c > '\u007e')
{
output.write("\\u");
output.write(Character.forDigit(c >>> 12, 16));
output.write(Character.forDigit((c >>> 8) & 0xff,
16));
output.write(Character.forDigit((c >>> 4) & 0xff,
16));
output.write(Character.forDigit(c & 0xff, 16));
}
else
output.write(c);
}
leading = new_lead;
}
output.write(newline);
}
output.flush();
}
catch (IOException ignore)
{
}
}
}

View file

@ -0,0 +1,148 @@
/* Copyright (C) 1998, 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.util;
import java.io.Serializable;
/**
* @author Warren Levy <warrenl@cygnus.com>
* @date August 25, 1998.
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
* Status: Believed complete and correct
*/
/* This class is completely specified by the spec to ensure absolute
* portability between all implementations of Java
*/
public class Random implements Serializable
{
/* Used by next() to hold the state of the pseudorandom number generator */
protected long seed;
/* Used by nextGaussian() to hold a precomputed value */
/* to be delivered by that method the next time it is called */
protected double nextNextGaussian;
/* Used by nextGaussian() to keep track of whether it is has precomputed */
/* and stashed away the next value to be delivered by that method */
protected boolean haveNextNextGaussian = false;
public Random()
{
this(System.currentTimeMillis());
}
public Random(long seed)
{
setSeed(seed);
}
protected synchronized int next(int bits)
{
seed = (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1);
return (int)(seed >>> (48 - bits));
}
// JDK1.2
public boolean nextBoolean()
{
return next(1) != 0;
}
/* The method nextBytes() is not fully specified in the published specs.
* At first I implemented it simply via:
* for (int i = 0; i < buf.length; i++)
* buf[i] = (byte)next(8);
* but a simple test did not yield the same results as the std implementation.
* There seemed to be a relationship where each i byte above was at pos 4*i+3
* in the std. For efficiency, by reducing calls to the expensive math
* routines, the std probably was calling next(32) once rather than next(8)
* 4 times. Changing the algorithm to the one below based on that assumption
* then yielded identical results to the std.
*/
public void nextBytes(byte[] buf)
{
int randInt = 0;
for (int i = 0; i < buf.length; i++)
{
int shift = (i % 4) * 8;
if (shift == 0)
randInt = next(32);
buf[i] = (byte) (randInt >> shift);
}
}
public double nextDouble()
{
return (((long)next(26) << 27) + next(27)) / (double)(1L << 53);
}
public float nextFloat()
{
return next(24) / ((float)(1 << 24));
}
public synchronized double nextGaussian()
{
if (haveNextNextGaussian)
{
haveNextNextGaussian = false;
return nextNextGaussian;
}
else
{
double v1, v2, s;
do
{
v1 = 2 * nextDouble() - 1; // between -1.0 and 1.0
v2 = 2 * nextDouble() - 1; // between -1.0 and 1.0
s = v1 * v1 + v2 * v2;
} while (s >= 1);
double norm = Math.sqrt(-2 * Math.log(s)/s);
nextNextGaussian = v2 * norm;
haveNextNextGaussian = true;
return v1 * norm;
}
}
public int nextInt()
{
return next(32);
}
// JDK1.2
public int nextInt(int n)
{
if (n <= 0)
throw new IllegalArgumentException("n must be positive");
int bits, val;
do
{
bits = next(31);
val = bits % n;
} while (bits - val + (n-1) < 0);
return val;
}
public long nextLong()
{
return ((long)next(32) << 32) + next(32);
}
public synchronized void setSeed(long seed)
{
this.seed = (seed ^ 0x5DEECE66DL) & ((1L << 48) - 1);
haveNextNextGaussian = false;
}
}

View file

@ -0,0 +1,188 @@
/* Copyright (C) 1998, 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.util;
/**
* @author Anthony Green <green@cygnus.com>
* @date November 26, 1998.
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3,
* and "The Java Language Specification", ISBN 0-201-63451-1. */
public abstract class ResourceBundle
{
protected ResourceBundle parent;
public ResourceBundle ()
{
}
public final String getString (String key) throws MissingResourceException
{
return (String) getObject(key);
}
public final String[] getStringArray (String key)
throws MissingResourceException
{
return (String[]) getObject(key);
}
public final Object getObject(String key) throws MissingResourceException
{
Object result;
try
{
return handleGetObject (key);
}
catch (MissingResourceException ex)
{
if (parent != null)
return parent.getObject(key);
else
throw ex;
}
}
public static final ResourceBundle getBundle(String baseName)
throws MissingResourceException
{
return getBundle(baseName, Locale.getDefault());
}
// Start searching with the name bundleName. Continue searching by
// stripping off the '_' delimited tails until the search name is
// the same as stopHere.
private static final ResourceBundle trySomeGetBundle (String bundleName,
String stopHere)
{
Class rbc;
while (true)
{
try
{
rbc = Class.forName(bundleName);
try
{
return (ResourceBundle) rbc.newInstance();
}
catch (IllegalAccessException ex)
{
// Fall through
}
catch (InstantiationException ex)
{
// Fall through
}
return null;
}
catch (ClassNotFoundException ex)
{
if (bundleName.compareTo(stopHere) == 0)
return null;
else
{
int last = bundleName.lastIndexOf('_');
// No more underscores?
if (last == -1)
return null;
// Loop around, testing this new shorter name.
bundleName = bundleName.substring(0, last);
}
}
}
}
// Search for bundles, but stop at baseName_language.
private static final ResourceBundle partialGetBundle (String baseName,
Locale locale)
{
ResourceBundle rb;
String bundleName = (baseName
+ "_"
+ locale.getLanguage() + "_"
+ locale.getCountry() + "_"
+ locale.getVariant());
String stopHere = (baseName
+ "_"
+ locale.getLanguage());
rb = trySomeGetBundle(bundleName, stopHere);
return rb;
}
public static final ResourceBundle getBundle (String baseName,
Locale locale)
throws MissingResourceException
{
ResourceBundle rb;
Class rbc;
// FIXME: We can't currently rely on NullPointerException being
// thrown when we invoke a method on a null object.
if (locale == null)
throw new NullPointerException ();
rb = partialGetBundle(baseName, locale);
if (rb != null)
return rb;
if (! locale.equals(Locale.getDefault()))
{
rb = partialGetBundle(baseName, Locale.getDefault());
if (rb != null)
return rb;
}
// Try just the baseName.
try
{
rbc = Class.forName (baseName);
try
{
return (ResourceBundle) rbc.newInstance();
}
catch (IllegalAccessException ex)
{
// Fall through.
}
catch (InstantiationException ex)
{
// Fall through.
}
}
catch (ClassNotFoundException ex)
{
// Fall through.
}
throw new MissingResourceException("can't load bundle",
baseName,
"bundle");
}
protected void setParent(ResourceBundle parent)
{
this.parent = parent;
}
protected abstract Object handleGetObject(String key)
throws MissingResourceException;
public abstract Enumeration getKeys();
}

View file

@ -0,0 +1,182 @@
/* Copyright (C) 1998, 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.util;
/**
* @author Per Bothner <bothner@cygnus.com>
* @date October 24, 1998.
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3.
* Status: Does not know how to figure out if daylight savings time
* is in effect; hence only correct for zones without DST.
* No known spec for hashCode.
*/
public class SimpleTimeZone extends TimeZone
{
// The fields are as specified in Sun's "Serialized Form"
// in the JDK 1.2 beta 4 API specification.
int dstSavings = 60 * 60 * 1000;
int rawOffset;
// int serialVersionOnStream;
int startDay;
int startDayOfWeek;
int startMode; /// Seems to be JDK 1.2 only.
int startMonth;
int startTime;
int startYear;
int endDay;
int endDayOfWeek;
int endMode; // Seems to be JDK 1.2 only.
int endMonth;
int endTime;
// byte[] monthLength;
boolean useDaylight;
public SimpleTimeZone (int rawOffset, String ID)
{
setID(ID);
this.rawOffset = rawOffset;
}
public SimpleTimeZone (int rawOffset, String ID,
int startMonth, int startDay,
int startDayOfWeek, int startTime,
int endMonth, int endDay,
int endDayOfWeek, int endTime)
{
this(rawOffset, ID);
setStartRule (startMonth, startDay, startDayOfWeek, startTime);
setEndRule (endMonth, endDay, endDayOfWeek, endTime);
}
public int getRawOffset() { return rawOffset; }
public void setRawOffset (int offsetMillis) { rawOffset = offsetMillis; }
public int getOffset (int era, int year, int month, int day,
int dayOfWeek, int millis)
{
int offset = getRawOffset();
if (useDaylight)
{
if (startYear != 0
&& (year < startYear || era == GregorianCalendar.BC))
return offset;
boolean midYearSummer = startMonth < endMonth;
if (midYearSummer ? (month < startMonth || month > endMonth)
: (month < startMonth && month > endMonth))
return offset; // Definitely not DST.
if (midYearSummer ? (month > startMonth && month < endMonth)
: (month > startMonth || month < endMonth))
return offset + dstSavings; // Definitely DST.
// Now it gets more complicated. Bail for now.
throw new Error("not implemented - SimpleTimeZone.getOffset");
}
return offset;
}
public boolean useDaylightTime() { return useDaylight; }
public boolean inDaylightTime(Date date)
{
if (! useDaylight)
return false;
throw new Error("not implemented - SimpleTimeZone.inDaylightTime");
}
public int getDSTSavings () { return dstSavings; }
public void setDSTSavings (int millisSavedDuringDST)
{ dstSavings = millisSavedDuringDST; }
public void setStartRule (int month, int dayOfWeekInMonth,
int dayOfWeek, int time)
{
this.startMonth = month;
this.startDay = dayOfWeekInMonth;
this.startDayOfWeek = dayOfWeek;
this.startTime = time;
this.useDaylight = true;
}
public void setEndRule (int month, int dayOfWeekInMonth,
int dayOfWeek, int time)
{
this.endMonth = month;
this.endDay = dayOfWeekInMonth;
this.endDayOfWeek = dayOfWeek;
this.endTime = time;
this.useDaylight = true;
}
public void setStartYear (int year)
{
this.startYear = startYear;
}
public boolean hasSameRules (TimeZone other)
{
if (this == other)
return true;
if (! (other instanceof SimpleTimeZone))
return false;
SimpleTimeZone o = (SimpleTimeZone) other;
if (rawOffset != o.rawOffset)
return false;
if (useDaylight != o.useDaylight)
return false;
if (! useDaylight)
return true;
return startDay == o.startDay
&& startDayOfWeek == o.startDayOfWeek
&& startMonth == o.startMonth
&& startTime == o.startTime
&& endDay == o.endDay
&& endDayOfWeek == o.endDayOfWeek
&& endMonth == o.endMonth
&& endTime == o.endTime
&& startYear == o.startYear
&& startMode == o.startMode
&& endMode == o.endMode;
}
public boolean equals (Object obj)
{
if (! (obj instanceof SimpleTimeZone))
return false;
SimpleTimeZone other = (SimpleTimeZone) obj;
return getID() == other.getID() && hasSameRules(other);
}
public int hashCode ()
{
// FIXME - this does not folow any spec (since none is public)!
int hash = rawOffset;
if (useDaylight)
hash += dstSavings + startYear + startMode + endMode
+ startDay + startDayOfWeek + startMonth + startTime
+ endDay + endDayOfWeek + endMonth + endTime;
return hash;
}
}

View file

@ -0,0 +1,74 @@
/* Copyright (C) 1998, 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.util;
/**
* @author Warren Levy <warrenl@cygnus.com>
* @date August 20, 1998.
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
* Status: Believed complete and correct
*/
public class Stack extends Vector
{
// Could use Vector methods internally for the following methods
// but have used Vector fields directly for efficiency (i.e. this
// often reduces out duplicate bounds checking).
public boolean empty()
{
return elementCount == 0;
}
public synchronized Object peek()
{
if (elementCount == 0)
throw new EmptyStackException();
return elementData[elementCount - 1];
}
public synchronized Object pop()
{
if (elementCount == 0)
throw new EmptyStackException();
Object obj = elementData[--elementCount];
// Set topmost element to null to assist the gc in cleanup
elementData[elementCount] = null;
return obj;
}
public Object push(Object obj)
{
// When growing the Stack, use the Vector routines in case more
// memory is needed.
// Note: spec indicates that this method *always* returns obj passed in!
addElement(obj);
return obj;
}
public synchronized int search(Object obj)
{
// Return the position of obj on the stack as measured from the top;
// i.e. the top element is 1, the next element down is 2, etc.
// If obj is not on the stack, return -1
for (int i = elementCount-1; i >=0; --i)
if (elementData[i].equals(obj))
return elementCount - i;
return -1;
}
}

View file

@ -0,0 +1,185 @@
/* Copyright (C) 1998, 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.util;
/**
* @author Warren Levy <warrenl@cygnus.com>
* @date August 24, 1998.
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
* Status: Believed complete and correct
*/
public class StringTokenizer implements Enumeration
{
/* String to be parsed */
private String inputString;
/* String to be parsed put into a char array for efficient access */
private char[] chArray;
/* Set of delimiter characters for separating tokens */
private String delimiters;
/* Whether delimiters in this instance are treated as tokens themselves */
private boolean returnDelimiters;
/* Index into the input string to start parsing for the next token */
private int inputStringIndex;
public StringTokenizer(String str)
{
this(str, " \t\n\r", false);
}
public StringTokenizer(String str, String delims)
{
this(str, delims, false);
}
public StringTokenizer(String str, String delims, boolean retDelim)
{
inputString = str;
delimiters = delims;
returnDelimiters = retDelim;
inputStringIndex = 0;
// Work on a copy of the remaining string in a char array
// to gain efficiency of using primitives
chArray = new char[inputString.length()];
inputString.getChars(0, inputString.length(), chArray, 0);
}
public int countTokens()
{
int count = 0;
int delimiterCount = 0;
boolean tokenFound = false; // Set when a non-delimiter is found
int offset = inputStringIndex;
// Note for efficiency, we count up the delimiters rather than check
// returnDelimiters every time we encounter one. That way, we can
// just do the conditional once at the end of the method
while (offset < chArray.length)
{
if (isDelimiter(chArray[offset++]))
{
if (tokenFound)
{
// Got to the end of a token
count++;
tokenFound = false;
}
delimiterCount++; // Increment for this delimiter
}
else
{
tokenFound = true;
// Get to the end of the token
while (offset < chArray.length && !isDelimiter(chArray[offset]))
offset++;
}
}
// Make sure to count the last token
if (tokenFound)
count++;
// if counting delmiters add them into the token count
return returnDelimiters ? count + delimiterCount : count;
}
public boolean hasMoreElements()
{
return hasMoreTokens();
}
public boolean hasMoreTokens()
{
int offset = inputStringIndex;
while (offset < chArray.length)
if (!isDelimiter(chArray[offset++]) || returnDelimiters)
{
// update the current position with the start of the next token
inputStringIndex = --offset;
return true;
}
return false;
}
public Object nextElement()
{
return nextToken();
}
public String nextToken()
{
int offset = inputStringIndex;
int startSubstr = -1;
// Make sure we have more chars left to parse
// and then find the start of the next token
while (offset < chArray.length && startSubstr < 0)
{
// Find the start of the token; skipping initial delimiters
if (!isDelimiter(chArray[offset++]))
startSubstr = offset - 1;
else if (returnDelimiters)
{
// The single char delimiter is treated as a token
inputStringIndex = offset; // update the current position
return inputString.substring(offset - 1, inputStringIndex);
}
}
// Now look for the end of the token
while (offset < chArray.length)
{
if (isDelimiter(chArray[offset++]))
{
// Found the end of token
inputStringIndex = offset - 1; // update the current position
return inputString.substring(startSubstr, inputStringIndex);
}
}
// Got to the end of the string without finding the start of a token
if (startSubstr < 0)
throw new NoSuchElementException();
// Got to the end of the string before a delimiter
inputStringIndex = offset; // update the current position
return inputString.substring(startSubstr, inputStringIndex);
}
public String nextToken(String delims)
{
// First replace with new set of delimiters
delimiters = delims;
return nextToken();
}
// This private method could be inlined but the other methods are
// more readable this way, so we'll take the hit on efficiency.
private boolean isDelimiter(char ch)
{
return delimiters.indexOf(ch) >= 0;
}
}

View file

@ -0,0 +1,120 @@
/* Copyright (C) 1998, 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.util;
/**
* @author Per Bothner <bothner@cygnus.com>
* @date October 24, 1998.
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3.
* Status: getAvailableIDs, getDefault, getTimeZone only know about GMT.
*/
public abstract class TimeZone implements java.io.Serializable, Cloneable
{
public static final int SHORT = 0;
public static final int LONG = 1;
// The fields are as specified in Sun's "Serialized Form"
// in the JDK 1.2 beta 4 API specification.
String ID;
static final TimeZone zoneGMT = new SimpleTimeZone(0, "GMT");
private static TimeZone zoneDefault;
public TimeZone ()
{
}
public abstract int getOffset (int era, int year, int month,
int day, int dayOfWeek, int milliseconds);
public abstract void setRawOffset (int offsetMillis);
public abstract int getRawOffset ();
public String getID () { return ID; }
public void setID (String ID) { this.ID = ID; }
public final String getDisplayName()
{
return ID; // FIXME
}
// public final String getDisplayName (Local locale) { ... } FIXME
public final String getDisplayName (boolean daylight, int style)
{
return ID; // FIXME
}
/*
public final String getDisplayName (boolean daylight, int style, Locale locale)
{
return ID; // FIXME
}
*/
public abstract boolean useDaylightTime();
public abstract boolean inDaylightTime (Date date);
public static TimeZone getTimeZone (String ID)
{
return zoneGMT; // FIXME
}
public static String[] getAvailableIDs()
{ // FIXME - only knows about GMT
String[] zones = new String[1];
zones[0] = "GMT";
return zones;
}
public static String[] getAvailableIDs(int rawOffset)
{
return rawOffset == 0 ? getAvailableIDs() : new String[0]; // FIXME
}
private static synchronized TimeZone setDefault()
{
if (zoneDefault == null)
{
try
{
String id = System.getProperty("user.timezone");
if (id != null && ! id.equals("GMT"))
zoneDefault = getTimeZone(id);
}
catch (Exception ex)
{
}
if (zoneDefault == null)
zoneDefault = zoneGMT;
}
return zoneDefault;
}
public static TimeZone getDefault()
{
return zoneDefault == null ? setDefault() : zoneDefault;
}
public static void setDefault (TimeZone zone) { zoneDefault = zone; }
public boolean hasSameRules (TimeZone other)
{
return this == other;
}
// public Object clone ();
}

View file

@ -0,0 +1,32 @@
/* Copyright (C) 1998, 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.util;
/**
* @author Warren Levy <warrenl@cygnus.com>
* @date September 2, 1998.
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
* Status: Believed complete and correct.
*/
public class TooManyListenersException extends Exception
{
public TooManyListenersException()
{
super();
}
public TooManyListenersException(String msg)
{
super(msg);
}
}

View file

@ -0,0 +1,450 @@
/* Copyright (C) 1998, 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.util;
import java.io.Serializable;
/**
* @author Warren Levy <warrenl@cygnus.com>
* @date August 17, 1998.
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
* Status: Believed complete and correct
*/
class VectorEnumeration implements Enumeration
{
private int enumIndex;
private Vector enumVec;
public VectorEnumeration(Vector vec)
{
enumVec = vec;
enumIndex = 0;
}
public boolean hasMoreElements()
{
return enumIndex < enumVec.size();
}
public Object nextElement()
{
if (!hasMoreElements())
throw new NoSuchElementException();
return enumVec.elementData[enumIndex++];
}
}
// TODO12:
// public class Vector extends AbstractList
// implements List, Cloneable, Serializable
public class Vector implements Cloneable, Serializable
{
/* The size of the increment to use when growing this vector.
The default of 0 means to double the capacity when growing. */
protected int capacityIncrement;
/* The number of elements currently in elementData */
protected int elementCount;
/* The buffer in which elements of this vector are stored */
protected Object[] elementData;
public Vector()
{
this(10, 0);
}
public Vector(int initCap)
{
this(initCap, 0);
}
public Vector(int initCap, int capIncrement)
{
if (initCap < 0)
throw new IllegalArgumentException ();
elementData = new Object[initCap];
capacityIncrement = capIncrement;
elementCount = 0;
}
public final synchronized void addElement(Object obj)
{
// Make sure there's room for a new element
if (elementCount == elementData.length)
ensureCapacity(elementCount+1);
elementData[elementCount++] = obj;
}
public final int capacity()
{
return elementData.length;
}
public synchronized Object clone()
{
// New vector needs to have same size, capacity and capacityIncrement
Vector newVec = new Vector(elementData.length, capacityIncrement);
System.arraycopy(elementData, 0, newVec.elementData, 0, elementCount);
newVec.elementCount = elementCount;
return newVec;
}
public final boolean contains(Object obj)
{
for (int i = 0; i < elementCount; i++)
{
if (obj == null
? elementData[i] == null
: obj.equals(elementData[i]))
return true;
}
return false;
}
public final synchronized void copyInto(Object[] objArray)
{
System.arraycopy(elementData, 0, objArray, 0, elementCount);
}
public final synchronized Object elementAt(int idx)
{
if (idx < 0 || idx >= size())
throw new ArrayIndexOutOfBoundsException();
return elementData[idx];
}
public final synchronized Enumeration elements()
{
return new VectorEnumeration(this);
}
public final synchronized void ensureCapacity(int minCap)
{
// Increasing the vector could make it much larger than minCap;
// e.g. if minCap is just larger than the vector, size may double.
// If someone cares about this possibility they should set capacityIncrement
if (minCap > elementData.length)
{
// Increase the vector; double it if capacityIncrement is zero
int newSize = elementData.length;
newSize +=
(capacityIncrement > 0) ? capacityIncrement : elementData.length;
// Make sure newSize is at least minCap
if (newSize < minCap)
newSize = minCap;
Object[] newArray = new Object[newSize];
System.arraycopy(elementData, 0, newArray, 0, elementCount);
elementData = newArray;
}
}
public final synchronized Object firstElement()
{
if (elementCount == 0)
throw new NoSuchElementException();
return elementData[0];
}
public final int indexOf(Object obj)
{
return indexOf(obj, 0);
}
public final synchronized int indexOf(Object obj, int idx)
{
if (idx < 0)
throw new IllegalArgumentException ();
for (int i = idx; i < elementCount; i++)
{
if (obj == null
? elementData[i] == null
: obj.equals(elementData[i]))
return i;
}
return -1;
}
public final synchronized void insertElementAt(Object obj, int idx)
{
if (idx < 0 || idx > size())
throw new ArrayIndexOutOfBoundsException();
else if (idx == size()) // Spec says just use addElement()
addElement(obj);
else
{
// Make sure there's room for a new element
if (elementCount == elementData.length)
ensureCapacity(elementCount+1);
// Shift the existing elements up and increment elementCount
for (int i = elementCount++; i > idx; --i)
elementData[i] = elementData[i-1];
elementData[idx] = obj;
}
}
public final boolean isEmpty()
{
return elementCount == 0;
}
public final synchronized Object lastElement()
{
if (elementCount == 0)
throw new NoSuchElementException();
return elementData[elementCount - 1];
}
public final int lastIndexOf(Object obj)
{
return lastIndexOf(obj, size()-1);
}
public final synchronized int lastIndexOf(Object obj, int idx)
{
if (idx < 0)
throw new IllegalArgumentException ();
for (int i = idx; i >= 0; --i)
{
if (obj == null
? elementData[i] == null
: obj.equals(elementData[i]))
return i;
}
return -1;
}
public final synchronized void removeAllElements()
{
// Remove elements now to assist the gc in early cleanup
for (int i = elementCount-1; i >= 0; --i)
elementData[i] = null;
elementCount = 0;
}
public final synchronized boolean removeElement(Object obj)
{
for (int i = 0; i < elementCount; i++)
{
if (obj == null
? elementData[i] == null
: obj.equals(elementData[i]))
{
int j;
// Decrement count first to ensure we don't walk off end of array
--elementCount;
for (j = i; j < elementCount; j++)
elementData[j] = elementData[j+1];
// At this point, j was incrememented and points to old last element
// Remove element now to assist the gc in early cleanup
elementData[j] = null;
return true;
}
}
return false;
}
public final synchronized void removeElementAt(int idx)
{
int i;
if (idx < 0 || idx >= size())
throw new ArrayIndexOutOfBoundsException();
// Decrement count first to ensure we don't walk off the end of the array
--elementCount;
for (i = idx; i < elementCount; i++)
elementData[i] = elementData[i+1];
// At this point, i was incrememented and now points to the old last element
// Remove element now to assist the gc in early cleanup
elementData[i] = null;
}
public final synchronized void setElementAt(Object obj, int idx)
{
if (idx < 0 || idx >= size())
throw new ArrayIndexOutOfBoundsException();
elementData[idx] = obj;
}
public final synchronized void setSize(int newSize)
{
if (newSize < 0)
throw new ArrayIndexOutOfBoundsException();
// Java Lang Spec p. 658 says to remove the excess elements and discard
// when new size is smaller than old size.
// When truncating, we could alternatively just reset elementCount instead
// of freeing up the memory if the spec hadn't specified. The spec makes
// sense though; if someone cares enough to call a setSize() function
// they probably are doing so to free memory.
if (newSize < elementCount)
{
elementCount = newSize;
trimToSize();
}
else if (newSize > elementCount) // Skip == case
{
// TBD: ensureCapacity() may create a vector much larger than newSize;
// do we want to make the vector exactly newSize? Spec is unclear.
ensureCapacity(newSize);
// Make sure to null out new elements of grown vector
for (int i = elementCount; i < newSize; i++)
elementData[i] = null;
elementCount = newSize;
}
}
public final int size()
{
return elementCount;
}
public final synchronized String toString()
{
// Following the Java Lang Spec p. 656
// Prepend first element with open bracket
StringBuffer result = new StringBuffer("[");
if (elementCount > 0) // add first element if one exists
result.append(elementData[0].toString());
// Prepend subsequent elements with ", "
for (int i = 1; i < elementCount; i++)
result.append(", ").append(elementData[i].toString());
// Append last element with closing bracket
result.append("]");
return result.toString();
}
public final synchronized void trimToSize()
{
// Give up excess storage capacity to save memory
//
// Don't bother checking for the case where size() == the capacity of the
// vector since that is a much less likely case; it's more efficient to
// not do the check and lose a bit of performance in that infrequent case
Object[] newArray = new Object[elementCount];
System.arraycopy(elementData, 0, newArray, 0, elementCount);
elementData = newArray;
}
// TODO12:
// public Vector(Collection c)
// {
// }
// TODO12:
// public public boolean add(Object o)
// {
// }
// TODO12:
// public void add(int index, Object element)
// {
// }
// TODO12:
// public boolean addAll(Collection c)
// {
// }
// TODO12:
// public boolean addAll(int index, Collection c)
// {
// }
// TODO12:
// public void clear()
// {
// }
// TODO12:
// public boolean containsAll(Collection c)
// {
// }
// TODO12:
// public boolean equals(Object o)
// {
// }
// TODO12:
// public int hashCode()
// {
// }
// TODO12:
// public Object get(int index)
// {
// }
// TODO12:
// public boolean remove(Object o)
// {
// }
// TODO12:
// public Object remove(int index)
// {
// }
// TODO12:
// public boolean removeAll(Collection c)
// {
// }
// TODO12:
// public boolean retainAll(Collection c)
// {
// }
// TODO12:
// public Object set(int index, Object element)
// {
// }
// TODO12:
// public Object[] toArray()
// {
// }
// TODO12:
// public Object[] toArray(Object[] a)
// {
// }
}

View file

@ -0,0 +1,45 @@
/* Copyright (C) 1998, 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. */
#include <config.h>
// We want to make sure to pick up the POSIX ctime_r. Some systems,
// such as Solaris 2.6, have their own version as well.
#ifdef HAVE_CTIME_R
#define _POSIX_PTHREAD_SEMANTICS
#endif
#include <cni.h>
#include <java/util/Date.h>
#include <java/lang/String.h>
#include <time.h>
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
jstring
java::util::Date::toString()
{
#ifdef HAVE_CTIME_R
time_t t = millis / 1000;
char buf[30];
return JvNewStringLatin1 (ctime_r (&t, buf));
#elif defined (HAVE_CTIME)
// FIXME: this isn't thread-safe.
time_t t = millis / 1000;
return JvNewStringLatin1 (ctime (&t));
#else
return NULL;
#endif
}

View file

@ -0,0 +1,124 @@
/* Copyright (C) 1998, 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. */
#include <config.h>
// We want to make sure to pick up the POSIX `_r' functions. Some
// systems, such as Solaris 2.6, require this define in order to
// declare the functions in the appropriate header.
#if defined (HAVE_GMTIME_R) || defined (HAVE_LOCALTIME_R)
# define _POSIX_PTHREAD_SEMANTICS
# ifndef _REENTRANT
# define _REENTRANT
# endif /* _REENTRANT */
#endif
#ifdef ECOS
#include <string.h>
#endif
#include <cni.h>
#include <java/util/TimeZone.h>
#include <java/util/GregorianCalendar.h>
#include <time.h>
void
java::util::GregorianCalendar::computeTime ()
{
struct tm tim;
tim.tm_sec = elements(fields)[SECOND];
tim.tm_min = elements(fields)[MINUTE];
tim.tm_hour = elements(fields)[HOUR_OF_DAY];
tim.tm_mday = elements(fields)[DATE];
tim.tm_mon = elements(fields)[MONTH];
tim.tm_year = elements(fields)[YEAR] - 1900;
tim.tm_isdst = 0; // FIXME
#ifndef ECOS
// FIXME: None of the standard C library access to the ECOS calendar
// is yet available.
time_t t = mktime (&tim);
#else
time_t t = 0;
#endif
// Adjust for local timezone (introduced by mktime) and our
// timezone.
#if defined (STRUCT_TM_HAS_GMTOFF)
t += tim.tm_gmtoff;
#elif defined (HAVE_TIMEZONE)
t -= timezone;
#endif
java::util::TimeZone *zone = getTimeZone ();
t += zone->getRawOffset();
// Adjust for milliseconds.
time = t * 1000 + elements(fields)[MILLISECOND];
isTimeSet = true;
}
void
java::util::GregorianCalendar::computeFields ()
{
time_t t = time / 1000;
int millis = time % 1000;
if (t < 0 && millis != 0)
{
t--;
millis = t - 1000 * t;
}
elements(fields)[MILLISECOND] = millis;
struct tm tim;
java::util::TimeZone *zone = getTimeZone ();
// FIXME: None of the standard C library access to the ECOS calendar
// is yet available.
#ifdef ECOS
memset (&tim, 0, sizeof tim);
#else
if (zone->getRawOffset() == 0 || ! zone->useDaylightTime())
{
#if defined(__JV_POSIX_THREADS__) && defined(HAVE_GMTIME_R)
gmtime_r (&t, &tim);
#else
// Get global lock (because gmtime uses a global buffer). FIXME
tim = *(struct tm*) gmtime (&t);
// Release global lock. FIXME
#endif
}
else
{
#if defined(__JV_POSIX_THREADS__) && defined(HAVE_LOCALTIME_R)
localtime_r (&t, &tim);
#else
// Get global lock (because localtime uses a global buffer). FIXME
tim = *(struct tm*) localtime (&t);
// Release global lock. FIXME
#endif
}
#endif /* ECOS */
elements(fields)[SECOND] = tim.tm_sec;
elements(fields)[MINUTE] = tim.tm_min;
elements(fields)[HOUR_OF_DAY] = tim.tm_hour;
elements(fields)[AM_PM] = tim.tm_hour < 12 ? AM : PM;
elements(fields)[HOUR] = tim.tm_hour % 12;
elements(fields)[DATE] = tim.tm_mday;
elements(fields)[MONTH] = tim.tm_mon;
elements(fields)[YEAR] = 1900 + tim.tm_year;
elements(fields)[DAY_OF_WEEK] = tim.tm_wday + 1;
elements(fields)[DAY_OF_WEEK_IN_MONTH] = ((tim.tm_mday - 1) / 7) + 1;
elements(fields)[DAY_OF_YEAR] = tim.tm_yday + 1;
elements(fields)[WEEK_OF_MONTH]
= (tim.tm_mday + 6 + (5 - tim.tm_wday + getFirstDayOfWeek()) % 7) / 7;
elements(fields)[WEEK_OF_YEAR]
= (tim.tm_yday + 7 + (5 - tim.tm_wday + getFirstDayOfWeek()) % 7) / 7;
elements(fields)[ERA] = AD;
elements(fields)[DST_OFFSET] = tim.tm_isdst <= 0 ? 0 : 60*60*1000;
elements(fields)[ZONE_OFFSET] = getTimeZone()->getRawOffset();
areFieldsSet = true;
}

View file

@ -0,0 +1,101 @@
/* 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.util.zip;
/**
* @author Per Bothner
* @date April 6, 1999.
*/
/*
* Written using on-line Java Platform 1.2 API Specification, as well
* as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
* The actual Adler32 algorithm is taken from RFC 1950.
* Status: Believed complete and correct.
*/
public class Adler32 implements Checksum
{
private static int BASE = 65521; /* largest prime smaller than 65536 */
int s1;
int s2;
public Adler32 ()
{
reset();
}
public void reset () { s1 = 1; s2 = 0; }
public void update (int bval)
{
s1 = (s1 + (bval & 0xFF)) % BASE;
s2 = (s1 + s2) % BASE;
}
public void update (byte[] buffer)
{
update(buffer, 0, buffer.length);
}
public void update (byte[] buf, int off, int len)
{
int s1 = this.s1;
int s2 = this.s2;
while (len > 0)
{
// We can defer the modulo operation.
int n = 4000;
if (n > len)
n = len;
len -= n;
while (--n >= 0)
{
s1 = s1 + (buf[off++] & 0xFF);
s2 = s2 + s1;
}
s1 %= BASE;
s2 %= BASE;
}
this.s1 = s1;
this.s2 = s2;
}
public long getValue()
{
return ((long) s2 << 16) + s1;
}
}

View file

@ -0,0 +1,70 @@
/* 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.util.zip;
/**
* @author Per Bothner
* @date April 1, 1999.
*/
/*
* Written using on-line Java Platform 1.2 API Specification, as well
* as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
* The actual CRC32 algorithm is taken from RFC 1952.
* Status: Believed complete and correct.
*/
public class CRC32 implements Checksum
{
int crc = 0;
static int[] crc_table = make_crc_table();
/* Make the table for a fast CRC. */
static int[] make_crc_table ()
{
int[] crc_table = new int[256];
for (int n = 0; n < 256; n++)
{
int c = n;
for (int k = 8; --k >= 0; )
{
if ((c & 1) != 0)
c = 0xedb88320 ^ (c >>> 1);
else
c = c >>> 1;
}
crc_table[n] = c;
}
return crc_table;
}
public long getValue ()
{
return (long) crc & 0xffffffffL;
}
public void reset () { crc = 0; }
public void update (int bval)
{
int c = ~crc;
c = crc_table[(c ^ bval) & 0xff] ^ (c >>> 8);
crc = ~c;
}
public void update (byte[] buf, int off, int len)
{
int c = ~crc;
while (--len >= 0)
c = crc_table[(c ^ buf[off++]) & 0xff] ^ (c >>> 8);
crc = ~c;
}
public void update (byte[] buf) { update(buf, 0, buf.length); }
}

View file

@ -0,0 +1,31 @@
/* 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.util.zip;
/**
* @author Per Bothner
* @date January 9, 1999.
*/
/*
* Written using on-line Java Platform 1.2 API Specification, as well
* as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
* Status: Believed complete and correct.
*/
public interface Checksum
{
public long getValue ();
public void reset ();
public void update (int bval);
public void update (byte[] buf, int off, int len);
}

View file

@ -0,0 +1,13 @@
/* 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.util.zip;
public class Deflater
{
}

View file

@ -0,0 +1,46 @@
/* 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.util.zip;
import java.io.*;
/** JUST AN INCOMPLETE STUB! */
public class DeflaterOutputStream extends FilterOutputStream
{
protected byte[] buf;
protected Deflater def;
public DeflaterOutputStream(OutputStream out)
{
this(out, null, 512);
}
public DeflaterOutputStream(OutputStream out, Deflater defl)
{
this(out, defl, 512);
}
public DeflaterOutputStream(OutputStream out, Deflater defl, int bufsize)
{
super(out);
buf = new byte[bufsize];
def = defl;
}
public void finish () throws IOException
{
}
public void close () throws IOException
{
finish();
out.close();
}
}

View file

@ -0,0 +1,13 @@
/* 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.util.zip;
public interface ZipConstants
{
}

View file

@ -0,0 +1,84 @@
/* 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.util.zip;
/**
* @author Per Bothner
* @date January 6, 1999.
*/
/*
* Written using on-line Java Platform 1.2 API Specification, as well
* as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
* Status: Believed complete and correct.
*/
public class ZipEntry
{
// These values were determined using a simple test program.
public static final int STORED = 0;
public static final int DEFLATED = 8;
String comment;
long compressedSize = -1;
long crc = -1;
byte[] extra;
int method = -1;
String name;
long size = -1;
long time = -1;
ZipEntry next;
public ZipEntry (String name)
{
this.name = name;
}
public String getComment () { return comment; }
public long getCompressedSize () { return compressedSize; }
public long getCrc () { return crc; }
public byte[] getExtra() { return extra; }
public int getMethod () { return method; }
public String getName () { return name; }
public long getSize () { return size; }
public long getTime () { return time; }
public boolean isDirectory ()
{
if (name != null)
{
int nlen = name.length();
if (nlen > 0 && name.charAt(nlen-1) == '/')
return true;
}
return false;
}
public void setComment (String comment) { this.comment = comment; }
public void setCrc (long crc) { this.crc = crc; }
public void setExtra (byte[] extra) { this.extra = extra; }
public void setMethod(int method) { this.method = method; }
public void setSize (long size) { this.size = size; }
public void setTime (long time) { this.time = time; }
public String toString () { return name; }
}

View file

@ -0,0 +1,33 @@
// ZipException.java
/* Copyright (C) 1998, 1999 Cygnus Solutions
This file is part of libjava.
This software is copyrighted work licensed under the terms of the
Libjava License. Please consult the file "LIBJAVA_LICENSE" for
details. */
package java.util.zip;
/**
* @author Per Bothner
* @date January 9, 1999.
*/
/* Written using on-line Java Platform 1.2 API Specification.
* Believed complete and correct.
*/
public class ZipException extends java.io.IOException
{
public ZipException ()
{
super();
}
public ZipException (String msg)
{
super(msg);
}
}

View file

@ -0,0 +1,81 @@
/* 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.util.zip;
import java.io.*;
/** JUST AN INCOMPLETE STUB! */
public class ZipFile implements ZipConstants
{
String name;
ZipEntry entries;
public ZipFile (String fname) throws IOException
{
name = fname;
// FIXME
}
public ZipFile (File f) throws IOException
{
this(f.getPath());
}
public java.util.Enumeration entries()
{
return new ZipEnumeration(this);
}
public void close() throws IOException
{
// FIXME
}
public ZipEntry getEntry(String name)
{
for (ZipEntry entry = entries; entry != null; entry = entry.next)
{
if (name.equals(entry.getName()))
return entry;
}
return null;
}
public InputStream getInputStream(ZipEntry ze) throws IOException
{
return null; // FIXME
}
public String getName () { return name; }
}
class ZipEnumeration implements java.util.Enumeration
{
ZipEntry entry;
ZipEnumeration (ZipFile zfile)
{
entry = zfile.entries;
}
public boolean hasMoreElements ()
{
return entry != null;
}
public Object nextElement ()
{
ZipEntry cur = entry;
if (cur == null)
throw new java.util.NoSuchElementException();
entry = cur.next;
return cur;
}
}

View file

@ -0,0 +1,26 @@
/* 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.util.zip;
import java.io.*;
/** JUST AN INCOMPLETE STUB! */
public class ZipOutputStream extends DeflaterOutputStream
implements ZipConstants
{
public ZipOutputStream (OutputStream out)
{
super(out);
}
public void putNextEntry (ZipEntry entry) throws IOException
{
throw new Error ("java.util.zip.ZipOutputStream.putNextEntry: not implemented");
}
}