From 01021fcb0c9026e81ac2c262caf5e2ec830a7025 Mon Sep 17 00:00:00 2001 From: Jesse Wilson Date: Mon, 10 Aug 2009 18:43:30 -0700 Subject: [PATCH] Update Luni to Harmony r802921. Notable changes: - replaced StringBuffer with StringBuilder in several places - fixed a problem with BufferedInputStream's newline characters (EBCDIC) - cleanup Timer's finalizer helper object - new cache for the canonical path of a file - fixed concurrency issue with ArrayList - floating point parsing now trims length for very small numbers - encoding specified "UTF-8" when converting some byte[]s to strings (JarURLConnection, Util, OSFileSystem) - Harmony now implements floor and ceil in Java. We continue to use native code. --- .../luni/src/main/java/java/io/BufferedReader.java | 38 +- .../src/main/java/java/io/DataInputStream.java | 2 +- libcore/luni/src/main/java/java/io/File.java | 11 +- .../src/main/java/java/io/PipedInputStream.java | 16 + .../src/main/java/java/io/PushbackInputStream.java | 6 +- .../src/main/java/java/io/StreamTokenizer.java | 4 +- .../main/java/java/lang/AbstractStringBuilder.java | 2 +- libcore/luni/src/main/java/java/lang/Math.java | 301 ++++++------ libcore/luni/src/main/java/java/lang/String.java | 183 ++++--- .../src/main/java/java/lang/reflect/Modifier.java | 4 +- .../luni/src/main/java/java/net/ServerSocket.java | 2 +- .../luni/src/main/java/java/net/SocketImpl.java | 2 +- .../src/main/java/java/net/SocketPermission.java | 4 +- libcore/luni/src/main/java/java/net/URI.java | 16 +- .../src/main/java/java/net/URIEncoderDecoder.java | 6 +- .../src/main/java/java/net/URLClassLoader.java | 10 +- .../luni/src/main/java/java/net/URLConnection.java | 2 +- .../luni/src/main/java/java/net/URLEncoder.java | 2 +- .../src/main/java/java/net/URLStreamHandler.java | 8 +- .../luni/src/main/java/java/util/AbstractList.java | 5 +- .../luni/src/main/java/java/util/ArrayList.java | 25 +- libcore/luni/src/main/java/java/util/BitSet.java | 2 +- libcore/luni/src/main/java/java/util/Calendar.java | 2 +- libcore/luni/src/main/java/java/util/Date.java | 2 +- libcore/luni/src/main/java/java/util/HashMap.java | 4 +- .../luni/src/main/java/java/util/Hashtable.java | 11 +- .../src/main/java/java/util/IdentityHashMap.java | 12 +- libcore/luni/src/main/java/java/util/Locale.java | 2 +- .../luni/src/main/java/java/util/Properties.java | 6 +- libcore/luni/src/main/java/java/util/TimeZone.java | 2 +- libcore/luni/src/main/java/java/util/Timer.java | 122 ++--- libcore/luni/src/main/java/java/util/Vector.java | 2 +- .../luni/internal/io/FileCanonPathCache.java | 136 ++++++ .../net/www/protocol/ftp/FtpURLConnection.java | 2 +- .../net/www/protocol/http/HttpURLConnection.java | 2 +- .../internal/net/www/protocol/jar/Handler.java | 2 +- .../net/www/protocol/jar/JarURLConnection.java | 6 +- .../harmony/luni/platform/IMemorySystem.java | 57 ++- .../apache/harmony/luni/platform/OSFileSystem.java | 10 +- .../harmony/luni/platform/OSNetworkSystem.java | 4 +- .../harmony/luni/util/ExternalMessages.properties | 1 + .../harmony/luni/util/FloatingPointParser.java | 527 +++++++++++---------- .../java/org/apache/harmony/luni/util/Util.java | 438 +++++++++-------- libcore/luni/src/main/native/cbigint.c | 6 +- .../harmony/luni/tests/java/io/AllTests.java | 1 + .../luni/tests/java/io/FileCanonPathCacheTest.java | 120 +++++ 46 files changed, 1273 insertions(+), 855 deletions(-) create mode 100644 libcore/luni/src/main/java/org/apache/harmony/luni/internal/io/FileCanonPathCache.java create mode 100644 libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/io/FileCanonPathCacheTest.java diff --git a/libcore/luni/src/main/java/java/io/BufferedReader.java b/libcore/luni/src/main/java/java/io/BufferedReader.java index 875840c35..77f19757e 100644 --- a/libcore/luni/src/main/java/java/io/BufferedReader.java +++ b/libcore/luni/src/main/java/java/io/BufferedReader.java @@ -30,13 +30,13 @@ import java.util.logging.Logger; * some extra space is required to hold the buffer and that copying takes place * when filling that buffer, but this is usually outweighed by the performance * benefits. - * + * *

A typical application pattern for the class looks like this:

* *

  * BufferedReader buf = new BufferedReader(new FileReader("file.java"));
  * 
- * + * * @see BufferedWriter * @since 1.1 */ @@ -57,7 +57,7 @@ public class BufferedReader extends Reader { /** * Constructs a new BufferedReader on the Reader {@code in}. The * buffer gets the default size (8 KB). - * + * * @param in * the Reader that is buffered. */ @@ -85,7 +85,7 @@ public class BufferedReader extends Reader { /** * Constructs a new BufferedReader on the Reader {@code in}. The buffer * size is specified by the parameter {@code size}. - * + * * @param in * the Reader that is buffered. * @param size @@ -106,7 +106,7 @@ public class BufferedReader extends Reader { * Closes this reader. This implementation closes the buffered source reader * and releases the buffer. Nothing is done if this reader has already been * closed. - * + * * @throws IOException * if an error occurs while closing this reader. */ @@ -154,7 +154,7 @@ public class BufferedReader extends Reader { /** * Indicates whether or not this reader is closed. - * + * * @return {@code true} if this reader is closed, {@code false} * otherwise. */ @@ -167,7 +167,7 @@ public class BufferedReader extends Reader { * indicates how many characters can be read before the mark is invalidated. * Calling {@code reset()} will reposition the reader back to the marked * position if {@code readlimit} has not been surpassed. - * + * * @param readlimit * the number of characters that can be read before the mark is * invalidated. @@ -195,7 +195,7 @@ public class BufferedReader extends Reader { /** * Indicates whether this reader supports the {@code mark()} and * {@code reset()} methods. This implementation returns {@code true}. - * + * * @return {@code true} for {@code BufferedReader}. * @see #mark(int) * @see #reset() @@ -240,7 +240,7 @@ public class BufferedReader extends Reader { * has not been set and the requested number of characters is larger than * this readers buffer size, BufferedReader bypasses the buffer and simply * places the results directly into {@code buffer}. - * + * * @param buffer * the character array to store the characters read. * @param offset @@ -329,9 +329,8 @@ public class BufferedReader extends Reader { * Returns the next line of text available from this reader. A line is * represented by zero or more characters followed by {@code '\n'}, * {@code '\r'}, {@code "\r\n"} or the end of the reader. The string does - * not include the newline sequence. In EBCDIC systems, a new line can also - * be represented by the {@code \u0085} (NEL) character. - * + * not include the newline sequence. + * * @return the contents of the line or {@code null} if no characters were * read before the end of the reader has been reached. * @throws IOException @@ -351,7 +350,7 @@ public class BufferedReader extends Reader { // BEGIN android-note // a switch statement may be more efficient // END android-note - if ((ch > '\r') && (ch != '\u0085')) { + if (ch > '\r') { continue; } if (ch == '\n') { @@ -366,11 +365,6 @@ public class BufferedReader extends Reader { pos++; } return res; - } else if (ch == '\u0085') { - /* Also handle the EBCDIC NEL character */ - String res = new String(buf, pos, charPos - pos); - pos = charPos + 1; - return res; } } @@ -398,7 +392,7 @@ public class BufferedReader extends Reader { // use a local variable for buf[charPos] and a switch statement // END android-note if (eol == '\0') { - if ((buf[charPos] == '\n' || buf[charPos] == '\r') || (buf[charPos] == '\u0085')) { + if ((buf[charPos] == '\n' || buf[charPos] == '\r')) { eol = buf[charPos]; } } else if (eol == '\r' && (buf[charPos] == '\n')) { @@ -407,7 +401,7 @@ public class BufferedReader extends Reader { } pos = charPos + 1; return result.toString(); - } else if (eol != '\0') { + } else { if (charPos > pos) { result.append(buf, pos, charPos - pos - 1); } @@ -451,7 +445,7 @@ public class BufferedReader extends Reader { * Resets this reader's position to the last {@code mark()} location. * Invocations of {@code read()} and {@code skip()} will occur from this new * location. - * + * * @throws IOException * if this reader is closed or no mark has been set. * @see #mark(int) @@ -475,7 +469,7 @@ public class BufferedReader extends Reader { * {@code read()}s will not return these characters unless {@code reset()} * is used. Skipping characters may invalidate a mark if {@code readlimit} * is surpassed. - * + * * @param amount * the maximum number of characters to skip. * @return the number of characters actually skipped. diff --git a/libcore/luni/src/main/java/java/io/DataInputStream.java b/libcore/luni/src/main/java/java/io/DataInputStream.java index 42e38a293..cb219863e 100644 --- a/libcore/luni/src/main/java/java/io/DataInputStream.java +++ b/libcore/luni/src/main/java/java/io/DataInputStream.java @@ -303,7 +303,7 @@ public class DataInputStream extends FilterInputStream implements DataInput { */ @Deprecated public final String readLine() throws IOException { - StringBuffer line = new StringBuffer(80); // Typical line length + StringBuilder line = new StringBuilder(80); // Typical line length boolean foundTerminator = false; while (true) { int nextByte = in.read(); diff --git a/libcore/luni/src/main/java/java/io/File.java b/libcore/luni/src/main/java/java/io/File.java index e34ab18fb..c802995f7 100644 --- a/libcore/luni/src/main/java/java/io/File.java +++ b/libcore/luni/src/main/java/java/io/File.java @@ -25,6 +25,7 @@ import java.security.SecureRandom; import java.util.ArrayList; import java.util.List; +import org.apache.harmony.luni.internal.io.FileCanonPathCache; import org.apache.harmony.luni.util.DeleteOnExit; import org.apache.harmony.luni.util.Msg; import org.apache.harmony.luni.util.PriviAction; @@ -495,6 +496,12 @@ public class File implements Serializable, Comparable { */ public String getCanonicalPath() throws IOException { byte[] result = properPath(false); + String absPath = Util.toUTF8String(result); + String canonPath = FileCanonPathCache.get(absPath); + + if (canonPath != null) { + return canonPath; + } if(separatorChar == '/') { // resolve the full path first result = resolveLink(result, result.length, false); @@ -566,7 +573,9 @@ public class File implements Serializable, Comparable { newResult[newLength] = 0; newResult = getCanonImpl(newResult); newLength = newResult.length; - return Util.toUTF8String(newResult, 0, newLength); + canonPath = Util.toUTF8String(newResult, 0, newLength); + FileCanonPathCache.put(absPath, canonPath); + return canonPath; } /* diff --git a/libcore/luni/src/main/java/java/io/PipedInputStream.java b/libcore/luni/src/main/java/java/io/PipedInputStream.java index d06143d7f..83987ecd9 100644 --- a/libcore/luni/src/main/java/java/io/PipedInputStream.java +++ b/libcore/luni/src/main/java/java/io/PipedInputStream.java @@ -150,11 +150,18 @@ public class PipedInputStream extends InputStream { @Override public synchronized int read() throws IOException { if (!isConnected) { + // K0074=Not connected throw new IOException(Msg.getString("K0074")); //$NON-NLS-1$ } if (buffer == null) { + // K0075=InputStream is closed throw new IOException(Msg.getString("K0075")); //$NON-NLS-1$ } + + if (lastWriter != null && !lastWriter.isAlive() && (in < 0)) { + // KA030=Write end dead + throw new IOException(Msg.getString("KA030")); //$NON-NLS-1$ + } /** * Set the last thread to be reading on this PipedInputStream. If * lastReader dies while someone is waiting to write an IOException of @@ -169,6 +176,7 @@ public class PipedInputStream extends InputStream { return -1; } if ((attempts-- <= 0) && lastWriter != null && !lastWriter.isAlive()) { + // K0076=Pipe broken throw new IOException(Msg.getString("K0076")); //$NON-NLS-1$ } // Notify callers of receive() @@ -244,13 +252,20 @@ public class PipedInputStream extends InputStream { } if (!isConnected) { + // K0074=Not connected throw new IOException(Msg.getString("K0074")); //$NON-NLS-1$ } if (buffer == null) { + // K0075=InputStream is closed throw new IOException(Msg.getString("K0075")); //$NON-NLS-1$ } + if (lastWriter != null && !lastWriter.isAlive() && (in < 0)) { + // KA030=Write end dead + throw new IOException(Msg.getString("KA030")); //$NON-NLS-1$ + } + /** * Set the last thread to be reading on this PipedInputStream. If * lastReader dies while someone is waiting to write an IOException of @@ -265,6 +280,7 @@ public class PipedInputStream extends InputStream { return -1; } if ((attempts-- <= 0) && lastWriter != null && !lastWriter.isAlive()) { + // K0076=Pipe broken throw new IOException(Msg.getString("K0076")); //$NON-NLS-1$ } // Notify callers of receive() diff --git a/libcore/luni/src/main/java/java/io/PushbackInputStream.java b/libcore/luni/src/main/java/java/io/PushbackInputStream.java index 178401204..4600fa257 100644 --- a/libcore/luni/src/main/java/java/io/PushbackInputStream.java +++ b/libcore/luni/src/main/java/java/io/PushbackInputStream.java @@ -314,9 +314,11 @@ public class PushbackInputStream extends FilterInputStream { } // END android-changed - for (int i = offset + length - 1; i >= offset; i--) { - unread(buffer[i]); + if (buf == null) { + throw new IOException(); } + System.arraycopy(buffer, offset, buf, pos - length, length); + pos = pos - length; } /** diff --git a/libcore/luni/src/main/java/java/io/StreamTokenizer.java b/libcore/luni/src/main/java/java/io/StreamTokenizer.java index d39e5a858..c87a0537d 100644 --- a/libcore/luni/src/main/java/java/io/StreamTokenizer.java +++ b/libcore/luni/src/main/java/java/io/StreamTokenizer.java @@ -336,7 +336,7 @@ public class StreamTokenizer { } // Check for words if ((currentType & TOKEN_WORD) != 0) { - StringBuffer word = new StringBuffer(20); + StringBuilder word = new StringBuilder(20); while (true) { word.append((char) currentChar); currentChar = read(); @@ -353,7 +353,7 @@ public class StreamTokenizer { // Check for quoted character if (currentType == TOKEN_QUOTE) { int matchQuote = currentChar; - StringBuffer quoteString = new StringBuffer(); + StringBuilder quoteString = new StringBuilder(); int peekOne = read(); while (peekOne >= 0 && peekOne != matchQuote && peekOne != '\r' && peekOne != '\n') { diff --git a/libcore/luni/src/main/java/java/lang/AbstractStringBuilder.java b/libcore/luni/src/main/java/java/lang/AbstractStringBuilder.java index 06f8c5014..c481e118d 100644 --- a/libcore/luni/src/main/java/java/lang/AbstractStringBuilder.java +++ b/libcore/luni/src/main/java/java/lang/AbstractStringBuilder.java @@ -231,7 +231,7 @@ abstract class AbstractStringBuilder { } if (end > start) { int length = count - end; - if (length > 0) { + if (length >= 0) { if (!shared) { System.arraycopy(value, end, value, start, length); } else { diff --git a/libcore/luni/src/main/java/java/lang/Math.java b/libcore/luni/src/main/java/java/lang/Math.java index 998856a41..d06e6e4e8 100644 --- a/libcore/luni/src/main/java/java/lang/Math.java +++ b/libcore/luni/src/main/java/java/lang/Math.java @@ -17,7 +17,6 @@ package java.lang; - /** * Class Math provides basic math constants and operations such as trigonometric * functions, hyperbolic functions, exponential, logarithms, etc. @@ -53,16 +52,16 @@ public final class Math { *
  • {@code abs(-infinity) = +infinity}
  • *
  • {@code abs(NaN) = NaN}
  • * - * + * * @param d * the value whose absolute value has to be computed. * @return the absolute value of the argument. */ - public static double abs(double d) { - long bits = Double.doubleToLongBits(d); - bits &= 0x7fffffffffffffffL; - return Double.longBitsToDouble(bits); - } + public static double abs(double d) { + long bits = Double.doubleToLongBits(d); + bits &= 0x7fffffffffffffffL; + return Double.longBitsToDouble(bits); + } /** * Returns the absolute value of the argument. @@ -74,45 +73,45 @@ public final class Math { *
  • {@code abs(-infinity) = +infinity}
  • *
  • {@code abs(NaN) = NaN}
  • * - * + * * @param f * the value whose absolute value has to be computed. * @return the argument if it is positive, otherwise the negation of the * argument. */ - public static float abs(float f) { - int bits = Float.floatToIntBits(f); - bits &= 0x7fffffff; - return Float.intBitsToFloat(bits); - } + public static float abs(float f) { + int bits = Float.floatToIntBits(f); + bits &= 0x7fffffff; + return Float.intBitsToFloat(bits); + } /** * Returns the absolute value of the argument. *

    * If the argument is {@code Integer.MIN_VALUE}, {@code Integer.MIN_VALUE} * is returned. - * + * * @param i * the value whose absolute value has to be computed. * @return the argument if it is positive, otherwise the negation of the * argument. */ - public static int abs(int i) { - return i >= 0 ? i : -i; - } + public static int abs(int i) { + return i >= 0 ? i : -i; + } /** * Returns the absolute value of the argument. If the argument is {@code * Long.MIN_VALUE}, {@code Long.MIN_VALUE} is returned. - * + * * @param l * the value whose absolute value has to be computed. * @return the argument if it is positive, otherwise the negation of the * argument. */ - public static long abs(long l) { - return l >= 0 ? l : -l; - } + public static long abs(long l) { + return l >= 0 ? l : -l; + } /** * Returns the closest double approximation of the arc cosine of the @@ -125,12 +124,12 @@ public final class Math { *

  • {@code acos((anything < -1) = NaN}
  • *
  • {@code acos(NaN) = NaN}
  • * - * + * * @param d * the value to compute arc cosine of. * @return the arc cosine of the argument. */ - public static native double acos(double d); + public static native double acos(double d); /** * Returns the closest double approximation of the arc sine of the argument @@ -143,12 +142,12 @@ public final class Math { *
  • {@code asin((anything < -1)) = NaN}
  • *
  • {@code asin(NaN) = NaN}
  • * - * + * * @param d * the value whose arc sine has to be computed. * @return the arc sine of the argument. */ - public static native double asin(double d); + public static native double asin(double d); /** * Returns the closest double approximation of the arc tangent of the @@ -163,7 +162,7 @@ public final class Math { *
  • {@code atan(-infinity) = -pi/2}
  • *
  • {@code atan(NaN) = NaN}
  • * - * + * * @param d * the value whose arc tangent has to be computed. * @return the arc tangent of the argument. @@ -171,10 +170,10 @@ public final class Math { public static native double atan(double d); /** - * Returns the closest double approximation of the arc tangent of - * {@code y/x} within the range {@code [-pi..pi]}. This is the angle of the - * polar representation of the rectangular coordinates (x,y). The returned - * result is within 2 ulps (units in the last place) of the real result. + * Returns the closest double approximation of the arc tangent of {@code + * y/x} within the range {@code [-pi..pi]}. This is the angle of the polar + * representation of the rectangular coordinates (x,y). The returned result + * is within 2 ulps (units in the last place) of the real result. *

    * Special cases: *

      @@ -196,12 +195,12 @@ public final class Math { *
    • {@code atan2(-infinity, +infinity ) = -pi/4}
    • *
    • {@code atan2(+infinity, -infinity ) = +3pi/4}
    • *
    • {@code atan2(-infinity, -infinity ) = -3pi/4}
    • - *
    • {@code atan2(+infinity, (anything but,0, NaN, and infinity))} - * {@code =} {@code +pi/2}
    • - *
    • {@code atan2(-infinity, (anything but,0, NaN, and infinity))} - * {@code =} {@code -pi/2}
    • + *
    • {@code atan2(+infinity, (anything but,0, NaN, and infinity))} {@code + * =} {@code +pi/2}
    • + *
    • {@code atan2(-infinity, (anything but,0, NaN, and infinity))} {@code + * =} {@code -pi/2}
    • *
    - * + * * @param y * the numerator of the value whose atan has to be computed. * @param x @@ -222,7 +221,7 @@ public final class Math { *
  • {@code cbrt(-infinity) = -infinity}
  • *
  • {@code cbrt(NaN) = NaN}
  • * - * + * * @param d * the value whose cube root has to be computed. * @return the cube root of the argument. @@ -230,8 +229,8 @@ public final class Math { public static native double cbrt(double d); /** - * Returns the double conversion of the most negative (closest to - * negative infinity) integer value which is greater than the argument. + * Returns the double conversion of the most negative (closest to negative + * infinity) integer value which is greater than the argument. *

    * Special cases: *

      @@ -242,14 +241,16 @@ public final class Math { *
    • {@code ceil(-infinity) = -infinity}
    • *
    • {@code ceil(NaN) = NaN}
    • *
    - * + * * @param d * the value whose closest integer value has to be computed. * @return the ceiling of the argument. */ + // BEGIN android-changed public static native double ceil(double d); + // END android-changed - /** + /** * Returns the closest double approximation of the cosine of the argument. * The returned result is within 1 ulp (unit in the last place) of the real * result. @@ -260,7 +261,7 @@ public final class Math { *
  • {@code cos(-infinity) = NaN}
  • *
  • {@code cos(NaN) = NaN}
  • * - * + * * @param d * the angle whose cosine has to be computed, in radians. * @return the cosine of the argument. @@ -278,7 +279,7 @@ public final class Math { *
  • {@code cosh(-infinity) = +infinity}
  • *
  • {@code cosh(NaN) = NaN}
  • * - * + * * @param d * the value whose hyperbolic cosine has to be computed. * @return the hyperbolic cosine of the argument. @@ -296,7 +297,7 @@ public final class Math { *
  • {@code exp(-infinity) = +0.0}
  • *
  • {@code exp(NaN) = NaN}
  • * - * + * * @param d * the value whose exponential has to be computed. * @return the exponential of the argument. @@ -304,9 +305,9 @@ public final class Math { public static native double exp(double d); /** - * Returns the closest double approximation of {@code e} - * {@code d}{@code - 1}. If the argument is very close to 0, it is - * much more accurate to use {@code expm1(d)+1} than {@code exp(d)} (due to + * Returns the closest double approximation of {@code e} {@code + * d}{@code - 1}. If the argument is very close to 0, it is much more + * accurate to use {@code expm1(d)+1} than {@code exp(d)} (due to * cancellation of significant digits). The returned result is within 1 ulp * (unit in the last place) of the real result. *

    @@ -321,12 +322,12 @@ public final class Math { *

  • {@code expm1(-infinity) = -1.0}
  • *
  • {@code expm1(NaN) = NaN}
  • * - * + * * @param d - * the value to compute the {@code e}{@code d} - * {@code - 1} of. - * @return the {@code e}{@code d}{@code - 1} value - * of the argument. + * the value to compute the {@code e}{@code d} + * {@code - 1} of. + * @return the {@code e}{@code d}{@code - 1} value of the + * argument. */ public static native double expm1(double d); @@ -342,19 +343,21 @@ public final class Math { *
  • {@code floor(-infinity) = -infinity}
  • *
  • {@code floor(NaN) = NaN}
  • * - * + * * @param d * the value whose closest integer value has to be computed. * @return the floor of the argument. */ + // BEGIN android-changed public static native double floor(double d); + // END android-changed /** - * Returns {@code sqrt(}{@code x}{@code 2}{@code +} - * {@code y}{@code 2}{@code )}. The final result is - * without medium underflow or overflow. The returned result is within 1 ulp - * (unit in the last place) of the real result. If one parameter remains - * constant, the result should be semi-monotonic. + * Returns {@code sqrt(}{@code x}{@code 2}{@code +} + * {@code y}{@code 2}{@code )}. The final result is without + * medium underflow or overflow. The returned result is within 1 ulp (unit + * in the last place) of the real result. If one parameter remains constant, + * the result should be semi-monotonic. *

    * Special cases: *

      @@ -364,7 +367,7 @@ public final class Math { *
    • {@code hypot((anything including NaN), -infinity) = +infinity}
    • *
    • {@code hypot(NaN, NaN) = NaN}
    • *
    - * + * * @param x * a double number. * @param y @@ -393,7 +396,7 @@ public final class Math { *
  • {@code IEEEremainder(x, -infinity) = x } where x is anything but * +/-infinity
  • * - * + * * @param x * the numerator of the operation. * @param y @@ -416,7 +419,7 @@ public final class Math { *
  • {@code log(-infinity) = NaN}
  • *
  • {@code log(NaN) = NaN}
  • * - * + * * @param d * the value whose log has to be computed. * @return the natural logarithm of the argument. @@ -437,7 +440,7 @@ public final class Math { *
  • {@code log10(-infinity) = NaN}
  • *
  • {@code log10(NaN) = NaN}
  • * - * + * * @param d * the value whose base 10 log has to be computed. * @return the natural logarithm of the argument. @@ -461,7 +464,7 @@ public final class Math { *
  • {@code log1p(-infinity) = NaN}
  • *
  • {@code log1p(NaN) = NaN}
  • * - * + * * @param d * the value to compute the {@code ln(1+d)} of. * @return the natural logarithm of the sum of the argument and 1. @@ -479,16 +482,14 @@ public final class Math { *
  • {@code max(+0.0, -0.0) = +0.0}
  • *
  • {@code max(-0.0, +0.0) = +0.0}
  • * - * + * * @param d1 * the first argument. * @param d2 * the second argument. * @return the larger of {@code d1} and {@code d2}. */ - public static double max(double d1, double d2) { - // BEGIN android-changed - // copied from a newer version of Harmony + public static double max(double d1, double d2) { if (d1 > d2) { return d1; } @@ -505,8 +506,7 @@ public final class Math { return d2; } return 0.0d; - // END android-changed - } + } /** * Returns the most positive (closest to positive infinity) of the two @@ -519,16 +519,14 @@ public final class Math { *
  • {@code max(+0.0, -0.0) = +0.0}
  • *
  • {@code max(-0.0, +0.0) = +0.0}
  • * - * + * * @param f1 * the first argument. * @param f2 * the second argument. * @return the larger of {@code f1} and {@code f2}. */ - public static float max(float f1, float f2) { - // BEGIN android-changed - // copied from a newer version of Harmony + public static float max(float f1, float f2) { if (f1 > f2) { return f1; } @@ -545,36 +543,35 @@ public final class Math { return f2; } return 0.0f; - // END android-changed - } + } /** * Returns the most positive (closest to positive infinity) of the two * arguments. - * + * * @param i1 * the first argument. * @param i2 * the second argument. * @return the larger of {@code i1} and {@code i2}. */ - public static int max(int i1, int i2) { - return i1 > i2 ? i1 : i2; - } + public static int max(int i1, int i2) { + return i1 > i2 ? i1 : i2; + } /** * Returns the most positive (closest to positive infinity) of the two * arguments. - * + * * @param l1 * the first argument. * @param l2 * the second argument. * @return the larger of {@code l1} and {@code l2}. */ - public static long max(long l1, long l2) { - return l1 > l2 ? l1 : l2; - } + public static long max(long l1, long l2) { + return l1 > l2 ? l1 : l2; + } /** * Returns the most negative (closest to negative infinity) of the two @@ -587,16 +584,14 @@ public final class Math { *
  • {@code min(+0.0, -0.0) = -0.0}
  • *
  • {@code min(-0.0, +0.0) = -0.0}
  • * - * + * * @param d1 * the first argument. * @param d2 * the second argument. * @return the smaller of {@code d1} and {@code d2}. */ - public static double min(double d1, double d2) { - // BEGIN android-changed - // copied from a newer version of Harmony + public static double min(double d1, double d2) { if (d1 > d2) { return d2; } @@ -613,8 +608,7 @@ public final class Math { return -0.0d; } return d2; - // END android-changed - } + } /** * Returns the most negative (closest to negative infinity) of the two @@ -627,16 +621,14 @@ public final class Math { *
  • {@code min(+0.0, -0.0) = -0.0}
  • *
  • {@code min(-0.0, +0.0) = -0.0}
  • * - * + * * @param f1 * the first argument. * @param f2 * the second argument. * @return the smaller of {@code f1} and {@code f2}. */ - public static float min(float f1, float f2) { - // BEGIN android-changed - // copied from a newer version of Harmony + public static float min(float f1, float f2) { if (f1 > f2) { return f2; } @@ -653,40 +645,39 @@ public final class Math { return -0.0f; } return f2; - // END android-changed - } + } /** * Returns the most negative (closest to negative infinity) of the two * arguments. - * + * * @param i1 * the first argument. * @param i2 * the second argument. * @return the smaller of {@code i1} and {@code i2}. */ - public static int min(int i1, int i2) { - return i1 < i2 ? i1 : i2; - } + public static int min(int i1, int i2) { + return i1 < i2 ? i1 : i2; + } /** * Returns the most negative (closest to negative infinity) of the two * arguments. - * + * * @param l1 * the first argument. * @param l2 * the second argument. * @return the smaller of {@code l1} and {@code l2}. */ - public static long min(long l1, long l2) { - return l1 < l2 ? l1 : l2; - } + public static long min(long l1, long l2) { + return l1 < l2 ? l1 : l2; + } /** - * Returns the closest double approximation of the result of raising - * {@code x} to the power of {@code y}. + * Returns the closest double approximation of the result of raising {@code + * x} to the power of {@code y}. *

    * Special cases: *

      @@ -710,11 +701,11 @@ public final class Math { *
    • {@code pow(+infinity, (+anything except 0, NaN)) = +infinity}
    • *
    • {@code pow(+infinity, (-anything except 0, NaN)) = +0.0}
    • *
    • {@code pow(-infinity, (anything)) = -pow(0, (-anything))}
    • - *
    • {@code pow((-anything), (integer))} {@code =} - * {@code pow(-1,(integer))*pow(+anything,integer) }
    • + *
    • {@code pow((-anything), (integer))} {@code =} {@code + * pow(-1,(integer))*pow(+anything,integer) }
    • *
    • {@code pow((-anything except 0 and inf), (non-integer)) = NAN}
    • *
    - * + * * @param x * the base of the operation. * @param y @@ -735,14 +726,16 @@ public final class Math { *
  • {@code rint(-infinity) = -infinity}
  • *
  • {@code rint(NaN) = NaN}
  • * - * + * * @param d * the value to be rounded. * @return the closest integer to the argument (as a double). */ + // BEGIN android-changed public static native double rint(double d); + // END android-changed - /** + /** * Returns the result of rounding the argument to an integer. The result is * equivalent to {@code (long) Math.floor(d+0.5)}. *

    @@ -756,17 +749,18 @@ public final class Math { *

  • {@code round(-infintiy) = Long.MIN_VALUE}
  • *
  • {@code round(NaN) = +0.0}
  • * - * + * * @param d * the value to be rounded. * @return the closest integer to the argument. */ - public static long round(double d) { - // check for NaN - if (d != d) - return 0L; - return (long) floor(d + 0.5d); - } + public static long round(double d) { + // check for NaN + if (d != d) { + return 0L; + } + return (long) floor(d + 0.5d); + } /** * Returns the result of rounding the argument to an integer. The result is @@ -782,17 +776,18 @@ public final class Math { *
  • {@code round(-infintiy) = Integer.MIN_VALUE}
  • *
  • {@code round(NaN) = +0.0}
  • * - * + * * @param f * the value to be rounded. * @return the closest integer to the argument. */ - public static int round(float f) { - // check for NaN - if (f != f) - return 0; - return (int) floor(f + 0.5f); - } + public static int round(float f) { + // check for NaN + if (f != f) { + return 0; + } + return (int) floor(f + 0.5f); + } /** * Returns the signum function of the argument. If the argument is less than @@ -808,7 +803,7 @@ public final class Math { *
  • {@code signum(-infinity) = -1.0}
  • *
  • {@code signum(NaN) = NaN}
  • * - * + * * @param d * the value whose signum has to be computed. * @return the value of the signum function. @@ -831,7 +826,7 @@ public final class Math { *
  • {@code signum(-infinity) = -1.0}
  • *
  • {@code signum(NaN) = NaN}
  • * - * + * * @param f * the value whose signum has to be computed. * @return the value of the signum function. @@ -853,7 +848,7 @@ public final class Math { *
  • {@code sin(-infinity) = NaN}
  • *
  • {@code sin(NaN) = NaN}
  • * - * + * * @param d * the angle whose sin has to be computed, in radians. * @return the sine of the argument. @@ -873,7 +868,7 @@ public final class Math { *
  • {@code sinh(-infinity) = -infinity}
  • *
  • {@code sinh(NaN) = NaN}
  • * - * + * * @param d * the value whose hyperbolic sine has to be computed. * @return the hyperbolic sine of the argument. @@ -892,7 +887,7 @@ public final class Math { *
  • {@code sqrt(+infinity) = +infinity}
  • *
  • {@code sqrt(NaN) = NaN}
  • * - * + * * @param d * the value whose square root has to be computed. * @return the square root of the argument. @@ -912,7 +907,7 @@ public final class Math { *
  • {@code tan(-infinity) = NaN}
  • *
  • {@code tan(NaN) = NaN}
  • * - * + * * @param d * the angle whose tangens has to be computed, in radians. * @return the tangent of the argument. @@ -934,7 +929,7 @@ public final class Math { *
  • {@code tanh(-infinity) = -1.0}
  • *
  • {@code tanh(NaN) = NaN}
  • * - * + * * @param d * the value whose hyperbolic tangent has to be computed. * @return the hyperbolic tangent of the argument. @@ -944,15 +939,15 @@ public final class Math { /** * Returns a pseudo-random number between 0.0 (inclusive) and 1.0 * (exclusive). - * + * * @return a pseudo-random number. */ - public static double random() { - if (random == null) { - random = new java.util.Random(); - } - return random.nextDouble(); - } + public static double random() { + if (random == null) { + random = new java.util.Random(); + } + return random.nextDouble(); + } /** * Returns the measure in radians of the supplied degree angle. The result @@ -966,14 +961,14 @@ public final class Math { *
  • {@code toRadians(-infinity) = -infinity}
  • *
  • {@code toRadians(NaN) = NaN}
  • * - * + * * @param angdeg * an angle in degrees. * @return the radian measure of the angle. */ - public static double toRadians(double angdeg) { - return angdeg / 180d * PI; - } + public static double toRadians(double angdeg) { + return angdeg / 180d * PI; + } /** * Returns the measure in degrees of the supplied radian angle. The result @@ -987,20 +982,20 @@ public final class Math { *
  • {@code toDegrees(-infinity) = -infinity}
  • *
  • {@code toDegrees(NaN) = NaN}
  • * - * + * * @param angrad * an angle in radians. * @return the degree measure of the angle. */ - public static double toDegrees(double angrad) { - return angrad * 180d / PI; - } + public static double toDegrees(double angrad) { + return angrad * 180d / PI; + } - /** + /** * Returns the argument's ulp (unit in the last place). The size of a ulp of * a double value is the positive distance between this value and the double - * value next larger in magnitude. For non-NaN {@code x}, - * {@code ulp(-x) == ulp(x)}. + * value next larger in magnitude. For non-NaN {@code x}, {@code ulp(-x) == + * ulp(x)}. *

    * Special cases: *

      @@ -1010,7 +1005,7 @@ public final class Math { *
    • {@code ulp(-infintiy) = infinity}
    • *
    • {@code ulp(NaN) = NaN}
    • *
    - * + * * @param d * the floating-point value to compute ulp of. * @return the size of a ulp of the argument. @@ -1029,8 +1024,8 @@ public final class Math { /** * Returns the argument's ulp (unit in the last place). The size of a ulp of * a float value is the positive distance between this value and the float - * value next larger in magnitude. For non-NaN {@code x}, - * {@code ulp(-x) == ulp(x)}. + * value next larger in magnitude. For non-NaN {@code x}, {@code ulp(-x) == + * ulp(x)}. *

    * Special cases: *

      @@ -1040,7 +1035,7 @@ public final class Math { *
    • {@code ulp(-infintiy) = infinity}
    • *
    • {@code ulp(NaN) = NaN}
    • *
    - * + * * @param f * the floating-point value to compute ulp of. * @return the size of a ulp of the argument. @@ -1060,5 +1055,5 @@ public final class Math { private native static double nextafter(double x, double y); - private native static float nextafterf(float x, float y); + private native static float nextafterf(float x, float y); } diff --git a/libcore/luni/src/main/java/java/lang/String.java b/libcore/luni/src/main/java/java/lang/String.java index 22f72cb9b..6d533571d 100644 --- a/libcore/luni/src/main/java/java/lang/String.java +++ b/libcore/luni/src/main/java/java/lang/String.java @@ -77,7 +77,7 @@ public final class String implements Serializable, Comparable, /** * Create a ConsolePrintStream on the specified OutputStream, usually * System.out. - * + * * @param out * the console OutputStream */ @@ -168,6 +168,9 @@ public final class String implements Serializable, Comparable, count = 0; } + /* + * Private constructor used for JIT optimization. + */ @SuppressWarnings("unused") private String(String s, char c) { offset = 0; @@ -182,7 +185,7 @@ public final class String implements Serializable, Comparable, * specified by the file.encoding system property. If the system property is * not defined, the default encoding is ISO8859_1 (ISO-Latin-1). If 8859-1 * is not available, an ASCII encoding is used. - * + * * @param data * the byte array to convert to a string. */ @@ -193,7 +196,7 @@ public final class String implements Serializable, Comparable, /** * Converts the byte array to a string, setting the high byte of every * character to the specified value. - * + * * @param data * the byte array to convert to a string. * @param high @@ -213,7 +216,7 @@ public final class String implements Serializable, Comparable, * specified by the file.encoding system property. If the system property is * not defined, the default encoding is ISO8859_1 (ISO-Latin-1). If 8859-1 * is not available, an ASCII encoding is used. - * + * * @param data * the byte array to convert to a string. * @param start @@ -288,7 +291,7 @@ public final class String implements Serializable, Comparable, /** * Converts the byte array to a string using the specified encoding. - * + * * @param data * the byte array to convert to a string. * @param start @@ -457,7 +460,7 @@ public final class String implements Serializable, Comparable, /** * Converts the byte array to a string using the specified encoding. - * + * * @param data * the byte array to convert to a string. * @param encoding @@ -475,7 +478,7 @@ public final class String implements Serializable, Comparable, * Initializes this string to contain the characters in the specified * character array. Modifying the character array after creating the string * has no effect on the string. - * + * * @param data * the array of characters. * @throws NullPointerException @@ -489,7 +492,7 @@ public final class String implements Serializable, Comparable, * Initializes this string to contain the specified characters in the * character array. Modifying the character array after creating the string * has no effect on the string. - * + * * @param data * the array of characters. * @param start @@ -527,7 +530,7 @@ public final class String implements Serializable, Comparable, /** * Creates a {@code String} that is a copy of the specified string. - * + * * @param string * the string to copy. */ @@ -537,10 +540,51 @@ public final class String implements Serializable, Comparable, count = string.count; } + /* + * Private constructor useful for JIT optimization. + */ + @SuppressWarnings( { "unused", "nls" }) + private String(String s1, String s2) { + if (s1 == null) { + s1 = "null"; + } + if (s2 == null) { + s2 = "null"; + } + count = s1.count + s2.count; + value = new char[count]; + offset = 0; + System.arraycopy(s1.value, s1.offset, value, 0, s1.count); + System.arraycopy(s2.value, s2.offset, value, s1.count, s2.count); + } + + /* + * Private constructor useful for JIT optimization. + */ + @SuppressWarnings( { "unused", "nls" }) + private String(String s1, String s2, String s3) { + if (s1 == null) { + s1 = "null"; + } + if (s2 == null) { + s2 = "null"; + } + if (s3 == null) { + s3 = "null"; + } + count = s1.count + s2.count + s3.count; + value = new char[count]; + offset = 0; + System.arraycopy(s1.value, s1.offset, value, 0, s1.count); + System.arraycopy(s2.value, s2.offset, value, s1.count, s2.count); + System.arraycopy(s3.value, s3.offset, value, s1.count + s2.count, + s3.count); + } + /** * Creates a {@code String} from the contents of the specified * {@code StringBuffer}. - * + * * @param stringbuffer * the buffer to get the contents from. */ @@ -594,7 +638,7 @@ public final class String implements Serializable, Comparable, /** * Creates a {@code String} from the contents of the specified {@code * StringBuilder}. - * + * * @param sb * the {@code StringBuilder} to copy the contents from. * @throws NullPointerException @@ -630,7 +674,7 @@ public final class String implements Serializable, Comparable, /** * Returns the character at the specified offset in this string. - * + * * @param index * the zero-based index in this string. * @return the character at the index. @@ -688,7 +732,7 @@ public final class String implements Serializable, Comparable, * Unicode value which is greater than the Unicode value of the character at * the same position in the specified string, or if the specified string is * a prefix of this string. - * + * * @param string * the string to compare. * @return 0 if the strings are equal, a negative integer if this string is @@ -721,7 +765,7 @@ public final class String implements Serializable, Comparable, * this string has a Unicode value which is greater than the Unicode value * of the character at the same position in the specified string, or if the * specified string is a prefix of this string. - * + * * @param string * the string to compare. * @return 0 if the strings are equal, a negative integer if this string is @@ -750,7 +794,7 @@ public final class String implements Serializable, Comparable, /** * Concatenates this string and the specified string. - * + * * @param string * the string to concatenate * @return a new string which is the concatenation of this string and the @@ -771,7 +815,7 @@ public final class String implements Serializable, Comparable, * Creates a new string containing the characters in the specified character * array. Modifying the character array after creating the string has no * effect on the string. - * + * * @param data * the array of characters. * @return the new string. @@ -786,7 +830,7 @@ public final class String implements Serializable, Comparable, * Creates a new string containing the specified characters in the character * array. Modifying the character array after creating the string has no * effect on the string. - * + * * @param data * the array of characters. * @param start @@ -829,7 +873,7 @@ public final class String implements Serializable, Comparable, /** * Compares the specified string to this string to determine if the * specified string is a suffix. - * + * * @param suffix * the suffix to look for. * @return {@code true} if the specified string is a suffix of this string, @@ -845,7 +889,7 @@ public final class String implements Serializable, Comparable, * Compares the specified object to this string and returns true if they are * equal. The object must be an instance of string with the same characters * in the same order. - * + * * @param object * the object to compare. * @return {@code true} if the specified object is equal to this string, @@ -885,7 +929,7 @@ public final class String implements Serializable, Comparable, /** * Compares the specified string to this string ignoring the case of the * characters and returns true if they are equal. - * + * * @param string * the string to compare. * @return {@code true} if the specified string is equal to this string, @@ -919,7 +963,7 @@ public final class String implements Serializable, Comparable, * specified by the file.encoding system property. If the system property is * not defined, the default encoding is ISO8859_1 (ISO-Latin-1). If 8859-1 * is not available, an ASCII encoding is used. - * + * * @return the byte array encoding of this string. */ public byte[] getBytes() { @@ -933,7 +977,7 @@ public final class String implements Serializable, Comparable, /** * Converts this string to a byte array, ignoring the high order bits of * each character. - * + * * @param start * the starting offset of characters to copy. * @param end @@ -967,7 +1011,7 @@ public final class String implements Serializable, Comparable, /** * Converts this string to a byte array using the specified encoding. - * + * * @param encoding * the encoding to use. * @return the encoded byte array of this string. @@ -1003,7 +1047,7 @@ public final class String implements Serializable, Comparable, /** * Copies the specified characters in this string to the character array * starting at the specified offset in the character array. - * + * * @param start * the starting offset of characters to copy. * @param end @@ -1065,7 +1109,7 @@ public final class String implements Serializable, Comparable, * Searches in this string for the first index of the specified character. * The search for the character starts at the beginning and moves towards * the end of this string. - * + * * @param c * the character to find. * @return the index in this string of the specified character, -1 if the @@ -1092,7 +1136,7 @@ public final class String implements Serializable, Comparable, * Searches in this string for the index of the specified character. The * search for the character starts at the specified offset and moves towards * the end of this string. - * + * * @param c * the character to find. * @param start @@ -1124,7 +1168,7 @@ public final class String implements Serializable, Comparable, * Searches in this string for the first index of the specified string. The * search for the string starts at the beginning and moves towards the end * of this string. - * + * * @param string * the string to find. * @return the index of the first character of the specified string in this @@ -1169,7 +1213,7 @@ public final class String implements Serializable, Comparable, * Searches in this string for the index of the specified string. The search * for the string starts at the specified offset and moves towards the end * of this string. - * + * * @param subString * the string to find. * @param start @@ -1219,17 +1263,16 @@ public final class String implements Serializable, Comparable, * If the string is not in the table, it is added. Returns the string * contained in the table which is equal to this string. The same string * object is always returned for strings which are equal. - * + * * @return the interned string equal to this string. */ native public String intern(); - /** * Searches in this string for the last index of the specified character. * The search for the character starts at the end and moves towards the * beginning of this string. - * + * * @param c * the character to find. * @return the index in this string of the specified character, -1 if the @@ -1253,7 +1296,7 @@ public final class String implements Serializable, Comparable, * Searches in this string for the index of the specified character. The * search for the character starts at the specified offset and moves towards * the beginning of this string. - * + * * @param c * the character to find. * @param start @@ -1284,7 +1327,7 @@ public final class String implements Serializable, Comparable, * Searches in this string for the last index of the specified string. The * search for the string starts at the end and moves towards the beginning * of this string. - * + * * @param string * the string to find. * @return the index of the first character of the specified string in this @@ -1301,7 +1344,7 @@ public final class String implements Serializable, Comparable, * Searches in this string for the index of the specified string. The search * for the string starts at the specified offset and moves towards the * beginning of this string. - * + * * @param subString * the string to find. * @param start @@ -1345,7 +1388,7 @@ public final class String implements Serializable, Comparable, /** * Returns the size of this string. - * + * * @return the number of characters in this string. */ public int length() { @@ -1355,7 +1398,7 @@ public final class String implements Serializable, Comparable, /** * Compares the specified string to this string and compares the specified * range of characters to determine if they are the same. - * + * * @param thisStart * the starting offset in this string. * @param string @@ -1400,7 +1443,7 @@ public final class String implements Serializable, Comparable, * Compares the specified string to this string and compares the specified * range of characters to determine if they are the same. When ignoreCase is * true, the case of the characters is ignored during the comparison. - * + * * @param ignoreCase * specifies if case should be ignored. * @param thisStart @@ -1451,7 +1494,7 @@ public final class String implements Serializable, Comparable, /** * Copies this string replacing occurrences of the specified character with * another character. - * + * * @param oldChar * the character to replace. * @param newChar @@ -1485,12 +1528,12 @@ public final class String implements Serializable, Comparable, return copied ? new String(0, count, buffer) : this; // END android-changed } - + /** * Copies this string replacing occurrences of the specified target sequence * with another sequence. The string is processed from the beginning to the * end. - * + * * @param target * the sequence to replace. * @param replacement @@ -1530,7 +1573,7 @@ public final class String implements Serializable, Comparable, /** * Compares the specified string to this string to determine if the * specified string is a prefix. - * + * * @param prefix * the string to look for. * @return {@code true} if the specified string is a prefix of this string, @@ -1545,7 +1588,7 @@ public final class String implements Serializable, Comparable, /** * Compares the specified string to this string, starting at the specified * offset, to determine if the specified string is a prefix. - * + * * @param prefix * the string to look for. * @param start @@ -1561,7 +1604,7 @@ public final class String implements Serializable, Comparable, /** * Copies a range of characters into a new string. - * + * * @param start * the offset of the first character. * @return a new string containing the characters from start to the end of @@ -1581,7 +1624,7 @@ public final class String implements Serializable, Comparable, /** * Copies a range of characters into a new string. - * + * * @param start * the offset of the first character. * @param end @@ -1605,7 +1648,7 @@ public final class String implements Serializable, Comparable, /** * Copies the characters in this string to a character array. - * + * * @return a character array containing the characters of this string. */ public char[] toCharArray() { @@ -1617,7 +1660,7 @@ public final class String implements Serializable, Comparable, /** * Converts the characters in this string to lowercase, using the default * Locale. - * + * * @return a new string containing the lowercase characters equivalent to * the characters in this string. */ @@ -1628,7 +1671,7 @@ public final class String implements Serializable, Comparable, /** * Converts the characters in this string to lowercase, using the specified * Locale. - * + * * @param locale * the Locale to use. * @return a new string containing the lowercase characters equivalent to @@ -1672,7 +1715,7 @@ public final class String implements Serializable, Comparable, /** * Converts the characters in this string to uppercase, using the default * Locale. - * + * * @return a new string containing the uppercase characters equivalent to * the characters in this string. */ @@ -1746,7 +1789,7 @@ public final class String implements Serializable, Comparable, /** * Converts the characters in this string to uppercase, using the specified * Locale. - * + * * @param locale * the Locale to use. * @return a new string containing the uppercase characters equivalent to @@ -1811,7 +1854,7 @@ public final class String implements Serializable, Comparable, /** * Copies this string removing white space characters from the beginning and * end of the string. - * + * * @return a new string with characters <= \\u0020 removed from * the beginning and the end. */ @@ -1834,7 +1877,7 @@ public final class String implements Serializable, Comparable, * Creates a new string containing the characters in the specified character * array. Modifying the character array after creating the string has no * effect on the string. - * + * * @param data * the array of characters. * @return the new string. @@ -1849,7 +1892,7 @@ public final class String implements Serializable, Comparable, * Creates a new string containing the specified characters in the character * array. Modifying the character array after creating the string has no * effect on the string. - * + * * @param data * the array of characters. * @param start @@ -1869,7 +1912,7 @@ public final class String implements Serializable, Comparable, /** * Converts the specified character to its string representation. - * + * * @param value * the character. * @return the character converted to a string. @@ -1887,7 +1930,7 @@ public final class String implements Serializable, Comparable, /** * Converts the specified double to its string representation. - * + * * @param value * the double. * @return the double converted to a string. @@ -1898,7 +1941,7 @@ public final class String implements Serializable, Comparable, /** * Converts the specified float to its string representation. - * + * * @param value * the float. * @return the float converted to a string. @@ -1909,7 +1952,7 @@ public final class String implements Serializable, Comparable, /** * Converts the specified integer to its string representation. - * + * * @param value * the integer. * @return the integer converted to a string. @@ -1920,7 +1963,7 @@ public final class String implements Serializable, Comparable, /** * Converts the specified long to its string representation. - * + * * @param value * the long. * @return the long converted to a string. @@ -1933,7 +1976,7 @@ public final class String implements Serializable, Comparable, * Converts the specified object to its string representation. If the object * is null return the string {@code "null"}, otherwise use {@code * toString()} to get the string representation. - * + * * @param value * the object. * @return the object converted to a string, or the string {@code "null"}. @@ -1946,7 +1989,7 @@ public final class String implements Serializable, Comparable, * Converts the specified boolean to its string representation. When the * boolean is {@code true} return {@code "true"}, otherwise return {@code * "false"}. - * + * * @param value * the boolean. * @return the boolean converted to a string. @@ -1958,7 +2001,7 @@ public final class String implements Serializable, Comparable, /** * Returns whether the characters in the StringBuffer {@code strbuf} are the * same as those in this string. - * + * * @param strbuf * the StringBuffer to compare this string to. * @return {@code true} if the characters in {@code strbuf} are identical to @@ -2008,7 +2051,7 @@ public final class String implements Serializable, Comparable, /** * Determines whether this string matches a given regular expression. - * + * * @param expr * the regular expression to be matched. * @return {@code true} if the expression matches, otherwise {@code false}. @@ -2026,7 +2069,7 @@ public final class String implements Serializable, Comparable, /** * Replace any substrings within this string that match the supplied regular * expression {@code expr}, with the string {@code substitute}. - * + * * @param expr * the regular expression to match. * @param substitute @@ -2045,7 +2088,7 @@ public final class String implements Serializable, Comparable, /** * Replace the first substring within this string that matches the supplied * regular expression {@code expr}, with the string {@code substitute}. - * + * * @param expr * the regular expression to match. * @param substitute @@ -2065,7 +2108,7 @@ public final class String implements Serializable, Comparable, /** * Splits this string using the supplied regular expression {@code expr}. - * + * * @param expr * the regular expression used to divide the string. * @return an array of Strings created by separating the string along @@ -2086,7 +2129,7 @@ public final class String implements Serializable, Comparable, * Splits this string using the supplied regular expression {@code expr}. * The parameter {@code max} controls the behavior how many times the * pattern is applied to the string. - * + * * @param expr * the regular expression used to divide the string. * @param max @@ -2108,7 +2151,7 @@ public final class String implements Serializable, Comparable, /** * Has the same result as the substring function, but is present so that * string may implement the CharSequence interface. - * + * * @param start * the offset the first character. * @param end @@ -2127,7 +2170,7 @@ public final class String implements Serializable, Comparable, /** * Retrieves the Unicode code point (character) value at the specified * {@code index}. - * + * * @param index * the index to the {@code char} code unit within this string. * @return the Unicode code point value. @@ -2148,7 +2191,7 @@ public final class String implements Serializable, Comparable, /** * Retrieves the Unicode code point value that precedes the specified * {@code index}. - * + * * @param index * the index to the {@code char} code unit within this string. * @return the Unicode code point value. @@ -2169,7 +2212,7 @@ public final class String implements Serializable, Comparable, /** * Calculates the number of Unicode code points between {@code beginIndex} * and {@code endIndex}. - * + * * @param beginIndex * the inclusive beginning index of the subsequence. * @param endIndex @@ -2232,7 +2275,7 @@ public final class String implements Serializable, Comparable, /** * Returns a formatted string, using the supplied format and arguments, * using the default locale. - * + * * @param format * a format string. * @param args diff --git a/libcore/luni/src/main/java/java/lang/reflect/Modifier.java b/libcore/luni/src/main/java/java/lang/reflect/Modifier.java index 0f9dc9848..900564772 100644 --- a/libcore/luni/src/main/java/java/lang/reflect/Modifier.java +++ b/libcore/luni/src/main/java/java/lang/reflect/Modifier.java @@ -279,9 +279,7 @@ public class Modifier { */ @SuppressWarnings("nls") public static java.lang.String toString(int modifiers) { - StringBuffer buf; - - buf = new StringBuffer(); + StringBuilder buf = new StringBuilder(); if (isPublic(modifiers)) { buf.append("public "); diff --git a/libcore/luni/src/main/java/java/net/ServerSocket.java b/libcore/luni/src/main/java/java/net/ServerSocket.java index fc3ad102d..99fad3f63 100644 --- a/libcore/luni/src/main/java/java/net/ServerSocket.java +++ b/libcore/luni/src/main/java/java/net/ServerSocket.java @@ -336,7 +336,7 @@ public class ServerSocket { */ @Override public String toString() { - StringBuffer result = new StringBuffer(64); + StringBuilder result = new StringBuilder(64); result.append("ServerSocket["); //$NON-NLS-1$ if (!isBound()) { return result.append("unbound]").toString(); //$NON-NLS-1$ diff --git a/libcore/luni/src/main/java/java/net/SocketImpl.java b/libcore/luni/src/main/java/java/net/SocketImpl.java index be13eca23..6ac41cde2 100644 --- a/libcore/luni/src/main/java/java/net/SocketImpl.java +++ b/libcore/luni/src/main/java/java/net/SocketImpl.java @@ -259,7 +259,7 @@ public abstract class SocketImpl implements SocketOptions { @SuppressWarnings("nls") @Override public String toString() { - return new StringBuffer(100).append("Socket[addr=").append( + return new StringBuilder(100).append("Socket[addr=").append( getInetAddress()).append(",port=").append(port).append( ",localport=").append(getLocalPort()).append("]").toString(); } diff --git a/libcore/luni/src/main/java/java/net/SocketPermission.java b/libcore/luni/src/main/java/java/net/SocketPermission.java index 25cc43f04..4353e2ed3 100644 --- a/libcore/luni/src/main/java/java/net/SocketPermission.java +++ b/libcore/luni/src/main/java/java/net/SocketPermission.java @@ -211,7 +211,7 @@ public final class SocketPermission extends Permission implements Serializable { } boolean parsing = true; String action; - StringBuffer sb = new StringBuffer(); + StringBuilder sb = new StringBuilder(); int pos = 0, length = actions.length(); while (parsing) { char c; @@ -360,7 +360,7 @@ public final class SocketPermission extends Permission implements Serializable { return actionNames[SP_RESOLVE]; // If none specified return the } // implied action resolve - StringBuffer sb = new StringBuffer(); + StringBuilder sb = new StringBuilder(); if ((actionsMask & SP_CONNECT) == SP_CONNECT) { sb.append(','); sb.append(actionNames[SP_CONNECT]); diff --git a/libcore/luni/src/main/java/java/net/URI.java b/libcore/luni/src/main/java/java/net/URI.java index 7fd08a573..85c16eba5 100644 --- a/libcore/luni/src/main/java/java/net/URI.java +++ b/libcore/luni/src/main/java/java/net/URI.java @@ -106,7 +106,7 @@ public final class URI implements Comparable, Serializable { */ public URI(String scheme, String ssp, String frag) throws URISyntaxException { - StringBuffer uri = new StringBuffer(); + StringBuilder uri = new StringBuilder(); if (scheme != null) { uri.append(scheme); uri.append(':'); @@ -166,7 +166,7 @@ public final class URI implements Comparable, Serializable { throw new URISyntaxException(path, Msg.getString("K0302")); //$NON-NLS-1$ } - StringBuffer uri = new StringBuffer(); + StringBuilder uri = new StringBuilder(); if (scheme != null) { uri.append(scheme); uri.append(':'); @@ -270,7 +270,7 @@ public final class URI implements Comparable, Serializable { throw new URISyntaxException(path, Msg.getString("K0302")); //$NON-NLS-1$ } - StringBuffer uri = new StringBuffer(); + StringBuilder uri = new StringBuilder(); if (scheme != null) { uri.append(scheme); uri.append(':'); @@ -994,7 +994,7 @@ public final class URI implements Comparable, Serializable { * converts the hex values following the '%' to lowercase */ private String convertHexToLowerCase(String s) { - StringBuffer result = new StringBuffer(""); //$NON-NLS-1$ + StringBuilder result = new StringBuilder(""); //$NON-NLS-1$ if (s.indexOf('%') == -1) { return s; } @@ -1357,7 +1357,7 @@ public final class URI implements Comparable, Serializable { } // put the path back together - StringBuffer newpath = new StringBuffer(); + StringBuilder newpath = new StringBuilder(); if (path.startsWith("/")) { //$NON-NLS-1$ newpath.append('/'); } @@ -1548,7 +1548,7 @@ public final class URI implements Comparable, Serializable { */ private void setSchemeSpecificPart() { // ssp = [//authority][path][?query] - StringBuffer ssp = new StringBuffer(); + StringBuilder ssp = new StringBuilder(); if (authority != null) { ssp.append("//" + authority); //$NON-NLS-1$ } @@ -1631,7 +1631,7 @@ public final class URI implements Comparable, Serializable { @Override public String toString() { if (string == null) { - StringBuffer result = new StringBuffer(); + StringBuilder result = new StringBuilder(); if (scheme != null) { result.append(scheme); result.append(':'); @@ -1670,7 +1670,7 @@ public final class URI implements Comparable, Serializable { * and converts escaped octets to lowercase. */ private String getHashString() { - StringBuffer result = new StringBuffer(); + StringBuilder result = new StringBuilder(); if (scheme != null) { result.append(scheme.toLowerCase()); result.append(':'); diff --git a/libcore/luni/src/main/java/java/net/URIEncoderDecoder.java b/libcore/luni/src/main/java/java/net/URIEncoderDecoder.java index 4bf95ab61..d2b00442c 100644 --- a/libcore/luni/src/main/java/java/net/URIEncoderDecoder.java +++ b/libcore/luni/src/main/java/java/net/URIEncoderDecoder.java @@ -112,7 +112,7 @@ class URIEncoderDecoder { */ static String quoteIllegal(String s, String legal) throws UnsupportedEncodingException { - StringBuffer buf = new StringBuffer(); + StringBuilder buf = new StringBuilder(); for (int i = 0; i < s.length(); i++) { char ch = s.charAt(i); if ((ch >= 'a' && ch <= 'z') @@ -148,7 +148,7 @@ class URIEncoderDecoder { * @return java.lang.String the converted string */ static String encodeOthers(String s) throws UnsupportedEncodingException { - StringBuffer buf = new StringBuffer(); + StringBuilder buf = new StringBuilder(); for (int i = 0; i < s.length(); i++) { char ch = s.charAt(i); if (ch <= 127) { @@ -183,7 +183,7 @@ class URIEncoderDecoder { */ static String decode(String s) throws UnsupportedEncodingException { - StringBuffer result = new StringBuffer(); + StringBuilder result = new StringBuilder(); ByteArrayOutputStream out = new ByteArrayOutputStream(); for (int i = 0; i < s.length();) { char c = s.charAt(i); diff --git a/libcore/luni/src/main/java/java/net/URLClassLoader.java b/libcore/luni/src/main/java/java/net/URLClassLoader.java index dd3c9bf53..6dfa3850e 100644 --- a/libcore/luni/src/main/java/java/net/URLClassLoader.java +++ b/libcore/luni/src/main/java/java/net/URLClassLoader.java @@ -1184,9 +1184,9 @@ public class URLClassLoader extends SecureClassLoader { String element = tokenizer.nextToken(); if (!element.equals("")) { //$NON-NLS-1$ try { - URL newURL = new URL(protocol, host, port, file + element - + "!/"); //$NON-NLS-1$ - addedURLs.add(newURL); + // Take absolute path case into consideration + URL url = new URL(new URL(file), element); + addedURLs.add(createSearchURL(url)); } catch (MalformedURLException e) { // Nothing is added } @@ -1196,10 +1196,6 @@ public class URLClassLoader extends SecureClassLoader { } Class findClassImpl(String className) { - Class loadedClass = findLoadedClass(className); - if (null != loadedClass) { - return loadedClass; - } String partialName = className.replace('.', '/'); final String classFileName = new StringBuilder(partialName).append(".class").toString(); //$NON-NLS-1$ String packageName = null; diff --git a/libcore/luni/src/main/java/java/net/URLConnection.java b/libcore/luni/src/main/java/java/net/URLConnection.java index b87b11adb..573a2d2b2 100644 --- a/libcore/luni/src/main/java/java/net/URLConnection.java +++ b/libcore/luni/src/main/java/java/net/URLConnection.java @@ -758,7 +758,7 @@ public abstract class URLConnection { * @return the string to be parsed */ private String parseTypeString(String typeString) { - StringBuffer typeStringBuffer = new StringBuffer(typeString); + StringBuilder typeStringBuffer = new StringBuilder(typeString); for (int i = 0; i < typeStringBuffer.length(); i++) { // if non-alphanumeric, replace it with '_' char c = typeStringBuffer.charAt(i); diff --git a/libcore/luni/src/main/java/java/net/URLEncoder.java b/libcore/luni/src/main/java/java/net/URLEncoder.java index 2c21aa620..b764cc7c9 100644 --- a/libcore/luni/src/main/java/java/net/URLEncoder.java +++ b/libcore/luni/src/main/java/java/net/URLEncoder.java @@ -49,7 +49,7 @@ public class URLEncoder { */ @Deprecated public static String encode(String s) { - StringBuffer buf = new StringBuffer(); + StringBuilder buf = new StringBuilder(); for (int i = 0; i < s.length(); i++) { char ch = s.charAt(i); if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') diff --git a/libcore/luni/src/main/java/java/net/URLStreamHandler.java b/libcore/luni/src/main/java/java/net/URLStreamHandler.java index f039b00f5..54e550b7f 100644 --- a/libcore/luni/src/main/java/java/net/URLStreamHandler.java +++ b/libcore/luni/src/main/java/java/net/URLStreamHandler.java @@ -305,8 +305,7 @@ public abstract class URLStreamHandler { * @see URL#toExternalForm() */ protected String toExternalForm(URL url) { - StringBuffer answer = new StringBuffer(url.getProtocol().length() - + url.getFile().length() + 16); + StringBuilder answer = new StringBuilder(); answer.append(url.getProtocol()); answer.append(':'); String authority = url.getAuthority(); @@ -317,8 +316,9 @@ public abstract class URLStreamHandler { String file = url.getFile(); String ref = url.getRef(); - // file is never null - answer.append(file); + if (file != null) { + answer.append(file); + } if (ref != null) { answer.append('#'); answer.append(ref); diff --git a/libcore/luni/src/main/java/java/util/AbstractList.java b/libcore/luni/src/main/java/java/util/AbstractList.java index 899affd05..8f1e79fee 100644 --- a/libcore/luni/src/main/java/java/util/AbstractList.java +++ b/libcore/luni/src/main/java/java/util/AbstractList.java @@ -360,7 +360,10 @@ public abstract class AbstractList extends AbstractCollection implements @Override public int size() { - return size; + if (modCount == fullList.modCount) { + return size; + } + throw new ConcurrentModificationException(); } void sizeChanged(boolean increment) { diff --git a/libcore/luni/src/main/java/java/util/ArrayList.java b/libcore/luni/src/main/java/java/util/ArrayList.java index ade5d27cf..b8c705633 100644 --- a/libcore/luni/src/main/java/java/util/ArrayList.java +++ b/libcore/luni/src/main/java/java/util/ArrayList.java @@ -81,10 +81,11 @@ public class ArrayList extends AbstractList implements List, * the collection of elements to add. */ public ArrayList(Collection collection) { - int size = collection.size(); firstIndex = 0; + Object[] objects = collection.toArray(); + int size = objects.length; array = newElementArray(size + (size / 10)); - collection.toArray(array); + System.arraycopy(objects, 0, array, 0, size); lastIndex = size; modCount = 1; } @@ -187,7 +188,12 @@ public class ArrayList extends AbstractList implements List, if (this == collection) { collection = (ArrayList)clone(); } - int growSize = collection.size(); + Object[] dumparray = collection.toArray(); + int growSize = dumparray.length; + if (growSize == 0) { + return false; + } + if (0 < location && location < size) { if (array.length - size < growSize) { growForInsert(location, growSize); @@ -219,15 +225,10 @@ public class ArrayList extends AbstractList implements List, lastIndex += growSize; } - if (growSize > 0) { - Object[] dumparray = new Object[growSize]; - collection.toArray(dumparray); - System.arraycopy(dumparray, 0, this.array, location + firstIndex, - growSize); - modCount++; - return true; - } - return false; + System.arraycopy(dumparray, 0, this.array, location + firstIndex, + growSize); + modCount++; + return true; } /** diff --git a/libcore/luni/src/main/java/java/util/BitSet.java b/libcore/luni/src/main/java/java/util/BitSet.java index d2d7c0a8a..4e01cbf5a 100644 --- a/libcore/luni/src/main/java/java/util/BitSet.java +++ b/libcore/luni/src/main/java/java/util/BitSet.java @@ -818,7 +818,7 @@ public class BitSet implements Serializable, Cloneable { */ @Override public String toString() { - StringBuffer sb = new StringBuffer(bits.length / 2); + StringBuilder sb = new StringBuilder(bits.length / 2); int bitCount = 0; sb.append('{'); boolean comma = false; diff --git a/libcore/luni/src/main/java/java/util/Calendar.java b/libcore/luni/src/main/java/java/util/Calendar.java index 088347d17..0ac574cb8 100644 --- a/libcore/luni/src/main/java/java/util/Calendar.java +++ b/libcore/luni/src/main/java/java/util/Calendar.java @@ -1322,7 +1322,7 @@ public abstract class Calendar implements Serializable, Cloneable, @Override @SuppressWarnings("nls") public String toString() { - StringBuffer result = new StringBuffer(getClass().getName() + "[time=" + StringBuilder result = new StringBuilder(getClass().getName() + "[time=" + (isTimeSet ? String.valueOf(time) : "?") + ",areFieldsSet=" + areFieldsSet diff --git a/libcore/luni/src/main/java/java/util/Date.java b/libcore/luni/src/main/java/java/util/Date.java index 7bd726178..80610d378 100644 --- a/libcore/luni/src/main/java/java/util/Date.java +++ b/libcore/luni/src/main/java/java/util/Date.java @@ -390,7 +390,7 @@ public class Date implements Serializable, Cloneable, Comparable { int hour = -1, minute = -1, second = -1, zoneOffset = 0, minutesOffset = 0; boolean zone = false; final int PAD = 0, LETTERS = 1, NUMBERS = 2; - StringBuffer buffer = new StringBuffer(); + StringBuilder buffer = new StringBuilder(); while (offset <= length) { char next = offset < length ? string.charAt(offset) : '\r'; diff --git a/libcore/luni/src/main/java/java/util/HashMap.java b/libcore/luni/src/main/java/java/util/HashMap.java index 4ec7a1b92..999063db0 100644 --- a/libcore/luni/src/main/java/java/util/HashMap.java +++ b/libcore/luni/src/main/java/java/util/HashMap.java @@ -852,11 +852,11 @@ public class HashMap extends AbstractMap implements Map, } static boolean areEqualKeys(Object key1, Object key2) { - return key1.equals(key2); + return (key1 == key2) || key1.equals(key2); } static boolean areEqualValues(Object value1, Object value2) { - return value1.equals(value2); + return (value1 == value2) || value1.equals(value2); } diff --git a/libcore/luni/src/main/java/java/util/Hashtable.java b/libcore/luni/src/main/java/java/util/Hashtable.java index f1c1f74f1..b23364d48 100644 --- a/libcore/luni/src/main/java/java/util/Hashtable.java +++ b/libcore/luni/src/main/java/java/util/Hashtable.java @@ -547,10 +547,15 @@ public class Hashtable extends Dictionary implements Map, while (it.hasNext()) { Map.Entry entry = it.next(); Object key = entry.getKey(); + if (key == this) { + continue; + } Object value = entry.getValue(); - int hash = (key != this ? key.hashCode() : 0) - ^ (value != this ? (value != null ? value.hashCode() : 0) - : 0); + if (value == this) { + continue; + } + int hash = (key != null ? key.hashCode() : 0) + ^ (value != null ? value.hashCode() : 0); result += hash; } return result; diff --git a/libcore/luni/src/main/java/java/util/IdentityHashMap.java b/libcore/luni/src/main/java/java/util/IdentityHashMap.java index 30330b58a..053de1d88 100644 --- a/libcore/luni/src/main/java/java/util/IdentityHashMap.java +++ b/libcore/luni/src/main/java/java/util/IdentityHashMap.java @@ -267,7 +267,10 @@ public class IdentityHashMap extends AbstractMap implements } private int computeElementArraySize() { - return (int) (((long) threshold * 10000) / loadFactor) * 2; + int arraySize = (int) (((long) threshold * 10000) / loadFactor) * 2; + // ensure arraySize is positive, the above cast from long to int type + // leads to overflow and negative arraySize if threshold is too big + return arraySize < 0 ? -arraySize : arraySize; } /** @@ -748,7 +751,12 @@ public class IdentityHashMap extends AbstractMap implements @Override public Object clone() { try { - return super.clone(); + IdentityHashMap cloneHashMap = (IdentityHashMap) super + .clone(); + cloneHashMap.elementData = newElementArray(elementData.length); + System.arraycopy(elementData, 0, cloneHashMap.elementData, 0, + elementData.length); + return cloneHashMap; } catch (CloneNotSupportedException e) { return null; } diff --git a/libcore/luni/src/main/java/java/util/Locale.java b/libcore/luni/src/main/java/java/util/Locale.java index b4558aaa0..b1a182181 100644 --- a/libcore/luni/src/main/java/java/util/Locale.java +++ b/libcore/luni/src/main/java/java/util/Locale.java @@ -564,7 +564,7 @@ public final class Locale implements Cloneable, Serializable { */ public String getDisplayName(Locale locale) { int count = 0; - StringBuffer buffer = new StringBuffer(); + StringBuilder buffer = new StringBuilder(); if (languageCode.length() > 0) { buffer.append(getDisplayLanguage(locale)); count++; diff --git a/libcore/luni/src/main/java/java/util/Properties.java b/libcore/luni/src/main/java/java/util/Properties.java index b1fa938d4..79d70693f 100644 --- a/libcore/luni/src/main/java/java/util/Properties.java +++ b/libcore/luni/src/main/java/java/util/Properties.java @@ -198,7 +198,7 @@ public class Properties extends Hashtable { if (out == null) { throw new NullPointerException(); } - StringBuffer buffer = new StringBuffer(80); + StringBuilder buffer = new StringBuilder(80); Enumeration keys = propertyNames(); while (keys.hasMoreElements()) { String key = (String) keys.nextElement(); @@ -234,7 +234,7 @@ public class Properties extends Hashtable { if (writer == null) { throw new NullPointerException(); } - StringBuffer buffer = new StringBuffer(80); + StringBuilder buffer = new StringBuilder(80); Enumeration keys = propertyNames(); while (keys.hasMoreElements()) { String key = (String) keys.nextElement(); @@ -392,7 +392,7 @@ public class Properties extends Hashtable { case '\r': mode = NONE; firstChar = true; - if (offset > 0) { + if (offset > 0 || (offset == 0 && keyLength == 0)) { if (keyLength == -1) { keyLength = offset; } diff --git a/libcore/luni/src/main/java/java/util/TimeZone.java b/libcore/luni/src/main/java/java/util/TimeZone.java index b0bcc6b3c..b4878cae9 100644 --- a/libcore/luni/src/main/java/java/util/TimeZone.java +++ b/libcore/luni/src/main/java/java/util/TimeZone.java @@ -446,7 +446,7 @@ public abstract class TimeZone implements Serializable, Cloneable { } private static String formatTimeZoneName(String name, int offset) { - StringBuffer buf = new StringBuffer(); + StringBuilder buf = new StringBuilder(); int index = offset, length = name.length(); buf.append(name.substring(0, offset)); diff --git a/libcore/luni/src/main/java/java/util/Timer.java b/libcore/luni/src/main/java/java/util/Timer.java index 48970be01..609003199 100644 --- a/libcore/luni/src/main/java/java/util/Timer.java +++ b/libcore/luni/src/main/java/java/util/Timer.java @@ -187,14 +187,10 @@ public class Timer { /** * Starts a new timer. - * - * @param isDaemon + * + * @param name thread's name + * @param isDaemon daemon thread or not */ - TimerImpl(boolean isDaemon) { - this.setDaemon(isDaemon); - this.start(); - } - TimerImpl(String name, boolean isDaemon) { this.setName(name); this.setDaemon(isDaemon); @@ -324,72 +320,78 @@ public class Timer { } } + + private static final class FinalizerHelper { + private final TimerImpl impl; + + FinalizerHelper(TimerImpl impl) { + super(); + this.impl = impl; + } + + @Override + protected void finalize() { + synchronized (impl) { + impl.finished = true; + impl.notify(); + } + } + } + + private static long timerId; + + private synchronized static long nextId() { + return timerId++; + } /* This object will be used in synchronization purposes */ - private TimerImpl impl; + private final TimerImpl impl; // Used to finalize thread @SuppressWarnings("unused") - private final Object finalizer; - - /** - * Creates a new {@code Timer} which may be specified to be run as a daemon thread. - * - * @param isDaemon - * {@code true} if the {@code Timer}'s thread should be a daemon thread. - */ - public Timer(boolean isDaemon) { - // BEGIN android-changed - impl = new TimerImpl("java.util.Timer", isDaemon); - // END android-changed - finalizer = newFinalizer(); - } - - /** - * Creates a new non-daemon {@code Timer}. - */ - public Timer() { - // BEGIN android-changed - impl = new TimerImpl("java.util.Timer", false); - // END android-changed - finalizer = newFinalizer(); - } + private final FinalizerHelper finalizer; /** * Creates a new named {@code Timer} which may be specified to be run as a * daemon thread. * - * @param name - * the name of the {@code Timer}. - * @param isDaemon - * true if {@code Timer}'s thread should be a daemon thread. + * @param name the name of the {@code Timer}. + * @param isDaemon true if {@code Timer}'s thread should be a daemon thread. + * @throws NullPointerException is {@code name} is {@code null} */ public Timer(String name, boolean isDaemon) { - impl = new TimerImpl(name, isDaemon); - finalizer = newFinalizer(); + super(); + if (name == null){ + throw new NullPointerException("name is null"); + } + this.impl = new TimerImpl(name, isDaemon); + this.finalizer = new FinalizerHelper(impl); } - + /** * Creates a new named {@code Timer} which does not run as a daemon thread. * - * @param name - * the name of the Timer. + * @param name the name of the Timer. + * @throws NullPointerException is {@code name} is {@code null} */ public Timer(String name) { - impl = new TimerImpl(name, false); - finalizer = newFinalizer(); + this(name, false); + } + + /** + * Creates a new {@code Timer} which may be specified to be run as a daemon thread. + * + * @param isDaemon {@code true} if the {@code Timer}'s thread should be a daemon thread. + */ + public Timer(boolean isDaemon) { + this("Timer-" + Timer.nextId(), isDaemon); } - private Object newFinalizer() { - return new Object() { // $NON-LOCK-1$ - @Override - protected void finalize() { - synchronized (impl) { - impl.finished = true; - impl.notify(); - } - } - }; + /** + * Creates a new non-daemon {@code Timer}. + */ + public Timer() { + this(false); } /** @@ -443,7 +445,7 @@ public class Timer { * @param task * the task to schedule. * @param delay - * amount of time before execution. + * amount of time in milliseconds before execution. * @throws IllegalArgumentException * if {@code delay < 0}. * @throws IllegalStateException @@ -463,9 +465,9 @@ public class Timer { * @param task * the task to schedule. * @param delay - * amount of time before first execution. + * amount of time in milliseconds before first execution. * @param period - * amount of time between subsequent executions. + * amount of time in milliseconds between subsequent executions. * @throws IllegalArgumentException * if {@code delay < 0} or {@code period < 0}. * @throws IllegalStateException @@ -488,7 +490,7 @@ public class Timer { * @param when * time of first execution. * @param period - * amount of time between subsequent executions. + * amount of time in milliseconds between subsequent executions. * @throws IllegalArgumentException * if {@code when.getTime() < 0} or {@code period < 0}. * @throws IllegalStateException @@ -510,9 +512,9 @@ public class Timer { * @param task * the task to schedule. * @param delay - * amount of time before first execution. + * amount of time in milliseconds before first execution. * @param period - * amount of time between subsequent executions. + * amount of time in milliseconds between subsequent executions. * @throws IllegalArgumentException * if {@code delay < 0} or {@code period < 0}. * @throws IllegalStateException @@ -535,7 +537,7 @@ public class Timer { * @param when * time of first execution. * @param period - * amount of time between subsequent executions. + * amount of time in milliseconds between subsequent executions. * @throws IllegalArgumentException * if {@code when.getTime() < 0} or {@code period < 0}. * @throws IllegalStateException diff --git a/libcore/luni/src/main/java/java/util/Vector.java b/libcore/luni/src/main/java/java/util/Vector.java index 8634c136f..6a4060a9e 100644 --- a/libcore/luni/src/main/java/java/util/Vector.java +++ b/libcore/luni/src/main/java/java/util/Vector.java @@ -1009,7 +1009,7 @@ public class Vector extends AbstractList implements List, return "[]"; //$NON-NLS-1$ } int length = elementCount - 1; - StringBuffer buffer = new StringBuffer(elementCount * 16); + StringBuilder buffer = new StringBuilder(elementCount * 16); buffer.append('['); for (int i = 0; i < length; i++) { if (elementData[i] == this) { diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/io/FileCanonPathCache.java b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/io/FileCanonPathCache.java new file mode 100644 index 000000000..e3ea7b513 --- /dev/null +++ b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/io/FileCanonPathCache.java @@ -0,0 +1,136 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.luni.internal.io; + +import java.util.HashMap; +import java.util.LinkedList; + +/** + * A simple cache implementation for file's canonical path. The cache has fixed + * size CACHE_SIZE and cached elements would be expired. If + * put method is invoked when cache is full, the oldest element will be removed. + * + */ +public class FileCanonPathCache { + + static private class CacheElement { + String canonicalPath; + + long timestamp; + + public CacheElement(String path) { + this.canonicalPath = path; + this.timestamp = System.currentTimeMillis(); + } + } + + /** + * Max elemnts could be hold in the cache. + */ + public static final int CACHE_SIZE = 256; + + private static HashMap cache = new HashMap( + CACHE_SIZE); + + /** + * FIFO queue for tracking age of elements. + */ + private static LinkedList list = new LinkedList(); + + private static Object lock = new Object(); + + /** + * Expired time. + */ + private static long timeout = 600000; + + /** + * Retrieve element from cache. + * + * @param path + * absolute path. + * @return canonical path of path if it's in cache. + * + */ + public static String get(String path) { + CacheElement element = null; + synchronized (lock) { + element = cache.get(path); + } + + if (element == null) { + return null; + } + + long time = System.currentTimeMillis(); + if (time - element.timestamp > timeout) { + // remove all elements older than this one + synchronized (lock) { + if (cache.get(path) != null) { + String oldest = null; + do { + oldest = list.removeFirst(); + cache.remove(path); + } while (!path.equals(oldest)); + } + } + return null; + } + + return element.canonicalPath; + } + + /** + * Put element to cache. + * + * @param path + * absolute path. + * @param canonicalPath + * the canonical path of path. + */ + public static void put(String path, String canonicalPath) { + CacheElement element = new CacheElement(canonicalPath); + synchronized (lock) { + if (cache.size() >= CACHE_SIZE) { + // cache is full + String oldest = list.removeFirst(); + cache.remove(oldest); + } + cache.put(path, element); + list.addLast(path); + } + } + + /** + * Remove all elements from cache. + */ + public static void clear() { + synchronized (lock) { + cache.clear(); + list.clear(); + } + } + + public static long getTimeout() { + return timeout; + } + + public static void setTimeout(long timeout) { + FileCanonPathCache.timeout = timeout; + } +} diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/ftp/FtpURLConnection.java b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/ftp/FtpURLConnection.java index 016d5a73a..3c361bfbc 100644 --- a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/ftp/FtpURLConnection.java +++ b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/ftp/FtpURLConnection.java @@ -399,7 +399,7 @@ public class FtpURLConnection extends URLConnection { * Read a line of text and return it for possible parsing */ private String readLine() throws IOException { - StringBuffer sb = new StringBuffer(); + StringBuilder sb = new StringBuilder(); int c; while ((c = ctrlInput.read()) != '\n') { sb.append((char) c); diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnection.java b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnection.java index 505c6b26a..104a9818e 100644 --- a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnection.java +++ b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnection.java @@ -1174,7 +1174,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection { */ String readln() throws IOException { boolean lastCr = false; - StringBuffer result = new StringBuffer(80); + StringBuilder result = new StringBuilder(80); int c = is.read(); if (c < 0) { return null; diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/Handler.java b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/Handler.java index d2999137b..4db9910ab 100644 --- a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/Handler.java +++ b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/Handler.java @@ -99,7 +99,7 @@ public class Handler extends URLStreamHandler { */ @Override protected String toExternalForm(URL url) { - StringBuffer sb = new StringBuffer(); + StringBuilder sb = new StringBuilder(); sb.append("jar:"); //$NON-NLS-1$ sb.append(url.getFile()); String ref = url.getRef(); diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/JarURLConnection.java b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/JarURLConnection.java index 56c1f3c99..34e7d07e0 100644 --- a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/JarURLConnection.java +++ b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/JarURLConnection.java @@ -138,9 +138,9 @@ public class JarURLConnection extends java.net.JarURLConnection { JarFile openJarFile() throws IOException { JarFile jar = null; if (jarFileURL.getProtocol().equals("file")) { //$NON-NLS-1$ - jar = new JarFile(new File(Util.decode(jarFileURL.getFile(), false)), - true, ZipFile.OPEN_READ); - } else{ + jar = new JarFile(new File(Util.decode(jarFileURL.getFile(), false, + "UTF-8")), true, ZipFile.OPEN_READ); + } else { final InputStream is = jarFileURL.openConnection().getInputStream(); try { jar = AccessController diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/IMemorySystem.java b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/IMemorySystem.java index b765c7d6c..6e8028ad5 100644 --- a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/IMemorySystem.java +++ b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/IMemorySystem.java @@ -30,10 +30,22 @@ import java.io.IOException; */ public interface IMemorySystem { + /** + * The constant representing read-only access to data in a memory map + * request. + */ public final int MMAP_READ_ONLY = 1; + /** + * The constant representing read-write access to data in a memory map + * request. + */ public final int MMAP_READ_WRITE = 2; + /** + * The constant representing copy-on-write access to data in a memory map + * request. + */ public final int MMAP_WRITE_COPY = 4; /** @@ -243,7 +255,17 @@ public interface IMemorySystem { throws NullPointerException, IndexOutOfBoundsException; // END android-added - // Primitive get & set methods + /** + * Returns the value of a single byte at the given address. + *

    + * The behavior is unspecified if address is not in the range + * that was previously allocated using malloc(). + *

    + * + * @param address + * the address at which to get the byte value. + * @return the value of the byte. + */ public byte getByte(int address); /** @@ -275,6 +297,21 @@ public interface IMemorySystem { */ public short getShort(int address); + /** + * Gets the value of the signed two-byte integer stored in the given byte + * order at the given address. + *

    + * The behavior is unspecified if (address ... address + 2) is + * not wholly within the range that was previously allocated using + * malloc(). + *

    + * + * @param address + * the platform address of the start of the two-byte value. + * @param endianness + * the required interpretation of the short endianness. + * @return the value of the two-byte integer as a Java short. + */ public short getShort(int address, Endianness endianness); /** @@ -474,17 +511,25 @@ public interface IMemorySystem { public void setAddress(int address, int value); /** - * TODO: JavaDoc - * + * Map file content into memory. + * * @param fileDescriptor + * a handle to the file that is to be memory mapped. * @param alignment + * the offset in the file where the mapping should begin. * @param size + * the number of bytes that are requested to map. * @param mapMode - * @return + * the desired access mode as defined by one of the constants + * {@link IMemorySystem#MMAP_READ_ONLY}, + * {@link IMemorySystem#MMAP_READ_WRITE}, + * {@link IMemorySystem#MMAP_WRITE_COPY} + * @return the start address of the mapped memory area. * @throws IOException + * if an exception occurs mapping the file into memory. */ - public int mmap(int fileDescriptor, long alignment, long size, - int mapMode) throws IOException; + public int mmap(int fileDescriptor, long alignment, long size, int mapMode) + throws IOException; /** * TODO: JavaDoc diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSFileSystem.java b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSFileSystem.java index 20cf7cbb6..08bdac6db 100644 --- a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSFileSystem.java +++ b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSFileSystem.java @@ -24,6 +24,7 @@ package org.apache.harmony.luni.platform; import java.io.FileDescriptor; import java.io.FileNotFoundException; import java.io.IOException; +import java.io.UnsupportedEncodingException; /** * This is the portable implementation of the file system interface. @@ -239,7 +240,14 @@ class OSFileSystem implements IFileSystem { } int handler = openImpl(fileName, mode); if (handler < 0) { - throw new FileNotFoundException(new String(fileName)); + try { + throw new FileNotFoundException(new String(fileName, "UTF-8")); + } catch (java.io.UnsupportedEncodingException e) { + // UTF-8 should always be supported, so throw an assertion + FileNotFoundException fnfe = new FileNotFoundException(new String(fileName)); + e.initCause(fnfe); + throw new AssertionError(e); + } } return handler; } diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSNetworkSystem.java b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSNetworkSystem.java index 0c9ac8a94..1ec6240d2 100644 --- a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSNetworkSystem.java +++ b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSNetworkSystem.java @@ -546,8 +546,8 @@ final class OSNetworkSystem implements INetworkSystem { * all sockets interested in write and connect * @param timeout * timeout in milliseconds - * @returns each element describes the corresponding state of the descriptor - * in the read and write arrays. + * @return each element describes the corresponding state of the descriptor + * in the read and write arrays. * @throws SocketException */ public int[] select(FileDescriptor[] readFDs, FileDescriptor[] writeFDs, diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/util/ExternalMessages.properties b/libcore/luni/src/main/java/org/apache/harmony/luni/util/ExternalMessages.properties index c740ae99a..280a8f565 100644 --- a/libcore/luni/src/main/java/org/apache/harmony/luni/util/ExternalMessages.properties +++ b/libcore/luni/src/main/java/org/apache/harmony/luni/util/ExternalMessages.properties @@ -325,3 +325,4 @@ KA026=JAR entry {0} not found in {1} KA027=Inputstream of the JarURLConnection has been closed KA028=Cannot set protocol version when stream in use KA029=Can't find resource for bundle {0}, key {1} +KA030=Write end dead diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/util/FloatingPointParser.java b/libcore/luni/src/main/java/org/apache/harmony/luni/util/FloatingPointParser.java index 642d309d0..873403976 100644 --- a/libcore/luni/src/main/java/org/apache/harmony/luni/util/FloatingPointParser.java +++ b/libcore/luni/src/main/java/org/apache/harmony/luni/util/FloatingPointParser.java @@ -24,94 +24,94 @@ package org.apache.harmony.luni.util; */ public final class FloatingPointParser { - private static final class StringExponentPair { - String s; - - int e; - - boolean negative; - - StringExponentPair(String s, int e, boolean negative) { - this.s = s; - this.e = e; - this.negative = negative; - } - } - - /** - * Takes a String and an integer exponent. The String should hold a positive - * integer value (or zero). The exponent will be used to calculate the - * floating point number by taking the positive integer the String - * represents and multiplying by 10 raised to the power of the of the - * exponent. Returns the closest double value to the real number - * - * @param s - * the String that will be parsed to a floating point - * @param e - * an int represent the 10 to part - * @return the double closest to the real number - * - * @exception NumberFormatException - * if the String doesn't represent a positive integer value - */ - private static native double parseDblImpl(String s, int e); - - /** - * Takes a String and an integer exponent. The String should hold a positive - * integer value (or zero). The exponent will be used to calculate the - * floating point number by taking the positive integer the String - * represents and multiplying by 10 raised to the power of the of the - * exponent. Returns the closest float value to the real number - * - * @param s - * the String that will be parsed to a floating point - * @param e - * an int represent the 10 to part - * @return the float closest to the real number - * - * @exception NumberFormatException - * if the String doesn't represent a positive integer value - */ - private static native float parseFltImpl(String s, int e); - - /** - * Takes a String and does some initial parsing. Should return a - * StringExponentPair containing a String with no leading or trailing white - * space and trailing zeroes eliminated. The exponent of the - * StringExponentPair will be used to calculate the floating point number by - * taking the positive integer the String represents and multiplying by 10 - * raised to the power of the of the exponent. - * - * @param s - * the String that will be parsed to a floating point - * @param length - * the length of s - * @return a StringExponentPair with necessary values - * - * @exception NumberFormatException - * if the String doesn't pass basic tests - */ - private static StringExponentPair initialParse(String s, int length) { - boolean negative = false; - char c; - int start, end, decimal; - int e = 0; - - start = 0; - if (length == 0) - throw new NumberFormatException(s); - - c = s.charAt(length - 1); - if (c == 'D' || c == 'd' || c == 'F' || c == 'f') { - length--; - if (length == 0) - throw new NumberFormatException(s); - } - - end = Math.max(s.indexOf('E'), s.indexOf('e')); - if (end > -1) { - if (end + 1 == length) - throw new NumberFormatException(s); + private static final class StringExponentPair { + String s; + + int e; + + boolean negative; + + StringExponentPair(String s, int e, boolean negative) { + this.s = s; + this.e = e; + this.negative = negative; + } + } + + /** + * Takes a String and an integer exponent. The String should hold a positive + * integer value (or zero). The exponent will be used to calculate the + * floating point number by taking the positive integer the String + * represents and multiplying by 10 raised to the power of the of the + * exponent. Returns the closest double value to the real number + * + * @param s + * the String that will be parsed to a floating point + * @param e + * an int represent the 10 to part + * @return the double closest to the real number + * + * @exception NumberFormatException + * if the String doesn't represent a positive integer value + */ + private static native double parseDblImpl(String s, int e); + + /** + * Takes a String and an integer exponent. The String should hold a positive + * integer value (or zero). The exponent will be used to calculate the + * floating point number by taking the positive integer the String + * represents and multiplying by 10 raised to the power of the of the + * exponent. Returns the closest float value to the real number + * + * @param s + * the String that will be parsed to a floating point + * @param e + * an int represent the 10 to part + * @return the float closest to the real number + * + * @exception NumberFormatException + * if the String doesn't represent a positive integer value + */ + private static native float parseFltImpl(String s, int e); + + /** + * Takes a String and does some initial parsing. Should return a + * StringExponentPair containing a String with no leading or trailing white + * space and trailing zeroes eliminated. The exponent of the + * StringExponentPair will be used to calculate the floating point number by + * taking the positive integer the String represents and multiplying by 10 + * raised to the power of the of the exponent. + * + * @param s + * the String that will be parsed to a floating point + * @param length + * the length of s + * @return a StringExponentPair with necessary values + * + * @exception NumberFormatException + * if the String doesn't pass basic tests + */ + private static StringExponentPair initialParse(String s, int length) { + boolean negative = false; + char c; + int start, end, decimal; + int e = 0; + + start = 0; + if (length == 0) + throw new NumberFormatException(s); + + c = s.charAt(length - 1); + if (c == 'D' || c == 'd' || c == 'F' || c == 'f') { + length--; + if (length == 0) + throw new NumberFormatException(s); + } + + end = Math.max(s.indexOf('E'), s.indexOf('e')); + if (end > -1) { + if (end + 1 == length) + throw new NumberFormatException(s); int exponent_offset = end + 1; if (s.charAt(exponent_offset) == '+') { @@ -120,197 +120,208 @@ public final class FloatingPointParser { } exponent_offset++; // skip the plus sign } - try { - e = Integer.parseInt(s.substring(exponent_offset, + try { + e = Integer.parseInt(s.substring(exponent_offset, length)); } catch (NumberFormatException ex) { // ex contains the exponent substring // only so throw a new exception with // the correct string - throw new NumberFormatException(s); + throw new NumberFormatException(s); } - } else { - end = length; - } - if (length == 0) - throw new NumberFormatException(s); - - c = s.charAt(start); - if (c == '-') { - ++start; - --length; - negative = true; - } else if (c == '+') { - ++start; - --length; - } - if (length == 0) - throw new NumberFormatException(s); - - decimal = s.indexOf('.'); - if (decimal > -1) { - e -= end - decimal - 1; - s = s.substring(start, decimal) + s.substring(decimal + 1, end); - } else { - s = s.substring(start, end); - } - - if ((length = s.length()) == 0) - throw new NumberFormatException(); - - end = length; - while (end > 1 && s.charAt(end - 1) == '0') - --end; - - start = 0; - while (start < end - 1 && s.charAt(start) == '0') - start++; - - if (end != length || start != 0) { - e += length - end; - s = s.substring(start, end); + } else { + end = length; + } + if (length == 0) + throw new NumberFormatException(s); + + c = s.charAt(start); + if (c == '-') { + ++start; + --length; + negative = true; + } else if (c == '+') { + ++start; + --length; + } + if (length == 0) + throw new NumberFormatException(s); + + decimal = s.indexOf('.'); + if (decimal > -1) { + e -= end - decimal - 1; + s = s.substring(start, decimal) + s.substring(decimal + 1, end); + } else { + s = s.substring(start, end); + } + + if ((length = s.length()) == 0) + throw new NumberFormatException(); + + end = length; + while (end > 1 && s.charAt(end - 1) == '0') + --end; + + start = 0; + while (start < end - 1 && s.charAt(start) == '0') + start++; + + if (end != length || start != 0) { + e += length - end; + s = s.substring(start, end); + } + + // Trim the length of very small numbers, natives can only handle down + // to E-309 + final int APPROX_MIN_MAGNITUDE = -359; + final int MAX_DIGITS = 52; + length = s.length(); + if (length > MAX_DIGITS && e < APPROX_MIN_MAGNITUDE) { + int d = Math.min(APPROX_MIN_MAGNITUDE - e, length - 1); + s = s.substring(0, length - d); + e += d; } - return new StringExponentPair(s, e, negative); - } - - /* - * Assumes the string is trimmed. - */ - private static double parseDblName(String namedDouble, int length) { - // Valid strings are only +Nan, NaN, -Nan, +Infinity, Infinity, - // -Infinity. - if ((length != 3) && (length != 4) && (length != 8) && (length != 9)) { - throw new NumberFormatException(); - } - - boolean negative = false; - int cmpstart = 0; - switch (namedDouble.charAt(0)) { - case '-': - negative = true; // fall through - case '+': - cmpstart = 1; - default: - } - - if (namedDouble.regionMatches(false, cmpstart, "Infinity", 0, 8)) { - return negative ? Double.NEGATIVE_INFINITY - : Float.POSITIVE_INFINITY; - } - - if (namedDouble.regionMatches(false, cmpstart, "NaN", 0, 3)) { - return Double.NaN; - } - - throw new NumberFormatException(); - } - - /* - * Assumes the string is trimmed. - */ - private static float parseFltName(String namedFloat, int length) { - // Valid strings are only +Nan, NaN, -Nan, +Infinity, Infinity, - // -Infinity. - if ((length != 3) && (length != 4) && (length != 8) && (length != 9)) { - throw new NumberFormatException(); - } - - boolean negative = false; - int cmpstart = 0; - switch (namedFloat.charAt(0)) { - case '-': - negative = true; // fall through - case '+': - cmpstart = 1; - default: - } - - if (namedFloat.regionMatches(false, cmpstart, "Infinity", 0, 8)) { - return negative ? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY; - } - - if (namedFloat.regionMatches(false, cmpstart, "NaN", 0, 3)) { - return Float.NaN; - } - - throw new NumberFormatException(); - } - - /** - * Returns the closest double value to the real number in the string. - * - * @param s - * the String that will be parsed to a floating point - * @return the double closest to the real number - * - * @exception NumberFormatException - * if the String doesn't represent a double - */ - public static double parseDouble(String s) { - s = s.trim(); - int length = s.length(); - - if (length == 0) { - throw new NumberFormatException(s); - } - - // See if this could be a named double - char last = s.charAt(length - 1); - if ((last == 'y') || (last == 'N')) { - return parseDblName(s, length); - } + return new StringExponentPair(s, e, negative); + } + + /* + * Assumes the string is trimmed. + */ + private static double parseDblName(String namedDouble, int length) { + // Valid strings are only +Nan, NaN, -Nan, +Infinity, Infinity, + // -Infinity. + if ((length != 3) && (length != 4) && (length != 8) && (length != 9)) { + throw new NumberFormatException(); + } + + boolean negative = false; + int cmpstart = 0; + switch (namedDouble.charAt(0)) { + case '-': + negative = true; // fall through + case '+': + cmpstart = 1; + default: + } + + if (namedDouble.regionMatches(false, cmpstart, "Infinity", 0, 8)) { + return negative ? Double.NEGATIVE_INFINITY + : Float.POSITIVE_INFINITY; + } + + if (namedDouble.regionMatches(false, cmpstart, "NaN", 0, 3)) { + return Double.NaN; + } + + throw new NumberFormatException(); + } + + /* + * Assumes the string is trimmed. + */ + private static float parseFltName(String namedFloat, int length) { + // Valid strings are only +Nan, NaN, -Nan, +Infinity, Infinity, + // -Infinity. + if ((length != 3) && (length != 4) && (length != 8) && (length != 9)) { + throw new NumberFormatException(); + } + + boolean negative = false; + int cmpstart = 0; + switch (namedFloat.charAt(0)) { + case '-': + negative = true; // fall through + case '+': + cmpstart = 1; + default: + } + + if (namedFloat.regionMatches(false, cmpstart, "Infinity", 0, 8)) { + return negative ? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY; + } + + if (namedFloat.regionMatches(false, cmpstart, "NaN", 0, 3)) { + return Float.NaN; + } + + throw new NumberFormatException(); + } + + /** + * Returns the closest double value to the real number in the string. + * + * @param s + * the String that will be parsed to a floating point + * @return the double closest to the real number + * + * @exception NumberFormatException + * if the String doesn't represent a double + */ + public static double parseDouble(String s) { + s = s.trim(); + int length = s.length(); + + if (length == 0) { + throw new NumberFormatException(s); + } + + // See if this could be a named double + char last = s.charAt(length - 1); + if ((last == 'y') || (last == 'N')) { + return parseDblName(s, length); + } // See if it could be a hexadecimal representation if (s.toLowerCase().indexOf("0x") != -1) { //$NON-NLS-1$ return HexStringParser.parseDouble(s); } - StringExponentPair info = initialParse(s, length); - - double result = parseDblImpl(info.s, info.e); - if (info.negative) - result = -result; - - return result; - } - - /** - * Returns the closest float value to the real number in the string. - * - * @param s - * the String that will be parsed to a floating point - * @return the float closest to the real number - * - * @exception NumberFormatException - * if the String doesn't represent a float - */ - public static float parseFloat(String s) { - s = s.trim(); - int length = s.length(); - - if (length == 0) { - throw new NumberFormatException(s); - } - - // See if this could be a named float - char last = s.charAt(length - 1); - if ((last == 'y') || (last == 'N')) { - return parseFltName(s, length); - } + StringExponentPair info = initialParse(s, length); + + double result = parseDblImpl(info.s, info.e); + if (info.negative) + result = -result; + + return result; + } + + /** + * Returns the closest float value to the real number in the string. + * + * @param s + * the String that will be parsed to a floating point + * @return the float closest to the real number + * + * @exception NumberFormatException + * if the String doesn't represent a float + */ + public static float parseFloat(String s) { + s = s.trim(); + int length = s.length(); + + if (length == 0) { + throw new NumberFormatException(s); + } + + // See if this could be a named float + char last = s.charAt(length - 1); + if ((last == 'y') || (last == 'N')) { + return parseFltName(s, length); + } // See if it could be a hexadecimal representation if (s.toLowerCase().indexOf("0x") != -1) { //$NON-NLS-1$ return HexStringParser.parseFloat(s); } - StringExponentPair info = initialParse(s, length); + StringExponentPair info = initialParse(s, length); - float result = parseFltImpl(info.s, info.e); - if (info.negative) - result = -result; + float result = parseFltImpl(info.s, info.e); + if (info.negative) + result = -result; - return result; - } + return result; + } } diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/util/Util.java b/libcore/luni/src/main/java/org/apache/harmony/luni/util/Util.java index 0688e7d2c..e4515aedc 100644 --- a/libcore/luni/src/main/java/org/apache/harmony/luni/util/Util.java +++ b/libcore/luni/src/main/java/org/apache/harmony/luni/util/Util.java @@ -20,33 +20,34 @@ package org.apache.harmony.luni.util; import java.io.ByteArrayOutputStream; import java.io.UTFDataFormatException; +import java.io.UnsupportedEncodingException; import java.util.Calendar; import java.util.TimeZone; public final class Util { - private static String[] WEEKDAYS = new String[] { "", "Sunday", "Monday", - "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; + private static String[] WEEKDAYS = new String[] { "", "Sunday", "Monday", + "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; - private static String[] MONTHS = new String[] { "January", "February", - "March", "April", "May", "June", "July", "August", "September", - "October", "November", "December" }; + private static String[] MONTHS = new String[] { "January", "February", + "March", "April", "May", "June", "July", "August", "September", + "October", "November", "December" }; - private static final String defaultEncoding; + private static final String defaultEncoding; - static { + static { // BEGIN android-changed String encoding = System.getProperty("file.encoding"); // END android-changed - if (encoding != null) { - try { - "".getBytes(encoding); + if (encoding != null) { + try { + "".getBytes(encoding); } catch (Throwable t) { encoding = null; - } - } + } + } defaultEncoding = encoding; - } + } /** * Get bytes from String using default encoding; default encoding can @@ -55,15 +56,15 @@ public final class Util { * @return byte array */ public static byte[] getBytes(String name) { - if (defaultEncoding != null) { - try { - return name.getBytes(defaultEncoding); - } catch (java.io.UnsupportedEncodingException e) { - } - } + if (defaultEncoding != null) { + try { + return name.getBytes(defaultEncoding); + } catch (java.io.UnsupportedEncodingException e) { + } + } return name.getBytes(); - } - + } + /** * Get bytes from String with UTF8 encoding * @param name @@ -78,29 +79,29 @@ public final class Util { } } - public static String toString(byte[] bytes) { - if (defaultEncoding != null) { - try { - return new String(bytes, 0, bytes.length, defaultEncoding); - } catch (java.io.UnsupportedEncodingException e) { - } - } - return new String(bytes, 0, bytes.length); - } + public static String toString(byte[] bytes) { + if (defaultEncoding != null) { + try { + return new String(bytes, 0, bytes.length, defaultEncoding); + } catch (java.io.UnsupportedEncodingException e) { + } + } + return new String(bytes, 0, bytes.length); + } public static String toUTF8String(byte[] bytes) { return toUTF8String(bytes, 0, bytes.length); - } - - public static String toString(byte[] bytes, int offset, int length) { - if (defaultEncoding != null) { - try { - return new String(bytes, offset, length, defaultEncoding); - } catch (java.io.UnsupportedEncodingException e) { - } - } - return new String(bytes, offset, length); - } + } + + public static String toString(byte[] bytes, int offset, int length) { + if (defaultEncoding != null) { + try { + return new String(bytes, offset, length, defaultEncoding); + } catch (java.io.UnsupportedEncodingException e) { + } + } + return new String(bytes, offset, length); + } public static String toUTF8String(byte[] bytes, int offset, int length) { try { @@ -109,174 +110,189 @@ public final class Util { return toString(bytes, offset, length); } } + + /** + * Answers the millisecond value of the date and time parsed from the + * specified String. Many date/time formats are recognized + * + * @param string + * the String to parse + * @return the millisecond value parsed from the String + */ + public static long parseDate(String string) { + int offset = 0, length = string.length(), state = 0; + int year = -1, month = -1, date = -1; + int hour = -1, minute = -1, second = -1; + final int PAD = 0, LETTERS = 1, NUMBERS = 2; + StringBuilder buffer = new StringBuilder(); - /** - * Returns the millisecond value of the date and time parsed from the - * specified String. Many date/time formats are recognized - * - * @param string - * the String to parse - * @return the millisecond value parsed from the String - */ - public static long parseDate(String string) { - int offset = 0, length = string.length(), state = 0; - int year = -1, month = -1, date = -1; - int hour = -1, minute = -1, second = -1; - final int PAD = 0, LETTERS = 1, NUMBERS = 2; - StringBuffer buffer = new StringBuffer(); - - while (offset <= length) { - char next = offset < length ? string.charAt(offset) : '\r'; - offset++; + while (offset <= length) { + char next = offset < length ? string.charAt(offset) : '\r'; + offset++; - int nextState; - if ((next >= 'a' && next <= 'z') || (next >= 'A' && next <= 'Z')) - nextState = LETTERS; - else if (next >= '0' && next <= '9') - nextState = NUMBERS; - else if (" ,-:\r\t".indexOf(next) == -1) - throw new IllegalArgumentException(); - else - nextState = PAD; + int nextState; + if ((next >= 'a' && next <= 'z') || (next >= 'A' && next <= 'Z')) + nextState = LETTERS; + else if (next >= '0' && next <= '9') + nextState = NUMBERS; + else if (" ,-:\r\t".indexOf(next) == -1) + throw new IllegalArgumentException(); + else + nextState = PAD; - if (state == NUMBERS && nextState != NUMBERS) { - int digit = Integer.parseInt(buffer.toString()); - buffer.setLength(0); - if (digit >= 70) { - if (year != -1 - || (next != ' ' && next != ',' && next != '\r')) - throw new IllegalArgumentException(); - year = digit; - } else if (next == ':') { - if (hour == -1) - hour = digit; - else if (minute == -1) - minute = digit; - else - throw new IllegalArgumentException(); - } else if (next == ' ' || next == ',' || next == '-' - || next == '\r') { - if (hour != -1 && minute == -1) - minute = digit; - else if (minute != -1 && second == -1) - second = digit; - else if (date == -1) - date = digit; - else if (year == -1) - year = digit; - else - throw new IllegalArgumentException(); - } else if (year == -1 && month != -1 && date != -1) - year = digit; - else - throw new IllegalArgumentException(); - } else if (state == LETTERS && nextState != LETTERS) { - String text = buffer.toString().toUpperCase(); - buffer.setLength(0); - if (text.length() < 3) - throw new IllegalArgumentException(); - if (parse(text, WEEKDAYS) != -1) { - } else if (month == -1 && (month = parse(text, MONTHS)) != -1) { - } else if (text.equals("GMT")) { - } else - throw new IllegalArgumentException(); - } + if (state == NUMBERS && nextState != NUMBERS) { + int digit = Integer.parseInt(buffer.toString()); + buffer.setLength(0); + if (digit >= 70) { + if (year != -1 + || (next != ' ' && next != ',' && next != '\r')) + throw new IllegalArgumentException(); + year = digit; + } else if (next == ':') { + if (hour == -1) + hour = digit; + else if (minute == -1) + minute = digit; + else + throw new IllegalArgumentException(); + } else if (next == ' ' || next == ',' || next == '-' + || next == '\r') { + if (hour != -1 && minute == -1) + minute = digit; + else if (minute != -1 && second == -1) + second = digit; + else if (date == -1) + date = digit; + else if (year == -1) + year = digit; + else + throw new IllegalArgumentException(); + } else if (year == -1 && month != -1 && date != -1) + year = digit; + else + throw new IllegalArgumentException(); + } else if (state == LETTERS && nextState != LETTERS) { + String text = buffer.toString().toUpperCase(); + buffer.setLength(0); + if (text.length() < 3) + throw new IllegalArgumentException(); + if (parse(text, WEEKDAYS) != -1) { + } else if (month == -1 && (month = parse(text, MONTHS)) != -1) { + } else if (text.equals("GMT")) { + } else + throw new IllegalArgumentException(); + } - if (nextState == LETTERS || nextState == NUMBERS) - buffer.append(next); - state = nextState; - } + if (nextState == LETTERS || nextState == NUMBERS) + buffer.append(next); + state = nextState; + } - if (year != -1 && month != -1 && date != -1) { - if (hour == -1) - hour = 0; - if (minute == -1) - minute = 0; - if (second == -1) - second = 0; - Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT")); - int current = cal.get(Calendar.YEAR) - 80; - if (year < 100) { - year += current / 100 * 100; - if (year < current) - year += 100; - } - cal.set(Calendar.YEAR, year); - cal.set(Calendar.MONTH, month); - cal.set(Calendar.DATE, date); - cal.set(Calendar.HOUR_OF_DAY, hour); - cal.set(Calendar.MINUTE, minute); - cal.set(Calendar.SECOND, second); - cal.set(Calendar.MILLISECOND, 0); - return cal.getTime().getTime(); - } - throw new IllegalArgumentException(); - } + if (year != -1 && month != -1 && date != -1) { + if (hour == -1) + hour = 0; + if (minute == -1) + minute = 0; + if (second == -1) + second = 0; + Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT")); + int current = cal.get(Calendar.YEAR) - 80; + if (year < 100) { + year += current / 100 * 100; + if (year < current) + year += 100; + } + cal.set(Calendar.YEAR, year); + cal.set(Calendar.MONTH, month); + cal.set(Calendar.DATE, date); + cal.set(Calendar.HOUR_OF_DAY, hour); + cal.set(Calendar.MINUTE, minute); + cal.set(Calendar.SECOND, second); + cal.set(Calendar.MILLISECOND, 0); + return cal.getTime().getTime(); + } + throw new IllegalArgumentException(); + } - private static int parse(String string, String[] array) { - int length = string.length(); - for (int i = 0; i < array.length; i++) { - if (string.regionMatches(true, 0, array[i], 0, length)) - return i; - } - return -1; - } + private static int parse(String string, String[] array) { + int length = string.length(); + for (int i = 0; i < array.length; i++) { + if (string.regionMatches(true, 0, array[i], 0, length)) + return i; + } + return -1; + } - public static String convertFromUTF8(byte[] buf, int offset, int utfSize) - throws UTFDataFormatException { - return convertUTF8WithBuf(buf, new char[utfSize], offset, utfSize); - } + public static String convertFromUTF8(byte[] buf, int offset, int utfSize) + throws UTFDataFormatException { + return convertUTF8WithBuf(buf, new char[utfSize], offset, utfSize); + } - public static String convertUTF8WithBuf(byte[] buf, char[] out, int offset, - int utfSize) throws UTFDataFormatException { - int count = 0, s = 0, a; - while (count < utfSize) { - if ((out[s] = (char) buf[offset + count++]) < '\u0080') - s++; - else if (((a = out[s]) & 0xe0) == 0xc0) { - if (count >= utfSize) - throw new UTFDataFormatException(Msg.getString("K0062", - count)); + public static String convertUTF8WithBuf(byte[] buf, char[] out, int offset, + int utfSize) throws UTFDataFormatException { + int count = 0, s = 0, a; + while (count < utfSize) { + if ((out[s] = (char) buf[offset + count++]) < '\u0080') + s++; + else if (((a = out[s]) & 0xe0) == 0xc0) { + if (count >= utfSize) + throw new UTFDataFormatException(Msg.getString("K0062", + count)); // BEGIN android-changed int b = buf[offset + count++]; // END android-changed - if ((b & 0xC0) != 0x80) - throw new UTFDataFormatException(Msg.getString("K0062", - (count - 1))); - out[s++] = (char) (((a & 0x1F) << 6) | (b & 0x3F)); - } else if ((a & 0xf0) == 0xe0) { - if (count + 1 >= utfSize) - throw new UTFDataFormatException(Msg.getString("K0063", - (count + 1))); + if ((b & 0xC0) != 0x80) + throw new UTFDataFormatException(Msg.getString("K0062", + (count - 1))); + out[s++] = (char) (((a & 0x1F) << 6) | (b & 0x3F)); + } else if ((a & 0xf0) == 0xe0) { + if (count + 1 >= utfSize) + throw new UTFDataFormatException(Msg.getString("K0063", + (count + 1))); // BEGIN android-changed int b = buf[offset + count++]; int c = buf[offset + count++]; // END android-changed - if (((b & 0xC0) != 0x80) || ((c & 0xC0) != 0x80)) - throw new UTFDataFormatException(Msg.getString("K0064", - (count - 2))); - out[s++] = (char) (((a & 0x0F) << 12) | ((b & 0x3F) << 6) | (c & 0x3F)); - } else { - throw new UTFDataFormatException(Msg.getString("K0065", - (count - 1))); - } - } - return new String(out, 0, s); + if (((b & 0xC0) != 0x80) || ((c & 0xC0) != 0x80)) + throw new UTFDataFormatException(Msg.getString("K0064", + (count - 2))); + out[s++] = (char) (((a & 0x0F) << 12) | ((b & 0x3F) << 6) | (c & 0x3F)); + } else { + throw new UTFDataFormatException(Msg.getString("K0065", + (count - 1))); + } + } + return new String(out, 0, s); + } + + /** + * '%' and two following hex digit characters are converted to the + * equivalent byte value. All other characters are passed through + * unmodified. e.g. "ABC %24%25" -> "ABC $%" + * + * @param s + * java.lang.String The encoded string. + * @return java.lang.String The decoded version. + */ + public static String decode(String s, boolean convertPlus) { + return decode(s, convertPlus, null); } /** * '%' and two following hex digit characters are converted to the * equivalent byte value. All other characters are passed through * unmodified. e.g. "ABC %24%25" -> "ABC $%" - * + * * @param s * java.lang.String The encoded string. + * @param encoding + * the specified encoding * @return java.lang.String The decoded version. */ - public static String decode(String s, boolean convertPlus) { + public static String decode(String s, boolean convertPlus, String encoding) { if (!convertPlus && s.indexOf('%') == -1) return s; - StringBuffer result = new StringBuffer(s.length()); + StringBuilder result = new StringBuilder(s.length()); ByteArrayOutputStream out = new ByteArrayOutputStream(); for (int i = 0; i < s.length();) { char c = s.charAt(i); @@ -297,7 +313,15 @@ public final class Util { out.write((byte) ((d1 << 4) + d2)); i += 3; } while (i < s.length() && s.charAt(i) == '%'); - result.append(out.toString()); + if (encoding == null) { + result.append(out.toString()); + } else { + try { + result.append(out.toString(encoding)); + } catch (UnsupportedEncodingException e) { + throw new IllegalArgumentException(e); + } + } continue; } else result.append(c); @@ -305,32 +329,32 @@ public final class Util { } return result.toString(); } - - public static String toASCIILowerCase(String s) { + + public static String toASCIILowerCase(String s) { int len = s.length(); - StringBuilder buffer = new StringBuilder(len); - for (int i = 0; i < len; i++) { - char c = s.charAt(i); - if ('A' <= c && c <= 'Z') { - buffer.append((char) (c + ('a' - 'A'))); - } else { - buffer.append(c); - } - } - return buffer.toString(); - } - - public static String toASCIIUpperCase(String s) { + StringBuilder buffer = new StringBuilder(len); + for (int i = 0; i < len; i++) { + char c = s.charAt(i); + if ('A' <= c && c <= 'Z') { + buffer.append((char) (c + ('a' - 'A'))); + } else { + buffer.append(c); + } + } + return buffer.toString(); + } + + public static String toASCIIUpperCase(String s) { int len = s.length(); StringBuilder buffer = new StringBuilder(len); for (int i = 0; i < len; i++) { - char c = s.charAt(i); - if ('a' <= c && c <= 'z') { - buffer.append((char) (c - ('a' - 'A'))); - } else { - buffer.append(c); - } - } - return buffer.toString(); - } + char c = s.charAt(i); + if ('a' <= c && c <= 'z') { + buffer.append((char) (c - ('a' - 'A'))); + } else { + buffer.append(c); + } + } + return buffer.toString(); + } } diff --git a/libcore/luni/src/main/native/cbigint.c b/libcore/luni/src/main/native/cbigint.c index 77ee0f8c5..d3279401e 100644 --- a/libcore/luni/src/main/native/cbigint.c +++ b/libcore/luni/src/main/native/cbigint.c @@ -18,7 +18,7 @@ #include #include "cbigint.h" -#if defined(LINUX) || defined(FREEBSD) || defined(ZOS) +#if defined(LINUX) || defined(FREEBSD) || defined(ZOS) || defined(MACOSX) || defined(AIX) #define USE_LL #endif @@ -665,7 +665,7 @@ tenToTheEHighPrecision (U_64 * result, IDATA length, jint e) do { overflow = simpleAppendDecimalDigitHighPrecision(result, length, 0); if (overflow) - result[length++] = overflow; + result[length++] = overflow; } while (--e); */ return length; @@ -686,7 +686,7 @@ timesTenToTheEHighPrecision (U_64 * result, IDATA length, jint e) do { overflow = simpleAppendDecimalDigitHighPrecision(result, length, 0); if (overflow) - result[length++] = overflow; + result[length++] = overflow; } while (--e); */ /* Replace the current implementaion which performs a diff --git a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/io/AllTests.java b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/io/AllTests.java index 778e52705..056b5214e 100644 --- a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/io/AllTests.java +++ b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/io/AllTests.java @@ -34,6 +34,7 @@ public class AllTests TestSuite suite = tests.TestSuiteFactory.createTestSuite("Tests for java.io"); suite.addTestSuite(BufferedReaderTest.class); + suite.addTestSuite(FileCanonPathCacheTest.class); suite.addTestSuite(FilePermissionTest.class); suite.addTestSuite(FileTest.class); suite.addTestSuite(InputStreamReaderTest.class); diff --git a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/io/FileCanonPathCacheTest.java b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/io/FileCanonPathCacheTest.java new file mode 100644 index 000000000..f2ac7f3df --- /dev/null +++ b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/io/FileCanonPathCacheTest.java @@ -0,0 +1,120 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.luni.tests.java.io; + +import java.io.File; + +import org.apache.harmony.luni.internal.io.FileCanonPathCache; + +import junit.framework.TestCase; + +public class FileCanonPathCacheTest extends TestCase { + + private static int DEFAULT_TIMEOUT = 600000; + + @Override + public void setUp() throws Exception { + FileCanonPathCache.clear(); + FileCanonPathCache.setTimeout(DEFAULT_TIMEOUT); + } + + public void testGetSet() throws Exception { + File file1 = new File("test/hello~1"); + assertNull(FileCanonPathCache.get(file1.getAbsolutePath())); + FileCanonPathCache.put(file1.getAbsolutePath(), file1 + .getCanonicalPath()); + assertEquals(file1.getCanonicalPath(), FileCanonPathCache.get(file1 + .getAbsolutePath())); + + File file2 = new File("test/world~1"); + assertNull(FileCanonPathCache.get(file2.getAbsolutePath())); + FileCanonPathCache.put(file2.getAbsolutePath(), file2 + .getCanonicalPath()); + assertEquals(file2.getCanonicalPath(), FileCanonPathCache.get(file2 + .getAbsolutePath())); + + assertNull(FileCanonPathCache.get("notexist")); + } + + public void testGetTimeout01() throws Exception { + FileCanonPathCache.setTimeout(10); + + File file1 = new File("test/hello~1"); + assertNull(FileCanonPathCache.get(file1.getAbsolutePath())); + FileCanonPathCache.put(file1.getAbsolutePath(), file1 + .getCanonicalPath()); + Thread.sleep(50); + assertNull(FileCanonPathCache.get(file1.getAbsolutePath())); + } + + public void testGetTimeout02() throws Exception { + FileCanonPathCache.setTimeout(10); + + File file1 = new File("test/hello~1"); + assertNull(FileCanonPathCache.get(file1.getAbsolutePath())); + FileCanonPathCache.put(file1.getAbsolutePath(), file1 + .getCanonicalPath()); + File file2 = new File("test/hello~2"); + assertNull(FileCanonPathCache.get(file2.getAbsolutePath())); + FileCanonPathCache.put(file2.getAbsolutePath(), file2 + .getCanonicalPath()); + File file3 = new File("test/hello~3"); + assertNull(FileCanonPathCache.get(file3.getAbsolutePath())); + FileCanonPathCache.put(file3.getAbsolutePath(), file3 + .getCanonicalPath()); + File file4 = new File("test/hello~4"); + assertNull(FileCanonPathCache.get(file4.getAbsolutePath())); + FileCanonPathCache.put(file4.getAbsolutePath(), file4 + .getCanonicalPath()); + File file5 = new File("test/hello~5"); + assertNull(FileCanonPathCache.get(file5.getAbsolutePath())); + FileCanonPathCache.put(file5.getAbsolutePath(), file5 + .getCanonicalPath()); + + Thread.sleep(50); + + assertNull(FileCanonPathCache.get(file1.getAbsolutePath())); + assertNull(FileCanonPathCache.get(file2.getAbsolutePath())); + assertNull(FileCanonPathCache.get(file3.getAbsolutePath())); + assertNull(FileCanonPathCache.get(file4.getAbsolutePath())); + assertNull(FileCanonPathCache.get(file5.getAbsolutePath())); + } + + public void testCacheFull() throws Exception { + int cacheSize = FileCanonPathCache.CACHE_SIZE; + File[] files = new File[cacheSize]; + for (int i = 0; i < cacheSize; ++i) { + files[i] = new File("test/world" + i); + FileCanonPathCache.put(files[i].getAbsolutePath(), files[i] + .getCanonicalPath()); + } + + for (int i = cacheSize; i < files.length; ++i) { + assertEquals(files[i - cacheSize].getCanonicalPath(), + FileCanonPathCache.get(files[i - cacheSize] + .getAbsolutePath())); + files[i] = new File("test/world" + i); + FileCanonPathCache.put(files[i].getAbsolutePath(), files[i] + .getCanonicalPath()); + assertEquals(files[i].getCanonicalPath(), FileCanonPathCache + .get(files[i].getAbsolutePath())); + assertNull(FileCanonPathCache.get(files[i - cacheSize] + .getAbsolutePath())); + } + } +} -- 2.11.0