1.1 --- a/emul/src/main/java/java/lang/String.java Sun Nov 18 08:51:58 2012 +0100
1.2 +++ b/emul/src/main/java/java/lang/String.java Sun Dec 02 23:10:51 2012 +0100
1.3 @@ -25,8 +25,11 @@
1.4
1.5 package java.lang;
1.6
1.7 +import java.util.Comparator;
1.8 import org.apidesign.bck2brwsr.core.ExtraJavaScript;
1.9 -import java.util.Comparator;
1.10 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
1.11 +import org.apidesign.bck2brwsr.core.JavaScriptOnly;
1.12 +import org.apidesign.bck2brwsr.core.JavaScriptPrototype;
1.13
1.14 /**
1.15 * The <code>String</code> class represents character strings. All
1.16 @@ -99,25 +102,41 @@
1.17
1.18 @ExtraJavaScript(
1.19 resource="/org/apidesign/vm4brwsr/emul/java_lang_String.js",
1.20 - processByteCode=false
1.21 + processByteCode=true
1.22 )
1.23 +@JavaScriptPrototype(container = "String.prototype", prototype = "new String")
1.24 public final class String
1.25 implements java.io.Serializable, Comparable<String>, CharSequence
1.26 {
1.27 + @JavaScriptOnly
1.28 /** The value is used for character storage. */
1.29 private final char value[];
1.30
1.31 + @JavaScriptOnly
1.32 /** The offset is the first index of the storage that is used. */
1.33 private final int offset;
1.34
1.35 + @JavaScriptOnly
1.36 /** The count is the number of characters in the String. */
1.37 private final int count;
1.38
1.39 + @JavaScriptOnly
1.40 /** Cache the hash code for the string */
1.41 private int hash; // Default to 0
1.42 +
1.43 + /** real string to delegate to */
1.44 + private Object r;
1.45
1.46 /** use serialVersionUID from JDK 1.0.2 for interoperability */
1.47 private static final long serialVersionUID = -6849794470754667710L;
1.48 +
1.49 + @JavaScriptOnly(name="toString", value="function() { return this.fld_r; }")
1.50 + private static void jsToString() {
1.51 + }
1.52 +
1.53 + @JavaScriptOnly(name="valueOf", value="function() { return this.toString().valueOf(); }")
1.54 + private static void jsValudOf() {
1.55 + }
1.56
1.57 /**
1.58 * Class String is special cased within the Serialization Stream Protocol.
1.59 @@ -139,6 +158,7 @@
1.60 * an empty character sequence. Note that use of this constructor is
1.61 * unnecessary since Strings are immutable.
1.62 */
1.63 + @JavaScriptBody(args = "self", body = "self.fld_r = '';")
1.64 public String() {
1.65 this.offset = 0;
1.66 this.count = 0;
1.67 @@ -155,6 +175,7 @@
1.68 * @param original
1.69 * A {@code String}
1.70 */
1.71 + @JavaScriptBody(args = {"self", "original"}, body = "self.fld_r = original.toString();")
1.72 public String(String original) {
1.73 int size = original.count;
1.74 char[] originalValue = original.value;
1.75 @@ -184,6 +205,12 @@
1.76 * @param value
1.77 * The initial value of the string
1.78 */
1.79 + @JavaScriptBody(args = { "self", "charArr" }, body=
1.80 + "for (var i = 0; i < charArr.length; i++) {\n"
1.81 + + " if (typeof charArr[i] === 'number') charArr[i] = String.fromCharCode(charArr[i]);\n"
1.82 + + "}\n"
1.83 + + "self.fld_r = charArr.join('');\n"
1.84 + )
1.85 public String(char value[]) {
1.86 int size = value.length;
1.87 this.offset = 0;
1.88 @@ -212,6 +239,13 @@
1.89 * If the {@code offset} and {@code count} arguments index
1.90 * characters outside the bounds of the {@code value} array
1.91 */
1.92 + @JavaScriptBody(args = { "self", "charArr", "off", "cnt" }, body =
1.93 + "var up = off + cnt;\n" +
1.94 + "for (var i = off; i < up; i++) {\n" +
1.95 + " if (typeof charArr[i] === 'number') charArr[i] = String.fromCharCode(charArr[i]);\n" +
1.96 + "}\n" +
1.97 + "self.fld_r = charArr.slice(off, up).join(\"\");\n"
1.98 + )
1.99 public String(char value[], int offset, int count) {
1.100 if (offset < 0) {
1.101 throw new StringIndexOutOfBoundsException(offset);
1.102 @@ -613,10 +647,10 @@
1.103 * A {@code StringBuffer}
1.104 */
1.105 public String(StringBuffer buffer) {
1.106 - String result = buffer.toString();
1.107 - this.value = result.value;
1.108 - this.count = result.count;
1.109 - this.offset = result.offset;
1.110 + r = buffer.toString();
1.111 + this.value = null;
1.112 + this.count = 0;
1.113 + this.offset = -1;
1.114 }
1.115
1.116 /**
1.117 @@ -635,10 +669,10 @@
1.118 * @since 1.5
1.119 */
1.120 public String(StringBuilder builder) {
1.121 - String result = builder.toString();
1.122 - this.value = result.value;
1.123 - this.count = result.count;
1.124 - this.offset = result.offset;
1.125 + r = builder.toString();
1.126 + this.value = null;
1.127 + this.count = 0;
1.128 + this.offset = -1;
1.129 }
1.130
1.131 /**
1.132 @@ -649,6 +683,7 @@
1.133 * @return the length of the sequence of characters represented by this
1.134 * object.
1.135 */
1.136 + @JavaScriptBody(args = "self", body = "return self.toString().length;")
1.137 public int length() {
1.138 return count;
1.139 }
1.140 @@ -661,6 +696,7 @@
1.141 *
1.142 * @since 1.6
1.143 */
1.144 + @JavaScriptBody(args = "self", body="return self.toString().length === 0;")
1.145 public boolean isEmpty() {
1.146 return count == 0;
1.147 }
1.148 @@ -683,6 +719,9 @@
1.149 * argument is negative or not less than the length of this
1.150 * string.
1.151 */
1.152 + @JavaScriptBody(args = { "self", "index" },
1.153 + body = "return self.toString().charCodeAt(index);"
1.154 + )
1.155 public char charAt(int index) {
1.156 if ((index < 0) || (index >= count)) {
1.157 throw new StringIndexOutOfBoundsException(index);
1.158 @@ -809,6 +848,12 @@
1.159 * Copy characters from this string into dst starting at dstBegin.
1.160 * This method doesn't perform any range checking.
1.161 */
1.162 + @JavaScriptBody(args = { "self", "arr", "to" }, body =
1.163 + "var s = self.toString();\n" +
1.164 + "for (var i = 0; i < s.length; i++) {\n" +
1.165 + " arr[to++] = s[i];\n" +
1.166 + "}"
1.167 + )
1.168 void getChars(char dst[], int dstBegin) {
1.169 AbstractStringBuilder.arraycopy(value, offset, dst, dstBegin, count);
1.170 }
1.171 @@ -843,6 +888,12 @@
1.172 * <li><code>dstBegin+(srcEnd-srcBegin)</code> is larger than
1.173 * <code>dst.length</code></ul>
1.174 */
1.175 + @JavaScriptBody(args = { "self", "beg", "end", "arr", "dst" }, body=
1.176 + "var s = self.toString();\n" +
1.177 + "while (beg < end) {\n" +
1.178 + " arr[dst++] = s[beg++];\n" +
1.179 + "}\n"
1.180 + )
1.181 public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
1.182 if (srcBegin < 0) {
1.183 throw new StringIndexOutOfBoundsException(srcBegin);
1.184 @@ -1010,6 +1061,10 @@
1.185 * @see #compareTo(String)
1.186 * @see #equalsIgnoreCase(String)
1.187 */
1.188 + @JavaScriptBody(args = { "self", "obj" }, body =
1.189 + "return obj.$instOf_java_lang_String && "
1.190 + + "self.toString() === obj.toString();"
1.191 + )
1.192 public boolean equals(Object anObject) {
1.193 if (this == anObject) {
1.194 return true;
1.195 @@ -1428,6 +1483,10 @@
1.196 * this.substring(toffset).startsWith(prefix)
1.197 * </pre>
1.198 */
1.199 + @JavaScriptBody(args = { "self", "find", "from" }, body=
1.200 + "find = find.toString();\n" +
1.201 + "return self.toString().substring(from, find.length) === find;\n"
1.202 + )
1.203 public boolean startsWith(String prefix, int toffset) {
1.204 char ta[] = value;
1.205 int to = offset + toffset;
1.206 @@ -1491,6 +1550,15 @@
1.207 *
1.208 * @return a hash code value for this object.
1.209 */
1.210 + @JavaScriptBody(args = "self", body =
1.211 + "var h = 0;\n" +
1.212 + "var s = self.toString();\n" +
1.213 + "for (var i = 0; i < s.length; i++) {\n" +
1.214 + " var high = (h >> 16) & 0xffff, low = h & 0xffff;\n" +
1.215 + " h = (((((31 * high) & 0xffff) << 16) >>> 0) + (31 * low) + s.charCodeAt(i)) & 0xffffffff;\n" +
1.216 + "}\n" +
1.217 + "return h;\n"
1.218 + )
1.219 public int hashCode() {
1.220 int h = hash;
1.221 if (h == 0 && count > 0) {
1.222 @@ -1573,6 +1641,10 @@
1.223 * than or equal to <code>fromIndex</code>, or <code>-1</code>
1.224 * if the character does not occur.
1.225 */
1.226 + @JavaScriptBody(args = { "self", "ch", "from" }, body =
1.227 + "if (typeof ch === 'number') ch = String.fromCharCode(ch);\n" +
1.228 + "return self.toString().indexOf(ch, from);\n"
1.229 + )
1.230 public int indexOf(int ch, int fromIndex) {
1.231 if (fromIndex < 0) {
1.232 fromIndex = 0;
1.233 @@ -1749,6 +1821,9 @@
1.234 * starting at the specified index,
1.235 * or {@code -1} if there is no such occurrence.
1.236 */
1.237 + @JavaScriptBody(args = { "self", "str", "fromIndex" }, body =
1.238 + "return self.toString().indexOf(str.toString(), fromIndex) >= 0;"
1.239 + )
1.240 public int indexOf(String str, int fromIndex) {
1.241 return indexOf(value, offset, count,
1.242 str.value, str.offset, str.count, fromIndex);
1.243 @@ -1947,6 +2022,9 @@
1.244 * <code>beginIndex</code> is larger than
1.245 * <code>endIndex</code>.
1.246 */
1.247 + @JavaScriptBody(args = { "self", "beginIndex", "endIndex" }, body =
1.248 + "return self.toString().substring(beginIndex, endIndex);"
1.249 + )
1.250 public String substring(int beginIndex, int endIndex) {
1.251 if (beginIndex < 0) {
1.252 throw new StringIndexOutOfBoundsException(beginIndex);
1.253 @@ -2053,6 +2131,18 @@
1.254 * @return a string derived from this string by replacing every
1.255 * occurrence of <code>oldChar</code> with <code>newChar</code>.
1.256 */
1.257 + @JavaScriptBody(args = { "self", "arg1", "arg2" }, body =
1.258 + "if (typeof arg1 === 'number') arg1 = String.fromCharCode(arg1);\n" +
1.259 + "if (typeof arg2 === 'number') arg2 = String.fromCharCode(arg2);\n" +
1.260 + "var s = self.toString();\n" +
1.261 + "for (;;) {\n" +
1.262 + " var ret = s.replace(arg1, arg2);\n" +
1.263 + " if (ret === s) {\n" +
1.264 + " return ret;\n" +
1.265 + " }\n" +
1.266 + " s = ret;\n" +
1.267 + "}"
1.268 + )
1.269 public String replace(char oldChar, char newChar) {
1.270 if (oldChar != newChar) {
1.271 int len = count;
1.272 @@ -2739,6 +2829,7 @@
1.273 *
1.274 * @return the string itself.
1.275 */
1.276 + @JavaScriptBody(args = "self", body = "return self.toString();")
1.277 public String toString() {
1.278 return this;
1.279 }
1.280 @@ -2750,6 +2841,7 @@
1.281 * of this string and whose contents are initialized to contain
1.282 * the character sequence represented by this string.
1.283 */
1.284 + @JavaScriptBody(args = "self", body = "return self.toString().split('');")
1.285 public char[] toCharArray() {
1.286 char result[] = new char[count];
1.287 getChars(0, count, result, 0);