diff --git a/c/vm_instance.c b/c/vm_instance.c index 5ecbdc6..91a2c91 100644 --- a/c/vm_instance.c +++ b/c/vm_instance.c @@ -25,12 +25,12 @@ struct objectref * vm_instance_create(struct vm * vm, const char * class_name) struct objectref * vm_instance_string_from_constant(struct vm * vm, struct constant * constant) { int32_t count = constant->utf8.length; - struct arrayref * arrayref = prim_array_allocate(vm, 1, count); + struct arrayref * arrayref = prim_array_allocate(vm, 2, count); assert(arrayref != nullptr); arrayref->class_entry = nullptr; // byte[] arrayref->length = constant->utf8.length; for (int i = 0; i < constant->utf8.length; i++) { - arrayref->u8[i] = constant->utf8.bytes[i]; + arrayref->u16[i] = constant->utf8.bytes[i]; } struct objectref * objectref = vm_instance_create(vm, "java/lang/String"); diff --git a/classes/java/io/IOException.java b/classes/java/io/IOException.java new file mode 100644 index 0000000..2b5d6cb --- /dev/null +++ b/classes/java/io/IOException.java @@ -0,0 +1,4 @@ +package java.io; + +public class IOException extends Exception { +} diff --git a/classes/java/lang/Appendable.java b/classes/java/lang/Appendable.java new file mode 100644 index 0000000..5f70e5b --- /dev/null +++ b/classes/java/lang/Appendable.java @@ -0,0 +1,11 @@ +package java.lang; + +import java.io.IOException; + +public interface Appendable { + Appendable append(char c) throws IOException; + + Appendable append(CharSequence csq) throws IOException; + + Appendable append(CharSequence csq, int start, int end) throws IOException; +} diff --git a/classes/java/lang/AutoCloseable.java b/classes/java/lang/AutoCloseable.java new file mode 100644 index 0000000..b6fbe46 --- /dev/null +++ b/classes/java/lang/AutoCloseable.java @@ -0,0 +1,5 @@ +package java.lang; + +public interface AutoCloseable { + void close() throws Exception; +} diff --git a/classes/java/lang/Boolean.java b/classes/java/lang/Boolean.java index 6985d20..eb954d6 100644 --- a/classes/java/lang/Boolean.java +++ b/classes/java/lang/Boolean.java @@ -1,4 +1,55 @@ package java.lang; class Boolean { + public static final Boolean FALSE = new Boolean(false); + + public static final Boolean TRUE = new Boolean(true); + + public static final Class TYPE = (Class)Class.getPrimitiveClass("boolean"); + + private final boolean value; + + public Boolean(boolean value) { + this.value = value; + } + + public Boolean(String s) { + this(parseBoolean(s)); + } + + public boolean booleanValue() { + return value; + } + + public int compareTo(Boolean b) { + return value == b.value ? 0 : (value ? 1 : -1); + } + + public boolean equals(Object obj) { + return (obj instanceof Boolean) && (value == ((Boolean)obj).booleanValue()); + } + + public int hashCode() { + return value ? 1231 : 1237; + } + + public static boolean parseBoolean(String s) { + return "true".equalsIgnoreCase(b) ? true : false; + } + + public String toString() { + return String.valueOf(value); + } + + public static String toString(boolean b) { + return String.valueOf(b); + } + + public static Boolean valueOf(boolean b) { + return (b ? TRUE : FALSE); + } + + public static Boolean valueOf(String s) { + return parseBoolean(s) ? TRUE : FALSE; + } } diff --git a/classes/java/lang/CharSequence.java b/classes/java/lang/CharSequence.java new file mode 100644 index 0000000..d6d1ceb --- /dev/null +++ b/classes/java/lang/CharSequence.java @@ -0,0 +1,11 @@ +package java.lang; + +public interface CharSequence { + char charAt(int index); + + int length(); + + CharSequence subSequence(int start, int end); + + public String toString(); +} diff --git a/classes/java/lang/Character.java b/classes/java/lang/Character.java index 2892c5a..faafb40 100644 --- a/classes/java/lang/Character.java +++ b/classes/java/lang/Character.java @@ -1,4 +1,143 @@ package java.lang; class Character { + public static final int MAX_RADIX = 36; + + public static final int MAX_VALUE = '\uFFFF'; + + public static final int MIN_RADIX = 2; + + public static final char MIN_VALUE = '\u0000'; + + public static final int SIZE = 16; + + private final char value; + + public Character(char value) { + this.value = value; + } + + public char charValue() { + return value; + } + + public int compareTo(Character anotherCharacter) { + return this.charValue() - anotherCharacter.charValue(); + } + + private static int _digit(char ch) { + if (Character.isDigit(ch)) + return ch - '0'; + if (ch >= 'A' && ch <= 'Z') + return ch - 'A' + 10; + if (ch >= 'a' && ch <= 'z') + return ch - 'a' + 10; + return -1; + } + + public static int digit(char ch, int radix) { + if (radix < MIN_RADIX || radix > MAX_RADIX) + return -1; + int value = _digit(ch); + return (value < radix) ? digit : -1; + } + + public boolean equals(Object obj) { + return obj instanceof Character && value == ((Character)obj).value; + } + + public static char forDigit(int digit, int radix) { + if (digit < 0 || digit > MAX_RADIX) + return '\u0000'; + if (digit < 10) { + return '0' + digit; + } else { + return 'a' + digit - 10; + } + } + + public int hashCode() { + return value; + } + + public static boolean isDigit(char ch) { + return ch >= '0' && ch <= '9'; + } + + public static boolean isISOControl(char ch) { + return (ch >= '\u0000' && ch <= '\u001F') || (ch >= '\u007F' && ch <= '\u009F'); + } + + public static boolean isLowerCase(char ch) { + return + (ch >= 'a' && ch <= 'z') || + (ch >= '\u00DF' && ch <= '\u00F6') || + (ch >= '\u00F8' && ch <= '\u00FF'); + } + + public static boolean isSpaceChar(char ch) { + switch (ch) { + case ' ': return true; + case '\t': return true; + case '\n': return true; + case '\r': return true; + case '\f': return true; + default: return false; + } + } + + public static boolean isUpperCase(char ch) { + return + (ch >= 'A' && ch <= 'Z') || + (ch >= '\u00C0' && ch <= '\u00D6') || + (ch >= '\u00D8' && ch <= '\u00DE'); + } + + public static boolean isWhitespace(char ch) { + switch (ch) { + case ' ': return true; + case '\t': return true; + case '\n': return true; + case '\u000B': return true; + case '\u000C': return true; + case '\r': return true; + case '\u001C': return true; + case '\u001D': return true; + case '\u001E': return true; + case '\u001F': return true; + default: return false; + } + } + + public static char toLowerCase(char ch) { + if (ch >= 'A' && ch <= 'Z') + return ch - 'A' + 'a'; + if (ch >= '\u00C0' && ch <= '\u00D6') + return ch - '\u00C0' + '\u00E0'; + if (ch >= '\u00D8' && ch <= '\u00DE') + return ch - '\u00D8' + '\u00F8'; + return ch; + } + + public String toString() { + return Character.toString(value); + } + + public static String toString(char c) { + return new String(new char[] { c }); + } + + public static char toUpperCase(char ch) { + if (ch >= 'a' && ch <= 'z') + return ch - 'a' + 'A'; + if (ch >= '\u00E0' && ch <= '\u00F6') + return ch - '\u00E0' + '\u00C0'; + if (ch >= '\u00F8' && ch <= '\u00FE') + return ch - '\u00F8' + '\u00D8'; + return ch; + } + + public static Character valueOf(char c) { + return new Character(c); + } } diff --git a/classes/java/lang/Cloneable.java b/classes/java/lang/Cloneable.java new file mode 100644 index 0000000..d14aed4 --- /dev/null +++ b/classes/java/lang/Cloneable.java @@ -0,0 +1,4 @@ +package java.lang; + +public interface Cloneable { +} diff --git a/classes/java/lang/Comparable.java b/classes/java/lang/Comparable.java new file mode 100644 index 0000000..650d5d1 --- /dev/null +++ b/classes/java/lang/Comparable.java @@ -0,0 +1,5 @@ +package java.lang; + +public interface Comparable { + public int compareTo(T o); +} diff --git a/classes/java/lang/Iterable.java b/classes/java/lang/Iterable.java new file mode 100644 index 0000000..e6b3b4e --- /dev/null +++ b/classes/java/lang/Iterable.java @@ -0,0 +1,5 @@ +package java.lang; + +public interface Iterable { + Iterator iterator(); +} diff --git a/classes/java/lang/Runnable.java b/classes/java/lang/Runnable.java new file mode 100644 index 0000000..765ec99 --- /dev/null +++ b/classes/java/lang/Runnable.java @@ -0,0 +1,5 @@ +package java.lang; + +public interface Runnable { + void run(); +} diff --git a/classes/java/lang/String.java b/classes/java/lang/String.java index 78f77f0..3943a5e 100644 --- a/classes/java/lang/String.java +++ b/classes/java/lang/String.java @@ -1,22 +1,63 @@ package java.lang; public class String { - private final byte[] value; + private final char[] value; public String() { - this.value = new byte[0]; + this.value = new char[0]; + } + + public String(byte[] bytes) { + this(bytes, 0, bytes.length); + } + + public String(byte[] bytes, int offset, int length) { + this.value = new char[length]; + int i = 0; + while (length > 0) { + this.value[i] = (char)bytes[offset]; + i += 1; + offset += 1; + length -= 1; + } + } + + public String(char[] value) { + this(value, 0, value.length); + } + + public String(char[] value, int offset, int length) { + this.value = new char[length]; + int i = 0; + while (length > 0) { + this.value[i] = value[offset]; + i += 1; + offset += 1; + length -= 1; + } } public String(String original) { + // shallow copy this.value = original.value; } - public String(byte[] value) { - this.value = value; + public char charAt(int index) { + return this.value[index]; } - public byte[] getBytes() { - return this.value; + public int compareTo(String anotherString) { + int length = this.length() < anotherString.length() + ? this.length() + : anotherString.length(); + + for (knt k = 0; k < length; k++) { + int difference = this.charAt(k) - anotherString.charAt(k); + if (difference != 0) + return difference; + } + + return this.length() - anotherString.length(); } public String toString() { @@ -32,7 +73,7 @@ public class String { } public static String valueOf(char c) { - return new String(new byte[] { (byte)c }); + return new String(new char[] { c }); } public static String valueOf(int i) {