rt/emul/mini/src/main/java/java/lang/String.java
changeset 772 d382dacfd73f
parent 670 3026d9c844f0
child 787 86fa8cc5a44e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/rt/emul/mini/src/main/java/java/lang/String.java	Tue Feb 26 16:54:16 2013 +0100
     1.3 @@ -0,0 +1,3079 @@
     1.4 +/*
     1.5 + * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
     1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 + *
     1.8 + * This code is free software; you can redistribute it and/or modify it
     1.9 + * under the terms of the GNU General Public License version 2 only, as
    1.10 + * published by the Free Software Foundation.  Oracle designates this
    1.11 + * particular file as subject to the "Classpath" exception as provided
    1.12 + * by Oracle in the LICENSE file that accompanied this code.
    1.13 + *
    1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.17 + * version 2 for more details (a copy is included in the LICENSE file that
    1.18 + * accompanied this code).
    1.19 + *
    1.20 + * You should have received a copy of the GNU General Public License version
    1.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.23 + *
    1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    1.25 + * or visit www.oracle.com if you need additional information or have any
    1.26 + * questions.
    1.27 + */
    1.28 +
    1.29 +package java.lang;
    1.30 +
    1.31 +import java.io.UnsupportedEncodingException;
    1.32 +import java.util.Comparator;
    1.33 +import org.apidesign.bck2brwsr.core.ExtraJavaScript;
    1.34 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
    1.35 +import org.apidesign.bck2brwsr.core.JavaScriptOnly;
    1.36 +import org.apidesign.bck2brwsr.core.JavaScriptPrototype;
    1.37 +import org.apidesign.bck2brwsr.emul.lang.System;
    1.38 +
    1.39 +/**
    1.40 + * The <code>String</code> class represents character strings. All
    1.41 + * string literals in Java programs, such as <code>"abc"</code>, are
    1.42 + * implemented as instances of this class.
    1.43 + * <p>
    1.44 + * Strings are constant; their values cannot be changed after they
    1.45 + * are created. String buffers support mutable strings.
    1.46 + * Because String objects are immutable they can be shared. For example:
    1.47 + * <p><blockquote><pre>
    1.48 + *     String str = "abc";
    1.49 + * </pre></blockquote><p>
    1.50 + * is equivalent to:
    1.51 + * <p><blockquote><pre>
    1.52 + *     char data[] = {'a', 'b', 'c'};
    1.53 + *     String str = new String(data);
    1.54 + * </pre></blockquote><p>
    1.55 + * Here are some more examples of how strings can be used:
    1.56 + * <p><blockquote><pre>
    1.57 + *     System.out.println("abc");
    1.58 + *     String cde = "cde";
    1.59 + *     System.out.println("abc" + cde);
    1.60 + *     String c = "abc".substring(2,3);
    1.61 + *     String d = cde.substring(1, 2);
    1.62 + * </pre></blockquote>
    1.63 + * <p>
    1.64 + * The class <code>String</code> includes methods for examining
    1.65 + * individual characters of the sequence, for comparing strings, for
    1.66 + * searching strings, for extracting substrings, and for creating a
    1.67 + * copy of a string with all characters translated to uppercase or to
    1.68 + * lowercase. Case mapping is based on the Unicode Standard version
    1.69 + * specified by the {@link java.lang.Character Character} class.
    1.70 + * <p>
    1.71 + * The Java language provides special support for the string
    1.72 + * concatenation operator (&nbsp;+&nbsp;), and for conversion of
    1.73 + * other objects to strings. String concatenation is implemented
    1.74 + * through the <code>StringBuilder</code>(or <code>StringBuffer</code>)
    1.75 + * class and its <code>append</code> method.
    1.76 + * String conversions are implemented through the method
    1.77 + * <code>toString</code>, defined by <code>Object</code> and
    1.78 + * inherited by all classes in Java. For additional information on
    1.79 + * string concatenation and conversion, see Gosling, Joy, and Steele,
    1.80 + * <i>The Java Language Specification</i>.
    1.81 + *
    1.82 + * <p> Unless otherwise noted, passing a <tt>null</tt> argument to a constructor
    1.83 + * or method in this class will cause a {@link NullPointerException} to be
    1.84 + * thrown.
    1.85 + *
    1.86 + * <p>A <code>String</code> represents a string in the UTF-16 format
    1.87 + * in which <em>supplementary characters</em> are represented by <em>surrogate
    1.88 + * pairs</em> (see the section <a href="Character.html#unicode">Unicode
    1.89 + * Character Representations</a> in the <code>Character</code> class for
    1.90 + * more information).
    1.91 + * Index values refer to <code>char</code> code units, so a supplementary
    1.92 + * character uses two positions in a <code>String</code>.
    1.93 + * <p>The <code>String</code> class provides methods for dealing with
    1.94 + * Unicode code points (i.e., characters), in addition to those for
    1.95 + * dealing with Unicode code units (i.e., <code>char</code> values).
    1.96 + *
    1.97 + * @author  Lee Boynton
    1.98 + * @author  Arthur van Hoff
    1.99 + * @author  Martin Buchholz
   1.100 + * @author  Ulf Zibis
   1.101 + * @see     java.lang.Object#toString()
   1.102 + * @see     java.lang.StringBuffer
   1.103 + * @see     java.lang.StringBuilder
   1.104 + * @see     java.nio.charset.Charset
   1.105 + * @since   JDK1.0
   1.106 + */
   1.107 +
   1.108 +@ExtraJavaScript(
   1.109 +    resource="/org/apidesign/vm4brwsr/emul/lang/java_lang_String.js",
   1.110 +    processByteCode=true
   1.111 +)
   1.112 +@JavaScriptPrototype(container = "String.prototype", prototype = "new String")
   1.113 +public final class String
   1.114 +    implements java.io.Serializable, Comparable<String>, CharSequence
   1.115 +{
   1.116 +    /** real string to delegate to */
   1.117 +    private Object r;
   1.118 +
   1.119 +    /** use serialVersionUID from JDK 1.0.2 for interoperability */
   1.120 +    private static final long serialVersionUID = -6849794470754667710L;
   1.121 +    
   1.122 +    @JavaScriptOnly(name="toString", value="String.prototype._r")
   1.123 +    private static void jsToString() {
   1.124 +    }
   1.125 +    
   1.126 +    @JavaScriptOnly(name="valueOf", value="function() { return this.toString().valueOf(); }")
   1.127 +    private static void jsValudOf() {
   1.128 +    }
   1.129 +
   1.130 +    /**
   1.131 +     * Class String is special cased within the Serialization Stream Protocol.
   1.132 +     *
   1.133 +     * A String instance is written initially into an ObjectOutputStream in the
   1.134 +     * following format:
   1.135 +     * <pre>
   1.136 +     *      <code>TC_STRING</code> (utf String)
   1.137 +     * </pre>
   1.138 +     * The String is written by method <code>DataOutput.writeUTF</code>.
   1.139 +     * A new handle is generated to  refer to all future references to the
   1.140 +     * string instance within the stream.
   1.141 +     */
   1.142 +//    private static final ObjectStreamField[] serialPersistentFields =
   1.143 +//        new ObjectStreamField[0];
   1.144 +
   1.145 +    /**
   1.146 +     * Initializes a newly created {@code String} object so that it represents
   1.147 +     * an empty character sequence.  Note that use of this constructor is
   1.148 +     * unnecessary since Strings are immutable.
   1.149 +     */
   1.150 +    public String() {
   1.151 +        this.r = "";
   1.152 +    }
   1.153 +
   1.154 +    /**
   1.155 +     * Initializes a newly created {@code String} object so that it represents
   1.156 +     * the same sequence of characters as the argument; in other words, the
   1.157 +     * newly created string is a copy of the argument string. Unless an
   1.158 +     * explicit copy of {@code original} is needed, use of this constructor is
   1.159 +     * unnecessary since Strings are immutable.
   1.160 +     *
   1.161 +     * @param  original
   1.162 +     *         A {@code String}
   1.163 +     */
   1.164 +    public String(String original) {
   1.165 +        this.r = original.toString();
   1.166 +    }
   1.167 +
   1.168 +    /**
   1.169 +     * Allocates a new {@code String} so that it represents the sequence of
   1.170 +     * characters currently contained in the character array argument. The
   1.171 +     * contents of the character array are copied; subsequent modification of
   1.172 +     * the character array does not affect the newly created string.
   1.173 +     *
   1.174 +     * @param  value
   1.175 +     *         The initial value of the string
   1.176 +     */
   1.177 +    @JavaScriptBody(args = { "charArr" }, body=
   1.178 +        "for (var i = 0; i < charArr.length; i++) {\n"
   1.179 +      + "  if (typeof charArr[i] === 'number') charArr[i] = String.fromCharCode(charArr[i]);\n"
   1.180 +      + "}\n"
   1.181 +      + "this._r(charArr.join(''));\n"
   1.182 +    )
   1.183 +    public String(char value[]) {
   1.184 +    }
   1.185 +
   1.186 +    /**
   1.187 +     * Allocates a new {@code String} that contains characters from a subarray
   1.188 +     * of the character array argument. The {@code offset} argument is the
   1.189 +     * index of the first character of the subarray and the {@code count}
   1.190 +     * argument specifies the length of the subarray. The contents of the
   1.191 +     * subarray are copied; subsequent modification of the character array does
   1.192 +     * not affect the newly created string.
   1.193 +     *
   1.194 +     * @param  value
   1.195 +     *         Array that is the source of characters
   1.196 +     *
   1.197 +     * @param  offset
   1.198 +     *         The initial offset
   1.199 +     *
   1.200 +     * @param  count
   1.201 +     *         The length
   1.202 +     *
   1.203 +     * @throws  IndexOutOfBoundsException
   1.204 +     *          If the {@code offset} and {@code count} arguments index
   1.205 +     *          characters outside the bounds of the {@code value} array
   1.206 +     */
   1.207 +    public String(char value[], int offset, int count) {
   1.208 +        initFromCharArray(value, offset, count);
   1.209 +    }
   1.210 +    
   1.211 +    @JavaScriptBody(args = { "charArr", "off", "cnt" }, body =
   1.212 +        "var up = off + cnt;\n" +
   1.213 +        "for (var i = off; i < up; i++) {\n" +
   1.214 +        "  if (typeof charArr[i] === 'number') charArr[i] = String.fromCharCode(charArr[i]);\n" +
   1.215 +        "}\n" +
   1.216 +        "this._r(charArr.slice(off, up).join(\"\"));\n"
   1.217 +    )
   1.218 +    private native void initFromCharArray(char value[], int offset, int count);
   1.219 +
   1.220 +    /**
   1.221 +     * Allocates a new {@code String} that contains characters from a subarray
   1.222 +     * of the <a href="Character.html#unicode">Unicode code point</a> array
   1.223 +     * argument.  The {@code offset} argument is the index of the first code
   1.224 +     * point of the subarray and the {@code count} argument specifies the
   1.225 +     * length of the subarray.  The contents of the subarray are converted to
   1.226 +     * {@code char}s; subsequent modification of the {@code int} array does not
   1.227 +     * affect the newly created string.
   1.228 +     *
   1.229 +     * @param  codePoints
   1.230 +     *         Array that is the source of Unicode code points
   1.231 +     *
   1.232 +     * @param  offset
   1.233 +     *         The initial offset
   1.234 +     *
   1.235 +     * @param  count
   1.236 +     *         The length
   1.237 +     *
   1.238 +     * @throws  IllegalArgumentException
   1.239 +     *          If any invalid Unicode code point is found in {@code
   1.240 +     *          codePoints}
   1.241 +     *
   1.242 +     * @throws  IndexOutOfBoundsException
   1.243 +     *          If the {@code offset} and {@code count} arguments index
   1.244 +     *          characters outside the bounds of the {@code codePoints} array
   1.245 +     *
   1.246 +     * @since  1.5
   1.247 +     */
   1.248 +    public String(int[] codePoints, int offset, int count) {
   1.249 +        if (offset < 0) {
   1.250 +            throw new StringIndexOutOfBoundsException(offset);
   1.251 +        }
   1.252 +        if (count < 0) {
   1.253 +            throw new StringIndexOutOfBoundsException(count);
   1.254 +        }
   1.255 +        // Note: offset or count might be near -1>>>1.
   1.256 +        if (offset > codePoints.length - count) {
   1.257 +            throw new StringIndexOutOfBoundsException(offset + count);
   1.258 +        }
   1.259 +
   1.260 +        final int end = offset + count;
   1.261 +
   1.262 +        // Pass 1: Compute precise size of char[]
   1.263 +        int n = count;
   1.264 +        for (int i = offset; i < end; i++) {
   1.265 +            int c = codePoints[i];
   1.266 +            if (Character.isBmpCodePoint(c))
   1.267 +                continue;
   1.268 +            else if (Character.isValidCodePoint(c))
   1.269 +                n++;
   1.270 +            else throw new IllegalArgumentException(Integer.toString(c));
   1.271 +        }
   1.272 +
   1.273 +        // Pass 2: Allocate and fill in char[]
   1.274 +        final char[] v = new char[n];
   1.275 +
   1.276 +        for (int i = offset, j = 0; i < end; i++, j++) {
   1.277 +            int c = codePoints[i];
   1.278 +            if (Character.isBmpCodePoint(c))
   1.279 +                v[j] = (char) c;
   1.280 +            else
   1.281 +                Character.toSurrogates(c, v, j++);
   1.282 +        }
   1.283 +
   1.284 +        this.r = new String(v, 0, n);
   1.285 +    }
   1.286 +
   1.287 +    /**
   1.288 +     * Allocates a new {@code String} constructed from a subarray of an array
   1.289 +     * of 8-bit integer values.
   1.290 +     *
   1.291 +     * <p> The {@code offset} argument is the index of the first byte of the
   1.292 +     * subarray, and the {@code count} argument specifies the length of the
   1.293 +     * subarray.
   1.294 +     *
   1.295 +     * <p> Each {@code byte} in the subarray is converted to a {@code char} as
   1.296 +     * specified in the method above.
   1.297 +     *
   1.298 +     * @deprecated This method does not properly convert bytes into characters.
   1.299 +     * As of JDK&nbsp;1.1, the preferred way to do this is via the
   1.300 +     * {@code String} constructors that take a {@link
   1.301 +     * java.nio.charset.Charset}, charset name, or that use the platform's
   1.302 +     * default charset.
   1.303 +     *
   1.304 +     * @param  ascii
   1.305 +     *         The bytes to be converted to characters
   1.306 +     *
   1.307 +     * @param  hibyte
   1.308 +     *         The top 8 bits of each 16-bit Unicode code unit
   1.309 +     *
   1.310 +     * @param  offset
   1.311 +     *         The initial offset
   1.312 +     * @param  count
   1.313 +     *         The length
   1.314 +     *
   1.315 +     * @throws  IndexOutOfBoundsException
   1.316 +     *          If the {@code offset} or {@code count} argument is invalid
   1.317 +     *
   1.318 +     * @see  #String(byte[], int)
   1.319 +     * @see  #String(byte[], int, int, java.lang.String)
   1.320 +     * @see  #String(byte[], int, int, java.nio.charset.Charset)
   1.321 +     * @see  #String(byte[], int, int)
   1.322 +     * @see  #String(byte[], java.lang.String)
   1.323 +     * @see  #String(byte[], java.nio.charset.Charset)
   1.324 +     * @see  #String(byte[])
   1.325 +     */
   1.326 +    @Deprecated
   1.327 +    public String(byte ascii[], int hibyte, int offset, int count) {
   1.328 +        checkBounds(ascii, offset, count);
   1.329 +        char value[] = new char[count];
   1.330 +
   1.331 +        if (hibyte == 0) {
   1.332 +            for (int i = count ; i-- > 0 ;) {
   1.333 +                value[i] = (char) (ascii[i + offset] & 0xff);
   1.334 +            }
   1.335 +        } else {
   1.336 +            hibyte <<= 8;
   1.337 +            for (int i = count ; i-- > 0 ;) {
   1.338 +                value[i] = (char) (hibyte | (ascii[i + offset] & 0xff));
   1.339 +            }
   1.340 +        }
   1.341 +        initFromCharArray(value, offset, count);
   1.342 +    }
   1.343 +
   1.344 +    /**
   1.345 +     * Allocates a new {@code String} containing characters constructed from
   1.346 +     * an array of 8-bit integer values. Each character <i>c</i>in the
   1.347 +     * resulting string is constructed from the corresponding component
   1.348 +     * <i>b</i> in the byte array such that:
   1.349 +     *
   1.350 +     * <blockquote><pre>
   1.351 +     *     <b><i>c</i></b> == (char)(((hibyte &amp; 0xff) &lt;&lt; 8)
   1.352 +     *                         | (<b><i>b</i></b> &amp; 0xff))
   1.353 +     * </pre></blockquote>
   1.354 +     *
   1.355 +     * @deprecated  This method does not properly convert bytes into
   1.356 +     * characters.  As of JDK&nbsp;1.1, the preferred way to do this is via the
   1.357 +     * {@code String} constructors that take a {@link
   1.358 +     * java.nio.charset.Charset}, charset name, or that use the platform's
   1.359 +     * default charset.
   1.360 +     *
   1.361 +     * @param  ascii
   1.362 +     *         The bytes to be converted to characters
   1.363 +     *
   1.364 +     * @param  hibyte
   1.365 +     *         The top 8 bits of each 16-bit Unicode code unit
   1.366 +     *
   1.367 +     * @see  #String(byte[], int, int, java.lang.String)
   1.368 +     * @see  #String(byte[], int, int, java.nio.charset.Charset)
   1.369 +     * @see  #String(byte[], int, int)
   1.370 +     * @see  #String(byte[], java.lang.String)
   1.371 +     * @see  #String(byte[], java.nio.charset.Charset)
   1.372 +     * @see  #String(byte[])
   1.373 +     */
   1.374 +    @Deprecated
   1.375 +    public String(byte ascii[], int hibyte) {
   1.376 +        this(ascii, hibyte, 0, ascii.length);
   1.377 +    }
   1.378 +
   1.379 +    /* Common private utility method used to bounds check the byte array
   1.380 +     * and requested offset & length values used by the String(byte[],..)
   1.381 +     * constructors.
   1.382 +     */
   1.383 +    private static void checkBounds(byte[] bytes, int offset, int length) {
   1.384 +        if (length < 0)
   1.385 +            throw new StringIndexOutOfBoundsException(length);
   1.386 +        if (offset < 0)
   1.387 +            throw new StringIndexOutOfBoundsException(offset);
   1.388 +        if (offset > bytes.length - length)
   1.389 +            throw new StringIndexOutOfBoundsException(offset + length);
   1.390 +    }
   1.391 +
   1.392 +    /**
   1.393 +     * Constructs a new {@code String} by decoding the specified subarray of
   1.394 +     * bytes using the specified charset.  The length of the new {@code String}
   1.395 +     * is a function of the charset, and hence may not be equal to the length
   1.396 +     * of the subarray.
   1.397 +     *
   1.398 +     * <p> The behavior of this constructor when the given bytes are not valid
   1.399 +     * in the given charset is unspecified.  The {@link
   1.400 +     * java.nio.charset.CharsetDecoder} class should be used when more control
   1.401 +     * over the decoding process is required.
   1.402 +     *
   1.403 +     * @param  bytes
   1.404 +     *         The bytes to be decoded into characters
   1.405 +     *
   1.406 +     * @param  offset
   1.407 +     *         The index of the first byte to decode
   1.408 +     *
   1.409 +     * @param  length
   1.410 +     *         The number of bytes to decode
   1.411 +
   1.412 +     * @param  charsetName
   1.413 +     *         The name of a supported {@linkplain java.nio.charset.Charset
   1.414 +     *         charset}
   1.415 +     *
   1.416 +     * @throws  UnsupportedEncodingException
   1.417 +     *          If the named charset is not supported
   1.418 +     *
   1.419 +     * @throws  IndexOutOfBoundsException
   1.420 +     *          If the {@code offset} and {@code length} arguments index
   1.421 +     *          characters outside the bounds of the {@code bytes} array
   1.422 +     *
   1.423 +     * @since  JDK1.1
   1.424 +     */
   1.425 +    public String(byte bytes[], int offset, int length, String charsetName)
   1.426 +        throws UnsupportedEncodingException
   1.427 +    {
   1.428 +        this(checkUTF8(bytes, charsetName), offset, length);
   1.429 +    }
   1.430 +
   1.431 +    /**
   1.432 +     * Constructs a new {@code String} by decoding the specified subarray of
   1.433 +     * bytes using the specified {@linkplain java.nio.charset.Charset charset}.
   1.434 +     * The length of the new {@code String} is a function of the charset, and
   1.435 +     * hence may not be equal to the length of the subarray.
   1.436 +     *
   1.437 +     * <p> This method always replaces malformed-input and unmappable-character
   1.438 +     * sequences with this charset's default replacement string.  The {@link
   1.439 +     * java.nio.charset.CharsetDecoder} class should be used when more control
   1.440 +     * over the decoding process is required.
   1.441 +     *
   1.442 +     * @param  bytes
   1.443 +     *         The bytes to be decoded into characters
   1.444 +     *
   1.445 +     * @param  offset
   1.446 +     *         The index of the first byte to decode
   1.447 +     *
   1.448 +     * @param  length
   1.449 +     *         The number of bytes to decode
   1.450 +     *
   1.451 +     * @param  charset
   1.452 +     *         The {@linkplain java.nio.charset.Charset charset} to be used to
   1.453 +     *         decode the {@code bytes}
   1.454 +     *
   1.455 +     * @throws  IndexOutOfBoundsException
   1.456 +     *          If the {@code offset} and {@code length} arguments index
   1.457 +     *          characters outside the bounds of the {@code bytes} array
   1.458 +     *
   1.459 +     * @since  1.6
   1.460 +     */
   1.461 +    /* don't want dependnecy on Charset
   1.462 +    public String(byte bytes[], int offset, int length, Charset charset) {
   1.463 +        if (charset == null)
   1.464 +            throw new NullPointerException("charset");
   1.465 +        checkBounds(bytes, offset, length);
   1.466 +        char[] v = StringCoding.decode(charset, bytes, offset, length);
   1.467 +        this.offset = 0;
   1.468 +        this.count = v.length;
   1.469 +        this.value = v;
   1.470 +    }
   1.471 +    */
   1.472 +
   1.473 +    /**
   1.474 +     * Constructs a new {@code String} by decoding the specified array of bytes
   1.475 +     * using the specified {@linkplain java.nio.charset.Charset charset}.  The
   1.476 +     * length of the new {@code String} is a function of the charset, and hence
   1.477 +     * may not be equal to the length of the byte array.
   1.478 +     *
   1.479 +     * <p> The behavior of this constructor when the given bytes are not valid
   1.480 +     * in the given charset is unspecified.  The {@link
   1.481 +     * java.nio.charset.CharsetDecoder} class should be used when more control
   1.482 +     * over the decoding process is required.
   1.483 +     *
   1.484 +     * @param  bytes
   1.485 +     *         The bytes to be decoded into characters
   1.486 +     *
   1.487 +     * @param  charsetName
   1.488 +     *         The name of a supported {@linkplain java.nio.charset.Charset
   1.489 +     *         charset}
   1.490 +     *
   1.491 +     * @throws  UnsupportedEncodingException
   1.492 +     *          If the named charset is not supported
   1.493 +     *
   1.494 +     * @since  JDK1.1
   1.495 +     */
   1.496 +    public String(byte bytes[], String charsetName)
   1.497 +        throws UnsupportedEncodingException
   1.498 +    {
   1.499 +        this(bytes, 0, bytes.length, charsetName);
   1.500 +    }
   1.501 +
   1.502 +    /**
   1.503 +     * Constructs a new {@code String} by decoding the specified array of
   1.504 +     * bytes using the specified {@linkplain java.nio.charset.Charset charset}.
   1.505 +     * The length of the new {@code String} is a function of the charset, and
   1.506 +     * hence may not be equal to the length of the byte array.
   1.507 +     *
   1.508 +     * <p> This method always replaces malformed-input and unmappable-character
   1.509 +     * sequences with this charset's default replacement string.  The {@link
   1.510 +     * java.nio.charset.CharsetDecoder} class should be used when more control
   1.511 +     * over the decoding process is required.
   1.512 +     *
   1.513 +     * @param  bytes
   1.514 +     *         The bytes to be decoded into characters
   1.515 +     *
   1.516 +     * @param  charset
   1.517 +     *         The {@linkplain java.nio.charset.Charset charset} to be used to
   1.518 +     *         decode the {@code bytes}
   1.519 +     *
   1.520 +     * @since  1.6
   1.521 +     */
   1.522 +    /* don't want dep on Charset
   1.523 +    public String(byte bytes[], Charset charset) {
   1.524 +        this(bytes, 0, bytes.length, charset);
   1.525 +    }
   1.526 +    */
   1.527 +
   1.528 +    /**
   1.529 +     * Constructs a new {@code String} by decoding the specified subarray of
   1.530 +     * bytes using the platform's default charset.  The length of the new
   1.531 +     * {@code String} is a function of the charset, and hence may not be equal
   1.532 +     * to the length of the subarray.
   1.533 +     *
   1.534 +     * <p> The behavior of this constructor when the given bytes are not valid
   1.535 +     * in the default charset is unspecified.  The {@link
   1.536 +     * java.nio.charset.CharsetDecoder} class should be used when more control
   1.537 +     * over the decoding process is required.
   1.538 +     *
   1.539 +     * @param  bytes
   1.540 +     *         The bytes to be decoded into characters
   1.541 +     *
   1.542 +     * @param  offset
   1.543 +     *         The index of the first byte to decode
   1.544 +     *
   1.545 +     * @param  length
   1.546 +     *         The number of bytes to decode
   1.547 +     *
   1.548 +     * @throws  IndexOutOfBoundsException
   1.549 +     *          If the {@code offset} and the {@code length} arguments index
   1.550 +     *          characters outside the bounds of the {@code bytes} array
   1.551 +     *
   1.552 +     * @since  JDK1.1
   1.553 +     */
   1.554 +    public String(byte bytes[], int offset, int length) {
   1.555 +        checkBounds(bytes, offset, length);
   1.556 +        char[] v  = new char[length];
   1.557 +        int[] at = { offset };
   1.558 +        int end = offset + length;
   1.559 +        int chlen = 0;
   1.560 +        while (at[0] < end) {
   1.561 +            int ch = nextChar(bytes, at);
   1.562 +            v[chlen++] = (char)ch;
   1.563 +        }
   1.564 +        initFromCharArray(v, 0, chlen);
   1.565 +    }
   1.566 +
   1.567 +    /**
   1.568 +     * Constructs a new {@code String} by decoding the specified array of bytes
   1.569 +     * using the platform's default charset.  The length of the new {@code
   1.570 +     * String} is a function of the charset, and hence may not be equal to the
   1.571 +     * length of the byte array.
   1.572 +     *
   1.573 +     * <p> The behavior of this constructor when the given bytes are not valid
   1.574 +     * in the default charset is unspecified.  The {@link
   1.575 +     * java.nio.charset.CharsetDecoder} class should be used when more control
   1.576 +     * over the decoding process is required.
   1.577 +     *
   1.578 +     * @param  bytes
   1.579 +     *         The bytes to be decoded into characters
   1.580 +     *
   1.581 +     * @since  JDK1.1
   1.582 +     */
   1.583 +    public String(byte bytes[]) {
   1.584 +        this(bytes, 0, bytes.length);
   1.585 +    }
   1.586 +
   1.587 +    /**
   1.588 +     * Allocates a new string that contains the sequence of characters
   1.589 +     * currently contained in the string buffer argument. The contents of the
   1.590 +     * string buffer are copied; subsequent modification of the string buffer
   1.591 +     * does not affect the newly created string.
   1.592 +     *
   1.593 +     * @param  buffer
   1.594 +     *         A {@code StringBuffer}
   1.595 +     */
   1.596 +    public String(StringBuffer buffer) {
   1.597 +        this.r = buffer.toString();
   1.598 +    }
   1.599 +
   1.600 +    /**
   1.601 +     * Allocates a new string that contains the sequence of characters
   1.602 +     * currently contained in the string builder argument. The contents of the
   1.603 +     * string builder are copied; subsequent modification of the string builder
   1.604 +     * does not affect the newly created string.
   1.605 +     *
   1.606 +     * <p> This constructor is provided to ease migration to {@code
   1.607 +     * StringBuilder}. Obtaining a string from a string builder via the {@code
   1.608 +     * toString} method is likely to run faster and is generally preferred.
   1.609 +     *
   1.610 +     * @param   builder
   1.611 +     *          A {@code StringBuilder}
   1.612 +     *
   1.613 +     * @since  1.5
   1.614 +     */
   1.615 +    public String(StringBuilder builder) {
   1.616 +        this.r = builder.toString();
   1.617 +    }
   1.618 +
   1.619 +    /**
   1.620 +     * Returns the length of this string.
   1.621 +     * The length is equal to the number of <a href="Character.html#unicode">Unicode
   1.622 +     * code units</a> in the string.
   1.623 +     *
   1.624 +     * @return  the length of the sequence of characters represented by this
   1.625 +     *          object.
   1.626 +     */
   1.627 +    @JavaScriptBody(args = {}, body = "return this.toString().length;")
   1.628 +    public int length() {
   1.629 +        throw new UnsupportedOperationException();
   1.630 +    }
   1.631 +
   1.632 +    /**
   1.633 +     * Returns <tt>true</tt> if, and only if, {@link #length()} is <tt>0</tt>.
   1.634 +     *
   1.635 +     * @return <tt>true</tt> if {@link #length()} is <tt>0</tt>, otherwise
   1.636 +     * <tt>false</tt>
   1.637 +     *
   1.638 +     * @since 1.6
   1.639 +     */
   1.640 +    @JavaScriptBody(args = {}, body="return this.toString().length === 0;")
   1.641 +    public boolean isEmpty() {
   1.642 +        return length() == 0;
   1.643 +    }
   1.644 +
   1.645 +    /**
   1.646 +     * Returns the <code>char</code> value at the
   1.647 +     * specified index. An index ranges from <code>0</code> to
   1.648 +     * <code>length() - 1</code>. The first <code>char</code> value of the sequence
   1.649 +     * is at index <code>0</code>, the next at index <code>1</code>,
   1.650 +     * and so on, as for array indexing.
   1.651 +     *
   1.652 +     * <p>If the <code>char</code> value specified by the index is a
   1.653 +     * <a href="Character.html#unicode">surrogate</a>, the surrogate
   1.654 +     * value is returned.
   1.655 +     *
   1.656 +     * @param      index   the index of the <code>char</code> value.
   1.657 +     * @return     the <code>char</code> value at the specified index of this string.
   1.658 +     *             The first <code>char</code> value is at index <code>0</code>.
   1.659 +     * @exception  IndexOutOfBoundsException  if the <code>index</code>
   1.660 +     *             argument is negative or not less than the length of this
   1.661 +     *             string.
   1.662 +     */
   1.663 +    @JavaScriptBody(args = { "index" }, 
   1.664 +        body = "return this.toString().charCodeAt(index);"
   1.665 +    )
   1.666 +    public char charAt(int index) {
   1.667 +        throw new UnsupportedOperationException();
   1.668 +    }
   1.669 +
   1.670 +    /**
   1.671 +     * Returns the character (Unicode code point) at the specified
   1.672 +     * index. The index refers to <code>char</code> values
   1.673 +     * (Unicode code units) and ranges from <code>0</code> to
   1.674 +     * {@link #length()}<code> - 1</code>.
   1.675 +     *
   1.676 +     * <p> If the <code>char</code> value specified at the given index
   1.677 +     * is in the high-surrogate range, the following index is less
   1.678 +     * than the length of this <code>String</code>, and the
   1.679 +     * <code>char</code> value at the following index is in the
   1.680 +     * low-surrogate range, then the supplementary code point
   1.681 +     * corresponding to this surrogate pair is returned. Otherwise,
   1.682 +     * the <code>char</code> value at the given index is returned.
   1.683 +     *
   1.684 +     * @param      index the index to the <code>char</code> values
   1.685 +     * @return     the code point value of the character at the
   1.686 +     *             <code>index</code>
   1.687 +     * @exception  IndexOutOfBoundsException  if the <code>index</code>
   1.688 +     *             argument is negative or not less than the length of this
   1.689 +     *             string.
   1.690 +     * @since      1.5
   1.691 +     */
   1.692 +    public int codePointAt(int index) {
   1.693 +        if ((index < 0) || (index >= length())) {
   1.694 +            throw new StringIndexOutOfBoundsException(index);
   1.695 +        }
   1.696 +        return Character.codePointAtImpl(toCharArray(), offset() + index, offset() + length());
   1.697 +    }
   1.698 +
   1.699 +    /**
   1.700 +     * Returns the character (Unicode code point) before the specified
   1.701 +     * index. The index refers to <code>char</code> values
   1.702 +     * (Unicode code units) and ranges from <code>1</code> to {@link
   1.703 +     * CharSequence#length() length}.
   1.704 +     *
   1.705 +     * <p> If the <code>char</code> value at <code>(index - 1)</code>
   1.706 +     * is in the low-surrogate range, <code>(index - 2)</code> is not
   1.707 +     * negative, and the <code>char</code> value at <code>(index -
   1.708 +     * 2)</code> is in the high-surrogate range, then the
   1.709 +     * supplementary code point value of the surrogate pair is
   1.710 +     * returned. If the <code>char</code> value at <code>index -
   1.711 +     * 1</code> is an unpaired low-surrogate or a high-surrogate, the
   1.712 +     * surrogate value is returned.
   1.713 +     *
   1.714 +     * @param     index the index following the code point that should be returned
   1.715 +     * @return    the Unicode code point value before the given index.
   1.716 +     * @exception IndexOutOfBoundsException if the <code>index</code>
   1.717 +     *            argument is less than 1 or greater than the length
   1.718 +     *            of this string.
   1.719 +     * @since     1.5
   1.720 +     */
   1.721 +    public int codePointBefore(int index) {
   1.722 +        int i = index - 1;
   1.723 +        if ((i < 0) || (i >= length())) {
   1.724 +            throw new StringIndexOutOfBoundsException(index);
   1.725 +        }
   1.726 +        return Character.codePointBeforeImpl(toCharArray(), offset() + index, offset());
   1.727 +    }
   1.728 +
   1.729 +    /**
   1.730 +     * Returns the number of Unicode code points in the specified text
   1.731 +     * range of this <code>String</code>. The text range begins at the
   1.732 +     * specified <code>beginIndex</code> and extends to the
   1.733 +     * <code>char</code> at index <code>endIndex - 1</code>. Thus the
   1.734 +     * length (in <code>char</code>s) of the text range is
   1.735 +     * <code>endIndex-beginIndex</code>. Unpaired surrogates within
   1.736 +     * the text range count as one code point each.
   1.737 +     *
   1.738 +     * @param beginIndex the index to the first <code>char</code> of
   1.739 +     * the text range.
   1.740 +     * @param endIndex the index after the last <code>char</code> of
   1.741 +     * the text range.
   1.742 +     * @return the number of Unicode code points in the specified text
   1.743 +     * range
   1.744 +     * @exception IndexOutOfBoundsException if the
   1.745 +     * <code>beginIndex</code> is negative, or <code>endIndex</code>
   1.746 +     * is larger than the length of this <code>String</code>, or
   1.747 +     * <code>beginIndex</code> is larger than <code>endIndex</code>.
   1.748 +     * @since  1.5
   1.749 +     */
   1.750 +    public int codePointCount(int beginIndex, int endIndex) {
   1.751 +        if (beginIndex < 0 || endIndex > length() || beginIndex > endIndex) {
   1.752 +            throw new IndexOutOfBoundsException();
   1.753 +        }
   1.754 +        return Character.codePointCountImpl(toCharArray(), offset()+beginIndex, endIndex-beginIndex);
   1.755 +    }
   1.756 +
   1.757 +    /**
   1.758 +     * Returns the index within this <code>String</code> that is
   1.759 +     * offset from the given <code>index</code> by
   1.760 +     * <code>codePointOffset</code> code points. Unpaired surrogates
   1.761 +     * within the text range given by <code>index</code> and
   1.762 +     * <code>codePointOffset</code> count as one code point each.
   1.763 +     *
   1.764 +     * @param index the index to be offset
   1.765 +     * @param codePointOffset the offset in code points
   1.766 +     * @return the index within this <code>String</code>
   1.767 +     * @exception IndexOutOfBoundsException if <code>index</code>
   1.768 +     *   is negative or larger then the length of this
   1.769 +     *   <code>String</code>, or if <code>codePointOffset</code> is positive
   1.770 +     *   and the substring starting with <code>index</code> has fewer
   1.771 +     *   than <code>codePointOffset</code> code points,
   1.772 +     *   or if <code>codePointOffset</code> is negative and the substring
   1.773 +     *   before <code>index</code> has fewer than the absolute value
   1.774 +     *   of <code>codePointOffset</code> code points.
   1.775 +     * @since 1.5
   1.776 +     */
   1.777 +    public int offsetByCodePoints(int index, int codePointOffset) {
   1.778 +        if (index < 0 || index > length()) {
   1.779 +            throw new IndexOutOfBoundsException();
   1.780 +        }
   1.781 +        return Character.offsetByCodePointsImpl(toCharArray(), offset(), length(),
   1.782 +                                                offset()+index, codePointOffset) - offset();
   1.783 +    }
   1.784 +
   1.785 +    /**
   1.786 +     * Copy characters from this string into dst starting at dstBegin.
   1.787 +     * This method doesn't perform any range checking.
   1.788 +     */
   1.789 +    @JavaScriptBody(args = { "arr", "to" }, body = 
   1.790 +        "var s = this.toString();\n" +
   1.791 +        "for (var i = 0; i < s.length; i++) {\n" +
   1.792 +        "   arr[to++] = s[i];\n" +
   1.793 +        "}"
   1.794 +    )
   1.795 +    void getChars(char dst[], int dstBegin) {
   1.796 +        System.arraycopy(toCharArray(), offset(), dst, dstBegin, length());
   1.797 +    }
   1.798 +
   1.799 +    /**
   1.800 +     * Copies characters from this string into the destination character
   1.801 +     * array.
   1.802 +     * <p>
   1.803 +     * The first character to be copied is at index <code>srcBegin</code>;
   1.804 +     * the last character to be copied is at index <code>srcEnd-1</code>
   1.805 +     * (thus the total number of characters to be copied is
   1.806 +     * <code>srcEnd-srcBegin</code>). The characters are copied into the
   1.807 +     * subarray of <code>dst</code> starting at index <code>dstBegin</code>
   1.808 +     * and ending at index:
   1.809 +     * <p><blockquote><pre>
   1.810 +     *     dstbegin + (srcEnd-srcBegin) - 1
   1.811 +     * </pre></blockquote>
   1.812 +     *
   1.813 +     * @param      srcBegin   index of the first character in the string
   1.814 +     *                        to copy.
   1.815 +     * @param      srcEnd     index after the last character in the string
   1.816 +     *                        to copy.
   1.817 +     * @param      dst        the destination array.
   1.818 +     * @param      dstBegin   the start offset in the destination array.
   1.819 +     * @exception IndexOutOfBoundsException If any of the following
   1.820 +     *            is true:
   1.821 +     *            <ul><li><code>srcBegin</code> is negative.
   1.822 +     *            <li><code>srcBegin</code> is greater than <code>srcEnd</code>
   1.823 +     *            <li><code>srcEnd</code> is greater than the length of this
   1.824 +     *                string
   1.825 +     *            <li><code>dstBegin</code> is negative
   1.826 +     *            <li><code>dstBegin+(srcEnd-srcBegin)</code> is larger than
   1.827 +     *                <code>dst.length</code></ul>
   1.828 +     */
   1.829 +    @JavaScriptBody(args = { "beg", "end", "arr", "dst" }, body=
   1.830 +        "var s = this.toString();\n" +
   1.831 +        "while (beg < end) {\n" +
   1.832 +        "  arr[dst++] = s.charCodeAt(beg++);\n" +
   1.833 +        "}\n"
   1.834 +    )
   1.835 +    public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
   1.836 +        if (srcBegin < 0) {
   1.837 +            throw new StringIndexOutOfBoundsException(srcBegin);
   1.838 +        }
   1.839 +        if (srcEnd > length()) {
   1.840 +            throw new StringIndexOutOfBoundsException(srcEnd);
   1.841 +        }
   1.842 +        if (srcBegin > srcEnd) {
   1.843 +            throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
   1.844 +        }
   1.845 +        System.arraycopy(toCharArray(), offset() + srcBegin, dst, dstBegin,
   1.846 +             srcEnd - srcBegin);
   1.847 +    }
   1.848 +
   1.849 +    /**
   1.850 +     * Copies characters from this string into the destination byte array. Each
   1.851 +     * byte receives the 8 low-order bits of the corresponding character. The
   1.852 +     * eight high-order bits of each character are not copied and do not
   1.853 +     * participate in the transfer in any way.
   1.854 +     *
   1.855 +     * <p> The first character to be copied is at index {@code srcBegin}; the
   1.856 +     * last character to be copied is at index {@code srcEnd-1}.  The total
   1.857 +     * number of characters to be copied is {@code srcEnd-srcBegin}. The
   1.858 +     * characters, converted to bytes, are copied into the subarray of {@code
   1.859 +     * dst} starting at index {@code dstBegin} and ending at index:
   1.860 +     *
   1.861 +     * <blockquote><pre>
   1.862 +     *     dstbegin + (srcEnd-srcBegin) - 1
   1.863 +     * </pre></blockquote>
   1.864 +     *
   1.865 +     * @deprecated  This method does not properly convert characters into
   1.866 +     * bytes.  As of JDK&nbsp;1.1, the preferred way to do this is via the
   1.867 +     * {@link #getBytes()} method, which uses the platform's default charset.
   1.868 +     *
   1.869 +     * @param  srcBegin
   1.870 +     *         Index of the first character in the string to copy
   1.871 +     *
   1.872 +     * @param  srcEnd
   1.873 +     *         Index after the last character in the string to copy
   1.874 +     *
   1.875 +     * @param  dst
   1.876 +     *         The destination array
   1.877 +     *
   1.878 +     * @param  dstBegin
   1.879 +     *         The start offset in the destination array
   1.880 +     *
   1.881 +     * @throws  IndexOutOfBoundsException
   1.882 +     *          If any of the following is true:
   1.883 +     *          <ul>
   1.884 +     *            <li> {@code srcBegin} is negative
   1.885 +     *            <li> {@code srcBegin} is greater than {@code srcEnd}
   1.886 +     *            <li> {@code srcEnd} is greater than the length of this String
   1.887 +     *            <li> {@code dstBegin} is negative
   1.888 +     *            <li> {@code dstBegin+(srcEnd-srcBegin)} is larger than {@code
   1.889 +     *                 dst.length}
   1.890 +     *          </ul>
   1.891 +     */
   1.892 +    @Deprecated
   1.893 +    public void getBytes(int srcBegin, int srcEnd, byte dst[], int dstBegin) {
   1.894 +        if (srcBegin < 0) {
   1.895 +            throw new StringIndexOutOfBoundsException(srcBegin);
   1.896 +        }
   1.897 +        if (srcEnd > length()) {
   1.898 +            throw new StringIndexOutOfBoundsException(srcEnd);
   1.899 +        }
   1.900 +        if (srcBegin > srcEnd) {
   1.901 +            throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
   1.902 +        }
   1.903 +        int j = dstBegin;
   1.904 +        int n = offset() + srcEnd;
   1.905 +        int i = offset() + srcBegin;
   1.906 +        char[] val = toCharArray();   /* avoid getfield opcode */
   1.907 +
   1.908 +        while (i < n) {
   1.909 +            dst[j++] = (byte)val[i++];
   1.910 +        }
   1.911 +    }
   1.912 +
   1.913 +    /**
   1.914 +     * Encodes this {@code String} into a sequence of bytes using the named
   1.915 +     * charset, storing the result into a new byte array.
   1.916 +     *
   1.917 +     * <p> The behavior of this method when this string cannot be encoded in
   1.918 +     * the given charset is unspecified.  The {@link
   1.919 +     * java.nio.charset.CharsetEncoder} class should be used when more control
   1.920 +     * over the encoding process is required.
   1.921 +     *
   1.922 +     * @param  charsetName
   1.923 +     *         The name of a supported {@linkplain java.nio.charset.Charset
   1.924 +     *         charset}
   1.925 +     *
   1.926 +     * @return  The resultant byte array
   1.927 +     *
   1.928 +     * @throws  UnsupportedEncodingException
   1.929 +     *          If the named charset is not supported
   1.930 +     *
   1.931 +     * @since  JDK1.1
   1.932 +     */
   1.933 +    public byte[] getBytes(String charsetName)
   1.934 +        throws UnsupportedEncodingException
   1.935 +    {
   1.936 +        checkUTF8(null, charsetName);
   1.937 +        return getBytes();
   1.938 +    }
   1.939 +
   1.940 +    /**
   1.941 +     * Encodes this {@code String} into a sequence of bytes using the given
   1.942 +     * {@linkplain java.nio.charset.Charset charset}, storing the result into a
   1.943 +     * new byte array.
   1.944 +     *
   1.945 +     * <p> This method always replaces malformed-input and unmappable-character
   1.946 +     * sequences with this charset's default replacement byte array.  The
   1.947 +     * {@link java.nio.charset.CharsetEncoder} class should be used when more
   1.948 +     * control over the encoding process is required.
   1.949 +     *
   1.950 +     * @param  charset
   1.951 +     *         The {@linkplain java.nio.charset.Charset} to be used to encode
   1.952 +     *         the {@code String}
   1.953 +     *
   1.954 +     * @return  The resultant byte array
   1.955 +     *
   1.956 +     * @since  1.6
   1.957 +     */
   1.958 +    /* don't want dep on Charset
   1.959 +    public byte[] getBytes(Charset charset) {
   1.960 +        if (charset == null) throw new NullPointerException();
   1.961 +        return StringCoding.encode(charset, value, offset, count);
   1.962 +    }
   1.963 +    */
   1.964 +
   1.965 +    /**
   1.966 +     * Encodes this {@code String} into a sequence of bytes using the
   1.967 +     * platform's default charset, storing the result into a new byte array.
   1.968 +     *
   1.969 +     * <p> The behavior of this method when this string cannot be encoded in
   1.970 +     * the default charset is unspecified.  The {@link
   1.971 +     * java.nio.charset.CharsetEncoder} class should be used when more control
   1.972 +     * over the encoding process is required.
   1.973 +     *
   1.974 +     * @return  The resultant byte array
   1.975 +     *
   1.976 +     * @since      JDK1.1
   1.977 +     */
   1.978 +    public byte[] getBytes() {
   1.979 +        int len = length();
   1.980 +        byte[] arr = new byte[len];
   1.981 +        for (int i = 0, j = 0; j < len; j++) {
   1.982 +            final int v = charAt(j);
   1.983 +            if (v < 128) {
   1.984 +                arr[i++] = (byte) v;
   1.985 +                continue;
   1.986 +            }
   1.987 +            if (v < 0x0800) {
   1.988 +                arr = System.expandArray(arr, i + 1);
   1.989 +                arr[i++] = (byte) (0xC0 | (v >> 6));
   1.990 +                arr[i++] = (byte) (0x80 | (0x3F & v));
   1.991 +                continue;
   1.992 +            }
   1.993 +            arr = System.expandArray(arr, i + 2);
   1.994 +            arr[i++] = (byte) (0xE0 | (v >> 12));
   1.995 +            arr[i++] = (byte) (0x80 | ((v >> 6) & 0x7F));
   1.996 +            arr[i++] = (byte) (0x80 | (0x3F & v));
   1.997 +        }
   1.998 +        return arr;
   1.999 +    }
  1.1000 +
  1.1001 +    /**
  1.1002 +     * Compares this string to the specified object.  The result is {@code
  1.1003 +     * true} if and only if the argument is not {@code null} and is a {@code
  1.1004 +     * String} object that represents the same sequence of characters as this
  1.1005 +     * object.
  1.1006 +     *
  1.1007 +     * @param  anObject
  1.1008 +     *         The object to compare this {@code String} against
  1.1009 +     *
  1.1010 +     * @return  {@code true} if the given object represents a {@code String}
  1.1011 +     *          equivalent to this string, {@code false} otherwise
  1.1012 +     *
  1.1013 +     * @see  #compareTo(String)
  1.1014 +     * @see  #equalsIgnoreCase(String)
  1.1015 +     */
  1.1016 +    @JavaScriptBody(args = { "obj" }, body = 
  1.1017 +        "return obj != null && obj.$instOf_java_lang_String && "
  1.1018 +        + "this.toString() === obj.toString();"
  1.1019 +    )
  1.1020 +    public boolean equals(Object anObject) {
  1.1021 +        if (this == anObject) {
  1.1022 +            return true;
  1.1023 +        }
  1.1024 +        if (anObject instanceof String) {
  1.1025 +            String anotherString = (String)anObject;
  1.1026 +            int n = length();
  1.1027 +            if (n == anotherString.length()) {
  1.1028 +                char v1[] = toCharArray();
  1.1029 +                char v2[] = anotherString.toCharArray();
  1.1030 +                int i = offset();
  1.1031 +                int j = anotherString.offset();
  1.1032 +                while (n-- != 0) {
  1.1033 +                    if (v1[i++] != v2[j++])
  1.1034 +                        return false;
  1.1035 +                }
  1.1036 +                return true;
  1.1037 +            }
  1.1038 +        }
  1.1039 +        return false;
  1.1040 +    }
  1.1041 +
  1.1042 +    /**
  1.1043 +     * Compares this string to the specified {@code StringBuffer}.  The result
  1.1044 +     * is {@code true} if and only if this {@code String} represents the same
  1.1045 +     * sequence of characters as the specified {@code StringBuffer}.
  1.1046 +     *
  1.1047 +     * @param  sb
  1.1048 +     *         The {@code StringBuffer} to compare this {@code String} against
  1.1049 +     *
  1.1050 +     * @return  {@code true} if this {@code String} represents the same
  1.1051 +     *          sequence of characters as the specified {@code StringBuffer},
  1.1052 +     *          {@code false} otherwise
  1.1053 +     *
  1.1054 +     * @since  1.4
  1.1055 +     */
  1.1056 +    public boolean contentEquals(StringBuffer sb) {
  1.1057 +        synchronized(sb) {
  1.1058 +            return contentEquals((CharSequence)sb);
  1.1059 +        }
  1.1060 +    }
  1.1061 +
  1.1062 +    /**
  1.1063 +     * Compares this string to the specified {@code CharSequence}.  The result
  1.1064 +     * is {@code true} if and only if this {@code String} represents the same
  1.1065 +     * sequence of char values as the specified sequence.
  1.1066 +     *
  1.1067 +     * @param  cs
  1.1068 +     *         The sequence to compare this {@code String} against
  1.1069 +     *
  1.1070 +     * @return  {@code true} if this {@code String} represents the same
  1.1071 +     *          sequence of char values as the specified sequence, {@code
  1.1072 +     *          false} otherwise
  1.1073 +     *
  1.1074 +     * @since  1.5
  1.1075 +     */
  1.1076 +    public boolean contentEquals(CharSequence cs) {
  1.1077 +        if (length() != cs.length())
  1.1078 +            return false;
  1.1079 +        // Argument is a StringBuffer, StringBuilder
  1.1080 +        if (cs instanceof AbstractStringBuilder) {
  1.1081 +            char v1[] = toCharArray();
  1.1082 +            char v2[] = ((AbstractStringBuilder)cs).getValue();
  1.1083 +            int i = offset();
  1.1084 +            int j = 0;
  1.1085 +            int n = length();
  1.1086 +            while (n-- != 0) {
  1.1087 +                if (v1[i++] != v2[j++])
  1.1088 +                    return false;
  1.1089 +            }
  1.1090 +            return true;
  1.1091 +        }
  1.1092 +        // Argument is a String
  1.1093 +        if (cs.equals(this))
  1.1094 +            return true;
  1.1095 +        // Argument is a generic CharSequence
  1.1096 +        char v1[] = toCharArray();
  1.1097 +        int i = offset();
  1.1098 +        int j = 0;
  1.1099 +        int n = length();
  1.1100 +        while (n-- != 0) {
  1.1101 +            if (v1[i++] != cs.charAt(j++))
  1.1102 +                return false;
  1.1103 +        }
  1.1104 +        return true;
  1.1105 +    }
  1.1106 +
  1.1107 +    /**
  1.1108 +     * Compares this {@code String} to another {@code String}, ignoring case
  1.1109 +     * considerations.  Two strings are considered equal ignoring case if they
  1.1110 +     * are of the same length and corresponding characters in the two strings
  1.1111 +     * are equal ignoring case.
  1.1112 +     *
  1.1113 +     * <p> Two characters {@code c1} and {@code c2} are considered the same
  1.1114 +     * ignoring case if at least one of the following is true:
  1.1115 +     * <ul>
  1.1116 +     *   <li> The two characters are the same (as compared by the
  1.1117 +     *        {@code ==} operator)
  1.1118 +     *   <li> Applying the method {@link
  1.1119 +     *        java.lang.Character#toUpperCase(char)} to each character
  1.1120 +     *        produces the same result
  1.1121 +     *   <li> Applying the method {@link
  1.1122 +     *        java.lang.Character#toLowerCase(char)} to each character
  1.1123 +     *        produces the same result
  1.1124 +     * </ul>
  1.1125 +     *
  1.1126 +     * @param  anotherString
  1.1127 +     *         The {@code String} to compare this {@code String} against
  1.1128 +     *
  1.1129 +     * @return  {@code true} if the argument is not {@code null} and it
  1.1130 +     *          represents an equivalent {@code String} ignoring case; {@code
  1.1131 +     *          false} otherwise
  1.1132 +     *
  1.1133 +     * @see  #equals(Object)
  1.1134 +     */
  1.1135 +    public boolean equalsIgnoreCase(String anotherString) {
  1.1136 +        return (this == anotherString) ? true :
  1.1137 +               (anotherString != null) && (anotherString.length() == length()) &&
  1.1138 +               regionMatches(true, 0, anotherString, 0, length());
  1.1139 +    }
  1.1140 +
  1.1141 +    /**
  1.1142 +     * Compares two strings lexicographically.
  1.1143 +     * The comparison is based on the Unicode value of each character in
  1.1144 +     * the strings. The character sequence represented by this
  1.1145 +     * <code>String</code> object is compared lexicographically to the
  1.1146 +     * character sequence represented by the argument string. The result is
  1.1147 +     * a negative integer if this <code>String</code> object
  1.1148 +     * lexicographically precedes the argument string. The result is a
  1.1149 +     * positive integer if this <code>String</code> object lexicographically
  1.1150 +     * follows the argument string. The result is zero if the strings
  1.1151 +     * are equal; <code>compareTo</code> returns <code>0</code> exactly when
  1.1152 +     * the {@link #equals(Object)} method would return <code>true</code>.
  1.1153 +     * <p>
  1.1154 +     * This is the definition of lexicographic ordering. If two strings are
  1.1155 +     * different, then either they have different characters at some index
  1.1156 +     * that is a valid index for both strings, or their lengths are different,
  1.1157 +     * or both. If they have different characters at one or more index
  1.1158 +     * positions, let <i>k</i> be the smallest such index; then the string
  1.1159 +     * whose character at position <i>k</i> has the smaller value, as
  1.1160 +     * determined by using the &lt; operator, lexicographically precedes the
  1.1161 +     * other string. In this case, <code>compareTo</code> returns the
  1.1162 +     * difference of the two character values at position <code>k</code> in
  1.1163 +     * the two string -- that is, the value:
  1.1164 +     * <blockquote><pre>
  1.1165 +     * this.charAt(k)-anotherString.charAt(k)
  1.1166 +     * </pre></blockquote>
  1.1167 +     * If there is no index position at which they differ, then the shorter
  1.1168 +     * string lexicographically precedes the longer string. In this case,
  1.1169 +     * <code>compareTo</code> returns the difference of the lengths of the
  1.1170 +     * strings -- that is, the value:
  1.1171 +     * <blockquote><pre>
  1.1172 +     * this.length()-anotherString.length()
  1.1173 +     * </pre></blockquote>
  1.1174 +     *
  1.1175 +     * @param   anotherString   the <code>String</code> to be compared.
  1.1176 +     * @return  the value <code>0</code> if the argument string is equal to
  1.1177 +     *          this string; a value less than <code>0</code> if this string
  1.1178 +     *          is lexicographically less than the string argument; and a
  1.1179 +     *          value greater than <code>0</code> if this string is
  1.1180 +     *          lexicographically greater than the string argument.
  1.1181 +     */
  1.1182 +    public int compareTo(String anotherString) {
  1.1183 +        int len1 = length();
  1.1184 +        int len2 = anotherString.length();
  1.1185 +        int n = Math.min(len1, len2);
  1.1186 +        char v1[] = toCharArray();
  1.1187 +        char v2[] = anotherString.toCharArray();
  1.1188 +        int i = offset();
  1.1189 +        int j = anotherString.offset();
  1.1190 +
  1.1191 +        if (i == j) {
  1.1192 +            int k = i;
  1.1193 +            int lim = n + i;
  1.1194 +            while (k < lim) {
  1.1195 +                char c1 = v1[k];
  1.1196 +                char c2 = v2[k];
  1.1197 +                if (c1 != c2) {
  1.1198 +                    return c1 - c2;
  1.1199 +                }
  1.1200 +                k++;
  1.1201 +            }
  1.1202 +        } else {
  1.1203 +            while (n-- != 0) {
  1.1204 +                char c1 = v1[i++];
  1.1205 +                char c2 = v2[j++];
  1.1206 +                if (c1 != c2) {
  1.1207 +                    return c1 - c2;
  1.1208 +                }
  1.1209 +            }
  1.1210 +        }
  1.1211 +        return len1 - len2;
  1.1212 +    }
  1.1213 +
  1.1214 +    /**
  1.1215 +     * A Comparator that orders <code>String</code> objects as by
  1.1216 +     * <code>compareToIgnoreCase</code>. This comparator is serializable.
  1.1217 +     * <p>
  1.1218 +     * Note that this Comparator does <em>not</em> take locale into account,
  1.1219 +     * and will result in an unsatisfactory ordering for certain locales.
  1.1220 +     * The java.text package provides <em>Collators</em> to allow
  1.1221 +     * locale-sensitive ordering.
  1.1222 +     *
  1.1223 +     * @see     java.text.Collator#compare(String, String)
  1.1224 +     * @since   1.2
  1.1225 +     */
  1.1226 +    public static final Comparator<String> CASE_INSENSITIVE_ORDER
  1.1227 +                                         = new CaseInsensitiveComparator();
  1.1228 +
  1.1229 +    private static int offset() {
  1.1230 +        return 0;
  1.1231 +    }
  1.1232 +
  1.1233 +    private static class CaseInsensitiveComparator
  1.1234 +                         implements Comparator<String>, java.io.Serializable {
  1.1235 +        // use serialVersionUID from JDK 1.2.2 for interoperability
  1.1236 +        private static final long serialVersionUID = 8575799808933029326L;
  1.1237 +
  1.1238 +        public int compare(String s1, String s2) {
  1.1239 +            int n1 = s1.length();
  1.1240 +            int n2 = s2.length();
  1.1241 +            int min = Math.min(n1, n2);
  1.1242 +            for (int i = 0; i < min; i++) {
  1.1243 +                char c1 = s1.charAt(i);
  1.1244 +                char c2 = s2.charAt(i);
  1.1245 +                if (c1 != c2) {
  1.1246 +                    c1 = Character.toUpperCase(c1);
  1.1247 +                    c2 = Character.toUpperCase(c2);
  1.1248 +                    if (c1 != c2) {
  1.1249 +                        c1 = Character.toLowerCase(c1);
  1.1250 +                        c2 = Character.toLowerCase(c2);
  1.1251 +                        if (c1 != c2) {
  1.1252 +                            // No overflow because of numeric promotion
  1.1253 +                            return c1 - c2;
  1.1254 +                        }
  1.1255 +                    }
  1.1256 +                }
  1.1257 +            }
  1.1258 +            return n1 - n2;
  1.1259 +        }
  1.1260 +    }
  1.1261 +
  1.1262 +    /**
  1.1263 +     * Compares two strings lexicographically, ignoring case
  1.1264 +     * differences. This method returns an integer whose sign is that of
  1.1265 +     * calling <code>compareTo</code> with normalized versions of the strings
  1.1266 +     * where case differences have been eliminated by calling
  1.1267 +     * <code>Character.toLowerCase(Character.toUpperCase(character))</code> on
  1.1268 +     * each character.
  1.1269 +     * <p>
  1.1270 +     * Note that this method does <em>not</em> take locale into account,
  1.1271 +     * and will result in an unsatisfactory ordering for certain locales.
  1.1272 +     * The java.text package provides <em>collators</em> to allow
  1.1273 +     * locale-sensitive ordering.
  1.1274 +     *
  1.1275 +     * @param   str   the <code>String</code> to be compared.
  1.1276 +     * @return  a negative integer, zero, or a positive integer as the
  1.1277 +     *          specified String is greater than, equal to, or less
  1.1278 +     *          than this String, ignoring case considerations.
  1.1279 +     * @see     java.text.Collator#compare(String, String)
  1.1280 +     * @since   1.2
  1.1281 +     */
  1.1282 +    public int compareToIgnoreCase(String str) {
  1.1283 +        return CASE_INSENSITIVE_ORDER.compare(this, str);
  1.1284 +    }
  1.1285 +
  1.1286 +    /**
  1.1287 +     * Tests if two string regions are equal.
  1.1288 +     * <p>
  1.1289 +     * A substring of this <tt>String</tt> object is compared to a substring
  1.1290 +     * of the argument other. The result is true if these substrings
  1.1291 +     * represent identical character sequences. The substring of this
  1.1292 +     * <tt>String</tt> object to be compared begins at index <tt>toffset</tt>
  1.1293 +     * and has length <tt>len</tt>. The substring of other to be compared
  1.1294 +     * begins at index <tt>ooffset</tt> and has length <tt>len</tt>. The
  1.1295 +     * result is <tt>false</tt> if and only if at least one of the following
  1.1296 +     * is true:
  1.1297 +     * <ul><li><tt>toffset</tt> is negative.
  1.1298 +     * <li><tt>ooffset</tt> is negative.
  1.1299 +     * <li><tt>toffset+len</tt> is greater than the length of this
  1.1300 +     * <tt>String</tt> object.
  1.1301 +     * <li><tt>ooffset+len</tt> is greater than the length of the other
  1.1302 +     * argument.
  1.1303 +     * <li>There is some nonnegative integer <i>k</i> less than <tt>len</tt>
  1.1304 +     * such that:
  1.1305 +     * <tt>this.charAt(toffset+<i>k</i>)&nbsp;!=&nbsp;other.charAt(ooffset+<i>k</i>)</tt>
  1.1306 +     * </ul>
  1.1307 +     *
  1.1308 +     * @param   toffset   the starting offset of the subregion in this string.
  1.1309 +     * @param   other     the string argument.
  1.1310 +     * @param   ooffset   the starting offset of the subregion in the string
  1.1311 +     *                    argument.
  1.1312 +     * @param   len       the number of characters to compare.
  1.1313 +     * @return  <code>true</code> if the specified subregion of this string
  1.1314 +     *          exactly matches the specified subregion of the string argument;
  1.1315 +     *          <code>false</code> otherwise.
  1.1316 +     */
  1.1317 +    public boolean regionMatches(int toffset, String other, int ooffset,
  1.1318 +                                 int len) {
  1.1319 +        char ta[] = toCharArray();
  1.1320 +        int to = offset() + toffset;
  1.1321 +        char pa[] = other.toCharArray();
  1.1322 +        int po = other.offset() + ooffset;
  1.1323 +        // Note: toffset, ooffset, or len might be near -1>>>1.
  1.1324 +        if ((ooffset < 0) || (toffset < 0) || (toffset > (long)length() - len)
  1.1325 +            || (ooffset > (long)other.length() - len)) {
  1.1326 +            return false;
  1.1327 +        }
  1.1328 +        while (len-- > 0) {
  1.1329 +            if (ta[to++] != pa[po++]) {
  1.1330 +                return false;
  1.1331 +            }
  1.1332 +        }
  1.1333 +        return true;
  1.1334 +    }
  1.1335 +
  1.1336 +    /**
  1.1337 +     * Tests if two string regions are equal.
  1.1338 +     * <p>
  1.1339 +     * A substring of this <tt>String</tt> object is compared to a substring
  1.1340 +     * of the argument <tt>other</tt>. The result is <tt>true</tt> if these
  1.1341 +     * substrings represent character sequences that are the same, ignoring
  1.1342 +     * case if and only if <tt>ignoreCase</tt> is true. The substring of
  1.1343 +     * this <tt>String</tt> object to be compared begins at index
  1.1344 +     * <tt>toffset</tt> and has length <tt>len</tt>. The substring of
  1.1345 +     * <tt>other</tt> to be compared begins at index <tt>ooffset</tt> and
  1.1346 +     * has length <tt>len</tt>. The result is <tt>false</tt> if and only if
  1.1347 +     * at least one of the following is true:
  1.1348 +     * <ul><li><tt>toffset</tt> is negative.
  1.1349 +     * <li><tt>ooffset</tt> is negative.
  1.1350 +     * <li><tt>toffset+len</tt> is greater than the length of this
  1.1351 +     * <tt>String</tt> object.
  1.1352 +     * <li><tt>ooffset+len</tt> is greater than the length of the other
  1.1353 +     * argument.
  1.1354 +     * <li><tt>ignoreCase</tt> is <tt>false</tt> and there is some nonnegative
  1.1355 +     * integer <i>k</i> less than <tt>len</tt> such that:
  1.1356 +     * <blockquote><pre>
  1.1357 +     * this.charAt(toffset+k) != other.charAt(ooffset+k)
  1.1358 +     * </pre></blockquote>
  1.1359 +     * <li><tt>ignoreCase</tt> is <tt>true</tt> and there is some nonnegative
  1.1360 +     * integer <i>k</i> less than <tt>len</tt> such that:
  1.1361 +     * <blockquote><pre>
  1.1362 +     * Character.toLowerCase(this.charAt(toffset+k)) !=
  1.1363 +               Character.toLowerCase(other.charAt(ooffset+k))
  1.1364 +     * </pre></blockquote>
  1.1365 +     * and:
  1.1366 +     * <blockquote><pre>
  1.1367 +     * Character.toUpperCase(this.charAt(toffset+k)) !=
  1.1368 +     *         Character.toUpperCase(other.charAt(ooffset+k))
  1.1369 +     * </pre></blockquote>
  1.1370 +     * </ul>
  1.1371 +     *
  1.1372 +     * @param   ignoreCase   if <code>true</code>, ignore case when comparing
  1.1373 +     *                       characters.
  1.1374 +     * @param   toffset      the starting offset of the subregion in this
  1.1375 +     *                       string.
  1.1376 +     * @param   other        the string argument.
  1.1377 +     * @param   ooffset      the starting offset of the subregion in the string
  1.1378 +     *                       argument.
  1.1379 +     * @param   len          the number of characters to compare.
  1.1380 +     * @return  <code>true</code> if the specified subregion of this string
  1.1381 +     *          matches the specified subregion of the string argument;
  1.1382 +     *          <code>false</code> otherwise. Whether the matching is exact
  1.1383 +     *          or case insensitive depends on the <code>ignoreCase</code>
  1.1384 +     *          argument.
  1.1385 +     */
  1.1386 +    public boolean regionMatches(boolean ignoreCase, int toffset,
  1.1387 +                           String other, int ooffset, int len) {
  1.1388 +        char ta[] = toCharArray();
  1.1389 +        int to = offset() + toffset;
  1.1390 +        char pa[] = other.toCharArray();
  1.1391 +        int po = other.offset() + ooffset;
  1.1392 +        // Note: toffset, ooffset, or len might be near -1>>>1.
  1.1393 +        if ((ooffset < 0) || (toffset < 0) || (toffset > (long)length() - len) ||
  1.1394 +                (ooffset > (long)other.length() - len)) {
  1.1395 +            return false;
  1.1396 +        }
  1.1397 +        while (len-- > 0) {
  1.1398 +            char c1 = ta[to++];
  1.1399 +            char c2 = pa[po++];
  1.1400 +            if (c1 == c2) {
  1.1401 +                continue;
  1.1402 +            }
  1.1403 +            if (ignoreCase) {
  1.1404 +                // If characters don't match but case may be ignored,
  1.1405 +                // try converting both characters to uppercase.
  1.1406 +                // If the results match, then the comparison scan should
  1.1407 +                // continue.
  1.1408 +                char u1 = Character.toUpperCase(c1);
  1.1409 +                char u2 = Character.toUpperCase(c2);
  1.1410 +                if (u1 == u2) {
  1.1411 +                    continue;
  1.1412 +                }
  1.1413 +                // Unfortunately, conversion to uppercase does not work properly
  1.1414 +                // for the Georgian alphabet, which has strange rules about case
  1.1415 +                // conversion.  So we need to make one last check before
  1.1416 +                // exiting.
  1.1417 +                if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) {
  1.1418 +                    continue;
  1.1419 +                }
  1.1420 +            }
  1.1421 +            return false;
  1.1422 +        }
  1.1423 +        return true;
  1.1424 +    }
  1.1425 +
  1.1426 +    /**
  1.1427 +     * Tests if the substring of this string beginning at the
  1.1428 +     * specified index starts with the specified prefix.
  1.1429 +     *
  1.1430 +     * @param   prefix    the prefix.
  1.1431 +     * @param   toffset   where to begin looking in this string.
  1.1432 +     * @return  <code>true</code> if the character sequence represented by the
  1.1433 +     *          argument is a prefix of the substring of this object starting
  1.1434 +     *          at index <code>toffset</code>; <code>false</code> otherwise.
  1.1435 +     *          The result is <code>false</code> if <code>toffset</code> is
  1.1436 +     *          negative or greater than the length of this
  1.1437 +     *          <code>String</code> object; otherwise the result is the same
  1.1438 +     *          as the result of the expression
  1.1439 +     *          <pre>
  1.1440 +     *          this.substring(toffset).startsWith(prefix)
  1.1441 +     *          </pre>
  1.1442 +     */
  1.1443 +    @JavaScriptBody(args = { "find", "from" }, body=
  1.1444 +        "find = find.toString();\n" +
  1.1445 +        "return this.toString().substring(from, from + find.length) === find;\n"
  1.1446 +    )
  1.1447 +    public boolean startsWith(String prefix, int toffset) {
  1.1448 +        char ta[] = toCharArray();
  1.1449 +        int to = offset() + toffset;
  1.1450 +        char pa[] = prefix.toCharArray();
  1.1451 +        int po = prefix.offset();
  1.1452 +        int pc = prefix.length();
  1.1453 +        // Note: toffset might be near -1>>>1.
  1.1454 +        if ((toffset < 0) || (toffset > length() - pc)) {
  1.1455 +            return false;
  1.1456 +        }
  1.1457 +        while (--pc >= 0) {
  1.1458 +            if (ta[to++] != pa[po++]) {
  1.1459 +                return false;
  1.1460 +            }
  1.1461 +        }
  1.1462 +        return true;
  1.1463 +    }
  1.1464 +
  1.1465 +    /**
  1.1466 +     * Tests if this string starts with the specified prefix.
  1.1467 +     *
  1.1468 +     * @param   prefix   the prefix.
  1.1469 +     * @return  <code>true</code> if the character sequence represented by the
  1.1470 +     *          argument is a prefix of the character sequence represented by
  1.1471 +     *          this string; <code>false</code> otherwise.
  1.1472 +     *          Note also that <code>true</code> will be returned if the
  1.1473 +     *          argument is an empty string or is equal to this
  1.1474 +     *          <code>String</code> object as determined by the
  1.1475 +     *          {@link #equals(Object)} method.
  1.1476 +     * @since   1. 0
  1.1477 +     */
  1.1478 +    public boolean startsWith(String prefix) {
  1.1479 +        return startsWith(prefix, 0);
  1.1480 +    }
  1.1481 +
  1.1482 +    /**
  1.1483 +     * Tests if this string ends with the specified suffix.
  1.1484 +     *
  1.1485 +     * @param   suffix   the suffix.
  1.1486 +     * @return  <code>true</code> if the character sequence represented by the
  1.1487 +     *          argument is a suffix of the character sequence represented by
  1.1488 +     *          this object; <code>false</code> otherwise. Note that the
  1.1489 +     *          result will be <code>true</code> if the argument is the
  1.1490 +     *          empty string or is equal to this <code>String</code> object
  1.1491 +     *          as determined by the {@link #equals(Object)} method.
  1.1492 +     */
  1.1493 +    public boolean endsWith(String suffix) {
  1.1494 +        return startsWith(suffix, length() - suffix.length());
  1.1495 +    }
  1.1496 +
  1.1497 +    /**
  1.1498 +     * Returns a hash code for this string. The hash code for a
  1.1499 +     * <code>String</code> object is computed as
  1.1500 +     * <blockquote><pre>
  1.1501 +     * s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
  1.1502 +     * </pre></blockquote>
  1.1503 +     * using <code>int</code> arithmetic, where <code>s[i]</code> is the
  1.1504 +     * <i>i</i>th character of the string, <code>n</code> is the length of
  1.1505 +     * the string, and <code>^</code> indicates exponentiation.
  1.1506 +     * (The hash value of the empty string is zero.)
  1.1507 +     *
  1.1508 +     * @return  a hash code value for this object.
  1.1509 +     */
  1.1510 +    public int hashCode() {
  1.1511 +        return super.hashCode();
  1.1512 +    }
  1.1513 +    int computeHashCode() {
  1.1514 +        int h = 0;
  1.1515 +        if (h == 0 && length() > 0) {
  1.1516 +            int off = offset();
  1.1517 +            int len = length();
  1.1518 +
  1.1519 +            for (int i = 0; i < len; i++) {
  1.1520 +                h = 31*h + charAt(off++);
  1.1521 +            }
  1.1522 +        }
  1.1523 +        return h;
  1.1524 +    }
  1.1525 +
  1.1526 +    /**
  1.1527 +     * Returns the index within this string of the first occurrence of
  1.1528 +     * the specified character. If a character with value
  1.1529 +     * <code>ch</code> occurs in the character sequence represented by
  1.1530 +     * this <code>String</code> object, then the index (in Unicode
  1.1531 +     * code units) of the first such occurrence is returned. For
  1.1532 +     * values of <code>ch</code> in the range from 0 to 0xFFFF
  1.1533 +     * (inclusive), this is the smallest value <i>k</i> such that:
  1.1534 +     * <blockquote><pre>
  1.1535 +     * this.charAt(<i>k</i>) == ch
  1.1536 +     * </pre></blockquote>
  1.1537 +     * is true. For other values of <code>ch</code>, it is the
  1.1538 +     * smallest value <i>k</i> such that:
  1.1539 +     * <blockquote><pre>
  1.1540 +     * this.codePointAt(<i>k</i>) == ch
  1.1541 +     * </pre></blockquote>
  1.1542 +     * is true. In either case, if no such character occurs in this
  1.1543 +     * string, then <code>-1</code> is returned.
  1.1544 +     *
  1.1545 +     * @param   ch   a character (Unicode code point).
  1.1546 +     * @return  the index of the first occurrence of the character in the
  1.1547 +     *          character sequence represented by this object, or
  1.1548 +     *          <code>-1</code> if the character does not occur.
  1.1549 +     */
  1.1550 +    public int indexOf(int ch) {
  1.1551 +        return indexOf(ch, 0);
  1.1552 +    }
  1.1553 +
  1.1554 +    /**
  1.1555 +     * Returns the index within this string of the first occurrence of the
  1.1556 +     * specified character, starting the search at the specified index.
  1.1557 +     * <p>
  1.1558 +     * If a character with value <code>ch</code> occurs in the
  1.1559 +     * character sequence represented by this <code>String</code>
  1.1560 +     * object at an index no smaller than <code>fromIndex</code>, then
  1.1561 +     * the index of the first such occurrence is returned. For values
  1.1562 +     * of <code>ch</code> in the range from 0 to 0xFFFF (inclusive),
  1.1563 +     * this is the smallest value <i>k</i> such that:
  1.1564 +     * <blockquote><pre>
  1.1565 +     * (this.charAt(<i>k</i>) == ch) && (<i>k</i> &gt;= fromIndex)
  1.1566 +     * </pre></blockquote>
  1.1567 +     * is true. For other values of <code>ch</code>, it is the
  1.1568 +     * smallest value <i>k</i> such that:
  1.1569 +     * <blockquote><pre>
  1.1570 +     * (this.codePointAt(<i>k</i>) == ch) && (<i>k</i> &gt;= fromIndex)
  1.1571 +     * </pre></blockquote>
  1.1572 +     * is true. In either case, if no such character occurs in this
  1.1573 +     * string at or after position <code>fromIndex</code>, then
  1.1574 +     * <code>-1</code> is returned.
  1.1575 +     *
  1.1576 +     * <p>
  1.1577 +     * There is no restriction on the value of <code>fromIndex</code>. If it
  1.1578 +     * is negative, it has the same effect as if it were zero: this entire
  1.1579 +     * string may be searched. If it is greater than the length of this
  1.1580 +     * string, it has the same effect as if it were equal to the length of
  1.1581 +     * this string: <code>-1</code> is returned.
  1.1582 +     *
  1.1583 +     * <p>All indices are specified in <code>char</code> values
  1.1584 +     * (Unicode code units).
  1.1585 +     *
  1.1586 +     * @param   ch          a character (Unicode code point).
  1.1587 +     * @param   fromIndex   the index to start the search from.
  1.1588 +     * @return  the index of the first occurrence of the character in the
  1.1589 +     *          character sequence represented by this object that is greater
  1.1590 +     *          than or equal to <code>fromIndex</code>, or <code>-1</code>
  1.1591 +     *          if the character does not occur.
  1.1592 +     */
  1.1593 +    @JavaScriptBody(args = { "ch", "from" }, body = 
  1.1594 +        "if (typeof ch === 'number') ch = String.fromCharCode(ch);\n" +
  1.1595 +        "return this.toString().indexOf(ch, from);\n"
  1.1596 +    )
  1.1597 +    public int indexOf(int ch, int fromIndex) {
  1.1598 +        if (fromIndex < 0) {
  1.1599 +            fromIndex = 0;
  1.1600 +        } else if (fromIndex >= length()) {
  1.1601 +            // Note: fromIndex might be near -1>>>1.
  1.1602 +            return -1;
  1.1603 +        }
  1.1604 +
  1.1605 +        if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
  1.1606 +            // handle most cases here (ch is a BMP code point or a
  1.1607 +            // negative value (invalid code point))
  1.1608 +            final char[] value = this.toCharArray();
  1.1609 +            final int offset = this.offset();
  1.1610 +            final int max = offset + length();
  1.1611 +            for (int i = offset + fromIndex; i < max ; i++) {
  1.1612 +                if (value[i] == ch) {
  1.1613 +                    return i - offset;
  1.1614 +                }
  1.1615 +            }
  1.1616 +            return -1;
  1.1617 +        } else {
  1.1618 +            return indexOfSupplementary(ch, fromIndex);
  1.1619 +        }
  1.1620 +    }
  1.1621 +
  1.1622 +    /**
  1.1623 +     * Handles (rare) calls of indexOf with a supplementary character.
  1.1624 +     */
  1.1625 +    private int indexOfSupplementary(int ch, int fromIndex) {
  1.1626 +        if (Character.isValidCodePoint(ch)) {
  1.1627 +            final char[] value = this.toCharArray();
  1.1628 +            final int offset = this.offset();
  1.1629 +            final char hi = Character.highSurrogate(ch);
  1.1630 +            final char lo = Character.lowSurrogate(ch);
  1.1631 +            final int max = offset + length() - 1;
  1.1632 +            for (int i = offset + fromIndex; i < max; i++) {
  1.1633 +                if (value[i] == hi && value[i+1] == lo) {
  1.1634 +                    return i - offset;
  1.1635 +                }
  1.1636 +            }
  1.1637 +        }
  1.1638 +        return -1;
  1.1639 +    }
  1.1640 +
  1.1641 +    /**
  1.1642 +     * Returns the index within this string of the last occurrence of
  1.1643 +     * the specified character. For values of <code>ch</code> in the
  1.1644 +     * range from 0 to 0xFFFF (inclusive), the index (in Unicode code
  1.1645 +     * units) returned is the largest value <i>k</i> such that:
  1.1646 +     * <blockquote><pre>
  1.1647 +     * this.charAt(<i>k</i>) == ch
  1.1648 +     * </pre></blockquote>
  1.1649 +     * is true. For other values of <code>ch</code>, it is the
  1.1650 +     * largest value <i>k</i> such that:
  1.1651 +     * <blockquote><pre>
  1.1652 +     * this.codePointAt(<i>k</i>) == ch
  1.1653 +     * </pre></blockquote>
  1.1654 +     * is true.  In either case, if no such character occurs in this
  1.1655 +     * string, then <code>-1</code> is returned.  The
  1.1656 +     * <code>String</code> is searched backwards starting at the last
  1.1657 +     * character.
  1.1658 +     *
  1.1659 +     * @param   ch   a character (Unicode code point).
  1.1660 +     * @return  the index of the last occurrence of the character in the
  1.1661 +     *          character sequence represented by this object, or
  1.1662 +     *          <code>-1</code> if the character does not occur.
  1.1663 +     */
  1.1664 +    public int lastIndexOf(int ch) {
  1.1665 +        return lastIndexOf(ch, length() - 1);
  1.1666 +    }
  1.1667 +
  1.1668 +    /**
  1.1669 +     * Returns the index within this string of the last occurrence of
  1.1670 +     * the specified character, searching backward starting at the
  1.1671 +     * specified index. For values of <code>ch</code> in the range
  1.1672 +     * from 0 to 0xFFFF (inclusive), the index returned is the largest
  1.1673 +     * value <i>k</i> such that:
  1.1674 +     * <blockquote><pre>
  1.1675 +     * (this.charAt(<i>k</i>) == ch) && (<i>k</i> &lt;= fromIndex)
  1.1676 +     * </pre></blockquote>
  1.1677 +     * is true. For other values of <code>ch</code>, it is the
  1.1678 +     * largest value <i>k</i> such that:
  1.1679 +     * <blockquote><pre>
  1.1680 +     * (this.codePointAt(<i>k</i>) == ch) && (<i>k</i> &lt;= fromIndex)
  1.1681 +     * </pre></blockquote>
  1.1682 +     * is true. In either case, if no such character occurs in this
  1.1683 +     * string at or before position <code>fromIndex</code>, then
  1.1684 +     * <code>-1</code> is returned.
  1.1685 +     *
  1.1686 +     * <p>All indices are specified in <code>char</code> values
  1.1687 +     * (Unicode code units).
  1.1688 +     *
  1.1689 +     * @param   ch          a character (Unicode code point).
  1.1690 +     * @param   fromIndex   the index to start the search from. There is no
  1.1691 +     *          restriction on the value of <code>fromIndex</code>. If it is
  1.1692 +     *          greater than or equal to the length of this string, it has
  1.1693 +     *          the same effect as if it were equal to one less than the
  1.1694 +     *          length of this string: this entire string may be searched.
  1.1695 +     *          If it is negative, it has the same effect as if it were -1:
  1.1696 +     *          -1 is returned.
  1.1697 +     * @return  the index of the last occurrence of the character in the
  1.1698 +     *          character sequence represented by this object that is less
  1.1699 +     *          than or equal to <code>fromIndex</code>, or <code>-1</code>
  1.1700 +     *          if the character does not occur before that point.
  1.1701 +     */
  1.1702 +    @JavaScriptBody(args = { "ch", "from" }, body = 
  1.1703 +        "if (typeof ch === 'number') ch = String.fromCharCode(ch);\n" +
  1.1704 +        "return this.toString().lastIndexOf(ch, from);"
  1.1705 +    )
  1.1706 +    public int lastIndexOf(int ch, int fromIndex) {
  1.1707 +        if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
  1.1708 +            // handle most cases here (ch is a BMP code point or a
  1.1709 +            // negative value (invalid code point))
  1.1710 +            final char[] value = this.toCharArray();
  1.1711 +            final int offset = this.offset();
  1.1712 +            int i = offset + Math.min(fromIndex, length() - 1);
  1.1713 +            for (; i >= offset ; i--) {
  1.1714 +                if (value[i] == ch) {
  1.1715 +                    return i - offset;
  1.1716 +                }
  1.1717 +            }
  1.1718 +            return -1;
  1.1719 +        } else {
  1.1720 +            return lastIndexOfSupplementary(ch, fromIndex);
  1.1721 +        }
  1.1722 +    }
  1.1723 +
  1.1724 +    /**
  1.1725 +     * Handles (rare) calls of lastIndexOf with a supplementary character.
  1.1726 +     */
  1.1727 +    private int lastIndexOfSupplementary(int ch, int fromIndex) {
  1.1728 +        if (Character.isValidCodePoint(ch)) {
  1.1729 +            final char[] value = this.toCharArray();
  1.1730 +            final int offset = this.offset();
  1.1731 +            char hi = Character.highSurrogate(ch);
  1.1732 +            char lo = Character.lowSurrogate(ch);
  1.1733 +            int i = offset + Math.min(fromIndex, length() - 2);
  1.1734 +            for (; i >= offset; i--) {
  1.1735 +                if (value[i] == hi && value[i+1] == lo) {
  1.1736 +                    return i - offset;
  1.1737 +                }
  1.1738 +            }
  1.1739 +        }
  1.1740 +        return -1;
  1.1741 +    }
  1.1742 +
  1.1743 +    /**
  1.1744 +     * Returns the index within this string of the first occurrence of the
  1.1745 +     * specified substring.
  1.1746 +     *
  1.1747 +     * <p>The returned index is the smallest value <i>k</i> for which:
  1.1748 +     * <blockquote><pre>
  1.1749 +     * this.startsWith(str, <i>k</i>)
  1.1750 +     * </pre></blockquote>
  1.1751 +     * If no such value of <i>k</i> exists, then {@code -1} is returned.
  1.1752 +     *
  1.1753 +     * @param   str   the substring to search for.
  1.1754 +     * @return  the index of the first occurrence of the specified substring,
  1.1755 +     *          or {@code -1} if there is no such occurrence.
  1.1756 +     */
  1.1757 +    public int indexOf(String str) {
  1.1758 +        return indexOf(str, 0);
  1.1759 +    }
  1.1760 +
  1.1761 +    /**
  1.1762 +     * Returns the index within this string of the first occurrence of the
  1.1763 +     * specified substring, starting at the specified index.
  1.1764 +     *
  1.1765 +     * <p>The returned index is the smallest value <i>k</i> for which:
  1.1766 +     * <blockquote><pre>
  1.1767 +     * <i>k</i> &gt;= fromIndex && this.startsWith(str, <i>k</i>)
  1.1768 +     * </pre></blockquote>
  1.1769 +     * If no such value of <i>k</i> exists, then {@code -1} is returned.
  1.1770 +     *
  1.1771 +     * @param   str         the substring to search for.
  1.1772 +     * @param   fromIndex   the index from which to start the search.
  1.1773 +     * @return  the index of the first occurrence of the specified substring,
  1.1774 +     *          starting at the specified index,
  1.1775 +     *          or {@code -1} if there is no such occurrence.
  1.1776 +     */
  1.1777 +    @JavaScriptBody(args = { "str", "fromIndex" }, body =
  1.1778 +        "return this.toString().indexOf(str.toString(), fromIndex);"
  1.1779 +    )
  1.1780 +    public native int indexOf(String str, int fromIndex);
  1.1781 +
  1.1782 +    /**
  1.1783 +     * Returns the index within this string of the last occurrence of the
  1.1784 +     * specified substring.  The last occurrence of the empty string ""
  1.1785 +     * is considered to occur at the index value {@code this.length()}.
  1.1786 +     *
  1.1787 +     * <p>The returned index is the largest value <i>k</i> for which:
  1.1788 +     * <blockquote><pre>
  1.1789 +     * this.startsWith(str, <i>k</i>)
  1.1790 +     * </pre></blockquote>
  1.1791 +     * If no such value of <i>k</i> exists, then {@code -1} is returned.
  1.1792 +     *
  1.1793 +     * @param   str   the substring to search for.
  1.1794 +     * @return  the index of the last occurrence of the specified substring,
  1.1795 +     *          or {@code -1} if there is no such occurrence.
  1.1796 +     */
  1.1797 +    public int lastIndexOf(String str) {
  1.1798 +        return lastIndexOf(str, length());
  1.1799 +    }
  1.1800 +
  1.1801 +    /**
  1.1802 +     * Returns the index within this string of the last occurrence of the
  1.1803 +     * specified substring, searching backward starting at the specified index.
  1.1804 +     *
  1.1805 +     * <p>The returned index is the largest value <i>k</i> for which:
  1.1806 +     * <blockquote><pre>
  1.1807 +     * <i>k</i> &lt;= fromIndex && this.startsWith(str, <i>k</i>)
  1.1808 +     * </pre></blockquote>
  1.1809 +     * If no such value of <i>k</i> exists, then {@code -1} is returned.
  1.1810 +     *
  1.1811 +     * @param   str         the substring to search for.
  1.1812 +     * @param   fromIndex   the index to start the search from.
  1.1813 +     * @return  the index of the last occurrence of the specified substring,
  1.1814 +     *          searching backward from the specified index,
  1.1815 +     *          or {@code -1} if there is no such occurrence.
  1.1816 +     */
  1.1817 +    @JavaScriptBody(args = { "s", "from" }, body = 
  1.1818 +        "return this.toString().lastIndexOf(s.toString(), from);"
  1.1819 +    )
  1.1820 +    public int lastIndexOf(String str, int fromIndex) {
  1.1821 +        return lastIndexOf(toCharArray(), offset(), length(), str.toCharArray(), str.offset(), str.length(), fromIndex);
  1.1822 +    }
  1.1823 +
  1.1824 +    /**
  1.1825 +     * Code shared by String and StringBuffer to do searches. The
  1.1826 +     * source is the character array being searched, and the target
  1.1827 +     * is the string being searched for.
  1.1828 +     *
  1.1829 +     * @param   source       the characters being searched.
  1.1830 +     * @param   sourceOffset offset of the source string.
  1.1831 +     * @param   sourceCount  count of the source string.
  1.1832 +     * @param   target       the characters being searched for.
  1.1833 +     * @param   targetOffset offset of the target string.
  1.1834 +     * @param   targetCount  count of the target string.
  1.1835 +     * @param   fromIndex    the index to begin searching from.
  1.1836 +     */
  1.1837 +    static int lastIndexOf(char[] source, int sourceOffset, int sourceCount,
  1.1838 +                           char[] target, int targetOffset, int targetCount,
  1.1839 +                           int fromIndex) {
  1.1840 +        /*
  1.1841 +         * Check arguments; return immediately where possible. For
  1.1842 +         * consistency, don't check for null str.
  1.1843 +         */
  1.1844 +        int rightIndex = sourceCount - targetCount;
  1.1845 +        if (fromIndex < 0) {
  1.1846 +            return -1;
  1.1847 +        }
  1.1848 +        if (fromIndex > rightIndex) {
  1.1849 +            fromIndex = rightIndex;
  1.1850 +        }
  1.1851 +        /* Empty string always matches. */
  1.1852 +        if (targetCount == 0) {
  1.1853 +            return fromIndex;
  1.1854 +        }
  1.1855 +
  1.1856 +        int strLastIndex = targetOffset + targetCount - 1;
  1.1857 +        char strLastChar = target[strLastIndex];
  1.1858 +        int min = sourceOffset + targetCount - 1;
  1.1859 +        int i = min + fromIndex;
  1.1860 +
  1.1861 +    startSearchForLastChar:
  1.1862 +        while (true) {
  1.1863 +            while (i >= min && source[i] != strLastChar) {
  1.1864 +                i--;
  1.1865 +            }
  1.1866 +            if (i < min) {
  1.1867 +                return -1;
  1.1868 +            }
  1.1869 +            int j = i - 1;
  1.1870 +            int start = j - (targetCount - 1);
  1.1871 +            int k = strLastIndex - 1;
  1.1872 +
  1.1873 +            while (j > start) {
  1.1874 +                if (source[j--] != target[k--]) {
  1.1875 +                    i--;
  1.1876 +                    continue startSearchForLastChar;
  1.1877 +                }
  1.1878 +            }
  1.1879 +            return start - sourceOffset + 1;
  1.1880 +        }
  1.1881 +    }
  1.1882 +
  1.1883 +    /**
  1.1884 +     * Returns a new string that is a substring of this string. The
  1.1885 +     * substring begins with the character at the specified index and
  1.1886 +     * extends to the end of this string. <p>
  1.1887 +     * Examples:
  1.1888 +     * <blockquote><pre>
  1.1889 +     * "unhappy".substring(2) returns "happy"
  1.1890 +     * "Harbison".substring(3) returns "bison"
  1.1891 +     * "emptiness".substring(9) returns "" (an empty string)
  1.1892 +     * </pre></blockquote>
  1.1893 +     *
  1.1894 +     * @param      beginIndex   the beginning index, inclusive.
  1.1895 +     * @return     the specified substring.
  1.1896 +     * @exception  IndexOutOfBoundsException  if
  1.1897 +     *             <code>beginIndex</code> is negative or larger than the
  1.1898 +     *             length of this <code>String</code> object.
  1.1899 +     */
  1.1900 +    public String substring(int beginIndex) {
  1.1901 +        return substring(beginIndex, length());
  1.1902 +    }
  1.1903 +
  1.1904 +    /**
  1.1905 +     * Returns a new string that is a substring of this string. The
  1.1906 +     * substring begins at the specified <code>beginIndex</code> and
  1.1907 +     * extends to the character at index <code>endIndex - 1</code>.
  1.1908 +     * Thus the length of the substring is <code>endIndex-beginIndex</code>.
  1.1909 +     * <p>
  1.1910 +     * Examples:
  1.1911 +     * <blockquote><pre>
  1.1912 +     * "hamburger".substring(4, 8) returns "urge"
  1.1913 +     * "smiles".substring(1, 5) returns "mile"
  1.1914 +     * </pre></blockquote>
  1.1915 +     *
  1.1916 +     * @param      beginIndex   the beginning index, inclusive.
  1.1917 +     * @param      endIndex     the ending index, exclusive.
  1.1918 +     * @return     the specified substring.
  1.1919 +     * @exception  IndexOutOfBoundsException  if the
  1.1920 +     *             <code>beginIndex</code> is negative, or
  1.1921 +     *             <code>endIndex</code> is larger than the length of
  1.1922 +     *             this <code>String</code> object, or
  1.1923 +     *             <code>beginIndex</code> is larger than
  1.1924 +     *             <code>endIndex</code>.
  1.1925 +     */
  1.1926 +    @JavaScriptBody(args = { "beginIndex", "endIndex" }, body = 
  1.1927 +        "return this.toString().substring(beginIndex, endIndex);"
  1.1928 +    )
  1.1929 +    public String substring(int beginIndex, int endIndex) {
  1.1930 +        if (beginIndex < 0) {
  1.1931 +            throw new StringIndexOutOfBoundsException(beginIndex);
  1.1932 +        }
  1.1933 +        if (endIndex > length()) {
  1.1934 +            throw new StringIndexOutOfBoundsException(endIndex);
  1.1935 +        }
  1.1936 +        if (beginIndex > endIndex) {
  1.1937 +            throw new StringIndexOutOfBoundsException(endIndex - beginIndex);
  1.1938 +        }
  1.1939 +        return ((beginIndex == 0) && (endIndex == length())) ? this :
  1.1940 +            new String(toCharArray(), offset() + beginIndex, endIndex - beginIndex);
  1.1941 +    }
  1.1942 +
  1.1943 +    /**
  1.1944 +     * Returns a new character sequence that is a subsequence of this sequence.
  1.1945 +     *
  1.1946 +     * <p> An invocation of this method of the form
  1.1947 +     *
  1.1948 +     * <blockquote><pre>
  1.1949 +     * str.subSequence(begin,&nbsp;end)</pre></blockquote>
  1.1950 +     *
  1.1951 +     * behaves in exactly the same way as the invocation
  1.1952 +     *
  1.1953 +     * <blockquote><pre>
  1.1954 +     * str.substring(begin,&nbsp;end)</pre></blockquote>
  1.1955 +     *
  1.1956 +     * This method is defined so that the <tt>String</tt> class can implement
  1.1957 +     * the {@link CharSequence} interface. </p>
  1.1958 +     *
  1.1959 +     * @param      beginIndex   the begin index, inclusive.
  1.1960 +     * @param      endIndex     the end index, exclusive.
  1.1961 +     * @return     the specified subsequence.
  1.1962 +     *
  1.1963 +     * @throws  IndexOutOfBoundsException
  1.1964 +     *          if <tt>beginIndex</tt> or <tt>endIndex</tt> are negative,
  1.1965 +     *          if <tt>endIndex</tt> is greater than <tt>length()</tt>,
  1.1966 +     *          or if <tt>beginIndex</tt> is greater than <tt>startIndex</tt>
  1.1967 +     *
  1.1968 +     * @since 1.4
  1.1969 +     * @spec JSR-51
  1.1970 +     */
  1.1971 +    public CharSequence subSequence(int beginIndex, int endIndex) {
  1.1972 +        return this.substring(beginIndex, endIndex);
  1.1973 +    }
  1.1974 +
  1.1975 +    /**
  1.1976 +     * Concatenates the specified string to the end of this string.
  1.1977 +     * <p>
  1.1978 +     * If the length of the argument string is <code>0</code>, then this
  1.1979 +     * <code>String</code> object is returned. Otherwise, a new
  1.1980 +     * <code>String</code> object is created, representing a character
  1.1981 +     * sequence that is the concatenation of the character sequence
  1.1982 +     * represented by this <code>String</code> object and the character
  1.1983 +     * sequence represented by the argument string.<p>
  1.1984 +     * Examples:
  1.1985 +     * <blockquote><pre>
  1.1986 +     * "cares".concat("s") returns "caress"
  1.1987 +     * "to".concat("get").concat("her") returns "together"
  1.1988 +     * </pre></blockquote>
  1.1989 +     *
  1.1990 +     * @param   str   the <code>String</code> that is concatenated to the end
  1.1991 +     *                of this <code>String</code>.
  1.1992 +     * @return  a string that represents the concatenation of this object's
  1.1993 +     *          characters followed by the string argument's characters.
  1.1994 +     */
  1.1995 +    public String concat(String str) {
  1.1996 +        int otherLen = str.length();
  1.1997 +        if (otherLen == 0) {
  1.1998 +            return this;
  1.1999 +        }
  1.2000 +        char buf[] = new char[length() + otherLen];
  1.2001 +        getChars(0, length(), buf, 0);
  1.2002 +        str.getChars(0, otherLen, buf, length());
  1.2003 +        return new String(buf, 0, length() + otherLen);
  1.2004 +    }
  1.2005 +
  1.2006 +    /**
  1.2007 +     * Returns a new string resulting from replacing all occurrences of
  1.2008 +     * <code>oldChar</code> in this string with <code>newChar</code>.
  1.2009 +     * <p>
  1.2010 +     * If the character <code>oldChar</code> does not occur in the
  1.2011 +     * character sequence represented by this <code>String</code> object,
  1.2012 +     * then a reference to this <code>String</code> object is returned.
  1.2013 +     * Otherwise, a new <code>String</code> object is created that
  1.2014 +     * represents a character sequence identical to the character sequence
  1.2015 +     * represented by this <code>String</code> object, except that every
  1.2016 +     * occurrence of <code>oldChar</code> is replaced by an occurrence
  1.2017 +     * of <code>newChar</code>.
  1.2018 +     * <p>
  1.2019 +     * Examples:
  1.2020 +     * <blockquote><pre>
  1.2021 +     * "mesquite in your cellar".replace('e', 'o')
  1.2022 +     *         returns "mosquito in your collar"
  1.2023 +     * "the war of baronets".replace('r', 'y')
  1.2024 +     *         returns "the way of bayonets"
  1.2025 +     * "sparring with a purple porpoise".replace('p', 't')
  1.2026 +     *         returns "starring with a turtle tortoise"
  1.2027 +     * "JonL".replace('q', 'x') returns "JonL" (no change)
  1.2028 +     * </pre></blockquote>
  1.2029 +     *
  1.2030 +     * @param   oldChar   the old character.
  1.2031 +     * @param   newChar   the new character.
  1.2032 +     * @return  a string derived from this string by replacing every
  1.2033 +     *          occurrence of <code>oldChar</code> with <code>newChar</code>.
  1.2034 +     */
  1.2035 +    @JavaScriptBody(args = { "arg1", "arg2" }, body =
  1.2036 +        "if (typeof arg1 === 'number') arg1 = String.fromCharCode(arg1);\n" +
  1.2037 +        "if (typeof arg2 === 'number') arg2 = String.fromCharCode(arg2);\n" +
  1.2038 +        "var s = this.toString();\n" +
  1.2039 +        "for (;;) {\n" +
  1.2040 +        "  var ret = s.replace(arg1, arg2);\n" +
  1.2041 +        "  if (ret === s) {\n" +
  1.2042 +        "    return ret;\n" +
  1.2043 +        "  }\n" +
  1.2044 +        "  s = ret;\n" +
  1.2045 +        "}"
  1.2046 +    )
  1.2047 +    public String replace(char oldChar, char newChar) {
  1.2048 +        if (oldChar != newChar) {
  1.2049 +            int len = length();
  1.2050 +            int i = -1;
  1.2051 +            char[] val = toCharArray(); /* avoid getfield opcode */
  1.2052 +            int off = offset();   /* avoid getfield opcode */
  1.2053 +
  1.2054 +            while (++i < len) {
  1.2055 +                if (val[off + i] == oldChar) {
  1.2056 +                    break;
  1.2057 +                }
  1.2058 +            }
  1.2059 +            if (i < len) {
  1.2060 +                char buf[] = new char[len];
  1.2061 +                for (int j = 0 ; j < i ; j++) {
  1.2062 +                    buf[j] = val[off+j];
  1.2063 +                }
  1.2064 +                while (i < len) {
  1.2065 +                    char c = val[off + i];
  1.2066 +                    buf[i] = (c == oldChar) ? newChar : c;
  1.2067 +                    i++;
  1.2068 +                }
  1.2069 +                return new String(buf, 0, len);
  1.2070 +            }
  1.2071 +        }
  1.2072 +        return this;
  1.2073 +    }
  1.2074 +
  1.2075 +    /**
  1.2076 +     * Tells whether or not this string matches the given <a
  1.2077 +     * href="../util/regex/Pattern.html#sum">regular expression</a>.
  1.2078 +     *
  1.2079 +     * <p> An invocation of this method of the form
  1.2080 +     * <i>str</i><tt>.matches(</tt><i>regex</i><tt>)</tt> yields exactly the
  1.2081 +     * same result as the expression
  1.2082 +     *
  1.2083 +     * <blockquote><tt> {@link java.util.regex.Pattern}.{@link
  1.2084 +     * java.util.regex.Pattern#matches(String,CharSequence)
  1.2085 +     * matches}(</tt><i>regex</i><tt>,</tt> <i>str</i><tt>)</tt></blockquote>
  1.2086 +     *
  1.2087 +     * @param   regex
  1.2088 +     *          the regular expression to which this string is to be matched
  1.2089 +     *
  1.2090 +     * @return  <tt>true</tt> if, and only if, this string matches the
  1.2091 +     *          given regular expression
  1.2092 +     *
  1.2093 +     * @throws  PatternSyntaxException
  1.2094 +     *          if the regular expression's syntax is invalid
  1.2095 +     *
  1.2096 +     * @see java.util.regex.Pattern
  1.2097 +     *
  1.2098 +     * @since 1.4
  1.2099 +     * @spec JSR-51
  1.2100 +     */
  1.2101 +    @JavaScriptBody(args = { "regex" }, body = 
  1.2102 +          "var self = this.toString();\n"
  1.2103 +        + "var re = new RegExp(regex.toString());\n"
  1.2104 +        + "var r = re.exec(self);\n"
  1.2105 +        + "return r != null && r.length > 0 && self.length == r[0].length;"
  1.2106 +    )
  1.2107 +    public boolean matches(String regex) {
  1.2108 +        throw new UnsupportedOperationException();
  1.2109 +    }
  1.2110 +
  1.2111 +    /**
  1.2112 +     * Returns true if and only if this string contains the specified
  1.2113 +     * sequence of char values.
  1.2114 +     *
  1.2115 +     * @param s the sequence to search for
  1.2116 +     * @return true if this string contains <code>s</code>, false otherwise
  1.2117 +     * @throws NullPointerException if <code>s</code> is <code>null</code>
  1.2118 +     * @since 1.5
  1.2119 +     */
  1.2120 +    public boolean contains(CharSequence s) {
  1.2121 +        return indexOf(s.toString()) > -1;
  1.2122 +    }
  1.2123 +
  1.2124 +    /**
  1.2125 +     * Replaces the first substring of this string that matches the given <a
  1.2126 +     * href="../util/regex/Pattern.html#sum">regular expression</a> with the
  1.2127 +     * given replacement.
  1.2128 +     *
  1.2129 +     * <p> An invocation of this method of the form
  1.2130 +     * <i>str</i><tt>.replaceFirst(</tt><i>regex</i><tt>,</tt> <i>repl</i><tt>)</tt>
  1.2131 +     * yields exactly the same result as the expression
  1.2132 +     *
  1.2133 +     * <blockquote><tt>
  1.2134 +     * {@link java.util.regex.Pattern}.{@link java.util.regex.Pattern#compile
  1.2135 +     * compile}(</tt><i>regex</i><tt>).{@link
  1.2136 +     * java.util.regex.Pattern#matcher(java.lang.CharSequence)
  1.2137 +     * matcher}(</tt><i>str</i><tt>).{@link java.util.regex.Matcher#replaceFirst
  1.2138 +     * replaceFirst}(</tt><i>repl</i><tt>)</tt></blockquote>
  1.2139 +     *
  1.2140 +     *<p>
  1.2141 +     * Note that backslashes (<tt>\</tt>) and dollar signs (<tt>$</tt>) in the
  1.2142 +     * replacement string may cause the results to be different than if it were
  1.2143 +     * being treated as a literal replacement string; see
  1.2144 +     * {@link java.util.regex.Matcher#replaceFirst}.
  1.2145 +     * Use {@link java.util.regex.Matcher#quoteReplacement} to suppress the special
  1.2146 +     * meaning of these characters, if desired.
  1.2147 +     *
  1.2148 +     * @param   regex
  1.2149 +     *          the regular expression to which this string is to be matched
  1.2150 +     * @param   replacement
  1.2151 +     *          the string to be substituted for the first match
  1.2152 +     *
  1.2153 +     * @return  The resulting <tt>String</tt>
  1.2154 +     *
  1.2155 +     * @throws  PatternSyntaxException
  1.2156 +     *          if the regular expression's syntax is invalid
  1.2157 +     *
  1.2158 +     * @see java.util.regex.Pattern
  1.2159 +     *
  1.2160 +     * @since 1.4
  1.2161 +     * @spec JSR-51
  1.2162 +     */
  1.2163 +    public String replaceFirst(String regex, String replacement) {
  1.2164 +        throw new UnsupportedOperationException();
  1.2165 +    }
  1.2166 +
  1.2167 +    /**
  1.2168 +     * Replaces each substring of this string that matches the given <a
  1.2169 +     * href="../util/regex/Pattern.html#sum">regular expression</a> with the
  1.2170 +     * given replacement.
  1.2171 +     *
  1.2172 +     * <p> An invocation of this method of the form
  1.2173 +     * <i>str</i><tt>.replaceAll(</tt><i>regex</i><tt>,</tt> <i>repl</i><tt>)</tt>
  1.2174 +     * yields exactly the same result as the expression
  1.2175 +     *
  1.2176 +     * <blockquote><tt>
  1.2177 +     * {@link java.util.regex.Pattern}.{@link java.util.regex.Pattern#compile
  1.2178 +     * compile}(</tt><i>regex</i><tt>).{@link
  1.2179 +     * java.util.regex.Pattern#matcher(java.lang.CharSequence)
  1.2180 +     * matcher}(</tt><i>str</i><tt>).{@link java.util.regex.Matcher#replaceAll
  1.2181 +     * replaceAll}(</tt><i>repl</i><tt>)</tt></blockquote>
  1.2182 +     *
  1.2183 +     *<p>
  1.2184 +     * Note that backslashes (<tt>\</tt>) and dollar signs (<tt>$</tt>) in the
  1.2185 +     * replacement string may cause the results to be different than if it were
  1.2186 +     * being treated as a literal replacement string; see
  1.2187 +     * {@link java.util.regex.Matcher#replaceAll Matcher.replaceAll}.
  1.2188 +     * Use {@link java.util.regex.Matcher#quoteReplacement} to suppress the special
  1.2189 +     * meaning of these characters, if desired.
  1.2190 +     *
  1.2191 +     * @param   regex
  1.2192 +     *          the regular expression to which this string is to be matched
  1.2193 +     * @param   replacement
  1.2194 +     *          the string to be substituted for each match
  1.2195 +     *
  1.2196 +     * @return  The resulting <tt>String</tt>
  1.2197 +     *
  1.2198 +     * @throws  PatternSyntaxException
  1.2199 +     *          if the regular expression's syntax is invalid
  1.2200 +     *
  1.2201 +     * @see java.util.regex.Pattern
  1.2202 +     *
  1.2203 +     * @since 1.4
  1.2204 +     * @spec JSR-51
  1.2205 +     */
  1.2206 +    public String replaceAll(String regex, String replacement) {
  1.2207 +        throw new UnsupportedOperationException();
  1.2208 +    }
  1.2209 +
  1.2210 +    /**
  1.2211 +     * Replaces each substring of this string that matches the literal target
  1.2212 +     * sequence with the specified literal replacement sequence. The
  1.2213 +     * replacement proceeds from the beginning of the string to the end, for
  1.2214 +     * example, replacing "aa" with "b" in the string "aaa" will result in
  1.2215 +     * "ba" rather than "ab".
  1.2216 +     *
  1.2217 +     * @param  target The sequence of char values to be replaced
  1.2218 +     * @param  replacement The replacement sequence of char values
  1.2219 +     * @return  The resulting string
  1.2220 +     * @throws NullPointerException if <code>target</code> or
  1.2221 +     *         <code>replacement</code> is <code>null</code>.
  1.2222 +     * @since 1.5
  1.2223 +     */
  1.2224 +    public String replace(CharSequence target, CharSequence replacement) {
  1.2225 +        throw new UnsupportedOperationException("This one should be supported, but without dep on rest of regexp");
  1.2226 +    }
  1.2227 +
  1.2228 +    /**
  1.2229 +     * Splits this string around matches of the given
  1.2230 +     * <a href="../util/regex/Pattern.html#sum">regular expression</a>.
  1.2231 +     *
  1.2232 +     * <p> The array returned by this method contains each substring of this
  1.2233 +     * string that is terminated by another substring that matches the given
  1.2234 +     * expression or is terminated by the end of the string.  The substrings in
  1.2235 +     * the array are in the order in which they occur in this string.  If the
  1.2236 +     * expression does not match any part of the input then the resulting array
  1.2237 +     * has just one element, namely this string.
  1.2238 +     *
  1.2239 +     * <p> The <tt>limit</tt> parameter controls the number of times the
  1.2240 +     * pattern is applied and therefore affects the length of the resulting
  1.2241 +     * array.  If the limit <i>n</i> is greater than zero then the pattern
  1.2242 +     * will be applied at most <i>n</i>&nbsp;-&nbsp;1 times, the array's
  1.2243 +     * length will be no greater than <i>n</i>, and the array's last entry
  1.2244 +     * will contain all input beyond the last matched delimiter.  If <i>n</i>
  1.2245 +     * is non-positive then the pattern will be applied as many times as
  1.2246 +     * possible and the array can have any length.  If <i>n</i> is zero then
  1.2247 +     * the pattern will be applied as many times as possible, the array can
  1.2248 +     * have any length, and trailing empty strings will be discarded.
  1.2249 +     *
  1.2250 +     * <p> The string <tt>"boo:and:foo"</tt>, for example, yields the
  1.2251 +     * following results with these parameters:
  1.2252 +     *
  1.2253 +     * <blockquote><table cellpadding=1 cellspacing=0 summary="Split example showing regex, limit, and result">
  1.2254 +     * <tr>
  1.2255 +     *     <th>Regex</th>
  1.2256 +     *     <th>Limit</th>
  1.2257 +     *     <th>Result</th>
  1.2258 +     * </tr>
  1.2259 +     * <tr><td align=center>:</td>
  1.2260 +     *     <td align=center>2</td>
  1.2261 +     *     <td><tt>{ "boo", "and:foo" }</tt></td></tr>
  1.2262 +     * <tr><td align=center>:</td>
  1.2263 +     *     <td align=center>5</td>
  1.2264 +     *     <td><tt>{ "boo", "and", "foo" }</tt></td></tr>
  1.2265 +     * <tr><td align=center>:</td>
  1.2266 +     *     <td align=center>-2</td>
  1.2267 +     *     <td><tt>{ "boo", "and", "foo" }</tt></td></tr>
  1.2268 +     * <tr><td align=center>o</td>
  1.2269 +     *     <td align=center>5</td>
  1.2270 +     *     <td><tt>{ "b", "", ":and:f", "", "" }</tt></td></tr>
  1.2271 +     * <tr><td align=center>o</td>
  1.2272 +     *     <td align=center>-2</td>
  1.2273 +     *     <td><tt>{ "b", "", ":and:f", "", "" }</tt></td></tr>
  1.2274 +     * <tr><td align=center>o</td>
  1.2275 +     *     <td align=center>0</td>
  1.2276 +     *     <td><tt>{ "b", "", ":and:f" }</tt></td></tr>
  1.2277 +     * </table></blockquote>
  1.2278 +     *
  1.2279 +     * <p> An invocation of this method of the form
  1.2280 +     * <i>str.</i><tt>split(</tt><i>regex</i><tt>,</tt>&nbsp;<i>n</i><tt>)</tt>
  1.2281 +     * yields the same result as the expression
  1.2282 +     *
  1.2283 +     * <blockquote>
  1.2284 +     * {@link java.util.regex.Pattern}.{@link java.util.regex.Pattern#compile
  1.2285 +     * compile}<tt>(</tt><i>regex</i><tt>)</tt>.{@link
  1.2286 +     * java.util.regex.Pattern#split(java.lang.CharSequence,int)
  1.2287 +     * split}<tt>(</tt><i>str</i><tt>,</tt>&nbsp;<i>n</i><tt>)</tt>
  1.2288 +     * </blockquote>
  1.2289 +     *
  1.2290 +     *
  1.2291 +     * @param  regex
  1.2292 +     *         the delimiting regular expression
  1.2293 +     *
  1.2294 +     * @param  limit
  1.2295 +     *         the result threshold, as described above
  1.2296 +     *
  1.2297 +     * @return  the array of strings computed by splitting this string
  1.2298 +     *          around matches of the given regular expression
  1.2299 +     *
  1.2300 +     * @throws  PatternSyntaxException
  1.2301 +     *          if the regular expression's syntax is invalid
  1.2302 +     *
  1.2303 +     * @see java.util.regex.Pattern
  1.2304 +     *
  1.2305 +     * @since 1.4
  1.2306 +     * @spec JSR-51
  1.2307 +     */
  1.2308 +    public String[] split(String regex, int limit) {
  1.2309 +        throw new UnsupportedOperationException("Needs regexp");
  1.2310 +    }
  1.2311 +
  1.2312 +    /**
  1.2313 +     * Splits this string around matches of the given <a
  1.2314 +     * href="../util/regex/Pattern.html#sum">regular expression</a>.
  1.2315 +     *
  1.2316 +     * <p> This method works as if by invoking the two-argument {@link
  1.2317 +     * #split(String, int) split} method with the given expression and a limit
  1.2318 +     * argument of zero.  Trailing empty strings are therefore not included in
  1.2319 +     * the resulting array.
  1.2320 +     *
  1.2321 +     * <p> The string <tt>"boo:and:foo"</tt>, for example, yields the following
  1.2322 +     * results with these expressions:
  1.2323 +     *
  1.2324 +     * <blockquote><table cellpadding=1 cellspacing=0 summary="Split examples showing regex and result">
  1.2325 +     * <tr>
  1.2326 +     *  <th>Regex</th>
  1.2327 +     *  <th>Result</th>
  1.2328 +     * </tr>
  1.2329 +     * <tr><td align=center>:</td>
  1.2330 +     *     <td><tt>{ "boo", "and", "foo" }</tt></td></tr>
  1.2331 +     * <tr><td align=center>o</td>
  1.2332 +     *     <td><tt>{ "b", "", ":and:f" }</tt></td></tr>
  1.2333 +     * </table></blockquote>
  1.2334 +     *
  1.2335 +     *
  1.2336 +     * @param  regex
  1.2337 +     *         the delimiting regular expression
  1.2338 +     *
  1.2339 +     * @return  the array of strings computed by splitting this string
  1.2340 +     *          around matches of the given regular expression
  1.2341 +     *
  1.2342 +     * @throws  PatternSyntaxException
  1.2343 +     *          if the regular expression's syntax is invalid
  1.2344 +     *
  1.2345 +     * @see java.util.regex.Pattern
  1.2346 +     *
  1.2347 +     * @since 1.4
  1.2348 +     * @spec JSR-51
  1.2349 +     */
  1.2350 +    public String[] split(String regex) {
  1.2351 +        return split(regex, 0);
  1.2352 +    }
  1.2353 +
  1.2354 +    /**
  1.2355 +     * Converts all of the characters in this <code>String</code> to lower
  1.2356 +     * case using the rules of the given <code>Locale</code>.  Case mapping is based
  1.2357 +     * on the Unicode Standard version specified by the {@link java.lang.Character Character}
  1.2358 +     * class. Since case mappings are not always 1:1 char mappings, the resulting
  1.2359 +     * <code>String</code> may be a different length than the original <code>String</code>.
  1.2360 +     * <p>
  1.2361 +     * Examples of lowercase  mappings are in the following table:
  1.2362 +     * <table border="1" summary="Lowercase mapping examples showing language code of locale, upper case, lower case, and description">
  1.2363 +     * <tr>
  1.2364 +     *   <th>Language Code of Locale</th>
  1.2365 +     *   <th>Upper Case</th>
  1.2366 +     *   <th>Lower Case</th>
  1.2367 +     *   <th>Description</th>
  1.2368 +     * </tr>
  1.2369 +     * <tr>
  1.2370 +     *   <td>tr (Turkish)</td>
  1.2371 +     *   <td>&#92;u0130</td>
  1.2372 +     *   <td>&#92;u0069</td>
  1.2373 +     *   <td>capital letter I with dot above -&gt; small letter i</td>
  1.2374 +     * </tr>
  1.2375 +     * <tr>
  1.2376 +     *   <td>tr (Turkish)</td>
  1.2377 +     *   <td>&#92;u0049</td>
  1.2378 +     *   <td>&#92;u0131</td>
  1.2379 +     *   <td>capital letter I -&gt; small letter dotless i </td>
  1.2380 +     * </tr>
  1.2381 +     * <tr>
  1.2382 +     *   <td>(all)</td>
  1.2383 +     *   <td>French Fries</td>
  1.2384 +     *   <td>french fries</td>
  1.2385 +     *   <td>lowercased all chars in String</td>
  1.2386 +     * </tr>
  1.2387 +     * <tr>
  1.2388 +     *   <td>(all)</td>
  1.2389 +     *   <td><img src="doc-files/capiota.gif" alt="capiota"><img src="doc-files/capchi.gif" alt="capchi">
  1.2390 +     *       <img src="doc-files/captheta.gif" alt="captheta"><img src="doc-files/capupsil.gif" alt="capupsil">
  1.2391 +     *       <img src="doc-files/capsigma.gif" alt="capsigma"></td>
  1.2392 +     *   <td><img src="doc-files/iota.gif" alt="iota"><img src="doc-files/chi.gif" alt="chi">
  1.2393 +     *       <img src="doc-files/theta.gif" alt="theta"><img src="doc-files/upsilon.gif" alt="upsilon">
  1.2394 +     *       <img src="doc-files/sigma1.gif" alt="sigma"></td>
  1.2395 +     *   <td>lowercased all chars in String</td>
  1.2396 +     * </tr>
  1.2397 +     * </table>
  1.2398 +     *
  1.2399 +     * @param locale use the case transformation rules for this locale
  1.2400 +     * @return the <code>String</code>, converted to lowercase.
  1.2401 +     * @see     java.lang.String#toLowerCase()
  1.2402 +     * @see     java.lang.String#toUpperCase()
  1.2403 +     * @see     java.lang.String#toUpperCase(Locale)
  1.2404 +     * @since   1.1
  1.2405 +     */
  1.2406 +//    public String toLowerCase(Locale locale) {
  1.2407 +//        if (locale == null) {
  1.2408 +//            throw new NullPointerException();
  1.2409 +//        }
  1.2410 +//
  1.2411 +//        int     firstUpper;
  1.2412 +//
  1.2413 +//        /* Now check if there are any characters that need to be changed. */
  1.2414 +//        scan: {
  1.2415 +//            for (firstUpper = 0 ; firstUpper < count; ) {
  1.2416 +//                char c = value[offset+firstUpper];
  1.2417 +//                if ((c >= Character.MIN_HIGH_SURROGATE) &&
  1.2418 +//                    (c <= Character.MAX_HIGH_SURROGATE)) {
  1.2419 +//                    int supplChar = codePointAt(firstUpper);
  1.2420 +//                    if (supplChar != Character.toLowerCase(supplChar)) {
  1.2421 +//                        break scan;
  1.2422 +//                    }
  1.2423 +//                    firstUpper += Character.charCount(supplChar);
  1.2424 +//                } else {
  1.2425 +//                    if (c != Character.toLowerCase(c)) {
  1.2426 +//                        break scan;
  1.2427 +//                    }
  1.2428 +//                    firstUpper++;
  1.2429 +//                }
  1.2430 +//            }
  1.2431 +//            return this;
  1.2432 +//        }
  1.2433 +//
  1.2434 +//        char[]  result = new char[count];
  1.2435 +//        int     resultOffset = 0;  /* result may grow, so i+resultOffset
  1.2436 +//                                    * is the write location in result */
  1.2437 +//
  1.2438 +//        /* Just copy the first few lowerCase characters. */
  1.2439 +//        System.arraycopy(value, offset, result, 0, firstUpper);
  1.2440 +//
  1.2441 +//        String lang = locale.getLanguage();
  1.2442 +//        boolean localeDependent =
  1.2443 +//            (lang == "tr" || lang == "az" || lang == "lt");
  1.2444 +//        char[] lowerCharArray;
  1.2445 +//        int lowerChar;
  1.2446 +//        int srcChar;
  1.2447 +//        int srcCount;
  1.2448 +//        for (int i = firstUpper; i < count; i += srcCount) {
  1.2449 +//            srcChar = (int)value[offset+i];
  1.2450 +//            if ((char)srcChar >= Character.MIN_HIGH_SURROGATE &&
  1.2451 +//                (char)srcChar <= Character.MAX_HIGH_SURROGATE) {
  1.2452 +//                srcChar = codePointAt(i);
  1.2453 +//                srcCount = Character.charCount(srcChar);
  1.2454 +//            } else {
  1.2455 +//                srcCount = 1;
  1.2456 +//            }
  1.2457 +//            if (localeDependent || srcChar == '\u03A3') { // GREEK CAPITAL LETTER SIGMA
  1.2458 +//                lowerChar = ConditionalSpecialCasing.toLowerCaseEx(this, i, locale);
  1.2459 +//            } else if (srcChar == '\u0130') { // LATIN CAPITAL LETTER I DOT
  1.2460 +//                lowerChar = Character.ERROR;
  1.2461 +//            } else {
  1.2462 +//                lowerChar = Character.toLowerCase(srcChar);
  1.2463 +//            }
  1.2464 +//            if ((lowerChar == Character.ERROR) ||
  1.2465 +//                (lowerChar >= Character.MIN_SUPPLEMENTARY_CODE_POINT)) {
  1.2466 +//                if (lowerChar == Character.ERROR) {
  1.2467 +//                     if (!localeDependent && srcChar == '\u0130') {
  1.2468 +//                         lowerCharArray =
  1.2469 +//                             ConditionalSpecialCasing.toLowerCaseCharArray(this, i, Locale.ENGLISH);
  1.2470 +//                     } else {
  1.2471 +//                        lowerCharArray =
  1.2472 +//                            ConditionalSpecialCasing.toLowerCaseCharArray(this, i, locale);
  1.2473 +//                     }
  1.2474 +//                } else if (srcCount == 2) {
  1.2475 +//                    resultOffset += Character.toChars(lowerChar, result, i + resultOffset) - srcCount;
  1.2476 +//                    continue;
  1.2477 +//                } else {
  1.2478 +//                    lowerCharArray = Character.toChars(lowerChar);
  1.2479 +//                }
  1.2480 +//
  1.2481 +//                /* Grow result if needed */
  1.2482 +//                int mapLen = lowerCharArray.length;
  1.2483 +//                if (mapLen > srcCount) {
  1.2484 +//                    char[] result2 = new char[result.length + mapLen - srcCount];
  1.2485 +//                    System.arraycopy(result, 0, result2, 0,
  1.2486 +//                        i + resultOffset);
  1.2487 +//                    result = result2;
  1.2488 +//                }
  1.2489 +//                for (int x=0; x<mapLen; ++x) {
  1.2490 +//                    result[i+resultOffset+x] = lowerCharArray[x];
  1.2491 +//                }
  1.2492 +//                resultOffset += (mapLen - srcCount);
  1.2493 +//            } else {
  1.2494 +//                result[i+resultOffset] = (char)lowerChar;
  1.2495 +//            }
  1.2496 +//        }
  1.2497 +//        return new String(0, count+resultOffset, result);
  1.2498 +//    }
  1.2499 +
  1.2500 +    /**
  1.2501 +     * Converts all of the characters in this <code>String</code> to lower
  1.2502 +     * case using the rules of the default locale. This is equivalent to calling
  1.2503 +     * <code>toLowerCase(Locale.getDefault())</code>.
  1.2504 +     * <p>
  1.2505 +     * <b>Note:</b> This method is locale sensitive, and may produce unexpected
  1.2506 +     * results if used for strings that are intended to be interpreted locale
  1.2507 +     * independently.
  1.2508 +     * Examples are programming language identifiers, protocol keys, and HTML
  1.2509 +     * tags.
  1.2510 +     * For instance, <code>"TITLE".toLowerCase()</code> in a Turkish locale
  1.2511 +     * returns <code>"t\u005Cu0131tle"</code>, where '\u005Cu0131' is the
  1.2512 +     * LATIN SMALL LETTER DOTLESS I character.
  1.2513 +     * To obtain correct results for locale insensitive strings, use
  1.2514 +     * <code>toLowerCase(Locale.ENGLISH)</code>.
  1.2515 +     * <p>
  1.2516 +     * @return  the <code>String</code>, converted to lowercase.
  1.2517 +     * @see     java.lang.String#toLowerCase(Locale)
  1.2518 +     */
  1.2519 +    @JavaScriptBody(args = {}, body = "return this.toLowerCase();")
  1.2520 +    public String toLowerCase() {
  1.2521 +        throw new UnsupportedOperationException("Should be supported but without connection to locale");
  1.2522 +    }
  1.2523 +
  1.2524 +    /**
  1.2525 +     * Converts all of the characters in this <code>String</code> to upper
  1.2526 +     * case using the rules of the given <code>Locale</code>. Case mapping is based
  1.2527 +     * on the Unicode Standard version specified by the {@link java.lang.Character Character}
  1.2528 +     * class. Since case mappings are not always 1:1 char mappings, the resulting
  1.2529 +     * <code>String</code> may be a different length than the original <code>String</code>.
  1.2530 +     * <p>
  1.2531 +     * Examples of locale-sensitive and 1:M case mappings are in the following table.
  1.2532 +     * <p>
  1.2533 +     * <table border="1" summary="Examples of locale-sensitive and 1:M case mappings. Shows Language code of locale, lower case, upper case, and description.">
  1.2534 +     * <tr>
  1.2535 +     *   <th>Language Code of Locale</th>
  1.2536 +     *   <th>Lower Case</th>
  1.2537 +     *   <th>Upper Case</th>
  1.2538 +     *   <th>Description</th>
  1.2539 +     * </tr>
  1.2540 +     * <tr>
  1.2541 +     *   <td>tr (Turkish)</td>
  1.2542 +     *   <td>&#92;u0069</td>
  1.2543 +     *   <td>&#92;u0130</td>
  1.2544 +     *   <td>small letter i -&gt; capital letter I with dot above</td>
  1.2545 +     * </tr>
  1.2546 +     * <tr>
  1.2547 +     *   <td>tr (Turkish)</td>
  1.2548 +     *   <td>&#92;u0131</td>
  1.2549 +     *   <td>&#92;u0049</td>
  1.2550 +     *   <td>small letter dotless i -&gt; capital letter I</td>
  1.2551 +     * </tr>
  1.2552 +     * <tr>
  1.2553 +     *   <td>(all)</td>
  1.2554 +     *   <td>&#92;u00df</td>
  1.2555 +     *   <td>&#92;u0053 &#92;u0053</td>
  1.2556 +     *   <td>small letter sharp s -&gt; two letters: SS</td>
  1.2557 +     * </tr>
  1.2558 +     * <tr>
  1.2559 +     *   <td>(all)</td>
  1.2560 +     *   <td>Fahrvergn&uuml;gen</td>
  1.2561 +     *   <td>FAHRVERGN&Uuml;GEN</td>
  1.2562 +     *   <td></td>
  1.2563 +     * </tr>
  1.2564 +     * </table>
  1.2565 +     * @param locale use the case transformation rules for this locale
  1.2566 +     * @return the <code>String</code>, converted to uppercase.
  1.2567 +     * @see     java.lang.String#toUpperCase()
  1.2568 +     * @see     java.lang.String#toLowerCase()
  1.2569 +     * @see     java.lang.String#toLowerCase(Locale)
  1.2570 +     * @since   1.1
  1.2571 +     */
  1.2572 +    /* not for javascript 
  1.2573 +    public String toUpperCase(Locale locale) {
  1.2574 +        if (locale == null) {
  1.2575 +            throw new NullPointerException();
  1.2576 +        }
  1.2577 +
  1.2578 +        int     firstLower;
  1.2579 +
  1.2580 +        // Now check if there are any characters that need to be changed. 
  1.2581 +        scan: {
  1.2582 +            for (firstLower = 0 ; firstLower < count; ) {
  1.2583 +                int c = (int)value[offset+firstLower];
  1.2584 +                int srcCount;
  1.2585 +                if ((c >= Character.MIN_HIGH_SURROGATE) &&
  1.2586 +                    (c <= Character.MAX_HIGH_SURROGATE)) {
  1.2587 +                    c = codePointAt(firstLower);
  1.2588 +                    srcCount = Character.charCount(c);
  1.2589 +                } else {
  1.2590 +                    srcCount = 1;
  1.2591 +                }
  1.2592 +                int upperCaseChar = Character.toUpperCaseEx(c);
  1.2593 +                if ((upperCaseChar == Character.ERROR) ||
  1.2594 +                    (c != upperCaseChar)) {
  1.2595 +                    break scan;
  1.2596 +                }
  1.2597 +                firstLower += srcCount;
  1.2598 +            }
  1.2599 +            return this;
  1.2600 +        }
  1.2601 +
  1.2602 +        char[]  result       = new char[count]; /* may grow *
  1.2603 +        int     resultOffset = 0;  /* result may grow, so i+resultOffset
  1.2604 +                                    * is the write location in result *
  1.2605 +
  1.2606 +        /* Just copy the first few upperCase characters. *
  1.2607 +        System.arraycopy(value, offset, result, 0, firstLower);
  1.2608 +
  1.2609 +        String lang = locale.getLanguage();
  1.2610 +        boolean localeDependent =
  1.2611 +            (lang == "tr" || lang == "az" || lang == "lt");
  1.2612 +        char[] upperCharArray;
  1.2613 +        int upperChar;
  1.2614 +        int srcChar;
  1.2615 +        int srcCount;
  1.2616 +        for (int i = firstLower; i < count; i += srcCount) {
  1.2617 +            srcChar = (int)value[offset+i];
  1.2618 +            if ((char)srcChar >= Character.MIN_HIGH_SURROGATE &&
  1.2619 +                (char)srcChar <= Character.MAX_HIGH_SURROGATE) {
  1.2620 +                srcChar = codePointAt(i);
  1.2621 +                srcCount = Character.charCount(srcChar);
  1.2622 +            } else {
  1.2623 +                srcCount = 1;
  1.2624 +            }
  1.2625 +            if (localeDependent) {
  1.2626 +                upperChar = ConditionalSpecialCasing.toUpperCaseEx(this, i, locale);
  1.2627 +            } else {
  1.2628 +                upperChar = Character.toUpperCaseEx(srcChar);
  1.2629 +            }
  1.2630 +            if ((upperChar == Character.ERROR) ||
  1.2631 +                (upperChar >= Character.MIN_SUPPLEMENTARY_CODE_POINT)) {
  1.2632 +                if (upperChar == Character.ERROR) {
  1.2633 +                    if (localeDependent) {
  1.2634 +                        upperCharArray =
  1.2635 +                            ConditionalSpecialCasing.toUpperCaseCharArray(this, i, locale);
  1.2636 +                    } else {
  1.2637 +                        upperCharArray = Character.toUpperCaseCharArray(srcChar);
  1.2638 +                    }
  1.2639 +                } else if (srcCount == 2) {
  1.2640 +                    resultOffset += Character.toChars(upperChar, result, i + resultOffset) - srcCount;
  1.2641 +                    continue;
  1.2642 +                } else {
  1.2643 +                    upperCharArray = Character.toChars(upperChar);
  1.2644 +                }
  1.2645 +
  1.2646 +                /* Grow result if needed *
  1.2647 +                int mapLen = upperCharArray.length;
  1.2648 +                if (mapLen > srcCount) {
  1.2649 +                    char[] result2 = new char[result.length + mapLen - srcCount];
  1.2650 +                    System.arraycopy(result, 0, result2, 0,
  1.2651 +                        i + resultOffset);
  1.2652 +                    result = result2;
  1.2653 +                }
  1.2654 +                for (int x=0; x<mapLen; ++x) {
  1.2655 +                    result[i+resultOffset+x] = upperCharArray[x];
  1.2656 +                }
  1.2657 +                resultOffset += (mapLen - srcCount);
  1.2658 +            } else {
  1.2659 +                result[i+resultOffset] = (char)upperChar;
  1.2660 +            }
  1.2661 +        }
  1.2662 +        return new String(0, count+resultOffset, result);
  1.2663 +    }
  1.2664 +    */
  1.2665 +
  1.2666 +    /**
  1.2667 +     * Converts all of the characters in this <code>String</code> to upper
  1.2668 +     * case using the rules of the default locale. This method is equivalent to
  1.2669 +     * <code>toUpperCase(Locale.getDefault())</code>.
  1.2670 +     * <p>
  1.2671 +     * <b>Note:</b> This method is locale sensitive, and may produce unexpected
  1.2672 +     * results if used for strings that are intended to be interpreted locale
  1.2673 +     * independently.
  1.2674 +     * Examples are programming language identifiers, protocol keys, and HTML
  1.2675 +     * tags.
  1.2676 +     * For instance, <code>"title".toUpperCase()</code> in a Turkish locale
  1.2677 +     * returns <code>"T\u005Cu0130TLE"</code>, where '\u005Cu0130' is the
  1.2678 +     * LATIN CAPITAL LETTER I WITH DOT ABOVE character.
  1.2679 +     * To obtain correct results for locale insensitive strings, use
  1.2680 +     * <code>toUpperCase(Locale.ENGLISH)</code>.
  1.2681 +     * <p>
  1.2682 +     * @return  the <code>String</code>, converted to uppercase.
  1.2683 +     * @see     java.lang.String#toUpperCase(Locale)
  1.2684 +     */
  1.2685 +    @JavaScriptBody(args = {}, body = "return this.toUpperCase();")
  1.2686 +    public String toUpperCase() {
  1.2687 +        throw new UnsupportedOperationException();
  1.2688 +    }
  1.2689 +
  1.2690 +    /**
  1.2691 +     * Returns a copy of the string, with leading and trailing whitespace
  1.2692 +     * omitted.
  1.2693 +     * <p>
  1.2694 +     * If this <code>String</code> object represents an empty character
  1.2695 +     * sequence, or the first and last characters of character sequence
  1.2696 +     * represented by this <code>String</code> object both have codes
  1.2697 +     * greater than <code>'&#92;u0020'</code> (the space character), then a
  1.2698 +     * reference to this <code>String</code> object is returned.
  1.2699 +     * <p>
  1.2700 +     * Otherwise, if there is no character with a code greater than
  1.2701 +     * <code>'&#92;u0020'</code> in the string, then a new
  1.2702 +     * <code>String</code> object representing an empty string is created
  1.2703 +     * and returned.
  1.2704 +     * <p>
  1.2705 +     * Otherwise, let <i>k</i> be the index of the first character in the
  1.2706 +     * string whose code is greater than <code>'&#92;u0020'</code>, and let
  1.2707 +     * <i>m</i> be the index of the last character in the string whose code
  1.2708 +     * is greater than <code>'&#92;u0020'</code>. A new <code>String</code>
  1.2709 +     * object is created, representing the substring of this string that
  1.2710 +     * begins with the character at index <i>k</i> and ends with the
  1.2711 +     * character at index <i>m</i>-that is, the result of
  1.2712 +     * <code>this.substring(<i>k</i>,&nbsp;<i>m</i>+1)</code>.
  1.2713 +     * <p>
  1.2714 +     * This method may be used to trim whitespace (as defined above) from
  1.2715 +     * the beginning and end of a string.
  1.2716 +     *
  1.2717 +     * @return  A copy of this string with leading and trailing white
  1.2718 +     *          space removed, or this string if it has no leading or
  1.2719 +     *          trailing white space.
  1.2720 +     */
  1.2721 +    public String trim() {
  1.2722 +        int len = length();
  1.2723 +        int st = 0;
  1.2724 +        int off = offset();      /* avoid getfield opcode */
  1.2725 +        char[] val = toCharArray();    /* avoid getfield opcode */
  1.2726 +
  1.2727 +        while ((st < len) && (val[off + st] <= ' ')) {
  1.2728 +            st++;
  1.2729 +        }
  1.2730 +        while ((st < len) && (val[off + len - 1] <= ' ')) {
  1.2731 +            len--;
  1.2732 +        }
  1.2733 +        return ((st > 0) || (len < length())) ? substring(st, len) : this;
  1.2734 +    }
  1.2735 +
  1.2736 +    /**
  1.2737 +     * This object (which is already a string!) is itself returned.
  1.2738 +     *
  1.2739 +     * @return  the string itself.
  1.2740 +     */
  1.2741 +    @JavaScriptBody(args = {}, body = "return this.toString();")
  1.2742 +    public String toString() {
  1.2743 +        return this;
  1.2744 +    }
  1.2745 +
  1.2746 +    /**
  1.2747 +     * Converts this string to a new character array.
  1.2748 +     *
  1.2749 +     * @return  a newly allocated character array whose length is the length
  1.2750 +     *          of this string and whose contents are initialized to contain
  1.2751 +     *          the character sequence represented by this string.
  1.2752 +     */
  1.2753 +    public char[] toCharArray() {
  1.2754 +        char result[] = new char[length()];
  1.2755 +        getChars(0, length(), result, 0);
  1.2756 +        return result;
  1.2757 +    }
  1.2758 +
  1.2759 +    /**
  1.2760 +     * Returns a formatted string using the specified format string and
  1.2761 +     * arguments.
  1.2762 +     *
  1.2763 +     * <p> The locale always used is the one returned by {@link
  1.2764 +     * java.util.Locale#getDefault() Locale.getDefault()}.
  1.2765 +     *
  1.2766 +     * @param  format
  1.2767 +     *         A <a href="../util/Formatter.html#syntax">format string</a>
  1.2768 +     *
  1.2769 +     * @param  args
  1.2770 +     *         Arguments referenced by the format specifiers in the format
  1.2771 +     *         string.  If there are more arguments than format specifiers, the
  1.2772 +     *         extra arguments are ignored.  The number of arguments is
  1.2773 +     *         variable and may be zero.  The maximum number of arguments is
  1.2774 +     *         limited by the maximum dimension of a Java array as defined by
  1.2775 +     *         <cite>The Java&trade; Virtual Machine Specification</cite>.
  1.2776 +     *         The behaviour on a
  1.2777 +     *         <tt>null</tt> argument depends on the <a
  1.2778 +     *         href="../util/Formatter.html#syntax">conversion</a>.
  1.2779 +     *
  1.2780 +     * @throws  IllegalFormatException
  1.2781 +     *          If a format string contains an illegal syntax, a format
  1.2782 +     *          specifier that is incompatible with the given arguments,
  1.2783 +     *          insufficient arguments given the format string, or other
  1.2784 +     *          illegal conditions.  For specification of all possible
  1.2785 +     *          formatting errors, see the <a
  1.2786 +     *          href="../util/Formatter.html#detail">Details</a> section of the
  1.2787 +     *          formatter class specification.
  1.2788 +     *
  1.2789 +     * @throws  NullPointerException
  1.2790 +     *          If the <tt>format</tt> is <tt>null</tt>
  1.2791 +     *
  1.2792 +     * @return  A formatted string
  1.2793 +     *
  1.2794 +     * @see  java.util.Formatter
  1.2795 +     * @since  1.5
  1.2796 +     */
  1.2797 +    public static String format(String format, Object ... args) {
  1.2798 +        throw new UnsupportedOperationException();
  1.2799 +    }
  1.2800 +
  1.2801 +    /**
  1.2802 +     * Returns a formatted string using the specified locale, format string,
  1.2803 +     * and arguments.
  1.2804 +     *
  1.2805 +     * @param  l
  1.2806 +     *         The {@linkplain java.util.Locale locale} to apply during
  1.2807 +     *         formatting.  If <tt>l</tt> is <tt>null</tt> then no localization
  1.2808 +     *         is applied.
  1.2809 +     *
  1.2810 +     * @param  format
  1.2811 +     *         A <a href="../util/Formatter.html#syntax">format string</a>
  1.2812 +     *
  1.2813 +     * @param  args
  1.2814 +     *         Arguments referenced by the format specifiers in the format
  1.2815 +     *         string.  If there are more arguments than format specifiers, the
  1.2816 +     *         extra arguments are ignored.  The number of arguments is
  1.2817 +     *         variable and may be zero.  The maximum number of arguments is
  1.2818 +     *         limited by the maximum dimension of a Java array as defined by
  1.2819 +     *         <cite>The Java&trade; Virtual Machine Specification</cite>.
  1.2820 +     *         The behaviour on a
  1.2821 +     *         <tt>null</tt> argument depends on the <a
  1.2822 +     *         href="../util/Formatter.html#syntax">conversion</a>.
  1.2823 +     *
  1.2824 +     * @throws  IllegalFormatException
  1.2825 +     *          If a format string contains an illegal syntax, a format
  1.2826 +     *          specifier that is incompatible with the given arguments,
  1.2827 +     *          insufficient arguments given the format string, or other
  1.2828 +     *          illegal conditions.  For specification of all possible
  1.2829 +     *          formatting errors, see the <a
  1.2830 +     *          href="../util/Formatter.html#detail">Details</a> section of the
  1.2831 +     *          formatter class specification
  1.2832 +     *
  1.2833 +     * @throws  NullPointerException
  1.2834 +     *          If the <tt>format</tt> is <tt>null</tt>
  1.2835 +     *
  1.2836 +     * @return  A formatted string
  1.2837 +     *
  1.2838 +     * @see  java.util.Formatter
  1.2839 +     * @since  1.5
  1.2840 +     */
  1.2841 +//    public static String format(Locale l, String format, Object ... args) {
  1.2842 +//        return new Formatter(l).format(format, args).toString();
  1.2843 +//    }
  1.2844 +
  1.2845 +    /**
  1.2846 +     * Returns the string representation of the <code>Object</code> argument.
  1.2847 +     *
  1.2848 +     * @param   obj   an <code>Object</code>.
  1.2849 +     * @return  if the argument is <code>null</code>, then a string equal to
  1.2850 +     *          <code>"null"</code>; otherwise, the value of
  1.2851 +     *          <code>obj.toString()</code> is returned.
  1.2852 +     * @see     java.lang.Object#toString()
  1.2853 +     */
  1.2854 +    public static String valueOf(Object obj) {
  1.2855 +        return (obj == null) ? "null" : obj.toString();
  1.2856 +    }
  1.2857 +
  1.2858 +    /**
  1.2859 +     * Returns the string representation of the <code>char</code> array
  1.2860 +     * argument. The contents of the character array are copied; subsequent
  1.2861 +     * modification of the character array does not affect the newly
  1.2862 +     * created string.
  1.2863 +     *
  1.2864 +     * @param   data   a <code>char</code> array.
  1.2865 +     * @return  a newly allocated string representing the same sequence of
  1.2866 +     *          characters contained in the character array argument.
  1.2867 +     */
  1.2868 +    public static String valueOf(char data[]) {
  1.2869 +        return new String(data);
  1.2870 +    }
  1.2871 +
  1.2872 +    /**
  1.2873 +     * Returns the string representation of a specific subarray of the
  1.2874 +     * <code>char</code> array argument.
  1.2875 +     * <p>
  1.2876 +     * The <code>offset</code> argument is the index of the first
  1.2877 +     * character of the subarray. The <code>count</code> argument
  1.2878 +     * specifies the length of the subarray. The contents of the subarray
  1.2879 +     * are copied; subsequent modification of the character array does not
  1.2880 +     * affect the newly created string.
  1.2881 +     *
  1.2882 +     * @param   data     the character array.
  1.2883 +     * @param   offset   the initial offset into the value of the
  1.2884 +     *                  <code>String</code>.
  1.2885 +     * @param   count    the length of the value of the <code>String</code>.
  1.2886 +     * @return  a string representing the sequence of characters contained
  1.2887 +     *          in the subarray of the character array argument.
  1.2888 +     * @exception IndexOutOfBoundsException if <code>offset</code> is
  1.2889 +     *          negative, or <code>count</code> is negative, or
  1.2890 +     *          <code>offset+count</code> is larger than
  1.2891 +     *          <code>data.length</code>.
  1.2892 +     */
  1.2893 +    public static String valueOf(char data[], int offset, int count) {
  1.2894 +        return new String(data, offset, count);
  1.2895 +    }
  1.2896 +
  1.2897 +    /**
  1.2898 +     * Returns a String that represents the character sequence in the
  1.2899 +     * array specified.
  1.2900 +     *
  1.2901 +     * @param   data     the character array.
  1.2902 +     * @param   offset   initial offset of the subarray.
  1.2903 +     * @param   count    length of the subarray.
  1.2904 +     * @return  a <code>String</code> that contains the characters of the
  1.2905 +     *          specified subarray of the character array.
  1.2906 +     */
  1.2907 +    public static String copyValueOf(char data[], int offset, int count) {
  1.2908 +        // All public String constructors now copy the data.
  1.2909 +        return new String(data, offset, count);
  1.2910 +    }
  1.2911 +
  1.2912 +    /**
  1.2913 +     * Returns a String that represents the character sequence in the
  1.2914 +     * array specified.
  1.2915 +     *
  1.2916 +     * @param   data   the character array.
  1.2917 +     * @return  a <code>String</code> that contains the characters of the
  1.2918 +     *          character array.
  1.2919 +     */
  1.2920 +    public static String copyValueOf(char data[]) {
  1.2921 +        return copyValueOf(data, 0, data.length);
  1.2922 +    }
  1.2923 +
  1.2924 +    /**
  1.2925 +     * Returns the string representation of the <code>boolean</code> argument.
  1.2926 +     *
  1.2927 +     * @param   b   a <code>boolean</code>.
  1.2928 +     * @return  if the argument is <code>true</code>, a string equal to
  1.2929 +     *          <code>"true"</code> is returned; otherwise, a string equal to
  1.2930 +     *          <code>"false"</code> is returned.
  1.2931 +     */
  1.2932 +    public static String valueOf(boolean b) {
  1.2933 +        return b ? "true" : "false";
  1.2934 +    }
  1.2935 +
  1.2936 +    /**
  1.2937 +     * Returns the string representation of the <code>char</code>
  1.2938 +     * argument.
  1.2939 +     *
  1.2940 +     * @param   c   a <code>char</code>.
  1.2941 +     * @return  a string of length <code>1</code> containing
  1.2942 +     *          as its single character the argument <code>c</code>.
  1.2943 +     */
  1.2944 +    public static String valueOf(char c) {
  1.2945 +        char data[] = {c};
  1.2946 +        return new String(data, 0, 1);
  1.2947 +    }
  1.2948 +
  1.2949 +    /**
  1.2950 +     * Returns the string representation of the <code>int</code> argument.
  1.2951 +     * <p>
  1.2952 +     * The representation is exactly the one returned by the
  1.2953 +     * <code>Integer.toString</code> method of one argument.
  1.2954 +     *
  1.2955 +     * @param   i   an <code>int</code>.
  1.2956 +     * @return  a string representation of the <code>int</code> argument.
  1.2957 +     * @see     java.lang.Integer#toString(int, int)
  1.2958 +     */
  1.2959 +    public static String valueOf(int i) {
  1.2960 +        return Integer.toString(i);
  1.2961 +    }
  1.2962 +
  1.2963 +    /**
  1.2964 +     * Returns the string representation of the <code>long</code> argument.
  1.2965 +     * <p>
  1.2966 +     * The representation is exactly the one returned by the
  1.2967 +     * <code>Long.toString</code> method of one argument.
  1.2968 +     *
  1.2969 +     * @param   l   a <code>long</code>.
  1.2970 +     * @return  a string representation of the <code>long</code> argument.
  1.2971 +     * @see     java.lang.Long#toString(long)
  1.2972 +     */
  1.2973 +    public static String valueOf(long l) {
  1.2974 +        return Long.toString(l);
  1.2975 +    }
  1.2976 +
  1.2977 +    /**
  1.2978 +     * Returns the string representation of the <code>float</code> argument.
  1.2979 +     * <p>
  1.2980 +     * The representation is exactly the one returned by the
  1.2981 +     * <code>Float.toString</code> method of one argument.
  1.2982 +     *
  1.2983 +     * @param   f   a <code>float</code>.
  1.2984 +     * @return  a string representation of the <code>float</code> argument.
  1.2985 +     * @see     java.lang.Float#toString(float)
  1.2986 +     */
  1.2987 +    public static String valueOf(float f) {
  1.2988 +        return Float.toString(f);
  1.2989 +    }
  1.2990 +
  1.2991 +    /**
  1.2992 +     * Returns the string representation of the <code>double</code> argument.
  1.2993 +     * <p>
  1.2994 +     * The representation is exactly the one returned by the
  1.2995 +     * <code>Double.toString</code> method of one argument.
  1.2996 +     *
  1.2997 +     * @param   d   a <code>double</code>.
  1.2998 +     * @return  a  string representation of the <code>double</code> argument.
  1.2999 +     * @see     java.lang.Double#toString(double)
  1.3000 +     */
  1.3001 +    public static String valueOf(double d) {
  1.3002 +        return Double.toString(d);
  1.3003 +    }
  1.3004 +
  1.3005 +    /**
  1.3006 +     * Returns a canonical representation for the string object.
  1.3007 +     * <p>
  1.3008 +     * A pool of strings, initially empty, is maintained privately by the
  1.3009 +     * class <code>String</code>.
  1.3010 +     * <p>
  1.3011 +     * When the intern method is invoked, if the pool already contains a
  1.3012 +     * string equal to this <code>String</code> object as determined by
  1.3013 +     * the {@link #equals(Object)} method, then the string from the pool is
  1.3014 +     * returned. Otherwise, this <code>String</code> object is added to the
  1.3015 +     * pool and a reference to this <code>String</code> object is returned.
  1.3016 +     * <p>
  1.3017 +     * It follows that for any two strings <code>s</code> and <code>t</code>,
  1.3018 +     * <code>s.intern()&nbsp;==&nbsp;t.intern()</code> is <code>true</code>
  1.3019 +     * if and only if <code>s.equals(t)</code> is <code>true</code>.
  1.3020 +     * <p>
  1.3021 +     * All literal strings and string-valued constant expressions are
  1.3022 +     * interned. String literals are defined in section 3.10.5 of the
  1.3023 +     * <cite>The Java&trade; Language Specification</cite>.
  1.3024 +     *
  1.3025 +     * @return  a string that has the same contents as this string, but is
  1.3026 +     *          guaranteed to be from a pool of unique strings.
  1.3027 +     */
  1.3028 +    public native String intern();
  1.3029 +    
  1.3030 +    
  1.3031 +    private static <T> T checkUTF8(T data, String charsetName)
  1.3032 +        throws UnsupportedEncodingException {
  1.3033 +        if (charsetName == null) {
  1.3034 +            throw new NullPointerException("charsetName");
  1.3035 +        }
  1.3036 +        if (!charsetName.equalsIgnoreCase("UTF-8")
  1.3037 +            && !charsetName.equalsIgnoreCase("UTF8")) {
  1.3038 +            throw new UnsupportedEncodingException(charsetName);
  1.3039 +        }
  1.3040 +        return data;
  1.3041 +    }
  1.3042 +    
  1.3043 +    private static int nextChar(byte[] arr, int[] index) throws IndexOutOfBoundsException {
  1.3044 +        int c = arr[index[0]++] & 0xff;
  1.3045 +        switch (c >> 4) {
  1.3046 +            case 0:
  1.3047 +            case 1:
  1.3048 +            case 2:
  1.3049 +            case 3:
  1.3050 +            case 4:
  1.3051 +            case 5:
  1.3052 +            case 6:
  1.3053 +            case 7:
  1.3054 +                /* 0xxxxxxx*/
  1.3055 +                return c;
  1.3056 +            case 12:
  1.3057 +            case 13: {
  1.3058 +                /* 110x xxxx   10xx xxxx*/
  1.3059 +                int char2 = (int) arr[index[0]++];
  1.3060 +                if ((char2 & 0xC0) != 0x80) {
  1.3061 +                    throw new IndexOutOfBoundsException("malformed input");
  1.3062 +                }
  1.3063 +                return (((c & 0x1F) << 6) | (char2 & 0x3F));
  1.3064 +            }
  1.3065 +            case 14: {
  1.3066 +                /* 1110 xxxx  10xx xxxx  10xx xxxx */
  1.3067 +                int char2 = arr[index[0]++];
  1.3068 +                int char3 = arr[index[0]++];
  1.3069 +                if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80)) {
  1.3070 +                    throw new IndexOutOfBoundsException("malformed input");
  1.3071 +                }
  1.3072 +                return (((c & 0x0F) << 12)
  1.3073 +                    | ((char2 & 0x3F) << 6)
  1.3074 +                    | ((char3 & 0x3F) << 0));
  1.3075 +            }
  1.3076 +            default:
  1.3077 +                /* 10xx xxxx,  1111 xxxx */
  1.3078 +                throw new IndexOutOfBoundsException("malformed input");
  1.3079 +        }
  1.3080 +        
  1.3081 +    }
  1.3082 +}