From 472ecb1713346c7e637622770cfaf3e1941c1bce Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 22 Jul 2007 13:06:21 -0600 Subject: [PATCH] flesh out some classpath classes --- classpath/java/lang/Character.java | 16 ++++ classpath/java/lang/Comparable.java | 5 + classpath/java/lang/String.java | 135 +++++++++++++++++++++++---- classpath/java/lang/System.java | 2 + classpath/java/util/ArrayList.java | 9 ++ classpath/java/util/Arrays.java | 13 +++ classpath/java/util/Collection.java | 2 + classpath/java/util/Collections.java | 4 + classpath/java/util/HashMap.java | 128 +++++++++++++------------ classpath/java/util/HashSet.java | 4 + classpath/java/util/Hashtable.java | 8 ++ classpath/java/util/LinkedList.java | 27 +++++- classpath/java/util/Map.java | 4 + classpath/java/util/Vector.java | 10 ++ classpath/java/util/WeakHashMap.java | 20 +++- src/builtin.cpp | 6 ++ src/system.cpp | 18 ++-- src/system.h | 1 + 18 files changed, 320 insertions(+), 92 deletions(-) create mode 100644 classpath/java/lang/Comparable.java diff --git a/classpath/java/lang/Character.java b/classpath/java/lang/Character.java index 3a14f10e21..85df317dde 100644 --- a/classpath/java/lang/Character.java +++ b/classpath/java/lang/Character.java @@ -10,4 +10,20 @@ public final class Character { public char charValue() { return value; } + + public static char toLowerCase(char c) { + if (c >= 'A' && c <= 'Z') { + return (char) ((c - 'A') + 'a'); + } else { + return c; + } + } + + public static char toUpperCase(char c) { + if (c >= 'a' && c <= 'z') { + return (char) ((c - 'a') + 'A'); + } else { + return c; + } + } } diff --git a/classpath/java/lang/Comparable.java b/classpath/java/lang/Comparable.java new file mode 100644 index 0000000000..36640936f1 --- /dev/null +++ b/classpath/java/lang/Comparable.java @@ -0,0 +1,5 @@ +package java.lang; + +public interface Comparable { + public int compareTo(T o); +} diff --git a/classpath/java/lang/String.java b/classpath/java/lang/String.java index 85379ae02c..d7218911d2 100644 --- a/classpath/java/lang/String.java +++ b/classpath/java/lang/String.java @@ -1,28 +1,27 @@ package java.lang; -public final class String { +public final class String implements Comparable { private Object data; private int offset; private int length; private int hash; public String(char[] data, int offset, int length, boolean copy) { - if (copy) { - char[] c = new char[length]; - System.arraycopy(data, offset, c, 0, length); - - this.data = c; - this.length = length; - } else { - this.data = data; - this.offset = offset; - this.length = length; - } + this((Object) data, offset, length, copy); } public String(byte[] data, int offset, int length, boolean copy) { + this((Object) data, offset, length, copy); + } + + private String(Object data, int offset, int length, boolean copy) { if (copy) { - byte[] c = new byte[length]; + Object c; + if (data instanceof char[]) { + c = new char[length]; + } else { + c = new byte[length]; + } System.arraycopy(data, offset, c, 0, length); this.data = c; @@ -34,19 +33,107 @@ public final class String { } } - public int length() { - return length; - } - public static String valueOf(int v) { return valueOf((long) v); } + public int length() { + return length; + } + + public int hashCode() { + if (hash == 0) { + for (int i = 0; i < length; ++i) hash = (hash * 31) + charAt(i); + } + return hash; + } + + public boolean equals(Object o) { + return o instanceof String && compareTo((String) o) == 0; + } + + public boolean equalsIgnoreCase(String s) { + return compareToIgnoreCase(s) == 0; + } + + public int compareTo(String s) { + int d = length - s.length; + if (d != 0) { + return d; + } else { + for (int i = 0; i < length; ++i) { + d = charAt(i) - s.charAt(i); + if (d != 0) { + return d; + } + } + return 0; + } + } + + public int compareToIgnoreCase(String s) { + int d = length - s.length; + if (d != 0) { + return d; + } else { + for (int i = 0; i < length; ++i) { + d = Character.toLowerCase(charAt(i)) + - Character.toLowerCase(s.charAt(i)); + if (d != 0) { + return d; + } + } + return 0; + } + } + + public String substring(int start) { + return substring(start, length); + } + + public String substring(int start, int end) { + if (start >= 0 && end >= start && end <= length) { + if (start == 0 && end == length) { + return this; + } else if (end - start == 0) { + return ""; + } else { + return new String(data, offset + start, end - start, false); + } + } else { + throw new IndexOutOfBoundsException(); + } + } + + public boolean startsWith(String s) { + if (length >= s.length) { + return substring(0, s.length).compareTo(s) != 0; + } else { + return false; + } + } + + public boolean endsWith(String s) { + if (length >= s.length) { + return substring(length - s.length).compareTo(s) != 0; + } else { + return false; + } + } + + public String concat(String s) { + if (s.length() == 0) { + return this; + } else { + return this + s; + } + } + public void getChars(int srcOffset, int srcLength, char[] dst, int dstOffset) { if (srcOffset + srcLength > length) { - throw new ArrayIndexOutOfBoundsException(); + throw new IndexOutOfBoundsException(); } if (data instanceof char[]) { @@ -60,6 +147,18 @@ public final class String { } } + public char charAt(int index) { + if (index < 0 || index > length) { + throw new IndexOutOfBoundsException(); + } + + if (data instanceof char[]) { + return ((char[]) data)[index + offset]; + } else { + return (char) ((byte[]) data)[index + offset]; + } + } + public static String valueOf(long v) { if (v == 0) { return valueOf('0'); diff --git a/classpath/java/lang/System.java b/classpath/java/lang/System.java index 4499401131..24ea95b03e 100644 --- a/classpath/java/lang/System.java +++ b/classpath/java/lang/System.java @@ -13,6 +13,8 @@ public abstract class System { public static native String getProperty(String name); + public static native long currentTimeMillis(); + public static void loadLibrary(String name) { Runtime.getRuntime().loadLibrary(name); } diff --git a/classpath/java/util/ArrayList.java b/classpath/java/util/ArrayList.java index 60121ee9b7..d1da10da40 100644 --- a/classpath/java/util/ArrayList.java +++ b/classpath/java/util/ArrayList.java @@ -45,6 +45,15 @@ public class ArrayList implements List { return size; } + public boolean contains(T element) { + for (int i = 0; i < size; ++i) { + if (equal(element, array[i])) { + return true; + } + } + return false; + } + public boolean add(T element) { resize(); array[size++] = element; diff --git a/classpath/java/util/Arrays.java b/classpath/java/util/Arrays.java index b1ca3f103d..94efeea5d6 100644 --- a/classpath/java/util/Arrays.java +++ b/classpath/java/util/Arrays.java @@ -3,6 +3,10 @@ package java.util; public class Arrays { private Arrays() { } + private static boolean equal(Object a, Object b) { + return (a == null && b == null) || (a != null && a.equals(b)); + } + public static List asList(final T ... array) { return new List() { public int size() { @@ -13,6 +17,15 @@ public class Arrays { throw new UnsupportedOperationException(); } + public boolean contains(T element) { + for (int i = 0; i < array.length; ++i) { + if (equal(element, array[i])) { + return true; + } + } + return false; + } + public T get(int index) { return array[index]; } diff --git a/classpath/java/util/Collection.java b/classpath/java/util/Collection.java index a39e1f8344..c1ff4748f7 100644 --- a/classpath/java/util/Collection.java +++ b/classpath/java/util/Collection.java @@ -3,6 +3,8 @@ package java.util; public interface Collection extends Iterable { public int size(); + public boolean contains(T element); + public boolean add(T element); public boolean remove(T element); diff --git a/classpath/java/util/Collections.java b/classpath/java/util/Collections.java index e7f7352c1f..fb5ac3c685 100644 --- a/classpath/java/util/Collections.java +++ b/classpath/java/util/Collections.java @@ -32,6 +32,10 @@ public class Collections { synchronized (lock) { return collection.size(); } } + public synchronized boolean contains(T e) { + synchronized (lock) { return collection.contains(e); } + } + public synchronized boolean add(T e) { synchronized (lock) { return collection.add(e); } } diff --git a/classpath/java/util/HashMap.java b/classpath/java/util/HashMap.java index 77ecae8a02..c7f129d786 100644 --- a/classpath/java/util/HashMap.java +++ b/classpath/java/util/HashMap.java @@ -3,7 +3,6 @@ package java.util; public class HashMap implements Map { private int size; private Cell[] array; - private Cell nullCell; private final CellFactory factory; HashMap(int capacity, CellFactory factory) { @@ -31,6 +30,14 @@ public class HashMap implements Map { return size; } + private static int hash(Object a) { + return (a == null ? 0 : a.hashCode()); + } + + private static boolean equal(Object a, Object b) { + return (a == null && b == null) || (a != null && a.equals(b)); + } + private void resize() { if (array == null || size >= array.length * 2) { resize(array == null ? 16 : array.length * 2); @@ -64,58 +71,45 @@ public class HashMap implements Map { } private Cell find(K key) { - if (key == null) { - return nullCell; - } else { - if (array != null) { - int index = key.hashCode() & (array.length - 1); - for (Cell c = array[index]; c != null; c = c.next()) { - if (key.equals(c.getKey())) { - return c; - } + if (array != null) { + int index = hash(key) & (array.length - 1); + for (Cell c = array[index]; c != null; c = c.next()) { + if (equal(key, c.getKey())) { + return c; } } - - return null; } + + return null; } private void insert(Cell cell) { ++ size; - if (cell.getKey() == null) { - nullCell = cell; - } else { - resize(); + resize(); - int index = cell.hashCode() & (array.length - 1); - cell.setNext(array[index]); - array[index] = cell; - } + int index = cell.hashCode() & (array.length - 1); + cell.setNext(array[index]); + array[index] = cell; } // primarily for use by WeakHashMap: - void remove(Cell cell) { - if (cell == nullCell) { - nullCell = null; - -- size; - } else { - int index = cell.hashCode() & (array.length - 1); - Cell p = null; - for (Cell c = array[index]; c != null; c = c.next()) { - if (c == cell) { - if (p == null) { - array[index] = c.next(); - } else { - p.setNext(c.next()); - } - -- size; - break; + void remove(Cell cell) { + int index = cell.hashCode() & (array.length - 1); + Cell p = null; + for (Cell c = array[index]; c != null; c = c.next()) { + if (c == cell) { + if (p == null) { + array[index] = c.next(); + } else { + p.setNext(c.next()); } + -- size; + break; } - - resize(); } + + resize(); } private Cell putCell(K key, V value) { @@ -129,6 +123,14 @@ public class HashMap implements Map { return c; } + public boolean containsKey(K key) { + return find(key) != null; + } + + public boolean containsValue(V value) { + return values().contains(value); + } + public V get(K key) { Cell c = find(key); return (c == null ? null : c.getValue()); @@ -136,31 +138,23 @@ public class HashMap implements Map { public Cell removeCell(K key) { Cell old = null; - if (key == null) { - if (nullCell != null) { - old = nullCell; - nullCell = null; - -- size; - } - } else { - if (array != null) { - int index = key.hashCode() & (array.length - 1); - Cell p = null; - for (Cell c = array[index]; c != null; c = c.next()) { - if (key.equals(c.getKey())) { - old = c; - if (p == null) { - array[index] = c.next(); - } else { - p.setNext(c.next()); - } - -- size; - break; + if (array != null) { + int index = hash(key) & (array.length - 1); + Cell p = null; + for (Cell c = array[index]; c != null; c = c.next()) { + if (equal(key, c.getKey())) { + old = c; + if (p == null) { + array[index] = c.next(); + } else { + p.setNext(c.next()); } + -- size; + break; } - - resize(); } + + resize(); } return old; } @@ -238,7 +232,7 @@ public class HashMap implements Map { } public int hashCode() { - return key.hashCode(); + return (key == null ? 0 : key.hashCode()); } } @@ -253,6 +247,10 @@ public class HashMap implements Map { return HashMap.this.size(); } + public boolean contains(Entry e) { + return containsKey(e.getKey()); + } + public boolean add(Entry e) { return putCell(e.getKey(), e.getValue()) != null; } @@ -275,6 +273,10 @@ public class HashMap implements Map { return HashMap.this.size(); } + public boolean contains(K key) { + return containsKey(key); + } + public boolean add(K key) { return putCell(key, null) != null; } @@ -298,6 +300,10 @@ public class HashMap implements Map { return HashMap.this.size(); } + public boolean contains(V value) { + return containsValue(value); + } + public boolean add(V value) { throw new UnsupportedOperationException(); } diff --git a/classpath/java/util/HashSet.java b/classpath/java/util/HashSet.java index c685417db6..1b431c61dc 100644 --- a/classpath/java/util/HashSet.java +++ b/classpath/java/util/HashSet.java @@ -17,6 +17,10 @@ public class HashSet implements Set { return map.size(); } + public boolean contains(T element) { + return map.containsKey(element); + } + public boolean add(T element) { return map.put(element, Value) != Value; } diff --git a/classpath/java/util/Hashtable.java b/classpath/java/util/Hashtable.java index 5dd443ceaf..2043fc0633 100644 --- a/classpath/java/util/Hashtable.java +++ b/classpath/java/util/Hashtable.java @@ -15,6 +15,14 @@ public class Hashtable implements Map { return map.size(); } + public synchronized boolean containsKey(K key) { + return map.containsKey(key); + } + + public synchronized boolean containsValue(V value) { + return map.containsValue(value); + } + public synchronized V get(K key) { return map.get(key); } diff --git a/classpath/java/util/LinkedList.java b/classpath/java/util/LinkedList.java index 7fc1bd7e2c..8894453282 100644 --- a/classpath/java/util/LinkedList.java +++ b/classpath/java/util/LinkedList.java @@ -20,7 +20,7 @@ public class LinkedList implements List { return (a == null && b == null) || (a != null && a.equals(b)); } - private void add(Cell c) { + private void addFirst(Cell c) { ++ size; if (front == null) { @@ -31,6 +31,17 @@ public class LinkedList implements List { } } + private void addLast(Cell c) { + ++ size; + + if (front == null) { + front = rear = c; + } else { + c.next = front; + front = c; + } + } + private Cell find(T element) { for (Cell c = front; c != null; c = c.next) { if (equal(c.value, element)) { @@ -60,11 +71,23 @@ public class LinkedList implements List { return size; } + public boolean contains(T element) { + return find(element) != null; + } + public boolean add(T element) { - add(new Cell(element, null, null)); + addFirst(element); return true; } + public void addFirst(T element) { + addFirst(new Cell(element, null, null)); + } + + public void addLast(T element) { + addLast(new Cell(element, null, null)); + } + public T get(int index) { return find(index).value; } diff --git a/classpath/java/util/Map.java b/classpath/java/util/Map.java index b6de098b3f..f82c8386e3 100644 --- a/classpath/java/util/Map.java +++ b/classpath/java/util/Map.java @@ -3,6 +3,10 @@ package java.util; public interface Map { public int size(); + public boolean containsKey(K key); + + public boolean containsValue(V value); + public V get(K key); public V put(K key, V value); diff --git a/classpath/java/util/Vector.java b/classpath/java/util/Vector.java index 65ce7fb908..14cc5057f6 100644 --- a/classpath/java/util/Vector.java +++ b/classpath/java/util/Vector.java @@ -15,6 +15,10 @@ public class Vector implements List { return list.size(); } + public synchronized boolean contains(T element) { + return list.contains(element); + } + public synchronized boolean add(T element) { return list.add(element); } @@ -43,6 +47,12 @@ public class Vector implements List { list.clear(); } + public synchronized void copyInto(Object[] array) { + for (int i = 0; i < size(); ++i) { + array[i] = list.get(i); + } + } + public Iterator iterator() { return new Collections.ArrayListIterator(this); } diff --git a/classpath/java/util/WeakHashMap.java b/classpath/java/util/WeakHashMap.java index 08050b1aaa..340acb6d90 100644 --- a/classpath/java/util/WeakHashMap.java +++ b/classpath/java/util/WeakHashMap.java @@ -30,6 +30,16 @@ public class WeakHashMap implements Map { return map.size(); } + public boolean containsKey(K key) { + poll(); + return map.containsKey(key); + } + + public boolean containsValue(V value) { + poll(); + return map.containsValue(value); + } + public V get(K key) { poll(); return map.get(key); @@ -53,6 +63,14 @@ public class WeakHashMap implements Map { return map.entrySet(); } + public Set keySet() { + return map.keySet(); + } + + public Collection values() { + return map.values(); + } + private static class MyCell extends WeakReference implements HashMap.Cell @@ -65,7 +83,7 @@ public class WeakHashMap implements Map { super(key); this.value = value; this.next = next; - this.hashCode = key.hashCode(); + this.hashCode = (key == null ? 0 : key.hashCode()); } public K getKey() { diff --git a/src/builtin.cpp b/src/builtin.cpp index 6eabd1cb8c..5b3bed72c8 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -97,6 +97,12 @@ arraycopy(Thread* t, jobject src, jint srcOffset, jobject dst, jint dstOffset, t->exception = makeArrayStoreException(t); } +jlong +currentTimeMillis(Thread* t) +{ + return t->vm->system->now(); +} + void loadLibrary(Thread* t, jobject, jstring nameString) { diff --git a/src/system.cpp b/src/system.cpp index b98477e7e3..83ecb0fb6c 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -93,15 +93,6 @@ run(void* t) return 0; } -int64_t -now() -{ - timeval tv = { 0, 0 }; - gettimeofday(&tv, 0); - return (static_cast(tv.tv_sec) * 1000) + - (static_cast(tv.tv_usec) / 1000); -} - const bool Verbose = false; class MySystem: public System { @@ -183,7 +174,7 @@ class MySystem: public System { this->depth = 0; this->context = 0; if (time) { - int64_t then = now() + time; + int64_t then = s->now() + time; timespec ts = { then / 1000, (then % 1000) * 1000 * 1000 }; int rv = pthread_cond_timedwait(&condition, &mutex, &ts); assert(s, rv == 0); @@ -357,6 +348,13 @@ class MySystem: public System { nanosleep(&ts, 0); } + virtual int64_t now() { + timeval tv = { 0, 0 }; + gettimeofday(&tv, 0); + return (static_cast(tv.tv_sec) * 1000) + + (static_cast(tv.tv_usec) / 1000); + } + virtual uint64_t call(void* function, uintptr_t* arguments, uint8_t* types, unsigned count, unsigned size, unsigned returnType) { diff --git a/src/system.h b/src/system.h index f6db4ae5e8..5ccdb99f8e 100644 --- a/src/system.h +++ b/src/system.h @@ -61,6 +61,7 @@ class System: public Allocator { virtual Status start(Runnable*) = 0; virtual Status make(Monitor**) = 0; virtual void sleep(int64_t milliseconds) = 0; + virtual int64_t now() = 0; virtual uint64_t call(void* function, uintptr_t* arguments, uint8_t* types, unsigned count, unsigned size, unsigned returnType) = 0;