diff --git a/src/main/java/java/lang/Boolean.java b/src/main/java/java/lang/Boolean.java new file mode 100644 index 0000000..fee8ae1 --- /dev/null +++ b/src/main/java/java/lang/Boolean.java @@ -0,0 +1,339 @@ +/* + * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang; + +/** + * The Boolean class wraps a value of the primitive type + * {@code boolean} in an object. An object of type + * {@code Boolean} contains a single field whose type is + * {@code boolean}. + *

+ * In addition, this class provides many methods for + * converting a {@code boolean} to a {@code String} and a + * {@code String} to a {@code boolean}, as well as other + * constants and methods useful when dealing with a + * {@code boolean}. + * + * @author Arthur van Hoff + * @since JDK1.0 + */ +public final class Boolean implements java.io.Serializable, + Comparable +{ + /** + * The {@code Boolean} object corresponding to the primitive + * value {@code true}. + */ + public static final Boolean TRUE = new Boolean(true); + + /** + * The {@code Boolean} object corresponding to the primitive + * value {@code false}. + */ + public static final Boolean FALSE = new Boolean(false); + + /** + * The Class object representing the primitive type boolean. + * + * @since JDK1.1 + * + */ + // DIFFBLUE MODEL LIBRARY + // We use the int version of getPrimitiveClass instead of + // the original String version + @SuppressWarnings("unchecked") + public static final Class TYPE = (Class) Class.getPrimitiveClass(0); + + /** + * The value of the Boolean. + * + * @serial + */ + private final boolean value; + + /** use serialVersionUID from JDK 1.0.2 for interoperability */ + private static final long serialVersionUID = -3665804199014368530L; + + /** + * Allocates a {@code Boolean} object representing the + * {@code value} argument. + * + *

Note: It is rarely appropriate to use this constructor. + * Unless a new instance is required, the static factory + * {@link #valueOf(boolean)} is generally a better choice. It is + * likely to yield significantly better space and time performance. + * + * @param value the value of the {@code Boolean}. + */ + public Boolean(boolean value) { + this.value = value; + } + + /** + * Allocates a {@code Boolean} object representing the value + * {@code true} if the string argument is not {@code null} + * and is equal, ignoring case, to the string {@code "true"}. + * Otherwise, allocate a {@code Boolean} object representing the + * value {@code false}. Examples:

+ * {@code new Boolean("True")} produces a {@code Boolean} object + * that represents {@code true}.
+ * {@code new Boolean("yes")} produces a {@code Boolean} object + * that represents {@code false}. + * + * @param s the string to be converted to a {@code Boolean}. + */ + public Boolean(String s) { + this(parseBoolean(s)); + } + + /** + * Parses the string argument as a boolean. The {@code boolean} + * returned represents the value {@code true} if the string argument + * is not {@code null} and is equal, ignoring case, to the string + * {@code "true"}.

+ * Example: {@code Boolean.parseBoolean("True")} returns {@code true}.
+ * Example: {@code Boolean.parseBoolean("yes")} returns {@code false}. + * + * @param s the {@code String} containing the boolean + * representation to be parsed + * @return the boolean represented by the string argument + * @since 1.5 + */ + public static boolean parseBoolean(String s) { + return ((s != null) && s.equalsIgnoreCase("true")); + } + + /** + * Returns the value of this {@code Boolean} object as a boolean + * primitive. + * + * @return the primitive {@code boolean} value of this object. + */ + public boolean booleanValue() { + return value; + } + + /** + * Returns a {@code Boolean} instance representing the specified + * {@code boolean} value. If the specified {@code boolean} value + * is {@code true}, this method returns {@code Boolean.TRUE}; + * if it is {@code false}, this method returns {@code Boolean.FALSE}. + * If a new {@code Boolean} instance is not required, this method + * should generally be used in preference to the constructor + * {@link #Boolean(boolean)}, as this method is likely to yield + * significantly better space and time performance. + * + * @param b a boolean value. + * @return a {@code Boolean} instance representing {@code b}. + * @since 1.4 + */ + public static Boolean valueOf(boolean b) { + return (b ? TRUE : FALSE); + } + + /** + * Returns a {@code Boolean} with a value represented by the + * specified string. The {@code Boolean} returned represents a + * true value if the string argument is not {@code null} + * and is equal, ignoring case, to the string {@code "true"}. + * + * @param s a string. + * @return the {@code Boolean} value represented by the string. + */ + public static Boolean valueOf(String s) { + return parseBoolean(s) ? TRUE : FALSE; + } + + /** + * Returns a {@code String} object representing the specified + * boolean. If the specified boolean is {@code true}, then + * the string {@code "true"} will be returned, otherwise the + * string {@code "false"} will be returned. + * + * @param b the boolean to be converted + * @return the string representation of the specified {@code boolean} + * @since 1.4 + */ + public static String toString(boolean b) { + return b ? "true" : "false"; + } + + /** + * Returns a {@code String} object representing this Boolean's + * value. If this object represents the value {@code true}, + * a string equal to {@code "true"} is returned. Otherwise, a + * string equal to {@code "false"} is returned. + * + * @return a string representation of this object. + */ + public String toString() { + return value ? "true" : "false"; + } + + /** + * Returns a hash code for this {@code Boolean} object. + * + * @return the integer {@code 1231} if this object represents + * {@code true}; returns the integer {@code 1237} if this + * object represents {@code false}. + */ + @Override + public int hashCode() { + return Boolean.hashCode(value); + } + + /** + * Returns a hash code for a {@code boolean} value; compatible with + * {@code Boolean.hashCode()}. + * + * @param value the value to hash + * @return a hash code value for a {@code boolean} value. + * @since 1.8 + */ + public static int hashCode(boolean value) { + return value ? 1231 : 1237; + } + + /** + * Returns {@code true} if and only if the argument is not + * {@code null} and is a {@code Boolean} object that + * represents the same {@code boolean} value as this object. + * + * @param obj the object to compare with. + * @return {@code true} if the Boolean objects represent the + * same value; {@code false} otherwise. + */ + public boolean equals(Object obj) { + if (obj instanceof Boolean) { + return value == ((Boolean)obj).booleanValue(); + } + return false; + } + + /** + * Returns {@code true} if and only if the system property + * named by the argument exists and is equal to the string + * {@code "true"}. (Beginning with version 1.0.2 of the + * JavaTM platform, the test of + * this string is case insensitive.) A system property is accessible + * through {@code getProperty}, a method defined by the + * {@code System} class. + *

+ * If there is no property with the specified name, or if the specified + * name is empty or null, then {@code false} is returned. + * + * @param name the system property name. + * @return the {@code boolean} value of the system property. + * @throws SecurityException for the same reasons as + * {@link System#getProperty(String) System.getProperty} + * @see java.lang.System#getProperty(java.lang.String) + * @see java.lang.System#getProperty(java.lang.String, java.lang.String) + */ + public static boolean getBoolean(String name) { + boolean result = false; + try { + result = parseBoolean(System.getProperty(name)); + } catch (IllegalArgumentException | NullPointerException e) { + } + return result; + } + + /** + * Compares this {@code Boolean} instance with another. + * + * @param b the {@code Boolean} instance to be compared + * @return zero if this object represents the same boolean value as the + * argument; a positive value if this object represents true + * and the argument represents false; and a negative value if + * this object represents false and the argument represents true + * @throws NullPointerException if the argument is {@code null} + * @see Comparable + * @since 1.5 + */ + public int compareTo(Boolean b) { + return compare(this.value, b.value); + } + + /** + * Compares two {@code boolean} values. + * The value returned is identical to what would be returned by: + *

+     *    Boolean.valueOf(x).compareTo(Boolean.valueOf(y))
+     * 
+ * + * @param x the first {@code boolean} to compare + * @param y the second {@code boolean} to compare + * @return the value {@code 0} if {@code x == y}; + * a value less than {@code 0} if {@code !x && y}; and + * a value greater than {@code 0} if {@code x && !y} + * @since 1.7 + */ + public static int compare(boolean x, boolean y) { + return (x == y) ? 0 : (x ? 1 : -1); + } + + /** + * Returns the result of applying the logical AND operator to the + * specified {@code boolean} operands. + * + * @param a the first operand + * @param b the second operand + * @return the logical AND of {@code a} and {@code b} + * @see java.util.function.BinaryOperator + * @since 1.8 + */ + public static boolean logicalAnd(boolean a, boolean b) { + return a && b; + } + + /** + * Returns the result of applying the logical OR operator to the + * specified {@code boolean} operands. + * + * @param a the first operand + * @param b the second operand + * @return the logical OR of {@code a} and {@code b} + * @see java.util.function.BinaryOperator + * @since 1.8 + */ + public static boolean logicalOr(boolean a, boolean b) { + return a || b; + } + + /** + * Returns the result of applying the logical XOR operator to the + * specified {@code boolean} operands. + * + * @param a the first operand + * @param b the second operand + * @return the logical XOR of {@code a} and {@code b} + * @see java.util.function.BinaryOperator + * @since 1.8 + */ + public static boolean logicalXor(boolean a, boolean b) { + return a ^ b; + } +} diff --git a/src/main/java/java/lang/Byte.java b/src/main/java/java/lang/Byte.java new file mode 100644 index 0000000..5901176 --- /dev/null +++ b/src/main/java/java/lang/Byte.java @@ -0,0 +1,510 @@ +/* + * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang; + +import org.cprover.CProver; + +/** + * + * The {@code Byte} class wraps a value of primitive type {@code byte} + * in an object. An object of type {@code Byte} contains a single + * field whose type is {@code byte}. + * + *

In addition, this class provides several methods for converting + * a {@code byte} to a {@code String} and a {@code String} to a {@code + * byte}, as well as other constants and methods useful when dealing + * with a {@code byte}. + * + * @author Nakul Saraiya + * @author Joseph D. Darcy + * @see java.lang.Number + * @since JDK1.1 + */ +public final class Byte extends Number implements Comparable { + + /** + * A constant holding the minimum value a {@code byte} can + * have, -27. + */ + public static final byte MIN_VALUE = -128; + + /** + * A constant holding the maximum value a {@code byte} can + * have, 27-1. + */ + public static final byte MAX_VALUE = 127; + + /** + * The {@code Class} instance representing the primitive type + * {@code byte}. + */ + @SuppressWarnings("unchecked") + public static final Class TYPE = (Class) Class.getPrimitiveClass(7); + + /** + * Returns a new {@code String} object representing the + * specified {@code byte}. The radix is assumed to be 10. + * + * @param b the {@code byte} to be converted + * @return the string representation of the specified {@code byte} + * @see java.lang.Integer#toString(int) + */ + public static String toString(byte b) { + return Integer.toString((int)b, 10); + } + + /** + * Returns a {@code Byte} instance representing the specified + * {@code byte} value. + * If a new {@code Byte} instance is not required, this method + * should generally be used in preference to the constructor + * {@link #Byte(byte)}, as this method is likely to yield + * significantly better space and time performance since + * all byte values are cached. + * + * @param b a byte value. + * @return a {@code Byte} instance representing {@code b}. + * @since 1.5 + */ + public static Byte valueOf(byte b) { + return new Byte(b); + } + + /** + * Parses the string argument as a signed {@code byte} in the + * radix specified by the second argument. The characters in the + * string must all be digits, of the specified radix (as + * determined by whether {@link java.lang.Character#digit(char, + * int)} returns a nonnegative value) except that the first + * character may be an ASCII minus sign {@code '-'} + * ({@code '\u005Cu002D'}) to indicate a negative value or an + * ASCII plus sign {@code '+'} ({@code '\u005Cu002B'}) to + * indicate a positive value. The resulting {@code byte} value is + * returned. + * + *

An exception of type {@code NumberFormatException} is + * thrown if any of the following situations occurs: + *

+ * + * @param s the {@code String} containing the + * {@code byte} + * representation to be parsed + * @param radix the radix to be used while parsing {@code s} + * @return the {@code byte} value represented by the string + * argument in the specified radix + * @throws NumberFormatException If the string does + * not contain a parsable {@code byte}. + */ + public static byte parseByte(String s, int radix) + throws NumberFormatException { + int i = Integer.parseInt(s, radix); + if (i < MIN_VALUE || i > MAX_VALUE) + throw new NumberFormatException( + "Value out of range. Value:\"" + s + "\" Radix:" + radix); + return (byte)i; + } + + /** + * Parses the string argument as a signed decimal {@code + * byte}. The characters in the string must all be decimal digits, + * except that the first character may be an ASCII minus sign + * {@code '-'} ({@code '\u005Cu002D'}) to indicate a negative + * value or an ASCII plus sign {@code '+'} + * ({@code '\u005Cu002B'}) to indicate a positive value. The + * resulting {@code byte} value is returned, exactly as if the + * argument and the radix 10 were given as arguments to the {@link + * #parseByte(java.lang.String, int)} method. + * + * @param s a {@code String} containing the + * {@code byte} representation to be parsed + * @return the {@code byte} value represented by the + * argument in decimal + * @throws NumberFormatException if the string does not + * contain a parsable {@code byte}. + */ + public static byte parseByte(String s) throws NumberFormatException { + return CProver.nondetByte(); //The function is handled by cbmc internally + } + + /** + * Returns a {@code Byte} object holding the value + * extracted from the specified {@code String} when parsed + * with the radix given by the second argument. The first argument + * is interpreted as representing a signed {@code byte} in + * the radix specified by the second argument, exactly as if the + * argument were given to the {@link #parseByte(java.lang.String, + * int)} method. The result is a {@code Byte} object that + * represents the {@code byte} value specified by the string. + * + *

In other words, this method returns a {@code Byte} object + * equal to the value of: + * + *

+ * {@code new Byte(Byte.parseByte(s, radix))} + *
+ * + * @param s the string to be parsed + * @param radix the radix to be used in interpreting {@code s} + * @return a {@code Byte} object holding the value + * represented by the string argument in the + * specified radix. + * @throws NumberFormatException If the {@code String} does + * not contain a parsable {@code byte}. + */ + public static Byte valueOf(String s, int radix) + throws NumberFormatException { + return valueOf(parseByte(s, radix)); + } + + /** + * Returns a {@code Byte} object holding the value + * given by the specified {@code String}. The argument is + * interpreted as representing a signed decimal {@code byte}, + * exactly as if the argument were given to the {@link + * #parseByte(java.lang.String)} method. The result is a + * {@code Byte} object that represents the {@code byte} + * value specified by the string. + * + *

In other words, this method returns a {@code Byte} object + * equal to the value of: + * + *

+ * {@code new Byte(Byte.parseByte(s))} + *
+ * + * @param s the string to be parsed + * @return a {@code Byte} object holding the value + * represented by the string argument + * @throws NumberFormatException If the {@code String} does + * not contain a parsable {@code byte}. + */ + public static Byte valueOf(String s) throws NumberFormatException { + return valueOf(s, 10); + } + + /** + * Decodes a {@code String} into a {@code Byte}. + * Accepts decimal, hexadecimal, and octal numbers given by + * the following grammar: + * + *
+ *
+ *
DecodableString: + *
Signopt DecimalNumeral + *
Signopt {@code 0x} HexDigits + *
Signopt {@code 0X} HexDigits + *
Signopt {@code #} HexDigits + *
Signopt {@code 0} OctalDigits + * + *
Sign: + *
{@code -} + *
{@code +} + *
+ *
+ * + * DecimalNumeral, HexDigits, and OctalDigits + * are as defined in section 3.10.1 of + * The Java™ Language Specification, + * except that underscores are not accepted between digits. + * + *

The sequence of characters following an optional + * sign and/or radix specifier ("{@code 0x}", "{@code 0X}", + * "{@code #}", or leading zero) is parsed as by the {@code + * Byte.parseByte} method with the indicated radix (10, 16, or 8). + * This sequence of characters must represent a positive value or + * a {@link NumberFormatException} will be thrown. The result is + * negated if first character of the specified {@code String} is + * the minus sign. No whitespace characters are permitted in the + * {@code String}. + * + * @param nm the {@code String} to decode. + * @return a {@code Byte} object holding the {@code byte} + * value represented by {@code nm} + * @throws NumberFormatException if the {@code String} does not + * contain a parsable {@code byte}. + * @see java.lang.Byte#parseByte(java.lang.String, int) + */ + public static Byte decode(String nm) throws NumberFormatException { + int i = Integer.decode(nm); + if (i < MIN_VALUE || i > MAX_VALUE) + throw new NumberFormatException( + "Value " + i + " out of range from input " + nm); + return valueOf((byte)i); + } + + /** + * The value of the {@code Byte}. + * + * @serial + */ + private final byte value; + + /** + * Constructs a newly allocated {@code Byte} object that + * represents the specified {@code byte} value. + * + * @param value the value to be represented by the + * {@code Byte}. + */ + public Byte(byte value) { + this.value = value; + } + + /** + * Constructs a newly allocated {@code Byte} object that + * represents the {@code byte} value indicated by the + * {@code String} parameter. The string is converted to a + * {@code byte} value in exactly the manner used by the + * {@code parseByte} method for radix 10. + * + * @param s the {@code String} to be converted to a + * {@code Byte} + * @throws NumberFormatException If the {@code String} + * does not contain a parsable {@code byte}. + * @see java.lang.Byte#parseByte(java.lang.String, int) + */ + public Byte(String s) throws NumberFormatException { + this.value = parseByte(s, 10); + } + + /** + * Returns the value of this {@code Byte} as a + * {@code byte}. + */ + public byte byteValue() { + return value; + } + + /** + * Returns the value of this {@code Byte} as a {@code short} after + * a widening primitive conversion. + * @jls 5.1.2 Widening Primitive Conversions + */ + public short shortValue() { + return (short)value; + } + + /** + * Returns the value of this {@code Byte} as an {@code int} after + * a widening primitive conversion. + * @jls 5.1.2 Widening Primitive Conversions + */ + public int intValue() { + return (int)value; + } + + /** + * Returns the value of this {@code Byte} as a {@code long} after + * a widening primitive conversion. + * @jls 5.1.2 Widening Primitive Conversions + */ + public long longValue() { + return (long)value; + } + + /** + * Returns the value of this {@code Byte} as a {@code float} after + * a widening primitive conversion. + * @jls 5.1.2 Widening Primitive Conversions + */ + public float floatValue() { + return (float)value; + } + + /** + * Returns the value of this {@code Byte} as a {@code double} + * after a widening primitive conversion. + * @jls 5.1.2 Widening Primitive Conversions + */ + public double doubleValue() { + return (double)value; + } + + /** + * Returns a {@code String} object representing this + * {@code Byte}'s value. The value is converted to signed + * decimal representation and returned as a string, exactly as if + * the {@code byte} value were given as an argument to the + * {@link java.lang.Byte#toString(byte)} method. + * + * @return a string representation of the value of this object in + * base 10. + */ + public String toString() { + return Integer.toString((int)value); + } + + /** + * Returns a hash code for this {@code Byte}; equal to the result + * of invoking {@code intValue()}. + * + * @return a hash code value for this {@code Byte} + */ + @Override + public int hashCode() { + return Byte.hashCode(value); + } + + /** + * Returns a hash code for a {@code byte} value; compatible with + * {@code Byte.hashCode()}. + * + * @param value the value to hash + * @return a hash code value for a {@code byte} value. + * @since 1.8 + */ + public static int hashCode(byte value) { + return (int)value; + } + + /** + * Compares this object to the specified object. The result is + * {@code true} if and only if the argument is not + * {@code null} and is a {@code Byte} object that + * contains the same {@code byte} value as this object. + * + * @param obj the object to compare with + * @return {@code true} if the objects are the same; + * {@code false} otherwise. + */ + public boolean equals(Object obj) { + if (obj instanceof Byte) { + return value == ((Byte)obj).byteValue(); + } + return false; + } + + /** + * Compares two {@code Byte} objects numerically. + * + * @param anotherByte the {@code Byte} to be compared. + * @return the value {@code 0} if this {@code Byte} is + * equal to the argument {@code Byte}; a value less than + * {@code 0} if this {@code Byte} is numerically less + * than the argument {@code Byte}; and a value greater than + * {@code 0} if this {@code Byte} is numerically + * greater than the argument {@code Byte} (signed + * comparison). + * @since 1.2 + */ + public int compareTo(Byte anotherByte) { + return compare(this.value, anotherByte.value); + } + + /** + * Compares two {@code byte} values numerically. + * The value returned is identical to what would be returned by: + *

+     *    Byte.valueOf(x).compareTo(Byte.valueOf(y))
+     * 
+ * + * @param x the first {@code byte} to compare + * @param y the second {@code byte} to compare + * @return the value {@code 0} if {@code x == y}; + * a value less than {@code 0} if {@code x < y}; and + * a value greater than {@code 0} if {@code x > y} + * @since 1.7 + */ + public static int compare(byte x, byte y) { + return x - y; + } + + /** + * Converts the argument to an {@code int} by an unsigned + * conversion. In an unsigned conversion to an {@code int}, the + * high-order 24 bits of the {@code int} are zero and the + * low-order 8 bits are equal to the bits of the {@code byte} argument. + * + * Consequently, zero and positive {@code byte} values are mapped + * to a numerically equal {@code int} value and negative {@code + * byte} values are mapped to an {@code int} value equal to the + * input plus 28. + * + * @param x the value to convert to an unsigned {@code int} + * @return the argument converted to {@code int} by an unsigned + * conversion + * @since 1.8 + */ + public static int toUnsignedInt(byte x) { + return ((int) x) & 0xff; + } + + /** + * Converts the argument to a {@code long} by an unsigned + * conversion. In an unsigned conversion to a {@code long}, the + * high-order 56 bits of the {@code long} are zero and the + * low-order 8 bits are equal to the bits of the {@code byte} argument. + * + * Consequently, zero and positive {@code byte} values are mapped + * to a numerically equal {@code long} value and negative {@code + * byte} values are mapped to a {@code long} value equal to the + * input plus 28. + * + * @param x the value to convert to an unsigned {@code long} + * @return the argument converted to {@code long} by an unsigned + * conversion + * @since 1.8 + */ + public static long toUnsignedLong(byte x) { + return ((long) x) & 0xffL; + } + + + /** + * The number of bits used to represent a {@code byte} value in two's + * complement binary form. + * + * @since 1.5 + */ + public static final int SIZE = 8; + + /** + * The number of bytes used to represent a {@code byte} value in two's + * complement binary form. + * + * @since 1.8 + */ + public static final int BYTES = SIZE / Byte.SIZE; + + /** use serialVersionUID from JDK 1.1. for interoperability */ + private static final long serialVersionUID = -7183698231559129828L; +} diff --git a/src/main/java/java/lang/Character.java b/src/main/java/java/lang/Character.java index 8952165..75a15f7 100644 --- a/src/main/java/java/lang/Character.java +++ b/src/main/java/java/lang/Character.java @@ -25,13 +25,13 @@ package java.lang; -import org.cprover.CProver; - import java.util.Arrays; import java.util.Map; import java.util.HashMap; import java.util.Locale; +import org.cprover.CProver; + /** * The {@code Character} class wraps a value of the primitive * type {@code char} in an object. An object of type @@ -7217,8 +7217,15 @@ public static char reverseBytes(char ch) { * code point. * * @since 1.7 + * + * @diffblue.limitedSupport Only works for capital latin letters. */ public static String getName(int codePoint) { + if (!isValidCodePoint(codePoint)) { + throw new IllegalArgumentException(); + } + // DIFFBLUE MODEL LIBRARY + // removed for compatibility with Java 9 and newer // if (!isValidCodePoint(codePoint)) { // throw new IllegalArgumentException(); // } @@ -7233,7 +7240,13 @@ public static String getName(int codePoint) { // + Integer.toHexString(codePoint).toUpperCase(Locale.ENGLISH); // // should never come here // return Integer.toHexString(codePoint).toUpperCase(Locale.ENGLISH); - CProver.notModelled(); - return CProver.nondetWithoutNullForNotModelled(); + return cproverGetNameRestricted(codePoint); } + + public static String cproverGetNameRestricted(int codePoint) + { + CProver.assume(codePoint >= 65 && codePoint <= 90); + return "LATIN CAPITAL LETTER " + ((char) codePoint); + } + } diff --git a/src/main/java/java/lang/Class.java b/src/main/java/java/lang/Class.java index b8ad087..9a6350a 100644 --- a/src/main/java/java/lang/Class.java +++ b/src/main/java/java/lang/Class.java @@ -25,14 +25,19 @@ package java.lang; +import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; +import org.cprover.CProverString; + +// DIFFBLUE MODEL LIBRARY +// removed for compatibility with Java 9 and newer // import sun.reflect.CallerSensitive; // import sun.reflect.Reflection; import org.cprover.CProver; -import org.cprover.CProverString; public final class Class { @@ -42,13 +47,13 @@ private Class() {} // TODO: these boolean fields model the internal encoding of classes // they should be set by the getClass methods of the different classes - private boolean isAnnotation; - private boolean isArray; - private boolean isInterface; - private boolean isSynthetic; - private boolean isLocalClass; - private boolean isMemberClass; - private boolean isEnum; + private boolean cproverIsAnnotation; + private boolean cproverIsArray; + private boolean cproverIsInterface; + private boolean cproverIsSynthetic; + private boolean cproverIsLocalClass; + private boolean cproverIsMemberClass; + private boolean cproverIsEnum; public String toString() { return (isInterface() ? "interface " : (isPrimitive() ? "" : "class ")) @@ -118,8 +123,8 @@ public static Class forName(String name, boolean initialize, } public boolean isInstance(Object obj) { return obj.getClass()==this; } - public boolean isInterface() { return isInterface; } - public boolean isArray() { return isArray; } + public boolean isInterface() { return cproverIsInterface; } + public boolean isArray() { return cproverIsArray; } public boolean isPrimitive() { // DIFFBLUE MODEL LIBRARY // We use pointer equality instead of string equality because @@ -137,12 +142,12 @@ public boolean isPrimitive() { name == "void"; } - public boolean isAnnotation() { return isAnnotation; } - public boolean isSynthetic() { return isSynthetic; } - public boolean isLocalClass() { return isLocalClass; } - public boolean isMemberClass() { return isMemberClass; } + public boolean isAnnotation() { return cproverIsAnnotation; } + public boolean isSynthetic() { return cproverIsSynthetic; } + public boolean isLocalClass() { return cproverIsLocalClass; } + public boolean isMemberClass() { return cproverIsMemberClass; } public boolean isAnonymousClass() { return "".equals(getSimpleName()); } - public boolean isEnum() { return isEnum; } + public boolean isEnum() { return cproverIsEnum; } private boolean isLocalOrAnonymousClass() { return isLocalClass() || isAnonymousClass(); } @@ -179,17 +184,21 @@ public String getName() { * @see SecurityManager#checkPermission * @see java.lang.RuntimePermission */ + // DIFFBLUE MODEL LIBRARY + // removed for compatibility with Java 9 and newer // @CallerSensitive public ClassLoader getClassLoader() { - // ClassLoader cl = getClassLoader0(); - // if (cl == null) - // return null; - // SecurityManager sm = System.getSecurityManager(); - // if (sm != null) { - // ClassLoader.checkClassLoaderPermission(cl, Reflection.getCallerClass()); - // } - // return cl; - return null; + ClassLoader cl = getClassLoader0(); + if (cl == null) + return null; + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + // DIFFBLUE MODEL LIBRARY + // removed for compatibility with Java 9 and newer + // ClassLoader.checkClassLoaderPermission(cl, Reflection.getCallerClass()); + ClassLoader.checkClassLoaderPermission(cl, null); + } + return cl; } ClassLoader getClassLoader0() { @@ -338,9 +347,9 @@ public static Class getPrimitiveClass(String s){ // This version is nicer for the symbolic execution as it knows how to // compare integers but not Strings. - // This method should be used instead of the String version whenever + // This method should be used instead of the String version whenever // possible by our models. - // Experimenting with the test booleanValue_Fail, the String version + // Experimenting with the test booleanValue_Fail, the String version // takes 8 seconds while the int version takes 3 seconds. static Class getPrimitiveClass(int i){ if(i==0) @@ -462,13 +471,139 @@ public void cproverInitializeClassLiteral( boolean isMemberClass, boolean isEnum) { this.name = name; - this.isAnnotation = isAnnotation; - this.isArray = isArray; - this.isInterface = isInterface; - this.isSynthetic = isSynthetic; - this.isLocalClass = isLocalClass; - this.isMemberClass = isMemberClass; - this.isEnum = isEnum; + this.cproverIsAnnotation = isAnnotation; + this.cproverIsArray = isArray; + this.cproverIsInterface = isInterface; + this.cproverIsSynthetic = isSynthetic; + this.cproverIsLocalClass = isLocalClass; + this.cproverIsMemberClass = isMemberClass; + this.cproverIsEnum = isEnum; + } + + /** + * Returns a {@code Field} object that reflects the specified public member + * field of the class or interface represented by this {@code Class} + * object. The {@code name} parameter is a {@code String} specifying the + * simple name of the desired field. + * + *

The field to be reflected is determined by the algorithm that + * follows. Let C be the class or interface represented by this object: + * + *

    + *
  1. If C declares a public field with the name specified, that is the + * field to be reflected.
  2. + *
  3. If no field was found in step 1 above, this algorithm is applied + * recursively to each direct superinterface of C. The direct + * superinterfaces are searched in the order they were declared.
  4. + *
  5. If no field was found in steps 1 and 2 above, and C has a + * superclass S, then this algorithm is invoked recursively upon S. + * If C has no superclass, then a {@code NoSuchFieldException} + * is thrown.
  6. + *
+ * + *

If this {@code Class} object represents an array type, then this + * method does not find the {@code length} field of the array type. + * + * @param name the field name + * @return the {@code Field} object of this class specified by + * {@code name} + * @throws NoSuchFieldException if a field with the specified name is + * not found. + * @throws NullPointerException if {@code name} is {@code null} + * @throws SecurityException + * If a security manager, s, is present and + * the caller's class loader is not the same as or an + * ancestor of the class loader for the current class and + * invocation of {@link SecurityManager#checkPackageAccess + * s.checkPackageAccess()} denies access to the package + * of this class. + * + * @since JDK1.1 + * @jls 8.2 Class Members + * @jls 8.3 Field Declarations + */ + // DIFFBLUE MODEL LIBRARY + // removed for compatibility with Java 9 and newer + // @CallerSensitive + public Field getField(String name) throws NoSuchFieldException, SecurityException { + return new Field(this, name); } + /** + * Returns a {@code Method} object that reflects the specified public + * member method of the class or interface represented by this + * {@code Class} object. The {@code name} parameter is a + * {@code String} specifying the simple name of the desired method. The + * {@code parameterTypes} parameter is an array of {@code Class} + * objects that identify the method's formal parameter types, in declared + * order. If {@code parameterTypes} is {@code null}, it is + * treated as if it were an empty array. + * + *

If the {@code name} is "{@code }" or "{@code }" a + * {@code NoSuchMethodException} is raised. Otherwise, the method to + * be reflected is determined by the algorithm that follows. Let C be the + * class or interface represented by this object: + *

    + *
  1. C is searched for a matching method, as defined below. If a + * matching method is found, it is reflected.
  2. + *
  3. If no matching method is found by step 1 then: + *
      + *
    1. If C is a class other than {@code Object}, then this algorithm is + * invoked recursively on the superclass of C.
    2. + *
    3. If C is the class {@code Object}, or if C is an interface, then + * the superinterfaces of C (if any) are searched for a matching + * method. If any such method is found, it is reflected.
    4. + *
  4. + *
+ * + *

To find a matching method in a class or interface C:  If C + * declares exactly one public method with the specified name and exactly + * the same formal parameter types, that is the method reflected. If more + * than one such method is found in C, and one of these methods has a + * return type that is more specific than any of the others, that method is + * reflected; otherwise one of the methods is chosen arbitrarily. + * + *

Note that there may be more than one matching method in a + * class because while the Java language forbids a class to + * declare multiple methods with the same signature but different + * return types, the Java virtual machine does not. This + * increased flexibility in the virtual machine can be used to + * implement various language features. For example, covariant + * returns can be implemented with {@linkplain + * java.lang.reflect.Method#isBridge bridge methods}; the bridge + * method and the method being overridden would have the same + * signature but different return types. + * + *

If this {@code Class} object represents an array type, then this + * method does not find the {@code clone()} method. + * + *

Static methods declared in superinterfaces of the class or interface + * represented by this {@code Class} object are not considered members of + * the class or interface. + * + * @param name the name of the method + * @param parameterTypes the list of parameters + * @return the {@code Method} object that matches the specified + * {@code name} and {@code parameterTypes} + * @throws NoSuchMethodException if a matching method is not found + * or if the name is "<init>"or "<clinit>". + * @throws NullPointerException if {@code name} is {@code null} + * @throws SecurityException + * If a security manager, s, is present and + * the caller's class loader is not the same as or an + * ancestor of the class loader for the current class and + * invocation of {@link SecurityManager#checkPackageAccess + * s.checkPackageAccess()} denies access to the package + * of this class. + * + * @jls 8.2 Class Members + * @jls 8.4 Method Declarations + * @since JDK1.1 + */ + // DIFFBLUE MODEL LIBRARY + // removed for compatibility with Java 9 and newer + // @CallerSensitive + public Method getMethod(String name, Class... parameterTypes) throws NoSuchMethodException, SecurityException { + return new Method(this, name, parameterTypes); + } } diff --git a/src/main/java/java/lang/Double.java b/src/main/java/java/lang/Double.java new file mode 100644 index 0000000..2bb0975 --- /dev/null +++ b/src/main/java/java/lang/Double.java @@ -0,0 +1,1105 @@ +/* + * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang; + +import org.cprover.CProverString; +// DIFFBLUE MODEL LIBRARY +// removed for compatibility with Java 9 and newer +// import sun.misc.FloatingDecimal; +// import sun.misc.FpUtils; +import sun.misc.DoubleConsts; +import org.cprover.CProver; +/** + * The {@code Double} class wraps a value of the primitive type + * {@code double} in an object. An object of type + * {@code Double} contains a single field whose type is + * {@code double}. + * + *

In addition, this class provides several methods for converting a + * {@code double} to a {@code String} and a + * {@code String} to a {@code double}, as well as other + * constants and methods useful when dealing with a + * {@code double}. + * + * @author Lee Boynton + * @author Arthur van Hoff + * @author Joseph D. Darcy + * @since JDK1.0 + */ +public final class Double extends Number implements Comparable { + /** + * A constant holding the positive infinity of type + * {@code double}. It is equal to the value returned by + * {@code Double.longBitsToDouble(0x7ff0000000000000L)}. + */ + public static final double POSITIVE_INFINITY = 1.0 / 0.0; + + /** + * A constant holding the negative infinity of type + * {@code double}. It is equal to the value returned by + * {@code Double.longBitsToDouble(0xfff0000000000000L)}. + */ + public static final double NEGATIVE_INFINITY = -1.0 / 0.0; + + /** + * A constant holding a Not-a-Number (NaN) value of type + * {@code double}. It is equivalent to the value returned by + * {@code Double.longBitsToDouble(0x7ff8000000000000L)}. + */ + public static final double NaN = 0.0d / 0.0; + + /** + * A constant holding the largest positive finite value of type + * {@code double}, + * (2-2-52)·21023. It is equal to + * the hexadecimal floating-point literal + * {@code 0x1.fffffffffffffP+1023} and also equal to + * {@code Double.longBitsToDouble(0x7fefffffffffffffL)}. + */ + public static final double MAX_VALUE = 0x1.fffffffffffffP+1023; // 1.7976931348623157e+308 + + /** + * A constant holding the smallest positive normal value of type + * {@code double}, 2-1022. It is equal to the + * hexadecimal floating-point literal {@code 0x1.0p-1022} and also + * equal to {@code Double.longBitsToDouble(0x0010000000000000L)}. + * + * @since 1.6 + */ + public static final double MIN_NORMAL = 0x1.0p-1022; // 2.2250738585072014E-308 + + /** + * A constant holding the smallest positive nonzero value of type + * {@code double}, 2-1074. It is equal to the + * hexadecimal floating-point literal + * {@code 0x0.0000000000001P-1022} and also equal to + * {@code Double.longBitsToDouble(0x1L)}. + */ + public static final double MIN_VALUE = 0x0.0000000000001P-1022; // 4.9e-324 + + /** + * Maximum exponent a finite {@code double} variable may have. + * It is equal to the value returned by + * {@code Math.getExponent(Double.MAX_VALUE)}. + * + * @since 1.6 + */ + public static final int MAX_EXPONENT = 1023; + + /** + * Minimum exponent a normalized {@code double} variable may + * have. It is equal to the value returned by + * {@code Math.getExponent(Double.MIN_NORMAL)}. + * + * @since 1.6 + */ + public static final int MIN_EXPONENT = -1022; + + /** + * The number of bits used to represent a {@code double} value. + * + * @since 1.5 + */ + public static final int SIZE = 64; + + /** + * The number of bytes used to represent a {@code double} value. + * + * @since 1.8 + */ + public static final int BYTES = SIZE / Byte.SIZE; + + /** + * The {@code Class} instance representing the primitive type + * {@code double}. + * + * @since JDK1.1 + */ + /* + * MODELS-LIBRARY { + * We use the int version of getPrimitiveClass instead of + * the original String version for efficiency reasons. + * } + */ + @SuppressWarnings("unchecked") + public static final Class TYPE = (Class) Class.getPrimitiveClass(7); + + /** + * Returns a string representation of the {@code double} + * argument. All characters mentioned below are ASCII characters. + *

+ * How many digits must be printed for the fractional part of + * m or a? There must be at least one digit to represent + * the fractional part, and beyond that as many, but only as many, more + * digits as are needed to uniquely distinguish the argument value from + * adjacent values of type {@code double}. That is, suppose that + * x is the exact mathematical value represented by the decimal + * representation produced by this method for a finite nonzero argument + * d. Then d must be the {@code double} value nearest + * to x; or if two {@code double} values are equally close + * to x, then d must be one of them and the least + * significant bit of the significand of d must be {@code 0}. + * + *

To create localized string representations of a floating-point + * value, use subclasses of {@link java.text.NumberFormat}. + * + * @param d the {@code double} to be converted. + * @return a string representation of the argument. + * @diffblue.noSupport + */ + public static String toString(double d) { + // return FloatingDecimal.toJavaFormatString(d); + return String.valueOf(d); + } + + /** + * Returns a hexadecimal string representation of the + * {@code double} argument. All characters mentioned below + * are ASCII characters. + * + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Examples
Floating-point ValueHexadecimal String
{@code 1.0} {@code 0x1.0p0}
{@code -1.0} {@code -0x1.0p0}
{@code 2.0} {@code 0x1.0p1}
{@code 3.0} {@code 0x1.8p1}
{@code 0.5} {@code 0x1.0p-1}
{@code 0.25} {@code 0x1.0p-2}
{@code Double.MAX_VALUE}{@code 0x1.fffffffffffffp1023}
{@code Minimum Normal Value}{@code 0x1.0p-1022}
{@code Maximum Subnormal Value}{@code 0x0.fffffffffffffp-1022}
{@code Double.MIN_VALUE}{@code 0x0.0000000000001p-1022}
+ * @param d the {@code double} to be converted. + * @return a hex string representation of the argument. + * @since 1.5 + * @author Joseph D. Darcy + */ + public static String toHexString(double d) { + /* + * Modeled after the "a" conversion specifier in C99, section + * 7.19.6.1; however, the output of this method is more + * tightly specified. + */ + if (!isFinite(d) ) + // For infinity and NaN, use the decimal output. + return Double.toString(d); + else { + // Initialized to maximum size of output. + StringBuilder answer = new StringBuilder(24); + + if (Math.copySign(1.0, d) == -1.0) // value is negative, + answer.append("-"); // so append sign info + + answer.append("0x"); + + d = Math.abs(d); + + if(d == 0.0) { + answer.append("0.0p0"); + } else { + boolean subnormal = (d < DoubleConsts.MIN_NORMAL); + + // Isolate significand bits and OR in a high-order bit + // so that the string representation has a known + // length. + long signifBits = (Double.doubleToLongBits(d) + & DoubleConsts.SIGNIF_BIT_MASK) | + 0x1000000000000000L; + + // Subnormal values have a 0 implicit bit; normal + // values have a 1 implicit bit. + answer.append(subnormal ? "0." : "1."); + + // Isolate the low-order 13 digits of the hex + // representation. If all the digits are zero, + // replace with a single 0; otherwise, remove all + // trailing zeros. + String signif = CProverString.substring(Long.toHexString(signifBits), 3, 16); + answer.append(signif.equals("0000000000000") ? // 13 zeros + "0": + signif.replaceFirst("0{1,12}$", "")); + + answer.append('p'); + // If the value is subnormal, use the E_min exponent + // value for double; otherwise, extract and report d's + // exponent (the representation of a subnormal uses + // E_min -1). + answer.append(subnormal ? + DoubleConsts.MIN_EXPONENT: + Math.getExponent(d)); + } + return answer.toString(); + } + } + + /** + * Returns a {@code Double} object holding the + * {@code double} value represented by the argument string + * {@code s}. + * + *

If {@code s} is {@code null}, then a + * {@code NullPointerException} is thrown. + * + *

Leading and trailing whitespace characters in {@code s} + * are ignored. Whitespace is removed as if by the {@link + * String#trim} method; that is, both ASCII space and control + * characters are removed. The rest of {@code s} should + * constitute a FloatValue as described by the lexical + * syntax rules: + * + *

+ *
+ *
FloatValue: + *
Signopt {@code NaN} + *
Signopt {@code Infinity} + *
Signopt FloatingPointLiteral + *
Signopt HexFloatingPointLiteral + *
SignedInteger + *
+ * + *
+ *
HexFloatingPointLiteral: + *
HexSignificand BinaryExponent FloatTypeSuffixopt + *
+ * + *
+ *
HexSignificand: + *
HexNumeral + *
HexNumeral {@code .} + *
{@code 0x} HexDigitsopt + * {@code .} HexDigits + *
{@code 0X} HexDigitsopt + * {@code .} HexDigits + *
+ * + *
+ *
BinaryExponent: + *
BinaryExponentIndicator SignedInteger + *
+ * + *
+ *
BinaryExponentIndicator: + *
{@code p} + *
{@code P} + *
+ * + *
+ * + * where Sign, FloatingPointLiteral, + * HexNumeral, HexDigits, SignedInteger and + * FloatTypeSuffix are as defined in the lexical structure + * sections of + * The Java™ Language Specification, + * except that underscores are not accepted between digits. + * If {@code s} does not have the form of + * a FloatValue, then a {@code NumberFormatException} + * is thrown. Otherwise, {@code s} is regarded as + * representing an exact decimal value in the usual + * "computerized scientific notation" or as an exact + * hexadecimal value; this exact numerical value is then + * conceptually converted to an "infinitely precise" + * binary value that is then rounded to type {@code double} + * by the usual round-to-nearest rule of IEEE 754 floating-point + * arithmetic, which includes preserving the sign of a zero + * value. + * + * Note that the round-to-nearest rule also implies overflow and + * underflow behaviour; if the exact value of {@code s} is large + * enough in magnitude (greater than or equal to ({@link + * #MAX_VALUE} + {@link Math#ulp(double) ulp(MAX_VALUE)}/2), + * rounding to {@code double} will result in an infinity and if the + * exact value of {@code s} is small enough in magnitude (less + * than or equal to {@link #MIN_VALUE}/2), rounding to float will + * result in a zero. + * + * Finally, after rounding a {@code Double} object representing + * this {@code double} value is returned. + * + *

To interpret localized string representations of a + * floating-point value, use subclasses of {@link + * java.text.NumberFormat}. + * + *

Note that trailing format specifiers, specifiers that + * determine the type of a floating-point literal + * ({@code 1.0f} is a {@code float} value; + * {@code 1.0d} is a {@code double} value), do + * not influence the results of this method. In other + * words, the numerical value of the input string is converted + * directly to the target floating-point type. The two-step + * sequence of conversions, string to {@code float} followed + * by {@code float} to {@code double}, is not + * equivalent to converting a string directly to + * {@code double}. For example, the {@code float} + * literal {@code 0.1f} is equal to the {@code double} + * value {@code 0.10000000149011612}; the {@code float} + * literal {@code 0.1f} represents a different numerical + * value than the {@code double} literal + * {@code 0.1}. (The numerical value 0.1 cannot be exactly + * represented in a binary floating-point number.) + * + *

To avoid calling this method on an invalid string and having + * a {@code NumberFormatException} be thrown, the regular + * expression below can be used to screen the input string: + * + *

{@code
+     *  final String Digits     = "(\\p{Digit}+)";
+     *  final String HexDigits  = "(\\p{XDigit}+)";
+     *  // an exponent is 'e' or 'E' followed by an optionally
+     *  // signed decimal integer.
+     *  final String Exp        = "[eE][+-]?"+Digits;
+     *  final String fpRegex    =
+     *      ("[\\x00-\\x20]*"+  // Optional leading "whitespace"
+     *       "[+-]?(" + // Optional sign character
+     *       "NaN|" +           // "NaN" string
+     *       "Infinity|" +      // "Infinity" string
+     *
+     *       // A decimal floating-point string representing a finite positive
+     *       // number without a leading sign has at most five basic pieces:
+     *       // Digits . Digits ExponentPart FloatTypeSuffix
+     *       //
+     *       // Since this method allows integer-only strings as input
+     *       // in addition to strings of floating-point literals, the
+     *       // two sub-patterns below are simplifications of the grammar
+     *       // productions from section 3.10.2 of
+     *       // The Java Language Specification.
+     *
+     *       // Digits ._opt Digits_opt ExponentPart_opt FloatTypeSuffix_opt
+     *       "((("+Digits+"(\\.)?("+Digits+"?)("+Exp+")?)|"+
+     *
+     *       // . Digits ExponentPart_opt FloatTypeSuffix_opt
+     *       "(\\.("+Digits+")("+Exp+")?)|"+
+     *
+     *       // Hexadecimal strings
+     *       "((" +
+     *        // 0[xX] HexDigits ._opt BinaryExponent FloatTypeSuffix_opt
+     *        "(0[xX]" + HexDigits + "(\\.)?)|" +
+     *
+     *        // 0[xX] HexDigits_opt . HexDigits BinaryExponent FloatTypeSuffix_opt
+     *        "(0[xX]" + HexDigits + "?(\\.)" + HexDigits + ")" +
+     *
+     *        ")[pP][+-]?" + Digits + "))" +
+     *       "[fFdD]?))" +
+     *       "[\\x00-\\x20]*");// Optional trailing "whitespace"
+     *
+     *  if (Pattern.matches(fpRegex, myString))
+     *      Double.valueOf(myString); // Will not throw NumberFormatException
+     *  else {
+     *      // Perform suitable alternative action
+     *  }
+     * }
+ * + * @param s the string to be parsed. + * @return a {@code Double} object holding the value + * represented by the {@code String} argument. + * @throws NumberFormatException if the string does not contain a + * parsable number. + */ + public static Double valueOf(String s) throws NumberFormatException { + return new Double(parseDouble(s)); + } + + /** + * Returns a {@code Double} instance representing the specified + * {@code double} value. + * If a new {@code Double} instance is not required, this method + * should generally be used in preference to the constructor + * {@link #Double(double)}, as this method is likely to yield + * significantly better space and time performance by caching + * frequently requested values. + * + * @param d a double value. + * @return a {@code Double} instance representing {@code d}. + * @since 1.5 + */ + public static Double valueOf(double d) { + return new Double(d); + } + + /** + * Returns a new {@code double} initialized to the value + * represented by the specified {@code String}, as performed + * by the {@code valueOf} method of class + * {@code Double}. + * + * @param s the string to be parsed. + * @return the {@code double} value represented by the string + * argument. + * @throws NullPointerException if the string is null + * @throws NumberFormatException if the string does not contain + * a parsable {@code double}. + * @see java.lang.Double#valueOf(String) + * @since 1.2 + * + * @diffblue.noSupport + */ + public static double parseDouble(String s) throws NumberFormatException { + CProver.notModelled(); + return CProver.nondetDouble(); + } + + /** + * Returns {@code true} if the specified number is a + * Not-a-Number (NaN) value, {@code false} otherwise. + * + * @param v the value to be tested. + * @return {@code true} if the value of the argument is NaN; + * {@code false} otherwise. + */ + public static boolean isNaN(double v) { + return (v != v); + } + + /** + * Returns {@code true} if the specified number is infinitely + * large in magnitude, {@code false} otherwise. + * + * @param v the value to be tested. + * @return {@code true} if the value of the argument is positive + * infinity or negative infinity; {@code false} otherwise. + */ + public static boolean isInfinite(double v) { + return (v == POSITIVE_INFINITY) || (v == NEGATIVE_INFINITY); + } + + /** + * Returns {@code true} if the argument is a finite floating-point + * value; returns {@code false} otherwise (for NaN and infinity + * arguments). + * + * @param d the {@code double} value to be tested + * @return {@code true} if the argument is a finite + * floating-point value, {@code false} otherwise. + * @since 1.8 + */ + public static boolean isFinite(double d) { + return DoubleConsts.MIN_VALUE <= d && d <= DoubleConsts.MAX_VALUE; + } + + /** + * The value of the Double. + * + * @serial + */ + private final double value; + + /** + * Constructs a newly allocated {@code Double} object that + * represents the primitive {@code double} argument. + * + * @param value the value to be represented by the {@code Double}. + */ + public Double(double value) { + this.value = value; + } + + /** + * Constructs a newly allocated {@code Double} object that + * represents the floating-point value of type {@code double} + * represented by the string. The string is converted to a + * {@code double} value as if by the {@code valueOf} method. + * + * @param s a string to be converted to a {@code Double}. + * @throws NumberFormatException if the string does not contain a + * parsable number. + * @see java.lang.Double#valueOf(java.lang.String) + */ + public Double(String s) throws NumberFormatException { + value = parseDouble(s); + } + + /** + * Returns {@code true} if this {@code Double} value is + * a Not-a-Number (NaN), {@code false} otherwise. + * + * @return {@code true} if the value represented by this object is + * NaN; {@code false} otherwise. + */ + public boolean isNaN() { + return isNaN(value); + } + + /** + * Returns {@code true} if this {@code Double} value is + * infinitely large in magnitude, {@code false} otherwise. + * + * @return {@code true} if the value represented by this object is + * positive infinity or negative infinity; + * {@code false} otherwise. + */ + public boolean isInfinite() { + return isInfinite(value); + } + + /** + * Returns a string representation of this {@code Double} object. + * The primitive {@code double} value represented by this + * object is converted to a string exactly as if by the method + * {@code toString} of one argument. + * + * @return a {@code String} representation of this object. + * @see java.lang.Double#toString(double) + */ + public String toString() { + return toString(value); + } + + /** + * Returns the value of this {@code Double} as a {@code byte} + * after a narrowing primitive conversion. + * + * @return the {@code double} value represented by this object + * converted to type {@code byte} + * @jls 5.1.3 Narrowing Primitive Conversions + * @since JDK1.1 + */ + public byte byteValue() { + return (byte)value; + } + + /** + * Returns the value of this {@code Double} as a {@code short} + * after a narrowing primitive conversion. + * + * @return the {@code double} value represented by this object + * converted to type {@code short} + * @jls 5.1.3 Narrowing Primitive Conversions + * @since JDK1.1 + */ + public short shortValue() { + return (short)value; + } + + /** + * Returns the value of this {@code Double} as an {@code int} + * after a narrowing primitive conversion. + * @jls 5.1.3 Narrowing Primitive Conversions + * + * @return the {@code double} value represented by this object + * converted to type {@code int} + */ + public int intValue() { + return (int)value; + } + + /** + * Returns the value of this {@code Double} as a {@code long} + * after a narrowing primitive conversion. + * + * @return the {@code double} value represented by this object + * converted to type {@code long} + * @jls 5.1.3 Narrowing Primitive Conversions + */ + public long longValue() { + return (long)value; + } + + /** + * Returns the value of this {@code Double} as a {@code float} + * after a narrowing primitive conversion. + * + * @return the {@code double} value represented by this object + * converted to type {@code float} + * @jls 5.1.3 Narrowing Primitive Conversions + * @since JDK1.0 + */ + public float floatValue() { + return (float)value; + } + + /** + * Returns the {@code double} value of this {@code Double} object. + * + * @return the {@code double} value represented by this object + */ + public double doubleValue() { + return value; + } + + /** + * Returns a hash code for this {@code Double} object. The + * result is the exclusive OR of the two halves of the + * {@code long} integer bit representation, exactly as + * produced by the method {@link #doubleToLongBits(double)}, of + * the primitive {@code double} value represented by this + * {@code Double} object. That is, the hash code is the value + * of the expression: + * + *
+ * {@code (int)(v^(v>>>32))} + *
+ * + * where {@code v} is defined by: + * + *
+ * {@code long v = Double.doubleToLongBits(this.doubleValue());} + *
+ * + * @return a {@code hash code} value for this object. + */ + @Override + public int hashCode() { + // return Double.hashCode(value); + return 0; + } + + /** + * Returns a hash code for a {@code double} value; compatible with + * {@code Double.hashCode()}. + * + * @param value the value to hash + * @return a hash code value for a {@code double} value. + * @since 1.8 + */ + public static int hashCode(double value) { + // long bits = doubleToLongBits(value); + // return (int)(bits ^ (bits >>> 32)); + return 0; + } + + /** + * Compares this object against the specified object. The result + * is {@code true} if and only if the argument is not + * {@code null} and is a {@code Double} object that + * represents a {@code double} that has the same value as the + * {@code double} represented by this object. For this + * purpose, two {@code double} values are considered to be + * the same if and only if the method {@link + * #doubleToLongBits(double)} returns the identical + * {@code long} value when applied to each. + * + *

Note that in most cases, for two instances of class + * {@code Double}, {@code d1} and {@code d2}, the + * value of {@code d1.equals(d2)} is {@code true} if and + * only if + * + *

+ * {@code d1.doubleValue() == d2.doubleValue()} + *
+ * + *

also has the value {@code true}. However, there are two + * exceptions: + *

+ * This definition allows hash tables to operate properly. + * @param obj the object to compare with. + * @return {@code true} if the objects are the same; + * {@code false} otherwise. + * @see java.lang.Double#doubleToLongBits(double) + * + * @diffblue.fullSupport + * + * Until the native method doubleToRawLongBits(D) is implemented in + * CBMC, this model will allow test generation for checking equality + * between two Doubles. + */ + public boolean equals(Object obj) { + // return (obj instanceof Double) + // && (doubleToLongBits(((Double)obj).value) == + // doubleToLongBits(value)); + + // DIFFBLUE MODEL LIBRARY + if (!(obj instanceof Double)) + return false; + Double d = (Double) obj; + double dValue = d.doubleValue(); + // We inline isNaN here to avoid calls to a static method + boolean bothAreNaN = (dValue != dValue) && (value != value); + return bothAreNaN ||( + (value == 0.0 && dValue == 0.0) + ? ((1/value == POSITIVE_INFINITY && 1/dValue == POSITIVE_INFINITY) + || (1/value == NEGATIVE_INFINITY && 1/dValue == NEGATIVE_INFINITY)) + : ((value == POSITIVE_INFINITY && dValue == POSITIVE_INFINITY) + || (value == NEGATIVE_INFINITY && dValue == NEGATIVE_INFINITY) + || value == dValue)); + } + + /** + * Returns a representation of the specified floating-point value + * according to the IEEE 754 floating-point "double + * format" bit layout. + * + *

Bit 63 (the bit that is selected by the mask + * {@code 0x8000000000000000L}) represents the sign of the + * floating-point number. Bits + * 62-52 (the bits that are selected by the mask + * {@code 0x7ff0000000000000L}) represent the exponent. Bits 51-0 + * (the bits that are selected by the mask + * {@code 0x000fffffffffffffL}) represent the significand + * (sometimes called the mantissa) of the floating-point number. + * + *

If the argument is positive infinity, the result is + * {@code 0x7ff0000000000000L}. + * + *

If the argument is negative infinity, the result is + * {@code 0xfff0000000000000L}. + * + *

If the argument is NaN, the result is + * {@code 0x7ff8000000000000L}. + * + *

In all cases, the result is a {@code long} integer that, when + * given to the {@link #longBitsToDouble(long)} method, will produce a + * floating-point value the same as the argument to + * {@code doubleToLongBits} (except all NaN values are + * collapsed to a single "canonical" NaN value). + * + * @param value a {@code double} precision floating-point number. + * @return the bits that represent the floating-point number. + */ + public static long doubleToLongBits(double value) { + long result = doubleToRawLongBits(value); + // Check for NaN based on values of bit fields, maximum + // exponent and nonzero significand. + if ( ((result & DoubleConsts.EXP_BIT_MASK) == + DoubleConsts.EXP_BIT_MASK) && + (result & DoubleConsts.SIGNIF_BIT_MASK) != 0L) + result = 0x7ff8000000000000L; + return result; + } + + /** + * Returns a representation of the specified floating-point value + * according to the IEEE 754 floating-point "double + * format" bit layout, preserving Not-a-Number (NaN) values. + * + *

Bit 63 (the bit that is selected by the mask + * {@code 0x8000000000000000L}) represents the sign of the + * floating-point number. Bits + * 62-52 (the bits that are selected by the mask + * {@code 0x7ff0000000000000L}) represent the exponent. Bits 51-0 + * (the bits that are selected by the mask + * {@code 0x000fffffffffffffL}) represent the significand + * (sometimes called the mantissa) of the floating-point number. + * + *

If the argument is positive infinity, the result is + * {@code 0x7ff0000000000000L}. + * + *

If the argument is negative infinity, the result is + * {@code 0xfff0000000000000L}. + * + *

If the argument is NaN, the result is the {@code long} + * integer representing the actual NaN value. Unlike the + * {@code doubleToLongBits} method, + * {@code doubleToRawLongBits} does not collapse all the bit + * patterns encoding a NaN to a single "canonical" NaN + * value. + * + *

In all cases, the result is a {@code long} integer that, + * when given to the {@link #longBitsToDouble(long)} method, will + * produce a floating-point value the same as the argument to + * {@code doubleToRawLongBits}. + * + * @param value a {@code double} precision floating-point number. + * @return the bits that represent the floating-point number. + * @since 1.3 + */ + public static long doubleToRawLongBits(double value){ + //@TODO: implement this method internally in CBMC + return CProver.nondetLong(); + } + + /** + * Returns the {@code double} value corresponding to a given + * bit representation. + * The argument is considered to be a representation of a + * floating-point value according to the IEEE 754 floating-point + * "double format" bit layout. + * + *

If the argument is {@code 0x7ff0000000000000L}, the result + * is positive infinity. + * + *

If the argument is {@code 0xfff0000000000000L}, the result + * is negative infinity. + * + *

If the argument is any value in the range + * {@code 0x7ff0000000000001L} through + * {@code 0x7fffffffffffffffL} or in the range + * {@code 0xfff0000000000001L} through + * {@code 0xffffffffffffffffL}, the result is a NaN. No IEEE + * 754 floating-point operation provided by Java can distinguish + * between two NaN values of the same type with different bit + * patterns. Distinct values of NaN are only distinguishable by + * use of the {@code Double.doubleToRawLongBits} method. + * + *

In all other cases, let s, e, and m be three + * values that can be computed from the argument: + * + *

{@code
+     * int s = ((bits >> 63) == 0) ? 1 : -1;
+     * int e = (int)((bits >> 52) & 0x7ffL);
+     * long m = (e == 0) ?
+     *                 (bits & 0xfffffffffffffL) << 1 :
+     *                 (bits & 0xfffffffffffffL) | 0x10000000000000L;
+     * }
+ * + * Then the floating-point result equals the value of the mathematical + * expression s·m·2e-1075. + * + *

Note that this method may not be able to return a + * {@code double} NaN with exactly same bit pattern as the + * {@code long} argument. IEEE 754 distinguishes between two + * kinds of NaNs, quiet NaNs and signaling NaNs. The + * differences between the two kinds of NaN are generally not + * visible in Java. Arithmetic operations on signaling NaNs turn + * them into quiet NaNs with a different, but often similar, bit + * pattern. However, on some processors merely copying a + * signaling NaN also performs that conversion. In particular, + * copying a signaling NaN to return it to the calling method + * may perform this conversion. So {@code longBitsToDouble} + * may not be able to return a {@code double} with a + * signaling NaN bit pattern. Consequently, for some + * {@code long} values, + * {@code doubleToRawLongBits(longBitsToDouble(start))} may + * not equal {@code start}. Moreover, which + * particular bit patterns represent signaling NaNs is platform + * dependent; although all NaN bit patterns, quiet or signaling, + * must be in the NaN range identified above. + * + * @param bits any {@code long} integer. + * @return the {@code double} floating-point value with the same + * bit pattern. + */ + public static double longBitsToDouble(long bits){ + //@TODO: implement this method internally in CBMC + return CProver.nondetDouble(); + } + + /** + * Compares two {@code Double} objects numerically. There + * are two ways in which comparisons performed by this method + * differ from those performed by the Java language numerical + * comparison operators ({@code <, <=, ==, >=, >}) + * when applied to primitive {@code double} values: + *

+ * This ensures that the natural ordering of + * {@code Double} objects imposed by this method is consistent + * with equals. + * + * @param anotherDouble the {@code Double} to be compared. + * @return the value {@code 0} if {@code anotherDouble} is + * numerically equal to this {@code Double}; a value + * less than {@code 0} if this {@code Double} + * is numerically less than {@code anotherDouble}; + * and a value greater than {@code 0} if this + * {@code Double} is numerically greater than + * {@code anotherDouble}. + * + * @since 1.2 + */ + public int compareTo(Double anotherDouble) { + return Double.compare(value, anotherDouble.value); + } + + /** + * Compares the two specified {@code double} values. The sign + * of the integer value returned is the same as that of the + * integer that would be returned by the call: + *
+     *    new Double(d1).compareTo(new Double(d2))
+     * 
+ * + * @param d1 the first {@code double} to compare + * @param d2 the second {@code double} to compare + * @return the value {@code 0} if {@code d1} is + * numerically equal to {@code d2}; a value less than + * {@code 0} if {@code d1} is numerically less than + * {@code d2}; and a value greater than {@code 0} + * if {@code d1} is numerically greater than + * {@code d2}. + * @since 1.4 + */ + public static int compare(double d1, double d2) { + if (d1 < d2) + return -1; // Neither val is NaN, thisVal is smaller + if (d1 > d2) + return 1; // Neither val is NaN, thisVal is larger + + // Cannot use doubleToRawLongBits because of possibility of NaNs. + long thisBits = Double.doubleToLongBits(d1); + long anotherBits = Double.doubleToLongBits(d2); + + return (thisBits == anotherBits ? 0 : // Values are equal + (thisBits < anotherBits ? -1 : // (-0.0, 0.0) or (!NaN, NaN) + 1)); // (0.0, -0.0) or (NaN, !NaN) + } + + /** + * Adds two {@code double} values together as per the + operator. + * + * @param a the first operand + * @param b the second operand + * @return the sum of {@code a} and {@code b} + * @jls 4.2.4 Floating-Point Operations + * @see java.util.function.BinaryOperator + * @since 1.8 + */ + public static double sum(double a, double b) { + return a + b; + } + + /** + * Returns the greater of two {@code double} values + * as if by calling {@link Math#max(double, double) Math.max}. + * + * @param a the first operand + * @param b the second operand + * @return the greater of {@code a} and {@code b} + * @see java.util.function.BinaryOperator + * @since 1.8 + */ + public static double max(double a, double b) { + double result = CProver.nondetDouble(); + CProver.assume((result == a || result == b) && result >= a && result >= b); + return result; + } + + /** + * Returns the smaller of two {@code double} values + * as if by calling {@link Math#min(double, double) Math.min}. + * + * @param a the first operand + * @param b the second operand + * @return the smaller of {@code a} and {@code b}. + * @see java.util.function.BinaryOperator + * @since 1.8 + */ + public static double min(double a, double b) { + double result = CProver.nondetDouble(); + CProver.assume((result == a || result == b) && result <= a && result <= b); + return result; + } + + /** use serialVersionUID from JDK 1.0.2 for interoperability */ + private static final long serialVersionUID = -9172774392245257468L; +} diff --git a/src/main/java/java/lang/Float.java b/src/main/java/java/lang/Float.java new file mode 100644 index 0000000..1003bcc --- /dev/null +++ b/src/main/java/java/lang/Float.java @@ -0,0 +1,1005 @@ +/* + * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang; + +// DIFFBLUE MODEL LIBRARY +// removed for compatibility with Java 9 and newer +// import sun.misc.FloatingDecimal; +import sun.misc.FloatConsts; +import sun.misc.DoubleConsts; +import org.cprover.CProver; + +/** + * The {@code Float} class wraps a value of primitive type + * {@code float} in an object. An object of type + * {@code Float} contains a single field whose type is + * {@code float}. + * + *

In addition, this class provides several methods for converting a + * {@code float} to a {@code String} and a + * {@code String} to a {@code float}, as well as other + * constants and methods useful when dealing with a + * {@code float}. + * + * @author Lee Boynton + * @author Arthur van Hoff + * @author Joseph D. Darcy + * @since JDK1.0 + */ +public final class Float extends Number implements Comparable { + /** + * A constant holding the positive infinity of type + * {@code float}. It is equal to the value returned by + * {@code Float.intBitsToFloat(0x7f800000)}. + */ + public static final float POSITIVE_INFINITY = 1.0f / 0.0f; + + /** + * A constant holding the negative infinity of type + * {@code float}. It is equal to the value returned by + * {@code Float.intBitsToFloat(0xff800000)}. + */ + public static final float NEGATIVE_INFINITY = -1.0f / 0.0f; + + /** + * A constant holding a Not-a-Number (NaN) value of type + * {@code float}. It is equivalent to the value returned by + * {@code Float.intBitsToFloat(0x7fc00000)}. + */ + public static final float NaN = 0.0f / 0.0f; + + /** + * A constant holding the largest positive finite value of type + * {@code float}, (2-2-23)·2127. + * It is equal to the hexadecimal floating-point literal + * {@code 0x1.fffffeP+127f} and also equal to + * {@code Float.intBitsToFloat(0x7f7fffff)}. + */ + public static final float MAX_VALUE = 0x1.fffffeP+127f; // 3.4028235e+38f + + /** + * A constant holding the smallest positive normal value of type + * {@code float}, 2-126. It is equal to the + * hexadecimal floating-point literal {@code 0x1.0p-126f} and also + * equal to {@code Float.intBitsToFloat(0x00800000)}. + * + * @since 1.6 + */ + public static final float MIN_NORMAL = 0x1.0p-126f; // 1.17549435E-38f + + /** + * A constant holding the smallest positive nonzero value of type + * {@code float}, 2-149. It is equal to the + * hexadecimal floating-point literal {@code 0x0.000002P-126f} + * and also equal to {@code Float.intBitsToFloat(0x1)}. + */ + public static final float MIN_VALUE = 0x0.000002P-126f; // 1.4e-45f + + /** + * Maximum exponent a finite {@code float} variable may have. It + * is equal to the value returned by {@code + * Math.getExponent(Float.MAX_VALUE)}. + * + * @since 1.6 + */ + public static final int MAX_EXPONENT = 127; + + /** + * Minimum exponent a normalized {@code float} variable may have. + * It is equal to the value returned by {@code + * Math.getExponent(Float.MIN_NORMAL)}. + * + * @since 1.6 + */ + public static final int MIN_EXPONENT = -126; + + /** + * The number of bits used to represent a {@code float} value. + * + * @since 1.5 + */ + public static final int SIZE = 32; + + /** + * The number of bytes used to represent a {@code float} value. + * + * @since 1.8 + */ + public static final int BYTES = SIZE / Byte.SIZE; + + /** + * The {@code Class} instance representing the primitive type + * {@code float}. + * + * @since JDK1.1 + */ + @SuppressWarnings("unchecked") + public static final Class TYPE = (Class) Class.getPrimitiveClass(7); + + /** + * Returns a string representation of the {@code float} + * argument. All characters mentioned below are ASCII characters. + *

+ * How many digits must be printed for the fractional part of + * m or a? There must be at least one digit + * to represent the fractional part, and beyond that as many, but + * only as many, more digits as are needed to uniquely distinguish + * the argument value from adjacent values of type + * {@code float}. That is, suppose that x is the + * exact mathematical value represented by the decimal + * representation produced by this method for a finite nonzero + * argument f. Then f must be the {@code float} + * value nearest to x; or, if two {@code float} values are + * equally close to x, then f must be one of + * them and the least significant bit of the significand of + * f must be {@code 0}. + * + *

To create localized string representations of a floating-point + * value, use subclasses of {@link java.text.NumberFormat}. + * + * @param f the float to be converted. + * @return a string representation of the argument. + * @diffblue.noSupport + */ + public static String toString(float f) { + // DIFFBLUE MODEL LIBRARY + // removed for compatibility with Java 9 and newer + // return FloatingDecimal.toJavaFormatString(f); + CProver.notModelled(); + return CProver.nondetWithNullForNotModelled(); + } + + /** + * Returns a hexadecimal string representation of the + * {@code float} argument. All characters mentioned below are + * ASCII characters. + * + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Examples
Floating-point ValueHexadecimal String
{@code 1.0} {@code 0x1.0p0}
{@code -1.0} {@code -0x1.0p0}
{@code 2.0} {@code 0x1.0p1}
{@code 3.0} {@code 0x1.8p1}
{@code 0.5} {@code 0x1.0p-1}
{@code 0.25} {@code 0x1.0p-2}
{@code Float.MAX_VALUE}{@code 0x1.fffffep127}
{@code Minimum Normal Value}{@code 0x1.0p-126}
{@code Maximum Subnormal Value}{@code 0x0.fffffep-126}
{@code Float.MIN_VALUE}{@code 0x0.000002p-126}
+ * @param f the {@code float} to be converted. + * @return a hex string representation of the argument. + * @since 1.5 + * @author Joseph D. Darcy + */ + public static String toHexString(float f) { + if (Math.abs(f) < FloatConsts.MIN_NORMAL + && f != 0.0f ) {// float subnormal + // Adjust exponent to create subnormal double, then + // replace subnormal double exponent with subnormal float + // exponent + String s = Double.toHexString(Math.scalb((double)f, + /* -1022+126 */ + DoubleConsts.MIN_EXPONENT- + FloatConsts.MIN_EXPONENT)); + return s.replaceFirst("p-1022$", "p-126"); + } + else // double string will be the same as float string + return Double.toHexString(f); + } + + /** + * Returns a {@code Float} object holding the + * {@code float} value represented by the argument string + * {@code s}. + * + *

If {@code s} is {@code null}, then a + * {@code NullPointerException} is thrown. + * + *

Leading and trailing whitespace characters in {@code s} + * are ignored. Whitespace is removed as if by the {@link + * String#trim} method; that is, both ASCII space and control + * characters are removed. The rest of {@code s} should + * constitute a FloatValue as described by the lexical + * syntax rules: + * + *

+ *
+ *
FloatValue: + *
Signopt {@code NaN} + *
Signopt {@code Infinity} + *
Signopt FloatingPointLiteral + *
Signopt HexFloatingPointLiteral + *
SignedInteger + *
+ * + *
+ *
HexFloatingPointLiteral: + *
HexSignificand BinaryExponent FloatTypeSuffixopt + *
+ * + *
+ *
HexSignificand: + *
HexNumeral + *
HexNumeral {@code .} + *
{@code 0x} HexDigitsopt + * {@code .} HexDigits + *
{@code 0X} HexDigitsopt + * {@code .} HexDigits + *
+ * + *
+ *
BinaryExponent: + *
BinaryExponentIndicator SignedInteger + *
+ * + *
+ *
BinaryExponentIndicator: + *
{@code p} + *
{@code P} + *
+ * + *
+ * + * where Sign, FloatingPointLiteral, + * HexNumeral, HexDigits, SignedInteger and + * FloatTypeSuffix are as defined in the lexical structure + * sections of + * The Java™ Language Specification, + * except that underscores are not accepted between digits. + * If {@code s} does not have the form of + * a FloatValue, then a {@code NumberFormatException} + * is thrown. Otherwise, {@code s} is regarded as + * representing an exact decimal value in the usual + * "computerized scientific notation" or as an exact + * hexadecimal value; this exact numerical value is then + * conceptually converted to an "infinitely precise" + * binary value that is then rounded to type {@code float} + * by the usual round-to-nearest rule of IEEE 754 floating-point + * arithmetic, which includes preserving the sign of a zero + * value. + * + * Note that the round-to-nearest rule also implies overflow and + * underflow behaviour; if the exact value of {@code s} is large + * enough in magnitude (greater than or equal to ({@link + * #MAX_VALUE} + {@link Math#ulp(float) ulp(MAX_VALUE)}/2), + * rounding to {@code float} will result in an infinity and if the + * exact value of {@code s} is small enough in magnitude (less + * than or equal to {@link #MIN_VALUE}/2), rounding to float will + * result in a zero. + * + * Finally, after rounding a {@code Float} object representing + * this {@code float} value is returned. + * + *

To interpret localized string representations of a + * floating-point value, use subclasses of {@link + * java.text.NumberFormat}. + * + *

Note that trailing format specifiers, specifiers that + * determine the type of a floating-point literal + * ({@code 1.0f} is a {@code float} value; + * {@code 1.0d} is a {@code double} value), do + * not influence the results of this method. In other + * words, the numerical value of the input string is converted + * directly to the target floating-point type. In general, the + * two-step sequence of conversions, string to {@code double} + * followed by {@code double} to {@code float}, is + * not equivalent to converting a string directly to + * {@code float}. For example, if first converted to an + * intermediate {@code double} and then to + * {@code float}, the string
+ * {@code "1.00000017881393421514957253748434595763683319091796875001d"}
+ * results in the {@code float} value + * {@code 1.0000002f}; if the string is converted directly to + * {@code float}, 1.0000001f results. + * + *

To avoid calling this method on an invalid string and having + * a {@code NumberFormatException} be thrown, the documentation + * for {@link Double#valueOf Double.valueOf} lists a regular + * expression which can be used to screen the input. + * + * @param s the string to be parsed. + * @return a {@code Float} object holding the value + * represented by the {@code String} argument. + * @throws NumberFormatException if the string does not contain a + * parsable number. + */ + public static Float valueOf(String s) throws NumberFormatException { + return new Float(parseFloat(s)); + } + + /** + * Returns a {@code Float} instance representing the specified + * {@code float} value. + * If a new {@code Float} instance is not required, this method + * should generally be used in preference to the constructor + * {@link #Float(float)}, as this method is likely to yield + * significantly better space and time performance by caching + * frequently requested values. + * + * @param f a float value. + * @return a {@code Float} instance representing {@code f}. + * @since 1.5 + */ + public static Float valueOf(float f) { + return new Float(f); + } + + /** + * Returns a new {@code float} initialized to the value + * represented by the specified {@code String}, as performed + * by the {@code valueOf} method of class {@code Float}. + * + * @param s the string to be parsed. + * @return the {@code float} value represented by the string + * argument. + * @throws NullPointerException if the string is null + * @throws NumberFormatException if the string does not contain a + * parsable {@code float}. + * @see java.lang.Float#valueOf(String) + * @since 1.2 + */ + public static float parseFloat(String s) throws NumberFormatException { + return CProver.nondetFloat(); //The function is handled by cbmc internally + } + + /** + * Returns {@code true} if the specified number is a + * Not-a-Number (NaN) value, {@code false} otherwise. + * + * @param v the value to be tested. + * @return {@code true} if the argument is NaN; + * {@code false} otherwise. + */ + public static boolean isNaN(float v) { + return (v != v); + } + + /** + * Returns {@code true} if the specified number is infinitely + * large in magnitude, {@code false} otherwise. + * + * @param v the value to be tested. + * @return {@code true} if the argument is positive infinity or + * negative infinity; {@code false} otherwise. + */ + public static boolean isInfinite(float v) { + return (v == POSITIVE_INFINITY) || (v == NEGATIVE_INFINITY); + } + + + /** + * Returns {@code true} if the argument is a finite floating-point + * value; returns {@code false} otherwise (for NaN and infinity + * arguments). + * + * @param f the {@code float} value to be tested + * @return {@code true} if the argument is a finite + * floating-point value, {@code false} otherwise. + * @since 1.8 + */ + public static boolean isFinite(float f) { + return FloatConsts.MIN_VALUE <= f && f <= FloatConsts.MAX_VALUE; + } + + /** + * The value of the Float. + * + * @serial + */ + private final float value; + + /** + * Constructs a newly allocated {@code Float} object that + * represents the primitive {@code float} argument. + * + * @param value the value to be represented by the {@code Float}. + */ + public Float(float value) { + this.value = value; + } + + /** + * Constructs a newly allocated {@code Float} object that + * represents the argument converted to type {@code float}. + * + * @param value the value to be represented by the {@code Float}. + */ + public Float(double value) { + this.value = (float)value; + } + + /** + * Constructs a newly allocated {@code Float} object that + * represents the floating-point value of type {@code float} + * represented by the string. The string is converted to a + * {@code float} value as if by the {@code valueOf} method. + * + * @param s a string to be converted to a {@code Float}. + * @throws NumberFormatException if the string does not contain a + * parsable number. + * @see java.lang.Float#valueOf(java.lang.String) + */ + public Float(String s) throws NumberFormatException { + value = parseFloat(s); + } + + /** + * Returns {@code true} if this {@code Float} value is a + * Not-a-Number (NaN), {@code false} otherwise. + * + * @return {@code true} if the value represented by this object is + * NaN; {@code false} otherwise. + */ + public boolean isNaN() { + return isNaN(value); + } + + /** + * Returns {@code true} if this {@code Float} value is + * infinitely large in magnitude, {@code false} otherwise. + * + * @return {@code true} if the value represented by this object is + * positive infinity or negative infinity; + * {@code false} otherwise. + */ + public boolean isInfinite() { + return isInfinite(value); + } + + /** + * Returns a string representation of this {@code Float} object. + * The primitive {@code float} value represented by this object + * is converted to a {@code String} exactly as if by the method + * {@code toString} of one argument. + * + * @return a {@code String} representation of this object. + * @see java.lang.Float#toString(float) + */ + public String toString() { + return Float.toString(value); + } + + /** + * Returns the value of this {@code Float} as a {@code byte} after + * a narrowing primitive conversion. + * + * @return the {@code float} value represented by this object + * converted to type {@code byte} + * @jls 5.1.3 Narrowing Primitive Conversions + */ + public byte byteValue() { + return (byte)value; + } + + /** + * Returns the value of this {@code Float} as a {@code short} + * after a narrowing primitive conversion. + * + * @return the {@code float} value represented by this object + * converted to type {@code short} + * @jls 5.1.3 Narrowing Primitive Conversions + * @since JDK1.1 + */ + public short shortValue() { + return (short)value; + } + + /** + * Returns the value of this {@code Float} as an {@code int} after + * a narrowing primitive conversion. + * + * @return the {@code float} value represented by this object + * converted to type {@code int} + * @jls 5.1.3 Narrowing Primitive Conversions + */ + public int intValue() { + return (int)value; + } + + /** + * Returns value of this {@code Float} as a {@code long} after a + * narrowing primitive conversion. + * + * @return the {@code float} value represented by this object + * converted to type {@code long} + * @jls 5.1.3 Narrowing Primitive Conversions + */ + public long longValue() { + return (long)value; + } + + /** + * Returns the {@code float} value of this {@code Float} object. + * + * @return the {@code float} value represented by this object + */ + public float floatValue() { + return value; + } + + /** + * Returns the value of this {@code Float} as a {@code double} + * after a widening primitive conversion. + * + * @return the {@code float} value represented by this + * object converted to type {@code double} + * @jls 5.1.2 Widening Primitive Conversions + */ + public double doubleValue() { + return (double)value; + } + + /** + * Returns a hash code for this {@code Float} object. The + * result is the integer bit representation, exactly as produced + * by the method {@link #floatToIntBits(float)}, of the primitive + * {@code float} value represented by this {@code Float} + * object. + * + * @return a hash code value for this object. + */ + @Override + public int hashCode() { + // return Float.hashCode(value); + return 0; + } + + /** + * Returns a hash code for a {@code float} value; compatible with + * {@code Float.hashCode()}. + * + * @param value the value to hash + * @return a hash code value for a {@code float} value. + * @since 1.8 + */ + public static int hashCode(float value) { + // return floatToIntBits(value); + return 0; + } + + /** + * Compares this object against the specified object. The result + * is {@code true} if and only if the argument is not + * {@code null} and is a {@code Float} object that + * represents a {@code float} with the same value as the + * {@code float} represented by this object. For this + * purpose, two {@code float} values are considered to be the + * same if and only if the method {@link #floatToIntBits(float)} + * returns the identical {@code int} value when applied to + * each. + * + *

Note that in most cases, for two instances of class + * {@code Float}, {@code f1} and {@code f2}, the value + * of {@code f1.equals(f2)} is {@code true} if and only if + * + *

+     *   f1.floatValue() == f2.floatValue()
+     * 
+ * + *

also has the value {@code true}. However, there are two exceptions: + *

+ * + * This definition allows hash tables to operate properly. + * + * @param obj the object to be compared + * @return {@code true} if the objects are the same; + * {@code false} otherwise. + * @see java.lang.Float#floatToIntBits(float) + * + * @diffblue.fullSupport + * + * Until the native method floatToRawIntBits(F) is implemented in + * CBMC, this model will allow test generation for checking equality + * between two Floats. + */ + public boolean equals(Object obj) { + // return (obj instanceof Float) + // && (floatToIntBits(((Float)obj).value) == floatToIntBits(value)); + + // DIFFBLUE MODEL LIBRARY + if (!(obj instanceof Float)) + return false; + Float f = (Float) obj; + float fValue = f.floatValue(); + // We inline isNaN here to avoid calls to a static method + boolean bothAreNaN = (value != value) && (fValue != fValue); + return bothAreNaN || + ((value == 0.0 && fValue == 0.0) + ? ((1/value == POSITIVE_INFINITY && 1/fValue == POSITIVE_INFINITY) + || (1/value == NEGATIVE_INFINITY && 1/fValue == NEGATIVE_INFINITY)) + : ((value == POSITIVE_INFINITY && fValue == POSITIVE_INFINITY) + || (value == NEGATIVE_INFINITY && fValue == NEGATIVE_INFINITY) + || value == fValue)); + } + + /** + * Returns a representation of the specified floating-point value + * according to the IEEE 754 floating-point "single format" bit + * layout. + * + *

Bit 31 (the bit that is selected by the mask + * {@code 0x80000000}) represents the sign of the floating-point + * number. + * Bits 30-23 (the bits that are selected by the mask + * {@code 0x7f800000}) represent the exponent. + * Bits 22-0 (the bits that are selected by the mask + * {@code 0x007fffff}) represent the significand (sometimes called + * the mantissa) of the floating-point number. + * + *

If the argument is positive infinity, the result is + * {@code 0x7f800000}. + * + *

If the argument is negative infinity, the result is + * {@code 0xff800000}. + * + *

If the argument is NaN, the result is {@code 0x7fc00000}. + * + *

In all cases, the result is an integer that, when given to the + * {@link #intBitsToFloat(int)} method, will produce a floating-point + * value the same as the argument to {@code floatToIntBits} + * (except all NaN values are collapsed to a single + * "canonical" NaN value). + * + * @param value a floating-point number. + * @return the bits that represent the floating-point number. + */ + public static int floatToIntBits(float value) { + int result = floatToRawIntBits(value); + // Check for NaN based on values of bit fields, maximum + // exponent and nonzero significand. + if ( ((result & FloatConsts.EXP_BIT_MASK) == + FloatConsts.EXP_BIT_MASK) && + (result & FloatConsts.SIGNIF_BIT_MASK) != 0) + result = 0x7fc00000; + return result; + } + + /** + * Returns a representation of the specified floating-point value + * according to the IEEE 754 floating-point "single format" bit + * layout, preserving Not-a-Number (NaN) values. + * + *

Bit 31 (the bit that is selected by the mask + * {@code 0x80000000}) represents the sign of the floating-point + * number. + * Bits 30-23 (the bits that are selected by the mask + * {@code 0x7f800000}) represent the exponent. + * Bits 22-0 (the bits that are selected by the mask + * {@code 0x007fffff}) represent the significand (sometimes called + * the mantissa) of the floating-point number. + * + *

If the argument is positive infinity, the result is + * {@code 0x7f800000}. + * + *

If the argument is negative infinity, the result is + * {@code 0xff800000}. + * + *

If the argument is NaN, the result is the integer representing + * the actual NaN value. Unlike the {@code floatToIntBits} + * method, {@code floatToRawIntBits} does not collapse all the + * bit patterns encoding a NaN to a single "canonical" + * NaN value. + * + *

In all cases, the result is an integer that, when given to the + * {@link #intBitsToFloat(int)} method, will produce a + * floating-point value the same as the argument to + * {@code floatToRawIntBits}. + * + * @param value a floating-point number. + * @return the bits that represent the floating-point number. + * @since 1.3 + */ + public static int floatToRawIntBits(float value){ + //@TODO: implement this method internally in CBMC + return CProver.nondetInt(); + } + + /** + * Returns the {@code float} value corresponding to a given + * bit representation. + * The argument is considered to be a representation of a + * floating-point value according to the IEEE 754 floating-point + * "single format" bit layout. + * + *

If the argument is {@code 0x7f800000}, the result is positive + * infinity. + * + *

If the argument is {@code 0xff800000}, the result is negative + * infinity. + * + *

If the argument is any value in the range + * {@code 0x7f800001} through {@code 0x7fffffff} or in + * the range {@code 0xff800001} through + * {@code 0xffffffff}, the result is a NaN. No IEEE 754 + * floating-point operation provided by Java can distinguish + * between two NaN values of the same type with different bit + * patterns. Distinct values of NaN are only distinguishable by + * use of the {@code Float.floatToRawIntBits} method. + * + *

In all other cases, let s, e, and m be three + * values that can be computed from the argument: + * + *

{@code
+     * int s = ((bits >> 31) == 0) ? 1 : -1;
+     * int e = ((bits >> 23) & 0xff);
+     * int m = (e == 0) ?
+     *                 (bits & 0x7fffff) << 1 :
+     *                 (bits & 0x7fffff) | 0x800000;
+     * }
+ * + * Then the floating-point result equals the value of the mathematical + * expression s·m·2e-150. + * + *

Note that this method may not be able to return a + * {@code float} NaN with exactly same bit pattern as the + * {@code int} argument. IEEE 754 distinguishes between two + * kinds of NaNs, quiet NaNs and signaling NaNs. The + * differences between the two kinds of NaN are generally not + * visible in Java. Arithmetic operations on signaling NaNs turn + * them into quiet NaNs with a different, but often similar, bit + * pattern. However, on some processors merely copying a + * signaling NaN also performs that conversion. In particular, + * copying a signaling NaN to return it to the calling method may + * perform this conversion. So {@code intBitsToFloat} may + * not be able to return a {@code float} with a signaling NaN + * bit pattern. Consequently, for some {@code int} values, + * {@code floatToRawIntBits(intBitsToFloat(start))} may + * not equal {@code start}. Moreover, which + * particular bit patterns represent signaling NaNs is platform + * dependent; although all NaN bit patterns, quiet or signaling, + * must be in the NaN range identified above. + * + * @param bits an integer. + * @return the {@code float} floating-point value with the same bit + * pattern. + */ + public static float intBitsToFloat(int bits){ + //@TODO: implement this method internally in CBMC + return CProver.nondetFloat(); + } + + /** + * Compares two {@code Float} objects numerically. There are + * two ways in which comparisons performed by this method differ + * from those performed by the Java language numerical comparison + * operators ({@code <, <=, ==, >=, >}) when + * applied to primitive {@code float} values: + * + *

+ * + * This ensures that the natural ordering of {@code Float} + * objects imposed by this method is consistent with equals. + * + * @param anotherFloat the {@code Float} to be compared. + * @return the value {@code 0} if {@code anotherFloat} is + * numerically equal to this {@code Float}; a value + * less than {@code 0} if this {@code Float} + * is numerically less than {@code anotherFloat}; + * and a value greater than {@code 0} if this + * {@code Float} is numerically greater than + * {@code anotherFloat}. + * + * @since 1.2 + * @see Comparable#compareTo(Object) + */ + public int compareTo(Float anotherFloat) { + return Float.compare(value, anotherFloat.value); + } + + /** + * Compares the two specified {@code float} values. The sign + * of the integer value returned is the same as that of the + * integer that would be returned by the call: + *
+     *    new Float(f1).compareTo(new Float(f2))
+     * 
+ * + * @param f1 the first {@code float} to compare. + * @param f2 the second {@code float} to compare. + * @return the value {@code 0} if {@code f1} is + * numerically equal to {@code f2}; a value less than + * {@code 0} if {@code f1} is numerically less than + * {@code f2}; and a value greater than {@code 0} + * if {@code f1} is numerically greater than + * {@code f2}. + * @since 1.4 + */ + public static int compare(float f1, float f2) { + if (f1 < f2) + return -1; // Neither val is NaN, thisVal is smaller + if (f1 > f2) + return 1; // Neither val is NaN, thisVal is larger + + // Cannot use floatToRawIntBits because of possibility of NaNs. + int thisBits = Float.floatToIntBits(f1); + int anotherBits = Float.floatToIntBits(f2); + + return (thisBits == anotherBits ? 0 : // Values are equal + (thisBits < anotherBits ? -1 : // (-0.0, 0.0) or (!NaN, NaN) + 1)); // (0.0, -0.0) or (NaN, !NaN) + } + + /** + * Adds two {@code float} values together as per the + operator. + * + * @param a the first operand + * @param b the second operand + * @return the sum of {@code a} and {@code b} + * @jls 4.2.4 Floating-Point Operations + * @see java.util.function.BinaryOperator + * @since 1.8 + */ + public static float sum(float a, float b) { + return a + b; + } + + /** + * Returns the greater of two {@code float} values + * as if by calling {@link Math#max(float, float) Math.max}. + * + * @param a the first operand + * @param b the second operand + * @return the greater of {@code a} and {@code b} + * @see java.util.function.BinaryOperator + * @since 1.8 + */ + public static float max(float a, float b) { + float result = CProver.nondetFloat(); + CProver.assume((result == a || result == b) && result >= a && result >= b); + return result; + } + + /** + * Returns the smaller of two {@code float} values + * as if by calling {@link Math#min(float, float) Math.min}. + * + * @param a the first operand + * @param b the second operand + * @return the smaller of {@code a} and {@code b} + * @see java.util.function.BinaryOperator + * @since 1.8 + */ + public static float min(float a, float b) { + float result = CProver.nondetFloat(); + CProver.assume((result == a || result == b) && result <= a && result <= b); + return result; + } + + /** use serialVersionUID from JDK 1.0.2 for interoperability */ + private static final long serialVersionUID = -2671257302660747028L; +} diff --git a/src/main/java/java/lang/Long.java b/src/main/java/java/lang/Long.java new file mode 100644 index 0000000..4cc5e3f --- /dev/null +++ b/src/main/java/java/lang/Long.java @@ -0,0 +1,1537 @@ +/* + * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang; + +import java.lang.annotation.Native; +import java.math.*; +import org.cprover.CProver; +import org.cprover.CProverString; + +/** + * The {@code Long} class wraps a value of the primitive type {@code + * long} in an object. An object of type {@code Long} contains a + * single field whose type is {@code long}. + * + *

In addition, this class provides several methods for converting + * a {@code long} to a {@code String} and a {@code String} to a {@code + * long}, as well as other constants and methods useful when dealing + * with a {@code long}. + * + *

Implementation note: The implementations of the "bit twiddling" + * methods (such as {@link #highestOneBit(long) highestOneBit} and + * {@link #numberOfTrailingZeros(long) numberOfTrailingZeros}) are + * based on material from Henry S. Warren, Jr.'s Hacker's + * Delight, (Addison Wesley, 2002). + * + * @author Lee Boynton + * @author Arthur van Hoff + * @author Josh Bloch + * @author Joseph D. Darcy + * @since JDK1.0 + */ +public final class Long extends Number implements Comparable { + /** + * A constant holding the minimum value a {@code long} can + * have, -263. + */ + @Native public static final long MIN_VALUE = 0x8000000000000000L; + + /** + * A constant holding the maximum value a {@code long} can + * have, 263-1. + */ + @Native public static final long MAX_VALUE = 0x7fffffffffffffffL; + + /** + * The {@code Class} instance representing the primitive type + * {@code long}. + * + * @since JDK1.1 + */ + /* + * MODELS-LIBRARY { + * We use the int version of getPrimitiveClass instead of + * the original String version + * } + */ + @SuppressWarnings("unchecked") + public static final Class TYPE = (Class) Class.getPrimitiveClass(5); + + /** + * Returns a string representation of the first argument in the + * radix specified by the second argument. + * + *

If the radix is smaller than {@code Character.MIN_RADIX} + * or larger than {@code Character.MAX_RADIX}, then the radix + * {@code 10} is used instead. + * + *

If the first argument is negative, the first element of the + * result is the ASCII minus sign {@code '-'} + * ({@code '\u005Cu002d'}). If the first argument is not + * negative, no sign character appears in the result. + * + *

The remaining characters of the result represent the magnitude + * of the first argument. If the magnitude is zero, it is + * represented by a single zero character {@code '0'} + * ({@code '\u005Cu0030'}); otherwise, the first character of + * the representation of the magnitude will not be the zero + * character. The following ASCII characters are used as digits: + * + *

+ * {@code 0123456789abcdefghijklmnopqrstuvwxyz} + *
+ * + * These are {@code '\u005Cu0030'} through + * {@code '\u005Cu0039'} and {@code '\u005Cu0061'} through + * {@code '\u005Cu007a'}. If {@code radix} is + * N, then the first N of these characters + * are used as radix-N digits in the order shown. Thus, + * the digits for hexadecimal (radix 16) are + * {@code 0123456789abcdef}. If uppercase letters are + * desired, the {@link java.lang.String#toUpperCase()} method may + * be called on the result: + * + *
+ * {@code Long.toString(n, 16).toUpperCase()} + *
+ * + * @param i a {@code long} to be converted to a string. + * @param radix the radix to use in the string representation. + * @return a string representation of the argument in the specified radix. + * @see java.lang.Character#MAX_RADIX + * @see java.lang.Character#MIN_RADIX + */ + public static String toString(long i, int radix) { + return CProver.nondetWithoutNullForNotModelled(); + } + + /** + * Returns a string representation of the first argument as an + * unsigned integer value in the radix specified by the second + * argument. + * + *

If the radix is smaller than {@code Character.MIN_RADIX} + * or larger than {@code Character.MAX_RADIX}, then the radix + * {@code 10} is used instead. + * + *

Note that since the first argument is treated as an unsigned + * value, no leading sign character is printed. + * + *

If the magnitude is zero, it is represented by a single zero + * character {@code '0'} ({@code '\u005Cu0030'}); otherwise, + * the first character of the representation of the magnitude will + * not be the zero character. + * + *

The behavior of radixes and the characters used as digits + * are the same as {@link #toString(long, int) toString}. + * + * @param i an integer to be converted to an unsigned string. + * @param radix the radix to use in the string representation. + * @return an unsigned string representation of the argument in the specified radix. + * @see #toString(long, int) + * @since 1.8 + */ + public static String toUnsignedString(long i, int radix) { + if (i >= 0) + return toString(i, radix); + else { + switch (radix) { + case 2: + return toBinaryString(i); + + case 4: + return toUnsignedString0(i, 2); + + case 8: + return toOctalString(i); + + case 10: + /* + * We can get the effect of an unsigned division by 10 + * on a long value by first shifting right, yielding a + * positive value, and then dividing by 5. This + * allows the last digit and preceding digits to be + * isolated more quickly than by an initial conversion + * to BigInteger. + */ + long quot = (i >>> 1) / 5; + long rem = i - quot * 10; + return toString(quot) + rem; + + case 16: + return toHexString(i); + + case 32: + return toUnsignedString0(i, 5); + + default: + return toUnsignedBigInteger(i).toString(radix); + } + } + } + + /** + * Return a BigInteger equal to the unsigned value of the + * argument. + */ + private static BigInteger toUnsignedBigInteger(long i) { + if (i >= 0L) + return BigInteger.valueOf(i); + else { + int upper = (int) (i >>> 32); + int lower = (int) i; + + // return (upper << 32) + lower + return (BigInteger.valueOf(Integer.toUnsignedLong(upper))).shiftLeft(32). + add(BigInteger.valueOf(Integer.toUnsignedLong(lower))); + } + } + + /** + * Returns a string representation of the {@code long} + * argument as an unsigned integer in base 16. + * + *

The unsigned {@code long} value is the argument plus + * 264 if the argument is negative; otherwise, it is + * equal to the argument. This value is converted to a string of + * ASCII digits in hexadecimal (base 16) with no extra + * leading {@code 0}s. + * + *

The value of the argument can be recovered from the returned + * string {@code s} by calling {@link + * Long#parseUnsignedLong(String, int) Long.parseUnsignedLong(s, + * 16)}. + * + *

If the unsigned magnitude is zero, it is represented by a + * single zero character {@code '0'} ({@code '\u005Cu0030'}); + * otherwise, the first character of the representation of the + * unsigned magnitude will not be the zero character. The + * following characters are used as hexadecimal digits: + * + *

+ * {@code 0123456789abcdef} + *
+ * + * These are the characters {@code '\u005Cu0030'} through + * {@code '\u005Cu0039'} and {@code '\u005Cu0061'} through + * {@code '\u005Cu0066'}. If uppercase letters are desired, + * the {@link java.lang.String#toUpperCase()} method may be called + * on the result: + * + *
+ * {@code Long.toHexString(n).toUpperCase()} + *
+ * + * @param i a {@code long} to be converted to a string. + * @return the string representation of the unsigned {@code long} + * value represented by the argument in hexadecimal + * (base 16). + * @see #parseUnsignedLong(String, int) + * @see #toUnsignedString(long, int) + * @since JDK 1.0.2 + */ + public static String toHexString(long i) { + return toUnsignedString0(i, 4); + } + + /** + * Returns a string representation of the {@code long} + * argument as an unsigned integer in base 8. + * + *

The unsigned {@code long} value is the argument plus + * 264 if the argument is negative; otherwise, it is + * equal to the argument. This value is converted to a string of + * ASCII digits in octal (base 8) with no extra leading + * {@code 0}s. + * + *

The value of the argument can be recovered from the returned + * string {@code s} by calling {@link + * Long#parseUnsignedLong(String, int) Long.parseUnsignedLong(s, + * 8)}. + * + *

If the unsigned magnitude is zero, it is represented by a + * single zero character {@code '0'} ({@code '\u005Cu0030'}); + * otherwise, the first character of the representation of the + * unsigned magnitude will not be the zero character. The + * following characters are used as octal digits: + * + *

+ * {@code 01234567} + *
+ * + * These are the characters {@code '\u005Cu0030'} through + * {@code '\u005Cu0037'}. + * + * @param i a {@code long} to be converted to a string. + * @return the string representation of the unsigned {@code long} + * value represented by the argument in octal (base 8). + * @see #parseUnsignedLong(String, int) + * @see #toUnsignedString(long, int) + * @since JDK 1.0.2 + */ + public static String toOctalString(long i) { + return toUnsignedString0(i, 3); + } + + /** + * Returns a string representation of the {@code long} + * argument as an unsigned integer in base 2. + * + *

The unsigned {@code long} value is the argument plus + * 264 if the argument is negative; otherwise, it is + * equal to the argument. This value is converted to a string of + * ASCII digits in binary (base 2) with no extra leading + * {@code 0}s. + * + *

The value of the argument can be recovered from the returned + * string {@code s} by calling {@link + * Long#parseUnsignedLong(String, int) Long.parseUnsignedLong(s, + * 2)}. + * + *

If the unsigned magnitude is zero, it is represented by a + * single zero character {@code '0'} ({@code '\u005Cu0030'}); + * otherwise, the first character of the representation of the + * unsigned magnitude will not be the zero character. The + * characters {@code '0'} ({@code '\u005Cu0030'}) and {@code + * '1'} ({@code '\u005Cu0031'}) are used as binary digits. + * + * @param i a {@code long} to be converted to a string. + * @return the string representation of the unsigned {@code long} + * value represented by the argument in binary (base 2). + * @see #parseUnsignedLong(String, int) + * @see #toUnsignedString(long, int) + * @since JDK 1.0.2 + */ + public static String toBinaryString(long i) { + return toUnsignedString0(i, 1); + } + + /** + * Format a long (treated as unsigned) into a String. + * @param val the value to format + * @param shift the log2 of the base to format in (4 for hex, 3 for octal, 1 for binary) + */ + // DIFFBLUE MODEL LIBRARY: Handled internally by CBMC + static String toUnsignedString0(long val, int shift) { + CProver.assume(0 <= val && val <= Integer.MAX_VALUE); + return Integer.toString((int)val, 1 << shift); + } + + /** + * Returns a {@code String} object representing the specified + * {@code long}. The argument is converted to signed decimal + * representation and returned as a string, exactly as if the + * argument and the radix 10 were given as arguments to the {@link + * #toString(long, int)} method. + * + * @param i a {@code long} to be converted. + * @return a string representation of the argument in base 10. + */ + public static String toString(long i) { + // this function is handled by cbmc internally + return CProver.nondetWithoutNullForNotModelled(); + } + + /** + * Returns a string representation of the argument as an unsigned + * decimal value. + * + * The argument is converted to unsigned decimal representation + * and returned as a string exactly as if the argument and radix + * 10 were given as arguments to the {@link #toUnsignedString(long, + * int)} method. + * + * @param i an integer to be converted to an unsigned string. + * @return an unsigned string representation of the argument. + * @see #toUnsignedString(long, int) + * @since 1.8 + */ + public static String toUnsignedString(long i) { + return toUnsignedString(i, 10); + } + + /** + * Places characters representing the integer i into the + * character array buf. The characters are placed into + * the buffer backwards starting with the least significant + * digit at the specified index (exclusive), and working + * backwards from there. + * + * Will fail if i == Long.MIN_VALUE + */ + + // Requires positive x + static int stringSize(long x) { + long p = 10; + for (int i=1; i<19; i++) { + if (x < p) + return i; + p = 10*p; + } + return 19; + } + + /** + * Parses the string argument as a signed {@code long} in the + * radix specified by the second argument. The characters in the + * string must all be digits of the specified radix (as determined + * by whether {@link java.lang.Character#digit(char, int)} returns + * a nonnegative value), except that the first character may be an + * ASCII minus sign {@code '-'} ({@code '\u005Cu002D'}) to + * indicate a negative value or an ASCII plus sign {@code '+'} + * ({@code '\u005Cu002B'}) to indicate a positive value. The + * resulting {@code long} value is returned. + * + *

Note that neither the character {@code L} + * ({@code '\u005Cu004C'}) nor {@code l} + * ({@code '\u005Cu006C'}) is permitted to appear at the end + * of the string as a type indicator, as would be permitted in + * Java programming language source code - except that either + * {@code L} or {@code l} may appear as a digit for a + * radix greater than or equal to 22. + * + *

An exception of type {@code NumberFormatException} is + * thrown if any of the following situations occurs: + *

+ * + *

Examples: + *

+     * parseLong("0", 10) returns 0L
+     * parseLong("473", 10) returns 473L
+     * parseLong("+42", 10) returns 42L
+     * parseLong("-0", 10) returns 0L
+     * parseLong("-FF", 16) returns -255L
+     * parseLong("1100110", 2) returns 102L
+     * parseLong("99", 8) throws a NumberFormatException
+     * parseLong("Hazelnut", 10) throws a NumberFormatException
+     * parseLong("Hazelnut", 36) returns 1356099454469L
+     * 
+ * + * @param s the {@code String} containing the + * {@code long} representation to be parsed. + * @param radix the radix to be used while parsing {@code s}. + * @return the {@code long} represented by the string argument in + * the specified radix. + * @throws NumberFormatException if the string does not contain a + * parsable {@code long}. + */ + public static long parseLong(String s, int radix) + throws NumberFormatException + { + if (s == null) { + throw new NumberFormatException("null"); + } + + if (radix < Character.MIN_RADIX) { + throw new NumberFormatException("radix " + radix + + " less than Character.MIN_RADIX"); + } + if (radix > Character.MAX_RADIX) { + throw new NumberFormatException("radix " + radix + + " greater than Character.MAX_RADIX"); + } + + long result = 0; + boolean negative = false; + int i = 0, len = s.length(); + long limit = -Long.MAX_VALUE; + long multmin; + int digit; + + if (len > 0) { + char firstChar = CProverString.charAt(s, 0); + if (firstChar < '0') { // Possible leading "+" or "-" + if (firstChar == '-') { + negative = true; + limit = Long.MIN_VALUE; + } else if (firstChar != '+') + throw NumberFormatException.forInputString(s); + + if (len == 1) // Cannot have lone "+" or "-" + throw NumberFormatException.forInputString(s); + i++; + } + multmin = limit / radix; + while (i < len) { + // Accumulating negatively avoids surprises near MAX_VALUE + digit = Character.digit(CProverString.charAt(s, i++), radix); + if (digit < 0) { + throw NumberFormatException.forInputString(s); + } + if (result < multmin) { + throw NumberFormatException.forInputString(s); + } + result *= radix; + if (result < limit + digit) { + throw NumberFormatException.forInputString(s); + } + result -= digit; + } + } else { + throw NumberFormatException.forInputString(s); + } + return negative ? result : -result; + } + + /** + * Parses the string argument as a signed decimal {@code long}. + * The characters in the string must all be decimal digits, except + * that the first character may be an ASCII minus sign {@code '-'} + * ({@code \u005Cu002D'}) to indicate a negative value or an + * ASCII plus sign {@code '+'} ({@code '\u005Cu002B'}) to + * indicate a positive value. The resulting {@code long} value is + * returned, exactly as if the argument and the radix {@code 10} + * were given as arguments to the {@link + * #parseLong(java.lang.String, int)} method. + * + *

Note that neither the character {@code L} + * ({@code '\u005Cu004C'}) nor {@code l} + * ({@code '\u005Cu006C'}) is permitted to appear at the end + * of the string as a type indicator, as would be permitted in + * Java programming language source code. + * + * @param s a {@code String} containing the {@code long} + * representation to be parsed + * @return the {@code long} represented by the argument in + * decimal. + * @throws NumberFormatException if the string does not contain a + * parsable {@code long}. + */ + public static long parseLong(String s) throws NumberFormatException { + return CProver.nondetLong(); //The function is handled by cbmc internally + } + + /** + * Parses the string argument as an unsigned {@code long} in the + * radix specified by the second argument. An unsigned integer + * maps the values usually associated with negative numbers to + * positive numbers larger than {@code MAX_VALUE}. + * + * The characters in the string must all be digits of the + * specified radix (as determined by whether {@link + * java.lang.Character#digit(char, int)} returns a nonnegative + * value), except that the first character may be an ASCII plus + * sign {@code '+'} ({@code '\u005Cu002B'}). The resulting + * integer value is returned. + * + *

An exception of type {@code NumberFormatException} is + * thrown if any of the following situations occurs: + *

+ * + * + * @param s the {@code String} containing the unsigned integer + * representation to be parsed + * @param radix the radix to be used while parsing {@code s}. + * @return the unsigned {@code long} represented by the string + * argument in the specified radix. + * @throws NumberFormatException if the {@code String} + * does not contain a parsable {@code long}. + * @since 1.8 + */ + public static long parseUnsignedLong(String s, int radix) + throws NumberFormatException { + if (s == null) { + throw new NumberFormatException("null"); + } + + int len = s.length(); + if (len > 0) { + char firstChar = CProverString.charAt(s, 0); + if (firstChar == '-') { + throw new + NumberFormatException(String.format("Illegal leading minus sign " + + "on unsigned string %s.", s)); + } else { + if (len <= 12 || // Long.MAX_VALUE in Character.MAX_RADIX is 13 digits + (radix == 10 && len <= 18) ) { // Long.MAX_VALUE in base 10 is 19 digits + return parseLong(s, radix); + } + + // No need for range checks on len due to testing above. + long first = parseLong(CProverString.substring(s, 0, len - 1), radix); + int second = Character.digit(CProverString.charAt(s, len - 1), radix); + if (second < 0) { + throw new NumberFormatException("Bad digit at end of " + s); + } + long result = first * radix + second; + if (compareUnsigned(result, first) < 0) { + /* + * The maximum unsigned value, (2^64)-1, takes at + * most one more digit to represent than the + * maximum signed value, (2^63)-1. Therefore, + * parsing (len - 1) digits will be appropriately + * in-range of the signed parsing. In other + * words, if parsing (len -1) digits overflows + * signed parsing, parsing len digits will + * certainly overflow unsigned parsing. + * + * The compareUnsigned check above catches + * situations where an unsigned overflow occurs + * incorporating the contribution of the final + * digit. + */ + throw new NumberFormatException(String.format("String value %s exceeds " + + "range of unsigned long.", s)); + } + return result; + } + } else { + throw NumberFormatException.forInputString(s); + } + } + + /** + * Parses the string argument as an unsigned decimal {@code long}. The + * characters in the string must all be decimal digits, except + * that the first character may be an an ASCII plus sign {@code + * '+'} ({@code '\u005Cu002B'}). The resulting integer value + * is returned, exactly as if the argument and the radix 10 were + * given as arguments to the {@link + * #parseUnsignedLong(java.lang.String, int)} method. + * + * @param s a {@code String} containing the unsigned {@code long} + * representation to be parsed + * @return the unsigned {@code long} value represented by the decimal string argument + * @throws NumberFormatException if the string does not contain a + * parsable unsigned integer. + * @since 1.8 + */ + public static long parseUnsignedLong(String s) throws NumberFormatException { + return parseUnsignedLong(s, 10); + } + + /** + * Returns a {@code Long} object holding the value + * extracted from the specified {@code String} when parsed + * with the radix given by the second argument. The first + * argument is interpreted as representing a signed + * {@code long} in the radix specified by the second + * argument, exactly as if the arguments were given to the {@link + * #parseLong(java.lang.String, int)} method. The result is a + * {@code Long} object that represents the {@code long} + * value specified by the string. + * + *

In other words, this method returns a {@code Long} object equal + * to the value of: + * + *

+ * {@code new Long(Long.parseLong(s, radix))} + *
+ * + * @param s the string to be parsed + * @param radix the radix to be used in interpreting {@code s} + * @return a {@code Long} object holding the value + * represented by the string argument in the specified + * radix. + * @throws NumberFormatException If the {@code String} does not + * contain a parsable {@code long}. + */ + public static Long valueOf(String s, int radix) throws NumberFormatException { + return Long.valueOf(parseLong(s, radix)); + } + + /** + * Returns a {@code Long} object holding the value + * of the specified {@code String}. The argument is + * interpreted as representing a signed decimal {@code long}, + * exactly as if the argument were given to the {@link + * #parseLong(java.lang.String)} method. The result is a + * {@code Long} object that represents the integer value + * specified by the string. + * + *

In other words, this method returns a {@code Long} object + * equal to the value of: + * + *

+ * {@code new Long(Long.parseLong(s))} + *
+ * + * @param s the string to be parsed. + * @return a {@code Long} object holding the value + * represented by the string argument. + * @throws NumberFormatException If the string cannot be parsed + * as a {@code long}. + */ + public static Long valueOf(String s) throws NumberFormatException + { + return Long.valueOf(parseLong(s, 10)); + } + + private static class LongCache { + private LongCache(){} + + static final Long cache[] = new Long[-(-128) + 127 + 1]; + + static { + for(int i = 0; i < cache.length; i++) + cache[i] = new Long(i - 128); + } + } + + /** + * Returns a {@code Long} instance representing the specified + * {@code long} value. + * If a new {@code Long} instance is not required, this method + * should generally be used in preference to the constructor + * {@link #Long(long)}, as this method is likely to yield + * significantly better space and time performance by caching + * frequently requested values. + * + * Note that unlike the {@linkplain Integer#valueOf(int) + * corresponding method} in the {@code Integer} class, this method + * is not required to cache values within a particular + * range. + * + * @param l a long value. + * @return a {@code Long} instance representing {@code l}. + * @since 1.5 + */ + public static Long valueOf(long l) { + return new Long(l); + } + + /** + * Decodes a {@code String} into a {@code Long}. + * Accepts decimal, hexadecimal, and octal numbers given by the + * following grammar: + * + *
+ *
+ *
DecodableString: + *
Signopt DecimalNumeral + *
Signopt {@code 0x} HexDigits + *
Signopt {@code 0X} HexDigits + *
Signopt {@code #} HexDigits + *
Signopt {@code 0} OctalDigits + * + *
Sign: + *
{@code -} + *
{@code +} + *
+ *
+ * + * DecimalNumeral, HexDigits, and OctalDigits + * are as defined in section 3.10.1 of + * The Java™ Language Specification, + * except that underscores are not accepted between digits. + * + *

The sequence of characters following an optional + * sign and/or radix specifier ("{@code 0x}", "{@code 0X}", + * "{@code #}", or leading zero) is parsed as by the {@code + * Long.parseLong} method with the indicated radix (10, 16, or 8). + * This sequence of characters must represent a positive value or + * a {@link NumberFormatException} will be thrown. The result is + * negated if first character of the specified {@code String} is + * the minus sign. No whitespace characters are permitted in the + * {@code String}. + * + * @param nm the {@code String} to decode. + * @return a {@code Long} object holding the {@code long} + * value represented by {@code nm} + * @throws NumberFormatException if the {@code String} does not + * contain a parsable {@code long}. + * @see java.lang.Long#parseLong(String, int) + * @since 1.2 + */ + public static Long decode(String nm) throws NumberFormatException { + int radix = 10; + int index = 0; + boolean negative = false; + Long result; + + if (nm.length() == 0) + throw new NumberFormatException("Zero length string"); + char firstChar = CProverString.charAt(nm, 0); + // Handle sign, if present + if (firstChar == '-') { + negative = true; + index++; + } else if (firstChar == '+') + index++; + + // Handle radix specifier, if present + if (nm.startsWith("0x", index) || nm.startsWith("0X", index)) { + index += 2; + radix = 16; + } + else if (nm.startsWith("#", index)) { + index ++; + radix = 16; + } + else if (nm.startsWith("0", index) && nm.length() > 1 + index) { + index ++; + radix = 8; + } + + if (nm.startsWith("-", index) || nm.startsWith("+", index)) + throw new NumberFormatException("Sign character in wrong position"); + + // DIFFBLUE MODEL LIBRARY we compute the sub index only once + String nm_sub_index = CProverString.substring(nm, index); + try { + // DIFFBLUE MODEL LIBRARY + // result = Long.valueOf(nm.substring(index), radix); + result = Long.valueOf(nm_sub_index, radix); + result = negative ? Long.valueOf(-result.longValue()) : result; + } catch (NumberFormatException e) { + // If number is Long.MIN_VALUE, we'll end up here. The next line + // handles this case, and causes any genuine format error to be + // rethrown. + // DIFFBLUE MODEL LIBRARY + // String constant = negative ? ("-" + nm_sub_index) + // : nm.substring(index); + String constant = negative ? ("-" + nm_sub_index) + : nm_sub_index; + result = Long.valueOf(constant, radix); + } + return result; + } + + /** + * The value of the {@code Long}. + * + * @serial + */ + private final long value; + + /** + * Constructs a newly allocated {@code Long} object that + * represents the specified {@code long} argument. + * + * @param value the value to be represented by the + * {@code Long} object. + */ + public Long(long value) { + this.value = value; + } + + /** + * Constructs a newly allocated {@code Long} object that + * represents the {@code long} value indicated by the + * {@code String} parameter. The string is converted to a + * {@code long} value in exactly the manner used by the + * {@code parseLong} method for radix 10. + * + * @param s the {@code String} to be converted to a + * {@code Long}. + * @throws NumberFormatException if the {@code String} does not + * contain a parsable {@code long}. + * @see java.lang.Long#parseLong(java.lang.String, int) + */ + public Long(String s) throws NumberFormatException { + this.value = parseLong(s, 10); + } + + /** + * Returns the value of this {@code Long} as a {@code byte} after + * a narrowing primitive conversion. + * @jls 5.1.3 Narrowing Primitive Conversions + */ + public byte byteValue() { + return (byte)value; + } + + /** + * Returns the value of this {@code Long} as a {@code short} after + * a narrowing primitive conversion. + * @jls 5.1.3 Narrowing Primitive Conversions + */ + public short shortValue() { + return (short)value; + } + + /** + * Returns the value of this {@code Long} as an {@code int} after + * a narrowing primitive conversion. + * @jls 5.1.3 Narrowing Primitive Conversions + */ + public int intValue() { + return (int)value; + } + + /** + * Returns the value of this {@code Long} as a + * {@code long} value. + */ + public long longValue() { + return value; + } + + /** + * Returns the value of this {@code Long} as a {@code float} after + * a widening primitive conversion. + * @jls 5.1.2 Widening Primitive Conversions + */ + public float floatValue() { + return (float)value; + } + + /** + * Returns the value of this {@code Long} as a {@code double} + * after a widening primitive conversion. + * @jls 5.1.2 Widening Primitive Conversions + */ + public double doubleValue() { + return (double)value; + } + + /** + * Returns a {@code String} object representing this + * {@code Long}'s value. The value is converted to signed + * decimal representation and returned as a string, exactly as if + * the {@code long} value were given as an argument to the + * {@link java.lang.Long#toString(long)} method. + * + * @return a string representation of the value of this object in + * base 10. + */ + public String toString() { + return toString(value); + } + + /** + * Returns a hash code for this {@code Long}. The result is + * the exclusive OR of the two halves of the primitive + * {@code long} value held by this {@code Long} + * object. That is, the hashcode is the value of the expression: + * + *

+ * {@code (int)(this.longValue()^(this.longValue()>>>32))} + *
+ * + * @return a hash code value for this object. + */ + @Override + public int hashCode() { + return Long.hashCode(value); + } + + /** + * Returns a hash code for a {@code long} value; compatible with + * {@code Long.hashCode()}. + * + * @param value the value to hash + * @return a hash code value for a {@code long} value. + * @since 1.8 + */ + public static int hashCode(long value) { + return (int)(value ^ (value >>> 32)); + } + + /** + * Compares this object to the specified object. The result is + * {@code true} if and only if the argument is not + * {@code null} and is a {@code Long} object that + * contains the same {@code long} value as this object. + * + * @param obj the object to compare with. + * @return {@code true} if the objects are the same; + * {@code false} otherwise. + */ + public boolean equals(Object obj) { + if (obj instanceof Long) { + return value == ((Long)obj).longValue(); + } + return false; + } + + /** + * Determines the {@code long} value of the system property + * with the specified name. + * + *

The first argument is treated as the name of a system + * property. System properties are accessible through the {@link + * java.lang.System#getProperty(java.lang.String)} method. The + * string value of this property is then interpreted as a {@code + * long} value using the grammar supported by {@link Long#decode decode} + * and a {@code Long} object representing this value is returned. + * + *

If there is no property with the specified name, if the + * specified name is empty or {@code null}, or if the property + * does not have the correct numeric format, then {@code null} is + * returned. + * + *

In other words, this method returns a {@code Long} object + * equal to the value of: + * + *

+ * {@code getLong(nm, null)} + *
+ * + * @param nm property name. + * @return the {@code Long} value of the property. + * @throws SecurityException for the same reasons as + * {@link System#getProperty(String) System.getProperty} + * @see java.lang.System#getProperty(java.lang.String) + * @see java.lang.System#getProperty(java.lang.String, java.lang.String) + */ + public static Long getLong(String nm) { + return getLong(nm, null); + } + + /** + * Determines the {@code long} value of the system property + * with the specified name. + * + *

The first argument is treated as the name of a system + * property. System properties are accessible through the {@link + * java.lang.System#getProperty(java.lang.String)} method. The + * string value of this property is then interpreted as a {@code + * long} value using the grammar supported by {@link Long#decode decode} + * and a {@code Long} object representing this value is returned. + * + *

The second argument is the default value. A {@code Long} object + * that represents the value of the second argument is returned if there + * is no property of the specified name, if the property does not have + * the correct numeric format, or if the specified name is empty or null. + * + *

In other words, this method returns a {@code Long} object equal + * to the value of: + * + *

+ * {@code getLong(nm, new Long(val))} + *
+ * + * but in practice it may be implemented in a manner such as: + * + *
+     * Long result = getLong(nm, null);
+     * return (result == null) ? new Long(val) : result;
+     * 
+ * + * to avoid the unnecessary allocation of a {@code Long} object when + * the default value is not needed. + * + * @param nm property name. + * @param val default value. + * @return the {@code Long} value of the property. + * @throws SecurityException for the same reasons as + * {@link System#getProperty(String) System.getProperty} + * @see java.lang.System#getProperty(java.lang.String) + * @see java.lang.System#getProperty(java.lang.String, java.lang.String) + */ + public static Long getLong(String nm, long val) { + Long result = Long.getLong(nm, null); + return (result == null) ? Long.valueOf(val) : result; + } + + /** + * Returns the {@code long} value of the system property with + * the specified name. The first argument is treated as the name + * of a system property. System properties are accessible through + * the {@link java.lang.System#getProperty(java.lang.String)} + * method. The string value of this property is then interpreted + * as a {@code long} value, as per the + * {@link Long#decode decode} method, and a {@code Long} object + * representing this value is returned; in summary: + * + * + * + *

Note that, in every case, neither {@code L} + * ({@code '\u005Cu004C'}) nor {@code l} + * ({@code '\u005Cu006C'}) is permitted to appear at the end + * of the property value as a type indicator, as would be + * permitted in Java programming language source code. + * + *

The second argument is the default value. The default value is + * returned if there is no property of the specified name, if the + * property does not have the correct numeric format, or if the + * specified name is empty or {@code null}. + * + * @param nm property name. + * @param val default value. + * @return the {@code Long} value of the property. + * @throws SecurityException for the same reasons as + * {@link System#getProperty(String) System.getProperty} + * @see System#getProperty(java.lang.String) + * @see System#getProperty(java.lang.String, java.lang.String) + */ + public static Long getLong(String nm, Long val) { + String v = null; + try { + v = System.getProperty(nm); + } catch (IllegalArgumentException | NullPointerException e) { + } + if (v != null) { + try { + return Long.decode(v); + } catch (NumberFormatException e) { + } + } + return val; + } + + /** + * Compares two {@code Long} objects numerically. + * + * @param anotherLong the {@code Long} to be compared. + * @return the value {@code 0} if this {@code Long} is + * equal to the argument {@code Long}; a value less than + * {@code 0} if this {@code Long} is numerically less + * than the argument {@code Long}; and a value greater + * than {@code 0} if this {@code Long} is numerically + * greater than the argument {@code Long} (signed + * comparison). + * @since 1.2 + */ + public int compareTo(Long anotherLong) { + return compare(this.value, anotherLong.value); + } + + /** + * Compares two {@code long} values numerically. + * The value returned is identical to what would be returned by: + *

+     *    Long.valueOf(x).compareTo(Long.valueOf(y))
+     * 
+ * + * @param x the first {@code long} to compare + * @param y the second {@code long} to compare + * @return the value {@code 0} if {@code x == y}; + * a value less than {@code 0} if {@code x < y}; and + * a value greater than {@code 0} if {@code x > y} + * @since 1.7 + */ + public static int compare(long x, long y) { + return (x < y) ? -1 : ((x == y) ? 0 : 1); + } + + /** + * Compares two {@code long} values numerically treating the values + * as unsigned. + * + * @param x the first {@code long} to compare + * @param y the second {@code long} to compare + * @return the value {@code 0} if {@code x == y}; a value less + * than {@code 0} if {@code x < y} as unsigned values; and + * a value greater than {@code 0} if {@code x > y} as + * unsigned values + * @since 1.8 + */ + public static int compareUnsigned(long x, long y) { + return compare(x + MIN_VALUE, y + MIN_VALUE); + } + + + /** + * Returns the unsigned quotient of dividing the first argument by + * the second where each argument and the result is interpreted as + * an unsigned value. + * + *

Note that in two's complement arithmetic, the three other + * basic arithmetic operations of add, subtract, and multiply are + * bit-wise identical if the two operands are regarded as both + * being signed or both being unsigned. Therefore separate {@code + * addUnsigned}, etc. methods are not provided. + * + * @param dividend the value to be divided + * @param divisor the value doing the dividing + * @return the unsigned quotient of the first argument divided by + * the second argument + * @see #remainderUnsigned + * @since 1.8 + */ + public static long divideUnsigned(long dividend, long divisor) { + if (divisor < 0L) { // signed comparison + // Answer must be 0 or 1 depending on relative magnitude + // of dividend and divisor. + return (compareUnsigned(dividend, divisor)) < 0 ? 0L :1L; + } + + if (dividend > 0) // Both inputs non-negative + return dividend/divisor; + else { + /* + * For simple code, leveraging BigInteger. Longer and faster + * code written directly in terms of operations on longs is + * possible; see "Hacker's Delight" for divide and remainder + * algorithms. + */ + return toUnsignedBigInteger(dividend). + divide(toUnsignedBigInteger(divisor)).longValue(); + } + } + + /** + * Returns the unsigned remainder from dividing the first argument + * by the second where each argument and the result is interpreted + * as an unsigned value. + * + * @param dividend the value to be divided + * @param divisor the value doing the dividing + * @return the unsigned remainder of the first argument divided by + * the second argument + * @see #divideUnsigned + * @since 1.8 + */ + public static long remainderUnsigned(long dividend, long divisor) { + if (dividend > 0 && divisor > 0) { // signed comparisons + return dividend % divisor; + } else { + if (compareUnsigned(dividend, divisor) < 0) // Avoid explicit check for 0 divisor + return dividend; + else + return toUnsignedBigInteger(dividend). + remainder(toUnsignedBigInteger(divisor)).longValue(); + } + } + + // Bit Twiddling + + /** + * The number of bits used to represent a {@code long} value in two's + * complement binary form. + * + * @since 1.5 + */ + @Native public static final int SIZE = 64; + + /** + * The number of bytes used to represent a {@code long} value in two's + * complement binary form. + * + * @since 1.8 + */ + public static final int BYTES = SIZE / Byte.SIZE; + + /** + * Returns a {@code long} value with at most a single one-bit, in the + * position of the highest-order ("leftmost") one-bit in the specified + * {@code long} value. Returns zero if the specified value has no + * one-bits in its two's complement binary representation, that is, if it + * is equal to zero. + * + * @param i the value whose highest one bit is to be computed + * @return a {@code long} value with a single one-bit, in the position + * of the highest-order one-bit in the specified value, or zero if + * the specified value is itself equal to zero. + * @since 1.5 + */ + public static long highestOneBit(long i) { + // HD, Figure 3-1 + i |= (i >> 1); + i |= (i >> 2); + i |= (i >> 4); + i |= (i >> 8); + i |= (i >> 16); + i |= (i >> 32); + return i - (i >>> 1); + } + + /** + * Returns a {@code long} value with at most a single one-bit, in the + * position of the lowest-order ("rightmost") one-bit in the specified + * {@code long} value. Returns zero if the specified value has no + * one-bits in its two's complement binary representation, that is, if it + * is equal to zero. + * + * @param i the value whose lowest one bit is to be computed + * @return a {@code long} value with a single one-bit, in the position + * of the lowest-order one-bit in the specified value, or zero if + * the specified value is itself equal to zero. + * @since 1.5 + */ + public static long lowestOneBit(long i) { + // HD, Section 2-1 + return i & -i; + } + + /** + * Returns the number of zero bits preceding the highest-order + * ("leftmost") one-bit in the two's complement binary representation + * of the specified {@code long} value. Returns 64 if the + * specified value has no one-bits in its two's complement representation, + * in other words if it is equal to zero. + * + *

Note that this method is closely related to the logarithm base 2. + * For all positive {@code long} values x: + *

+ * + * @param i the value whose number of leading zeros is to be computed + * @return the number of zero bits preceding the highest-order + * ("leftmost") one-bit in the two's complement binary representation + * of the specified {@code long} value, or 64 if the value + * is equal to zero. + * @since 1.5 + */ + public static int numberOfLeadingZeros(long i) { + // HD, Figure 5-6 + if (i == 0) + return 64; + int n = 1; + int x = (int)(i >>> 32); + if (x == 0) { n += 32; x = (int)i; } + if (x >>> 16 == 0) { n += 16; x <<= 16; } + if (x >>> 24 == 0) { n += 8; x <<= 8; } + if (x >>> 28 == 0) { n += 4; x <<= 4; } + if (x >>> 30 == 0) { n += 2; x <<= 2; } + n -= x >>> 31; + return n; + } + + /** + * Returns the number of zero bits following the lowest-order ("rightmost") + * one-bit in the two's complement binary representation of the specified + * {@code long} value. Returns 64 if the specified value has no + * one-bits in its two's complement representation, in other words if it is + * equal to zero. + * + * @param i the value whose number of trailing zeros is to be computed + * @return the number of zero bits following the lowest-order ("rightmost") + * one-bit in the two's complement binary representation of the + * specified {@code long} value, or 64 if the value is equal + * to zero. + * @since 1.5 + */ + public static int numberOfTrailingZeros(long i) { + // HD, Figure 5-14 + int x, y; + if (i == 0) return 64; + int n = 63; + y = (int)i; if (y != 0) { n = n -32; x = y; } else x = (int)(i>>>32); + y = x <<16; if (y != 0) { n = n -16; x = y; } + y = x << 8; if (y != 0) { n = n - 8; x = y; } + y = x << 4; if (y != 0) { n = n - 4; x = y; } + y = x << 2; if (y != 0) { n = n - 2; x = y; } + return n - ((x << 1) >>> 31); + } + + /** + * Returns the number of one-bits in the two's complement binary + * representation of the specified {@code long} value. This function is + * sometimes referred to as the population count. + * + * @param i the value whose bits are to be counted + * @return the number of one-bits in the two's complement binary + * representation of the specified {@code long} value. + * @since 1.5 + */ + public static int bitCount(long i) { + // HD, Figure 5-14 + i = i - ((i >>> 1) & 0x5555555555555555L); + i = (i & 0x3333333333333333L) + ((i >>> 2) & 0x3333333333333333L); + i = (i + (i >>> 4)) & 0x0f0f0f0f0f0f0f0fL; + i = i + (i >>> 8); + i = i + (i >>> 16); + i = i + (i >>> 32); + return (int)i & 0x7f; + } + + /** + * Returns the value obtained by rotating the two's complement binary + * representation of the specified {@code long} value left by the + * specified number of bits. (Bits shifted out of the left hand, or + * high-order, side reenter on the right, or low-order.) + * + *

Note that left rotation with a negative distance is equivalent to + * right rotation: {@code rotateLeft(val, -distance) == rotateRight(val, + * distance)}. Note also that rotation by any multiple of 64 is a + * no-op, so all but the last six bits of the rotation distance can be + * ignored, even if the distance is negative: {@code rotateLeft(val, + * distance) == rotateLeft(val, distance & 0x3F)}. + * + * @param i the value whose bits are to be rotated left + * @param distance the number of bit positions to rotate left + * @return the value obtained by rotating the two's complement binary + * representation of the specified {@code long} value left by the + * specified number of bits. + * @since 1.5 + */ + public static long rotateLeft(long i, int distance) { + return (i << distance) | (i >>> -distance); + } + + /** + * Returns the value obtained by rotating the two's complement binary + * representation of the specified {@code long} value right by the + * specified number of bits. (Bits shifted out of the right hand, or + * low-order, side reenter on the left, or high-order.) + * + *

Note that right rotation with a negative distance is equivalent to + * left rotation: {@code rotateRight(val, -distance) == rotateLeft(val, + * distance)}. Note also that rotation by any multiple of 64 is a + * no-op, so all but the last six bits of the rotation distance can be + * ignored, even if the distance is negative: {@code rotateRight(val, + * distance) == rotateRight(val, distance & 0x3F)}. + * + * @param i the value whose bits are to be rotated right + * @param distance the number of bit positions to rotate right + * @return the value obtained by rotating the two's complement binary + * representation of the specified {@code long} value right by the + * specified number of bits. + * @since 1.5 + */ + public static long rotateRight(long i, int distance) { + return (i >>> distance) | (i << -distance); + } + + /** + * Returns the value obtained by reversing the order of the bits in the + * two's complement binary representation of the specified {@code long} + * value. + * + * @param i the value to be reversed + * @return the value obtained by reversing order of the bits in the + * specified {@code long} value. + * @since 1.5 + */ + public static long reverse(long i) { + // HD, Figure 7-1 + i = (i & 0x5555555555555555L) << 1 | (i >>> 1) & 0x5555555555555555L; + i = (i & 0x3333333333333333L) << 2 | (i >>> 2) & 0x3333333333333333L; + i = (i & 0x0f0f0f0f0f0f0f0fL) << 4 | (i >>> 4) & 0x0f0f0f0f0f0f0f0fL; + i = (i & 0x00ff00ff00ff00ffL) << 8 | (i >>> 8) & 0x00ff00ff00ff00ffL; + i = (i << 48) | ((i & 0xffff0000L) << 16) | + ((i >>> 16) & 0xffff0000L) | (i >>> 48); + return i; + } + + /** + * Returns the signum function of the specified {@code long} value. (The + * return value is -1 if the specified value is negative; 0 if the + * specified value is zero; and 1 if the specified value is positive.) + * + * @param i the value whose signum is to be computed + * @return the signum function of the specified {@code long} value. + * @since 1.5 + */ + public static int signum(long i) { + // HD, Section 2-7 + return (int) ((i >> 63) | (-i >>> 63)); + } + + /** + * Returns the value obtained by reversing the order of the bytes in the + * two's complement representation of the specified {@code long} value. + * + * @param i the value whose bytes are to be reversed + * @return the value obtained by reversing the bytes in the specified + * {@code long} value. + * @since 1.5 + */ + public static long reverseBytes(long i) { + i = (i & 0x00ff00ff00ff00ffL) << 8 | (i >>> 8) & 0x00ff00ff00ff00ffL; + return (i << 48) | ((i & 0xffff0000L) << 16) | + ((i >>> 16) & 0xffff0000L) | (i >>> 48); + } + + /** + * Adds two {@code long} values together as per the + operator. + * + * @param a the first operand + * @param b the second operand + * @return the sum of {@code a} and {@code b} + * @see java.util.function.BinaryOperator + * @since 1.8 + */ + public static long sum(long a, long b) { + return a + b; + } + + /** + * Returns the greater of two {@code long} values + * as if by calling {@link Math#max(long, long) Math.max}. + * + * @param a the first operand + * @param b the second operand + * @return the greater of {@code a} and {@code b} + * @see java.util.function.BinaryOperator + * @since 1.8 + */ + public static long max(long a, long b) { + long result = CProver.nondetLong(); + CProver.assume((result == a || result == b) && result >= a && result >= b); + return result; + } + + /** + * Returns the smaller of two {@code long} values + * as if by calling {@link Math#min(long, long) Math.min}. + * + * @param a the first operand + * @param b the second operand + * @return the smaller of {@code a} and {@code b} + * @see java.util.function.BinaryOperator + * @since 1.8 + */ + public static long min(long a, long b) { + long result = CProver.nondetLong(); + CProver.assume((result == a || result == b) && result <= a && result <= b); + return result; + } + + /** use serialVersionUID from JDK 1.0.2 for interoperability */ + @Native private static final long serialVersionUID = 4290774380558885855L; +} diff --git a/src/main/java/java/lang/Math.java b/src/main/java/java/lang/Math.java index 1779ff3..9c214af 100644 --- a/src/main/java/java/lang/Math.java +++ b/src/main/java/java/lang/Math.java @@ -245,11 +245,11 @@ public static double atan(double a) { * @return the measurement of the angle {@code angdeg} * in radians. * @since 1.2 + * + * @diffblue.fullSupport */ public static double toRadians(double angdeg) { - CProver.notModelled(); - return CProver.nondetDouble(); - // return angdeg / 180.0 * PI; + return angdeg / 180.0 * PI; } /** @@ -358,15 +358,48 @@ public static double log10(double a) { * @param a a value. * @return the positive square root of {@code a}. * If the argument is NaN or less than zero, the result is NaN. + * + * @diffblue.limitedSupport + * This implementation using solver constraints only works if squaring the + * result of sqrt is equal to the original number, which is not always + * true. As a result, the solver will return UNSAT in many cases. + * For instance, {@code Math.sqrt(2.0)} will cause the solver to be UNSAT. + * Reported in: TG-5598 + * + * Also, there are precision issues on very small numbers. For instance, + * for values between 0 and {@code 0x0.0000000000001p-900}, the sqrt method + * is likely to not be equal to the result of the real Math.sqrt method. + * Reported in: TG-5602 */ public static double sqrt(double a) { - CProver.notModelled(); - return CProver.nondetDouble(); // return StrictMath.sqrt(a); // default impl. delegates to StrictMath // Note that hardware sqrt instructions // frequently can be directly used by JITs // and should be much faster than doing // Math.sqrt in software. + if (Double.isNaN(a) || a < 0.0) { + return Double.NaN; + } + if (a == Double.POSITIVE_INFINITY || a == 0.0) { + return a; + } + double sqrt = CProver.nondetDouble(); + CProver.assume(sqrt >= 0); + CProver.assume(sqrt * sqrt == a); + + // To solve the satisfiability issue, we should adapt the constraints + // to something like: + // + // double reMultiplied = sqrt * sqrt; + // CProver.assume(reMultiplied > lower); + // CProver.assume(reMultiplied <= upper); + // + // Where lower and upper only differ by one bit in their + // representation, which should ensure that they are the double values + // that are the closest to reMultiplied. + // This implementation cannot be done yet because it would require + // Double.doubleToRawLongBits() to be supported. + return sqrt; } @@ -1270,11 +1303,12 @@ public static long floorMod(long x, long y) { * * @param a the argument whose absolute value is to be determined * @return the absolute value of the argument. + * + * @diffblue.fullSupport + * @diffblue.untested */ public static int abs(int a) { - CProver.notModelled(); - return CProver.nondetInt(); - // return (a < 0) ? -a : a; + return (a < 0) ? -a : a; } /** @@ -1289,11 +1323,12 @@ public static int abs(int a) { * * @param a the argument whose absolute value is to be determined * @return the absolute value of the argument. + * + * @diffblue.fullSupport + * @diffblue.untested */ public static long abs(long a) { - CProver.notModelled(); - return CProver.nondetLong(); - // return (a < 0) ? -a : a; + return (a < 0) ? -a : a; } /** @@ -1310,11 +1345,11 @@ public static long abs(long a) { * * @param a the argument whose absolute value is to be determined * @return the absolute value of the argument. + * + * @diffblue.fullSupport */ public static float abs(float a) { - CProver.notModelled(); - return CProver.nondetFloat(); - // return (a <= 0.0F) ? 0.0F - a : a; + return (a <= 0.0F) ? 0.0F - a : a; } /** @@ -1331,11 +1366,11 @@ public static float abs(float a) { * * @param a the argument whose absolute value is to be determined * @return the absolute value of the argument. + * + * @diffblue.fullSupport */ public static double abs(double a) { - CProver.notModelled(); - return CProver.nondetDouble(); - // return (a <= 0.0D) ? 0.0D - a : a; + return (a <= 0.0D) ? 0.0D - a : a; } /** @@ -1664,11 +1699,15 @@ public static float ulp(float f) { * @return the signum function of the argument * @author Joseph D. Darcy * @since 1.5 + * + * @diffblue.fullSupport */ public static double signum(double d) { - CProver.notModelled(); - return CProver.nondetDouble(); // return (d == 0.0 || Double.isNaN(d))?d:copySign(1.0, d); + if (d == 0 || Double.isNaN(d)) { + return d; + } + return d > 0.0 ? 1.0 : -1.0; } /** @@ -1687,11 +1726,16 @@ public static double signum(double d) { * @return the signum function of the argument * @author Joseph D. Darcy * @since 1.5 + * + * @diffblue.fullSupport + * @diffblue.untested */ public static float signum(float f) { - CProver.notModelled(); - return CProver.nondetFloat(); // return (f == 0.0f || Float.isNaN(f))?f:copySign(1.0f, f); + if (f == 0 || Float.isNaN(f)) { + return f; + } + return f > 0.0f ? 1.0f : -1.0f; } /** diff --git a/src/main/java/java/lang/Number.java b/src/main/java/java/lang/Number.java new file mode 100644 index 0000000..d901609 --- /dev/null +++ b/src/main/java/java/lang/Number.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang; + +/** + * The abstract class {@code Number} is the superclass of platform + * classes representing numeric values that are convertible to the + * primitive types {@code byte}, {@code double}, {@code float}, {@code + * int}, {@code long}, and {@code short}. + * + * The specific semantics of the conversion from the numeric value of + * a particular {@code Number} implementation to a given primitive + * type is defined by the {@code Number} implementation in question. + * + * For platform classes, the conversion is often analogous to a + * narrowing primitive conversion or a widening primitive conversion + * as defining in The Java™ Language Specification + * for converting between primitive types. Therefore, conversions may + * lose information about the overall magnitude of a numeric value, may + * lose precision, and may even return a result of a different sign + * than the input. + * + * See the documentation of a given {@code Number} implementation for + * conversion details. + * + * @author Lee Boynton + * @author Arthur van Hoff + * @jls 5.1.2 Widening Primitive Conversions + * @jls 5.1.3 Narrowing Primitive Conversions + * @since JDK1.0 + */ +public abstract class Number implements java.io.Serializable { + /** + * Returns the value of the specified number as an {@code int}, + * which may involve rounding or truncation. + * + * @return the numeric value represented by this object after conversion + * to type {@code int}. + */ + public abstract int intValue(); + + /** + * Returns the value of the specified number as a {@code long}, + * which may involve rounding or truncation. + * + * @return the numeric value represented by this object after conversion + * to type {@code long}. + */ + public abstract long longValue(); + + /** + * Returns the value of the specified number as a {@code float}, + * which may involve rounding. + * + * @return the numeric value represented by this object after conversion + * to type {@code float}. + */ + public abstract float floatValue(); + + /** + * Returns the value of the specified number as a {@code double}, + * which may involve rounding. + * + * @return the numeric value represented by this object after conversion + * to type {@code double}. + */ + public abstract double doubleValue(); + + /** + * Returns the value of the specified number as a {@code byte}, + * which may involve rounding or truncation. + * + *

This implementation returns the result of {@link #intValue} cast + * to a {@code byte}. + * + * @return the numeric value represented by this object after conversion + * to type {@code byte}. + * @since JDK1.1 + */ + public byte byteValue() { + return (byte)intValue(); + } + + /** + * Returns the value of the specified number as a {@code short}, + * which may involve rounding or truncation. + * + *

This implementation returns the result of {@link #intValue} cast + * to a {@code short}. + * + * @return the numeric value represented by this object after conversion + * to type {@code short}. + * @since JDK1.1 + */ + public short shortValue() { + return (short)intValue(); + } + + /** use serialVersionUID from JDK 1.0.2 for interoperability */ + private static final long serialVersionUID = -8742448824652078965L; +} diff --git a/src/main/java/java/lang/Object.java b/src/main/java/java/lang/Object.java index ba9bf63..dfe9363 100644 --- a/src/main/java/java/lang/Object.java +++ b/src/main/java/java/lang/Object.java @@ -31,7 +31,7 @@ public class Object { - // lock needed for synchronization in cbmc + // lock needed for synchronization in JBMC // used by monitorenter, monitorexit, wait, and notify // Not present in the original Object class public int cproverMonitorCount; @@ -40,6 +40,13 @@ public Object() { cproverMonitorCount = 0; } + /** + * @diffblue.limitedSupport + * This relies on Class.forName whose model is only partial. The model of + * Class is made to work for combinations of calls to Object.getClass, + * Class.forName and Class.getName but other operations are unlikely to + * work. + */ public final Class getClass() { // DIFFBLUE MODEL LIBRARY return Class.forName(CProver.classIdentifier(this)); @@ -61,20 +68,17 @@ public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); } - public final void notify() - { - // FIXME: the thread must own the lock when it calls notify + public final void notify() { + // TODO: the thread must own the lock when it calls notify } - // See implementation of notify - public final void notifyAll() - { - // FIXME: the thread must own the lock when it calls notifyAll + public final void notifyAll() { + // TODO: the thread must own the lock when it calls notifyAll } public final void wait(long timeout) throws InterruptedException { - // FIXME: the thread must own the lock when it calls wait - // FIXME: should only throw if the interrupted flag in Thread is enabled + // TODO: the thread must own the lock when it calls wait + // should only throw if the interrupted flag in Thread is enabled throw new InterruptedException(); } @@ -112,8 +116,8 @@ protected void finalize() throws Throwable { } */ public static void monitorenter(Object object) { - //FIXME: we shoud remove the call to this method from the call - // stack appended to the thrown exception + // TODO: we shoud remove the call to this method from the call + // stack appended to the thrown exception if (object == null) throw new NullPointerException(); @@ -135,19 +139,17 @@ public static void monitorenter(Object object) */ public static void monitorexit(Object object) { - //FIXME: we shoud remove the call to this method from the call - // stack appended to the thrown exception - // FIXME: Enabling these exceptions makes - // jbmc-regression/synchronized-blocks/test_sync.desc - // run into an infinite loop during symex + // TODO: we shoud remove the call to this method from the call + // stack appended to the thrown exception + // TODO: Enabling these exceptions makes + // jbmc/synchronized-blocks/test_sync.desc + // run into an infinite loop during symex // if (object == null) // throw new NullPointerException(); - // if (object.cproverMonitorCount == 0) // throw new IllegalMonitorStateException(); CProver.atomicBegin(); object.cproverMonitorCount--; CProver.atomicEnd(); } - } diff --git a/src/main/java/java/lang/Short.java b/src/main/java/java/lang/Short.java new file mode 100644 index 0000000..a4a700d --- /dev/null +++ b/src/main/java/java/lang/Short.java @@ -0,0 +1,522 @@ +/* + * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang; + +import org.cprover.CProver; + +/** + * The {@code Short} class wraps a value of primitive type {@code + * short} in an object. An object of type {@code Short} contains a + * single field whose type is {@code short}. + * + *

In addition, this class provides several methods for converting + * a {@code short} to a {@code String} and a {@code String} to a + * {@code short}, as well as other constants and methods useful when + * dealing with a {@code short}. + * + * @author Nakul Saraiya + * @author Joseph D. Darcy + * @see java.lang.Number + * @since JDK1.1 + */ +public final class Short extends Number implements Comparable { + + /** + * A constant holding the minimum value a {@code short} can + * have, -215. + */ + public static final short MIN_VALUE = -32768; + + /** + * A constant holding the maximum value a {@code short} can + * have, 215-1. + */ + public static final short MAX_VALUE = 32767; + + /** + * The {@code Class} instance representing the primitive type + * {@code short}. + */ + @SuppressWarnings("unchecked") + public static final Class TYPE = (Class) Class.getPrimitiveClass(7); + /** + * Returns a new {@code String} object representing the + * specified {@code short}. The radix is assumed to be 10. + * + * @param s the {@code short} to be converted + * @return the string representation of the specified {@code short} + * @see java.lang.Integer#toString(int) + */ + public static String toString(short s) { + return Integer.toString((int)s, 10); + } + + /** + * Parses the string argument as a signed {@code short} in the + * radix specified by the second argument. The characters in the + * string must all be digits, of the specified radix (as + * determined by whether {@link java.lang.Character#digit(char, + * int)} returns a nonnegative value) except that the first + * character may be an ASCII minus sign {@code '-'} + * ({@code '\u005Cu002D'}) to indicate a negative value or an + * ASCII plus sign {@code '+'} ({@code '\u005Cu002B'}) to + * indicate a positive value. The resulting {@code short} value + * is returned. + * + *

An exception of type {@code NumberFormatException} is + * thrown if any of the following situations occurs: + *

+ * + * @param s the {@code String} containing the + * {@code short} representation to be parsed + * @param radix the radix to be used while parsing {@code s} + * @return the {@code short} represented by the string + * argument in the specified radix. + * @throws NumberFormatException If the {@code String} + * does not contain a parsable {@code short}. + */ + public static short parseShort(String s, int radix) + throws NumberFormatException { + int i = Integer.parseInt(s, radix); + if (i < MIN_VALUE || i > MAX_VALUE) + throw new NumberFormatException( + "Value out of range. Value:\"" + s + "\" Radix:" + radix); + return (short)i; + } + + /** + * Parses the string argument as a signed decimal {@code + * short}. The characters in the string must all be decimal + * digits, except that the first character may be an ASCII minus + * sign {@code '-'} ({@code '\u005Cu002D'}) to indicate a + * negative value or an ASCII plus sign {@code '+'} + * ({@code '\u005Cu002B'}) to indicate a positive value. The + * resulting {@code short} value is returned, exactly as if the + * argument and the radix 10 were given as arguments to the {@link + * #parseShort(java.lang.String, int)} method. + * + * @param s a {@code String} containing the {@code short} + * representation to be parsed + * @return the {@code short} value represented by the + * argument in decimal. + * @throws NumberFormatException If the string does not + * contain a parsable {@code short}. + */ + public static short parseShort(String s) throws NumberFormatException { + return CProver.nondetShort(); //The function is handled by cbmc internally + } + + /** + * Returns a {@code Short} object holding the value + * extracted from the specified {@code String} when parsed + * with the radix given by the second argument. The first argument + * is interpreted as representing a signed {@code short} in + * the radix specified by the second argument, exactly as if the + * argument were given to the {@link #parseShort(java.lang.String, + * int)} method. The result is a {@code Short} object that + * represents the {@code short} value specified by the string. + * + *

In other words, this method returns a {@code Short} object + * equal to the value of: + * + *

+ * {@code new Short(Short.parseShort(s, radix))} + *
+ * + * @param s the string to be parsed + * @param radix the radix to be used in interpreting {@code s} + * @return a {@code Short} object holding the value + * represented by the string argument in the + * specified radix. + * @throws NumberFormatException If the {@code String} does + * not contain a parsable {@code short}. + */ + public static Short valueOf(String s, int radix) + throws NumberFormatException { + return valueOf(parseShort(s, radix)); + } + + /** + * Returns a {@code Short} object holding the + * value given by the specified {@code String}. The argument + * is interpreted as representing a signed decimal + * {@code short}, exactly as if the argument were given to + * the {@link #parseShort(java.lang.String)} method. The result is + * a {@code Short} object that represents the + * {@code short} value specified by the string. + * + *

In other words, this method returns a {@code Short} object + * equal to the value of: + * + *

+ * {@code new Short(Short.parseShort(s))} + *
+ * + * @param s the string to be parsed + * @return a {@code Short} object holding the value + * represented by the string argument + * @throws NumberFormatException If the {@code String} does + * not contain a parsable {@code short}. + */ + public static Short valueOf(String s) throws NumberFormatException { + return valueOf(s, 10); + } + + /** + * Returns a {@code Short} instance representing the specified + * {@code short} value. + * If a new {@code Short} instance is not required, this method + * should generally be used in preference to the constructor + * {@link #Short(short)}, as this method is likely to yield + * significantly better space and time performance by caching + * frequently requested values. + * + * This method will always cache values in the range -128 to 127, + * inclusive, and may cache other values outside of this range. + * + * @param s a short value. + * @return a {@code Short} instance representing {@code s}. + * @since 1.5 + */ + public static Short valueOf(short s) { + return new Short(s); + } + + /** + * Decodes a {@code String} into a {@code Short}. + * Accepts decimal, hexadecimal, and octal numbers given by + * the following grammar: + * + *
+ *
+ *
DecodableString: + *
Signopt DecimalNumeral + *
Signopt {@code 0x} HexDigits + *
Signopt {@code 0X} HexDigits + *
Signopt {@code #} HexDigits + *
Signopt {@code 0} OctalDigits + * + *
Sign: + *
{@code -} + *
{@code +} + *
+ *
+ * + * DecimalNumeral, HexDigits, and OctalDigits + * are as defined in section 3.10.1 of + * The Java™ Language Specification, + * except that underscores are not accepted between digits. + * + *

The sequence of characters following an optional + * sign and/or radix specifier ("{@code 0x}", "{@code 0X}", + * "{@code #}", or leading zero) is parsed as by the {@code + * Short.parseShort} method with the indicated radix (10, 16, or + * 8). This sequence of characters must represent a positive + * value or a {@link NumberFormatException} will be thrown. The + * result is negated if first character of the specified {@code + * String} is the minus sign. No whitespace characters are + * permitted in the {@code String}. + * + * @param nm the {@code String} to decode. + * @return a {@code Short} object holding the {@code short} + * value represented by {@code nm} + * @throws NumberFormatException if the {@code String} does not + * contain a parsable {@code short}. + * @see java.lang.Short#parseShort(java.lang.String, int) + */ + public static Short decode(String nm) throws NumberFormatException { + int i = Integer.decode(nm); + if (i < MIN_VALUE || i > MAX_VALUE) + throw new NumberFormatException( + "Value " + i + " out of range from input " + nm); + return valueOf((short)i); + } + + /** + * The value of the {@code Short}. + * + * @serial + */ + private final short value; + + /** + * Constructs a newly allocated {@code Short} object that + * represents the specified {@code short} value. + * + * @param value the value to be represented by the + * {@code Short}. + */ + public Short(short value) { + this.value = value; + } + + /** + * Constructs a newly allocated {@code Short} object that + * represents the {@code short} value indicated by the + * {@code String} parameter. The string is converted to a + * {@code short} value in exactly the manner used by the + * {@code parseShort} method for radix 10. + * + * @param s the {@code String} to be converted to a + * {@code Short} + * @throws NumberFormatException If the {@code String} + * does not contain a parsable {@code short}. + * @see java.lang.Short#parseShort(java.lang.String, int) + */ + public Short(String s) throws NumberFormatException { + this.value = parseShort(s, 10); + } + + /** + * Returns the value of this {@code Short} as a {@code byte} after + * a narrowing primitive conversion. + * @jls 5.1.3 Narrowing Primitive Conversions + */ + public byte byteValue() { + return (byte)value; + } + + /** + * Returns the value of this {@code Short} as a + * {@code short}. + */ + public short shortValue() { + return value; + } + + /** + * Returns the value of this {@code Short} as an {@code int} after + * a widening primitive conversion. + * @jls 5.1.2 Widening Primitive Conversions + */ + public int intValue() { + return (int)value; + } + + /** + * Returns the value of this {@code Short} as a {@code long} after + * a widening primitive conversion. + * @jls 5.1.2 Widening Primitive Conversions + */ + public long longValue() { + return (long)value; + } + + /** + * Returns the value of this {@code Short} as a {@code float} + * after a widening primitive conversion. + * @jls 5.1.2 Widening Primitive Conversions + */ + public float floatValue() { + return (float)value; + } + + /** + * Returns the value of this {@code Short} as a {@code double} + * after a widening primitive conversion. + * @jls 5.1.2 Widening Primitive Conversions + */ + public double doubleValue() { + return (double)value; + } + + /** + * Returns a {@code String} object representing this + * {@code Short}'s value. The value is converted to signed + * decimal representation and returned as a string, exactly as if + * the {@code short} value were given as an argument to the + * {@link java.lang.Short#toString(short)} method. + * + * @return a string representation of the value of this object in + * base 10. + */ + public String toString() { + return Integer.toString((int)value); + } + + /** + * Returns a hash code for this {@code Short}; equal to the result + * of invoking {@code intValue()}. + * + * @return a hash code value for this {@code Short} + */ + @Override + public int hashCode() { + return Short.hashCode(value); + } + + /** + * Returns a hash code for a {@code short} value; compatible with + * {@code Short.hashCode()}. + * + * @param value the value to hash + * @return a hash code value for a {@code short} value. + * @since 1.8 + */ + public static int hashCode(short value) { + return (int)value; + } + + /** + * Compares this object to the specified object. The result is + * {@code true} if and only if the argument is not + * {@code null} and is a {@code Short} object that + * contains the same {@code short} value as this object. + * + * @param obj the object to compare with + * @return {@code true} if the objects are the same; + * {@code false} otherwise. + */ + public boolean equals(Object obj) { + if (obj instanceof Short) { + return value == ((Short)obj).shortValue(); + } + return false; + } + + /** + * Compares two {@code Short} objects numerically. + * + * @param anotherShort the {@code Short} to be compared. + * @return the value {@code 0} if this {@code Short} is + * equal to the argument {@code Short}; a value less than + * {@code 0} if this {@code Short} is numerically less + * than the argument {@code Short}; and a value greater than + * {@code 0} if this {@code Short} is numerically + * greater than the argument {@code Short} (signed + * comparison). + * @since 1.2 + */ + public int compareTo(Short anotherShort) { + return compare(this.value, anotherShort.value); + } + + /** + * Compares two {@code short} values numerically. + * The value returned is identical to what would be returned by: + *

+     *    Short.valueOf(x).compareTo(Short.valueOf(y))
+     * 
+ * + * @param x the first {@code short} to compare + * @param y the second {@code short} to compare + * @return the value {@code 0} if {@code x == y}; + * a value less than {@code 0} if {@code x < y}; and + * a value greater than {@code 0} if {@code x > y} + * @since 1.7 + */ + public static int compare(short x, short y) { + return x - y; + } + + /** + * The number of bits used to represent a {@code short} value in two's + * complement binary form. + * @since 1.5 + */ + public static final int SIZE = 16; + + /** + * The number of bytes used to represent a {@code short} value in two's + * complement binary form. + * + * @since 1.8 + */ + public static final int BYTES = SIZE / Byte.SIZE; + + /** + * Returns the value obtained by reversing the order of the bytes in the + * two's complement representation of the specified {@code short} value. + * + * @param i the value whose bytes are to be reversed + * @return the value obtained by reversing (or, equivalently, swapping) + * the bytes in the specified {@code short} value. + * @since 1.5 + */ + public static short reverseBytes(short i) { + return (short) (((i & 0xFF00) >> 8) | (i << 8)); + } + + + /** + * Converts the argument to an {@code int} by an unsigned + * conversion. In an unsigned conversion to an {@code int}, the + * high-order 16 bits of the {@code int} are zero and the + * low-order 16 bits are equal to the bits of the {@code short} argument. + * + * Consequently, zero and positive {@code short} values are mapped + * to a numerically equal {@code int} value and negative {@code + * short} values are mapped to an {@code int} value equal to the + * input plus 216. + * + * @param x the value to convert to an unsigned {@code int} + * @return the argument converted to {@code int} by an unsigned + * conversion + * @since 1.8 + */ + public static int toUnsignedInt(short x) { + return ((int) x) & 0xffff; + } + + /** + * Converts the argument to a {@code long} by an unsigned + * conversion. In an unsigned conversion to a {@code long}, the + * high-order 48 bits of the {@code long} are zero and the + * low-order 16 bits are equal to the bits of the {@code short} argument. + * + * Consequently, zero and positive {@code short} values are mapped + * to a numerically equal {@code long} value and negative {@code + * short} values are mapped to a {@code long} value equal to the + * input plus 216. + * + * @param x the value to convert to an unsigned {@code long} + * @return the argument converted to {@code long} by an unsigned + * conversion + * @since 1.8 + */ + public static long toUnsignedLong(short x) { + return ((long) x) & 0xffffL; + } + + /** use serialVersionUID from JDK 1.1. for interoperability */ + private static final long serialVersionUID = 7515723908773894738L; +} diff --git a/src/main/java/java/lang/String.java b/src/main/java/java/lang/String.java index f690b63..dd64c4a 100644 --- a/src/main/java/java/lang/String.java +++ b/src/main/java/java/lang/String.java @@ -151,7 +151,6 @@ public final class String * unnecessary since Strings are immutable. * * @diffblue.fullSupport - * @diffblue.untested */ public String() { // DIFFBLUE MODEL LIBRARY This is treated internally in CBMC @@ -169,7 +168,6 @@ public String() { * A {@code String} * * @diffblue.fullSupport - * @diffblue.untested */ public String(String original) { // DIFFBLUE MODEL LIBRARY This is treated internally in CBMC @@ -307,6 +305,8 @@ private static String cproverNonDet() * * @diffblue.limitedSupport * Assumes all codePoints are in the Basic Multilingual Plane. + * An implication of this limitation is that no trace is generated for + * the cases where IllegalArgumentException would be thrown. */ public String(int[] codePoints, int offset, int count) { // if (offset < 0) { @@ -595,7 +595,8 @@ public String(byte bytes[], int offset, int length, String charsetName) * The length of the String constructed is limited by the unwind * parameter. */ - public String(byte bytes[], int offset, int length, Charset charset) { + public String(byte bytes[], int offset, int length, Charset charset) + { // if (charset == null) // throw new NullPointerException("charset"); // checkBounds(bytes, offset, length); @@ -663,7 +664,8 @@ public String(byte bytes[], String charsetName) * * @return the constructed string */ - private static String cproverOfByteArray(byte[] bytes, Charset charset) { + private static String cproverOfByteArray(byte[] bytes, Charset charset) + { String s = CProver.nondetWithoutNull(""); byte[] getBytesResult = s.cproverReversibleGetBytes(charset); CProver.assume(getBytesResult.length == bytes.length); @@ -696,10 +698,9 @@ private static String cproverOfByteArray(byte[] bytes, Charset charset) { * @diffblue.limitedSupport * Only standard charsets are supported and for ASCII, UTF-8 and ISO-8859-1 * we restrict all the characters to be ASCII. - * Generated tests will not pass if the function under test takes a - * Charset argument because it is set using reflection. */ - public String(byte bytes[], Charset charset) { + public String(byte bytes[], Charset charset) + { // this(bytes, 0, bytes.length, charset); // DIFFBLUE MODEL LIBRARY @@ -734,7 +735,6 @@ public String(byte bytes[], Charset charset) { * * @diffblue.limitedSupport We assume all the bytes are ASCII characters, * and that the default charset encodes ASCII characters with one byte. - * In particular test may fail if the default charset is UTF-16. */ public String(byte bytes[], int offset, int length) { // DIFFBLUE MODEL LIBRARY @@ -772,7 +772,6 @@ public String(byte bytes[], int offset, int length) { * * @diffblue.limitedSupport We assume all the bytes are ASCII characters, * and that the default charset encodes ASCII characters with one byte. - * In particular test may fail if the default charset is UTF-16. */ public String(byte bytes[]) { this(bytes, 0, bytes.length); @@ -1080,15 +1079,17 @@ public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) { if (srcBegin < 0) { throw new StringIndexOutOfBoundsException(srcBegin); } + // if (srcEnd > value.length) { + // DIFFBLUE MODEL LIBRARY we have no value member if (srcEnd > length()) { throw new StringIndexOutOfBoundsException(srcEnd); } if (srcBegin > srcEnd) { throw new StringIndexOutOfBoundsException(srcEnd - srcBegin); } + // System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin); // DIFFBLUE MODEL LIBRARY we inline System.arraycopy here so that we // can specialize it for characters. - // System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin); for(int i = 0; i < srcEnd - srcBegin; i++) { dst[dstBegin + i] = CProverString.charAt(this, srcBegin + i); } @@ -1461,7 +1462,9 @@ else if(c<=0xFFFF) * @param charsetName * The name of the Charset used to encode the {@code String} */ - private byte[] cproverReversibleGetBytes(String charsetName) { + private byte[] cproverReversibleGetBytes(String charsetName) + throws UnsupportedEncodingException + { if (CProverString.equals(charsetName, "UTF-16BE")) { return getBytesUTF_16BE(); } @@ -1471,10 +1474,12 @@ private byte[] cproverReversibleGetBytes(String charsetName) { if (CProverString.equals(charsetName, "UTF-16")) { return getBytesUTF_16(); } - CProver.assume(CProverString.equals(charsetName, "UTF-8") + if (CProverString.equals(charsetName, "UTF-8") || CProverString.equals(charsetName, "ISO-8859-1") - || CProverString.equals(charsetName, "US-ASCII")); - return cproverGetBytesEnforceAscii(); + || CProverString.equals(charsetName, "US-ASCII")) { + return cproverGetBytesEnforceAscii(); + } + throw new UnsupportedEncodingException(charsetName); } /** @@ -1489,7 +1494,12 @@ private byte[] cproverReversibleGetBytes(Charset charset) { if (charset == null) { throw new NullPointerException(); } - return cproverReversibleGetBytes(charset.name()); + try { + return cproverReversibleGetBytes(charset.name()); + } catch (UnsupportedEncodingException e) { + CProver.assume(false); + return new byte[0]; + } } /** @@ -2976,13 +2986,32 @@ public String replaceFirst(String regex, String replacement) { * @since 1.4 * @spec JSR-51 * - * @diffblue.noSupport + * @diffblue.limitedSupport + * We enforce the regex argument is a string literal without any special + * characters used in regular expressions: + * '[', ']','.', '\\', '?', '^', '$', '*', '+', '{', '}', '|', '(', ')', + * hence PatternSyntaxException will never be thrown. */ public String replaceAll(String regex, String replacement) { - CProver.notModelled(); - return CProver.nondetWithNullForNotModelled(); // return Pattern.compile(regex).matcher(this).replaceAll(replacement); + // DIFFBLUE MODELS LIBRARY: we assume the expression is just a string literal + CProver.assume( + regex.indexOf('[') == -1 && + regex.indexOf(']') == -1 && + regex.indexOf('.') == -1 && + regex.indexOf('\\') == -1 && + regex.indexOf('?') == -1 && + regex.indexOf('^') == -1 && + regex.indexOf('$') == -1 && + regex.indexOf('*') == -1 && + regex.indexOf('+') == -1 && + regex.indexOf('{') == -1 && + regex.indexOf('}') == -1 && + regex.indexOf('|') == -1 && + regex.indexOf('(') == -1 && + regex.indexOf(')') == -1); + return replace(regex, replacement); } /** @@ -2997,10 +3026,14 @@ public String replaceAll(String regex, String replacement) * @return The resulting string * @since 1.5 * - * @diffblue.noSupport + * @diffblue.limitedSupport + * Only works for arguments that are constant strings with only 1 character. + * For instance, we can generate traces for s.replace("a", "b") but not + * s.replace("a", "bc") or s.replace(arg, "b"). + * @diffblue.untested */ public String replace(CharSequence target, CharSequence replacement) { - CProver.notModelled(); + // DIFFBLUE MODEL LIBRARY This is treated internally in CBMC return CProver.nondetWithNullForNotModelled(); // return Pattern.compile(target.toString(), Pattern.LITERAL).matcher( // this).replaceAll(Matcher.quoteReplacement(replacement.toString())); @@ -3092,7 +3125,17 @@ public String replace(CharSequence target, CharSequence replacement) { * @since 1.4 * @spec JSR-51 * - * @diffblue.noSupport + * @diffblue.limitedSupport + * This forces the regex argument to contain at most one character. + * The model assumes the regex is not a special regex character: + * \.[{()<>*+-=?^$| . + * So no trace can be generated for these characters. + * In particular this prevents any trace for the PatternSyntaxException case + * from being generated. + * + * The size of the computed array is limited by the unwind parameter. + * No trace can be generated for which the resulting array would be greater + * than the unwind value. */ public String[] split(String regex, int limit) { // /* fastpath if the regex is a @@ -3252,14 +3295,24 @@ public String[] split(String regex, int limit) { * @since 1.4 * @spec JSR-51 * - * @diffblue.noSupport + * @diffblue.limitedSupport + * This forces the regex argument to contain at most one character. + * The model assumes the regex is not a special regex character: + * \.[{()<>*+-=?^$| . + * So no trace can be generated for these characters. + * In particular this prevents any trace for the PatternSyntaxException case + * from being generated. + * + * The size of the computed array is limited by the unwind parameter. + * No trace can be generated for which the resulting array would be greater + * than the unwind value. */ public String[] split(String regex) { // return split(regex, 0); // DIFFBLUE MODEL LIBRARY // The (String, int) version in our model calls the String version, - // which is the other way in the original implementation. + // which the other way in the original implementation. // This way, if the String version is called in the code we analyse, // only the code for this one is loaded. // The 0 case is a bit special compared to the others in that it disregard trailing empty strings. @@ -3916,10 +3969,13 @@ static String cproverFormatArgument(Object obj) { } else if (obj instanceof Byte) { byte byteValue = ((Byte) obj); longValue = (long) byteValue; + } else if (obj instanceof Short) { + short shortValue = ((Short) obj); + longValue = (long) shortValue; } else if (obj instanceof Boolean) { longValue = ((Boolean) obj) ? 1 : 0; } else { - return CProver.nondetWithoutNull(""); + CProver.assume(false); } // The long value is encoded using a string of 4 characters @@ -3986,15 +4042,15 @@ static String cproverFormatArgument(Object obj) { * * @diffblue.untested */ public static String format(String format, Object... args) { // return new Formatter().format(format, args).toString(); // DIFFBLUE MODEL LIBRARY - if (args.length > 10) { - return CProver.nondetWithoutNull(""); - } + CProver.assume(args.length <= 10); String arg0 = args.length > 0 ? cproverFormatArgument(args[0]) : ""; String arg1 = args.length > 1 ? cproverFormatArgument(args[1]) : ""; String arg2 = args.length > 2 ? cproverFormatArgument(args[2]) : ""; @@ -4028,10 +4077,11 @@ public static String format(String format, Object... args) { String arg7 = args.length > 7 ? cproverFormatArgument(args[7]) : ""; String arg8 = args.length > 8 ? cproverFormatArgument(args[8]) : ""; String arg9 = args.length > 9 ? cproverFormatArgument(args[9]) : ""; - return CProverString.format(format, arg0, arg1, arg2, arg3, arg4, arg5, - arg6, arg7, arg8, arg9); + return CProverString.format(format, arg0, arg1, arg2, arg3, arg4, arg5, arg6, + arg7, arg8, arg9); } + /** * Returns a formatted string using the specified locale, format string, * and arguments. @@ -4069,8 +4119,7 @@ public static String format(String format, Object... args) { * @see java.util.Formatter * @since 1.5 * - * @diffblue.limitedSupport The locale argument is ignored and it has the - * same limitations as {@link #format(String, Object...)}. + * @diffblue.noSupport */ public static String format(Locale l, String format, Object... args) { // return new Formatter(l).format(format, args).toString(); @@ -4187,10 +4236,11 @@ public static String copyValueOf(char data[]) { * {@code "false"} is returned. * * @diffblue.fullSupport - * @diffblue.untested */ public static String valueOf(boolean b) { - return b ? "true" : "false"; + // DIFFBLUE MODEL LIBRARY This is treated internally in JBMC + return CProver.nondetWithoutNullForNotModelled(); + // return b ? "true" : "false"; } /** @@ -4285,7 +4335,7 @@ public static String valueOf(float f) { */ public static String valueOf(double d) { // DIFFBLUE MODEL LIBRARY we cast the number down to float because - // the string solver only knows how to convert floats to string + // string solver only knows how to convert floats to string return valueOf(CProver.doubleToFloat(d)); // return Double.toString(d); } @@ -4296,7 +4346,7 @@ public static String valueOf(double d) { static String[] cproverInternPool = null; /** - * Number of elements stored in the pool for {@code String.intern} pool. + * Number of elements stored in the pool for {@code String.intern}. * This can be smaller than {@code cproverInternPool.length} which * represents the capacity of the array and is fixed for each execution. */ @@ -4327,6 +4377,7 @@ public static String valueOf(double d) { * * @diffblue.limitedSupport literal strings and string-valued constant * expressions are not interned. + * @diffblue.untested */ // DIFFBLUE MODEL LIBRARY // public native String intern(); diff --git a/src/main/java/java/lang/StringBuffer.java b/src/main/java/java/lang/StringBuffer.java index 35c56dd..46f3cd9 100644 --- a/src/main/java/java/lang/StringBuffer.java +++ b/src/main/java/java/lang/StringBuffer.java @@ -505,11 +505,11 @@ public synchronized StringBuffer append(char[] str, int offset, int len) { */ @Override public synchronized StringBuffer append(boolean b) { - // DIFFBLUE MODEL LIBRARY do not use cache + // DIFFBLUE MODEL LIBRARY this is replaced internally // toStringCache = null; // super.append(b); // return this; - return append(b ? "true" : "false"); + return CProver.nondetWithoutNullForNotModelled(); } /** @@ -527,7 +527,6 @@ public synchronized StringBuffer append(char c) { /** * @diffblue.fullSupport - * @diffblue.untested */ @Override public synchronized StringBuffer append(int i) { @@ -567,11 +566,9 @@ public synchronized StringBuffer append(long lng) { /** * @diffblue.fullSupport - * @diffblue.untested */ @Override public synchronized StringBuffer append(float f) { - // DIFFBLUE MODEL LIBRARY this is replaced internally // toStringCache = null; // super.append(f); // return this; @@ -579,12 +576,10 @@ public synchronized StringBuffer append(float f) { } /** - * @diffblue.fullSupport - * @diffblue.untested + * @diffblue.partialSupport This uses float approximation, so might return incorrect results */ @Override public synchronized StringBuffer append(double d) { - // DIFFBLUE MODEL LIBRARY this is replaced internally // toStringCache = null; // super.append(d); // return this; diff --git a/src/main/java/java/lang/Throwable.java b/src/main/java/java/lang/Throwable.java index bed9779..23d3723 100644 --- a/src/main/java/java/lang/Throwable.java +++ b/src/main/java/java/lang/Throwable.java @@ -263,6 +263,7 @@ public class Throwable implements Serializable { */ public Throwable() { // fillInStackTrace(); + detailMessage = null; } /** diff --git a/src/main/java/java/lang/reflect/AccessibleObject.java b/src/main/java/java/lang/reflect/AccessibleObject.java new file mode 100644 index 0000000..0746796 --- /dev/null +++ b/src/main/java/java/lang/reflect/AccessibleObject.java @@ -0,0 +1,357 @@ +/* + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang.reflect; + +import org.cprover.CProver; + +import java.security.AccessController; +// DIFFBLUE MODEL LIBRARY +// removed for compatibility with Java 9 and newer +// import sun.reflect.Reflection; +// import sun.reflect.ReflectionFactory; +import java.lang.annotation.Annotation; + +/** + * The AccessibleObject class is the base class for Field, Method and + * Constructor objects. It provides the ability to flag a reflected + * object as suppressing default Java language access control checks + * when it is used. The access checks--for public, default (package) + * access, protected, and private members--are performed when Fields, + * Methods or Constructors are used to set or get fields, to invoke + * methods, or to create and initialize new instances of classes, + * respectively. + * + *

Setting the {@code accessible} flag in a reflected object + * permits sophisticated applications with sufficient privilege, such + * as Java Object Serialization or other persistence mechanisms, to + * manipulate objects in a manner that would normally be prohibited. + * + *

By default, a reflected object is not accessible. + * + * @see Field + * @see Method + * @see Constructor + * @see ReflectPermission + * + * @since 1.2 + * + * @diffblue.untested + * @diffblue.noSupport + * This model was automatically generated by the JDK Processor tool. + */ +public class AccessibleObject implements AnnotatedElement { + + /** + * The Permission object that is used to check whether a client + * has sufficient privilege to defeat Java language access + * control checks. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static final private java.security.Permission ACCESS_PERMISSION = + // new ReflectPermission("suppressAccessChecks"); + + /** + * Convenience method to set the {@code accessible} flag for an + * array of objects with a single security check (for efficiency). + * + *

First, if there is a security manager, its + * {@code checkPermission} method is called with a + * {@code ReflectPermission("suppressAccessChecks")} permission. + * + *

A {@code SecurityException} is raised if {@code flag} is + * {@code true} but accessibility of any of the elements of the input + * {@code array} may not be changed (for example, if the element + * object is a {@link Constructor} object for the class {@link + * java.lang.Class}). In the event of such a SecurityException, the + * accessibility of objects is set to {@code flag} for array elements + * upto (and excluding) the element for which the exception occurred; the + * accessibility of elements beyond (and including) the element for which + * the exception occurred is unchanged. + * + * @param array the array of AccessibleObjects + * @param flag the new value for the {@code accessible} flag + * in each object + * @throws SecurityException if the request is denied. + * @see SecurityManager#checkPermission + * @see java.lang.RuntimePermission + * + * @diffblue.untested + * @diffblue.noSupport + */ + public static void setAccessible(AccessibleObject[] array, boolean flag) + throws SecurityException { + // SecurityManager sm = System.getSecurityManager(); + // if (sm != null) sm.checkPermission(ACCESS_PERMISSION); + // for (int i = 0; i < array.length; i++) { + // setAccessible0(array[i], flag); + // } + CProver.notModelled(); + } + + /** + * Set the {@code accessible} flag for this object to + * the indicated boolean value. A value of {@code true} indicates that + * the reflected object should suppress Java language access + * checking when it is used. A value of {@code false} indicates + * that the reflected object should enforce Java language access checks. + * + *

First, if there is a security manager, its + * {@code checkPermission} method is called with a + * {@code ReflectPermission("suppressAccessChecks")} permission. + * + *

A {@code SecurityException} is raised if {@code flag} is + * {@code true} but accessibility of this object may not be changed + * (for example, if this element object is a {@link Constructor} object for + * the class {@link java.lang.Class}). + * + *

A {@code SecurityException} is raised if this object is a {@link + * java.lang.reflect.Constructor} object for the class + * {@code java.lang.Class}, and {@code flag} is true. + * + * @param flag the new value for the {@code accessible} flag + * @throws SecurityException if the request is denied. + * @see SecurityManager#checkPermission + * @see java.lang.RuntimePermission + * + * @diffblue.untested + * @diffblue.noSupport + */ + public void setAccessible(boolean flag) throws SecurityException { + // SecurityManager sm = System.getSecurityManager(); + // if (sm != null) sm.checkPermission(ACCESS_PERMISSION); + // setAccessible0(this, flag); + CProver.notModelled(); + } + + /* Check that you aren't exposing java.lang.Class. or sensitive + fields in java.lang.Class. */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private static void setAccessible0(AccessibleObject obj, boolean flag) + // throws SecurityException + // { + // if (obj instanceof Constructor && flag == true) { + // Constructor c = (Constructor)obj; + // if (c.getDeclaringClass() == Class.class) { + // throw new SecurityException("Cannot make a java.lang.Class" + + // " constructor accessible"); + // } + // } + // obj.override = flag; + // } + + /** + * Get the value of the {@code accessible} flag for this object. + * + * @return the value of the object's {@code accessible} flag + * + * @diffblue.untested + * @diffblue.fullSupport + */ + public boolean isAccessible() { + return override; + } + + /** + * Constructor: only used by the Java Virtual Machine. + */ + protected AccessibleObject() {} + + // Indicates whether language-level access checks are overridden + // by this object. Initializes to "false". This field is used by + // Field, Method, and Constructor. + // + // NOTE: for security purposes, this field must not be visible + // outside this package. + boolean override; + + // Reflection factory used by subclasses for creating field, + // method, and constructor accessors. Note that this is called + // very early in the bootstrapping process. + // DIFFBLUE MODEL LIBRARY - not used in model + // static final ReflectionFactory reflectionFactory = + // AccessController.doPrivileged( + // new sun.reflect.ReflectionFactory.GetReflectionFactoryAction()); + + /** + * @throws NullPointerException {@inheritDoc} + * @since 1.5 + * + * @diffblue.untested + * @diffblue.fullSupport + */ + public T getAnnotation(Class annotationClass) { + throw new AssertionError("All subclasses should override this method"); + } + + /** + * {@inheritDoc} + * @throws NullPointerException {@inheritDoc} + * @since 1.5 + * + * @diffblue.untested + * @diffblue.noSupport + */ + @Override + public boolean isAnnotationPresent(Class annotationClass) { + // return AnnotatedElement.super.isAnnotationPresent(annotationClass); + CProver.notModelled(); + return CProver.nondetBoolean(); + } + + /** + * @throws NullPointerException {@inheritDoc} + * @since 1.8 + * + * @diffblue.untested + * @diffblue.fullSupport + */ + @Override + public T[] getAnnotationsByType(Class annotationClass) { + throw new AssertionError("All subclasses should override this method"); + } + + /** + * @since 1.5 + * + * @diffblue.untested + * @diffblue.fullSupport + */ + public Annotation[] getAnnotations() { + return getDeclaredAnnotations(); + } + + /** + * @throws NullPointerException {@inheritDoc} + * @since 1.8 + * + * @diffblue.untested + * @diffblue.fullSupport + */ + @Override + public T getDeclaredAnnotation(Class annotationClass) { + // Only annotations on classes are inherited, for all other + // objects getDeclaredAnnotation is the same as + // getAnnotation. + return getAnnotation(annotationClass); + } + + /** + * @throws NullPointerException {@inheritDoc} + * @since 1.8 + * + * @diffblue.untested + * @diffblue.fullSupport + */ + @Override + public T[] getDeclaredAnnotationsByType(Class annotationClass) { + // Only annotations on classes are inherited, for all other + // objects getDeclaredAnnotationsByType is the same as + // getAnnotationsByType. + return getAnnotationsByType(annotationClass); + } + + /** + * @since 1.5 + * + * @diffblue.untested + * @diffblue.fullSupport + */ + public Annotation[] getDeclaredAnnotations() { + throw new AssertionError("All subclasses should override this method"); + } + + + // Shared access checking logic. + + // For non-public members or members in package-private classes, + // it is necessary to perform somewhat expensive security checks. + // If the security check succeeds for a given class, it will + // always succeed (it is not affected by the granting or revoking + // of permissions); we speed up the check in the common case by + // remembering the last Class for which the check succeeded. + // + // The simple security check for Constructor is to see if + // the caller has already been seen, verified, and cached. + // (See also Class.newInstance(), which uses a similar method.) + // + // A more complicated security check cache is needed for Method and Field + // The cache can be either null (empty cache), a 2-array of {caller,target}, + // or a caller (with target implicitly equal to this.clazz). + // In the 2-array case, the target is always different from the clazz. + // DIFFBLUE MODEL LIBRARY - not used in model + // volatile Object securityCheckCache; + + // DIFFBLUE MODEL LIBRARY - not used in model + // void checkAccess(Class caller, Class clazz, Object obj, int modifiers) + // throws IllegalAccessException + // { + // if (caller == clazz) { // quick check + // return; // ACCESS IS OK + // } + // Object cache = securityCheckCache; // read volatile + // Class targetClass = clazz; + // if (obj != null + // && Modifier.isProtected(modifiers) + // && ((targetClass = obj.getClass()) != clazz)) { + // // Must match a 2-list of { caller, targetClass }. + // if (cache instanceof Class[]) { + // Class[] cache2 = (Class[]) cache; + // if (cache2[1] == targetClass && + // cache2[0] == caller) { + // return; // ACCESS IS OK + // } + // // (Test cache[1] first since range check for [1] + // // subsumes range check for [0].) + // } + // } else if (cache == caller) { + // // Non-protected case (or obj.class == this.clazz). + // return; // ACCESS IS OK + // } + + // // If no return, fall through to the slow path. + // slowCheckMemberAccess(caller, clazz, obj, modifiers, targetClass); + // } + + // Keep all this slow stuff out of line: + // DIFFBLUE MODEL LIBRARY - not used in model + // void slowCheckMemberAccess(Class caller, Class clazz, Object obj, int modifiers, + // Class targetClass) + // throws IllegalAccessException + // { + // Reflection.ensureMemberAccess(caller, clazz, obj, modifiers); + + // // Success: Update the cache. + // Object cache = ((targetClass == clazz) + // ? caller + // : new Class[] { caller, targetClass }); + + // // Note: The two cache elements are not volatile, + // // but they are effectively final. The Java memory model + // // guarantees that the initializing stores for the cache + // // elements will occur before the volatile write. + // securityCheckCache = cache; // write volatile + // } +} diff --git a/src/main/java/java/lang/reflect/Executable.java b/src/main/java/java/lang/reflect/Executable.java new file mode 100644 index 0000000..1dda5d0 --- /dev/null +++ b/src/main/java/java/lang/reflect/Executable.java @@ -0,0 +1,805 @@ +/* + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang.reflect; + +import org.cprover.CProver; + +import java.lang.annotation.*; +import java.util.Map; +import java.util.Objects; +import sun.reflect.annotation.AnnotationParser; +import sun.reflect.annotation.AnnotationSupport; +import sun.reflect.annotation.TypeAnnotationParser; +import sun.reflect.annotation.TypeAnnotation; +import sun.reflect.generics.repository.ConstructorRepository; + +/** + * A shared superclass for the common functionality of {@link Method} + * and {@link Constructor}. + * + * @since 1.8 + * + * @diffblue.untested + * @diffblue.noSupport + * This model was automatically generated by the JDK Processor tool. + */ +public abstract class Executable extends AccessibleObject + implements Member, GenericDeclaration { + /* + * Only grant package-visibility to the constructor. + */ + Executable() {} + + /** + * Accessor method to allow code sharing + */ + abstract byte[] getAnnotationBytes(); + + /** + * Accessor method to allow code sharing + */ + abstract Executable getRoot(); + + /** + * Does the Executable have generic information. + */ + abstract boolean hasGenericInformation(); + + abstract ConstructorRepository getGenericInfo(); + + boolean equalParamTypes(Class[] params1, Class[] params2) { + /* Avoid unnecessary cloning */ + if (params1.length == params2.length) { + for (int i = 0; i < params1.length; i++) { + if (params1[i] != params2[i]) + return false; + } + return true; + } + return false; + } + + // DIFFBLUE MODEL LIBRARY - not used in model + // Annotation[][] parseParameterAnnotations(byte[] parameterAnnotations) { + // return AnnotationParser.parseParameterAnnotations( + // parameterAnnotations, + // sun.misc.SharedSecrets.getJavaLangAccess(). + // getConstantPool(getDeclaringClass()), + // getDeclaringClass()); + // } + + // DIFFBLUE MODEL LIBRARY - not used in model + // void separateWithCommas(Class[] types, StringBuilder sb) { + // for (int j = 0; j < types.length; j++) { + // sb.append(types[j].getTypeName()); + // if (j < (types.length - 1)) + // sb.append(","); + // } + + // } + + // DIFFBLUE MODEL LIBRARY - not used in model + // void printModifiersIfNonzero(StringBuilder sb, int mask, boolean isDefault) { + // int mod = getModifiers() & mask; + + // if (mod != 0 && !isDefault) { + // sb.append(Modifier.toString(mod)).append(' '); + // } else { + // int access_mod = mod & Modifier.ACCESS_MODIFIERS; + // if (access_mod != 0) + // sb.append(Modifier.toString(access_mod)).append(' '); + // if (isDefault) + // sb.append("default "); + // mod = (mod & ~Modifier.ACCESS_MODIFIERS); + // if (mod != 0) + // sb.append(Modifier.toString(mod)).append(' '); + // } + // } + + // DIFFBLUE MODEL LIBRARY - not used in model + // String sharedToString(int modifierMask, + // boolean isDefault, + // Class[] parameterTypes, + // Class[] exceptionTypes) { + // try { + // StringBuilder sb = new StringBuilder(); + + // printModifiersIfNonzero(sb, modifierMask, isDefault); + // specificToStringHeader(sb); + + // sb.append('('); + // separateWithCommas(parameterTypes, sb); + // sb.append(')'); + // if (exceptionTypes.length > 0) { + // sb.append(" throws "); + // separateWithCommas(exceptionTypes, sb); + // } + // return sb.toString(); + // } catch (Exception e) { + // return "<" + e + ">"; + // } + // } + + /** + * Generate toString header information specific to a method or + * constructor. + */ + abstract void specificToStringHeader(StringBuilder sb); + + String sharedToGenericString(int modifierMask, boolean isDefault) { + // try { + // StringBuilder sb = new StringBuilder(); + + // printModifiersIfNonzero(sb, modifierMask, isDefault); + + // TypeVariable[] typeparms = getTypeParameters(); + // if (typeparms.length > 0) { + // boolean first = true; + // sb.append('<'); + // for(TypeVariable typeparm: typeparms) { + // if (!first) + // sb.append(','); + // // Class objects can't occur here; no need to test + // // and call Class.getName(). + // sb.append(typeparm.toString()); + // first = false; + // } + // sb.append("> "); + // } + + // specificToGenericStringHeader(sb); + + // sb.append('('); + // Type[] params = getGenericParameterTypes(); + // for (int j = 0; j < params.length; j++) { + // String param = params[j].getTypeName(); + // if (isVarArgs() && (j == params.length - 1)) // replace T[] with T... + // param = param.replaceFirst("\\[\\]$", "..."); + // sb.append(param); + // if (j < (params.length - 1)) + // sb.append(','); + // } + // sb.append(')'); + // Type[] exceptions = getGenericExceptionTypes(); + // if (exceptions.length > 0) { + // sb.append(" throws "); + // for (int k = 0; k < exceptions.length; k++) { + // sb.append((exceptions[k] instanceof Class)? + // ((Class)exceptions[k]).getName(): + // exceptions[k].toString()); + // if (k < (exceptions.length - 1)) + // sb.append(','); + // } + // } + // return sb.toString(); + // } catch (Exception e) { + // return "<" + e + ">"; + // } + CProver.notModelled(); + return CProver.nondetWithoutNullForNotModelled(); + } + + /** + * Generate toGenericString header information specific to a + * method or constructor. + */ + abstract void specificToGenericStringHeader(StringBuilder sb); + + /** + * Returns the {@code Class} object representing the class or interface + * that declares the executable represented by this object. + */ + public abstract Class getDeclaringClass(); + + /** + * Returns the name of the executable represented by this object. + */ + public abstract String getName(); + + /** + * Returns the Java language {@linkplain Modifier modifiers} for + * the executable represented by this object. + */ + public abstract int getModifiers(); + + /** + * Returns an array of {@code TypeVariable} objects that represent the + * type variables declared by the generic declaration represented by this + * {@code GenericDeclaration} object, in declaration order. Returns an + * array of length 0 if the underlying generic declaration declares no type + * variables. + * + * @return an array of {@code TypeVariable} objects that represent + * the type variables declared by this generic declaration + * @throws GenericSignatureFormatError if the generic + * signature of this generic declaration does not conform to + * the format specified in + * The Java™ Virtual Machine Specification + */ + public abstract TypeVariable[] getTypeParameters(); + + /** + * Returns an array of {@code Class} objects that represent the formal + * parameter types, in declaration order, of the executable + * represented by this object. Returns an array of length + * 0 if the underlying executable takes no parameters. + * + * @return the parameter types for the executable this object + * represents + */ + public abstract Class[] getParameterTypes(); + + /** + * Returns the number of formal parameters (whether explicitly + * declared or implicitly declared or neither) for the executable + * represented by this object. + * + * @return The number of formal parameters for the executable this + * object represents + * + * @diffblue.untested + * @diffblue.fullSupport + */ + public int getParameterCount() { + throw new AbstractMethodError(); + } + + /** + * Returns an array of {@code Type} objects that represent the formal + * parameter types, in declaration order, of the executable represented by + * this object. Returns an array of length 0 if the + * underlying executable takes no parameters. + * + *

If a formal parameter type is a parameterized type, + * the {@code Type} object returned for it must accurately reflect + * the actual type parameters used in the source code. + * + *

If a formal parameter type is a type variable or a parameterized + * type, it is created. Otherwise, it is resolved. + * + * @return an array of {@code Type}s that represent the formal + * parameter types of the underlying executable, in declaration order + * @throws GenericSignatureFormatError + * if the generic method signature does not conform to the format + * specified in + * The Java™ Virtual Machine Specification + * @throws TypeNotPresentException if any of the parameter + * types of the underlying executable refers to a non-existent type + * declaration + * @throws MalformedParameterizedTypeException if any of + * the underlying executable's parameter types refer to a parameterized + * type that cannot be instantiated for any reason + * + * @diffblue.untested + * @diffblue.noSupport + */ + public Type[] getGenericParameterTypes() { + // if (hasGenericInformation()) + // return getGenericInfo().getParameterTypes(); + // else + // return getParameterTypes(); + CProver.notModelled(); + return CProver.nondetWithoutNullForNotModelled(); + } + + /** + * Behaves like {@code getGenericParameterTypes}, but returns type + * information for all parameters, including synthetic parameters. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // Type[] getAllGenericParameterTypes() { + // final boolean genericInfo = hasGenericInformation(); + + // // Easy case: we don't have generic parameter information. In + // // this case, we just return the result of + // // getParameterTypes(). + // if (!genericInfo) { + // return getParameterTypes(); + // } else { + // final boolean realParamData = hasRealParameterData(); + // final Type[] genericParamTypes = getGenericParameterTypes(); + // final Type[] nonGenericParamTypes = getParameterTypes(); + // final Type[] out = new Type[nonGenericParamTypes.length]; + // final Parameter[] params = getParameters(); + // int fromidx = 0; + // // If we have real parameter data, then we use the + // // synthetic and mandate flags to our advantage. + // if (realParamData) { + // for (int i = 0; i < out.length; i++) { + // final Parameter param = params[i]; + // if (param.isSynthetic() || param.isImplicit()) { + // // If we hit a synthetic or mandated parameter, + // // use the non generic parameter info. + // out[i] = nonGenericParamTypes[i]; + // } else { + // // Otherwise, use the generic parameter info. + // out[i] = genericParamTypes[fromidx]; + // fromidx++; + // } + // } + // } else { + // // Otherwise, use the non-generic parameter data. + // // Without method parameter reflection data, we have + // // no way to figure out which parameters are + // // synthetic/mandated, thus, no way to match up the + // // indexes. + // return genericParamTypes.length == nonGenericParamTypes.length ? + // genericParamTypes : nonGenericParamTypes; + // } + // return out; + // } + // } + + /** + * Returns an array of {@code Parameter} objects that represent + * all the parameters to the underlying executable represented by + * this object. Returns an array of length 0 if the executable + * has no parameters. + * + *

The parameters of the underlying executable do not necessarily + * have unique names, or names that are legal identifiers in the + * Java programming language (JLS 3.8). + * + * @throws MalformedParametersException if the class file contains + * a MethodParameters attribute that is improperly formatted. + * @return an array of {@code Parameter} objects representing all + * the parameters to the executable this object represents. + * + * @diffblue.untested + * @diffblue.noSupport + */ + public Parameter[] getParameters() { + // // TODO: This may eventually need to be guarded by security + // // mechanisms similar to those in Field, Method, etc. + // // + // // Need to copy the cached array to prevent users from messing + // // with it. Since parameters are immutable, we can + // // shallow-copy. + // return privateGetParameters().clone(); + CProver.notModelled(); + return CProver.nondetWithoutNullForNotModelled(); + } + + // DIFFBLUE MODEL LIBRARY - not used in model + // private Parameter[] synthesizeAllParams() { + // final int realparams = getParameterCount(); + // final Parameter[] out = new Parameter[realparams]; + // for (int i = 0; i < realparams; i++) + // // TODO: is there a way to synthetically derive the + // // modifiers? Probably not in the general case, since + // // we'd have no way of knowing about them, but there + // // may be specific cases. + // out[i] = new Parameter("arg" + i, 0, this, i); + // return out; + // } + + // DIFFBLUE MODEL LIBRARY - not used in model + // private void verifyParameters(final Parameter[] parameters) { + // final int mask = Modifier.FINAL | Modifier.SYNTHETIC | Modifier.MANDATED; + + // if (getParameterTypes().length != parameters.length) + // throw new MalformedParametersException("Wrong number of parameters in MethodParameters attribute"); + + // for (Parameter parameter : parameters) { + // final String name = parameter.getRealName(); + // final int mods = parameter.getModifiers(); + + // if (name != null) { + // if (name.isEmpty() || name.indexOf('.') != -1 || + // name.indexOf(';') != -1 || name.indexOf('[') != -1 || + // name.indexOf('/') != -1) { + // throw new MalformedParametersException("Invalid parameter name \"" + name + "\""); + // } + // } + + // if (mods != (mods & mask)) { + // throw new MalformedParametersException("Invalid parameter modifiers"); + // } + // } + // } + + // DIFFBLUE MODEL LIBRARY - not used in model + // private Parameter[] privateGetParameters() { + // // Use tmp to avoid multiple writes to a volatile. + // Parameter[] tmp = parameters; + + // if (tmp == null) { + + // // Otherwise, go to the JVM to get them + // try { + // tmp = getParameters0(); + // } catch(IllegalArgumentException e) { + // // Rethrow ClassFormatErrors + // throw new MalformedParametersException("Invalid constant pool index"); + // } + + // // If we get back nothing, then synthesize parameters + // if (tmp == null) { + // hasRealParameterData = false; + // tmp = synthesizeAllParams(); + // } else { + // hasRealParameterData = true; + // verifyParameters(tmp); + // } + + // parameters = tmp; + // } + + // return tmp; + // } + + // DIFFBLUE MODEL LIBRARY - not used in model + // boolean hasRealParameterData() { + // // If this somehow gets called before parameters gets + // // initialized, force it into existence. + // if (parameters == null) { + // privateGetParameters(); + // } + // return hasRealParameterData; + // } + + // DIFFBLUE MODEL LIBRARY - not used in model + // private transient volatile boolean hasRealParameterData; + // DIFFBLUE MODEL LIBRARY - not used in model + // private transient volatile Parameter[] parameters; + + // DIFFBLUE MODEL LIBRARY - not used in model + // private native Parameter[] getParameters0(); + // DIFFBLUE MODEL LIBRARY - not used in model + // native byte[] getTypeAnnotationBytes0(); + + // Needed by reflectaccess + // DIFFBLUE MODEL LIBRARY - not used in model + // byte[] getTypeAnnotationBytes() { + // return getTypeAnnotationBytes0(); + // } + + /** + * Returns an array of {@code Class} objects that represent the + * types of exceptions declared to be thrown by the underlying + * executable represented by this object. Returns an array of + * length 0 if the executable declares no exceptions in its {@code + * throws} clause. + * + * @return the exception types declared as being thrown by the + * executable this object represents + */ + public abstract Class[] getExceptionTypes(); + + /** + * Returns an array of {@code Type} objects that represent the + * exceptions declared to be thrown by this executable object. + * Returns an array of length 0 if the underlying executable declares + * no exceptions in its {@code throws} clause. + * + *

If an exception type is a type variable or a parameterized + * type, it is created. Otherwise, it is resolved. + * + * @return an array of Types that represent the exception types + * thrown by the underlying executable + * @throws GenericSignatureFormatError + * if the generic method signature does not conform to the format + * specified in + * The Java™ Virtual Machine Specification + * @throws TypeNotPresentException if the underlying executable's + * {@code throws} clause refers to a non-existent type declaration + * @throws MalformedParameterizedTypeException if + * the underlying executable's {@code throws} clause refers to a + * parameterized type that cannot be instantiated for any reason + * + * @diffblue.untested + * @diffblue.noSupport + */ + public Type[] getGenericExceptionTypes() { + // Type[] result; + // if (hasGenericInformation() && + // ((result = getGenericInfo().getExceptionTypes()).length > 0)) + // return result; + // else + // return getExceptionTypes(); + CProver.notModelled(); + return CProver.nondetWithoutNullForNotModelled(); + } + + /** + * Returns a string describing this {@code Executable}, including + * any type parameters. + * @return a string describing this {@code Executable}, including + * any type parameters + */ + public abstract String toGenericString(); + + /** + * Returns {@code true} if this executable was declared to take a + * variable number of arguments; returns {@code false} otherwise. + * + * @return {@code true} if an only if this executable was declared + * to take a variable number of arguments. + * + * @diffblue.untested + * @diffblue.noSupport + */ + public boolean isVarArgs() { + // return (getModifiers() & Modifier.VARARGS) != 0; + CProver.notModelled(); + return CProver.nondetBoolean(); + } + + /** + * Returns {@code true} if this executable is a synthetic + * construct; returns {@code false} otherwise. + * + * @return true if and only if this executable is a synthetic + * construct as defined by + * The Java™ Language Specification. + * @jls 13.1 The Form of a Binary + * + * @diffblue.untested + * @diffblue.noSupport + */ + public boolean isSynthetic() { + // return Modifier.isSynthetic(getModifiers()); + CProver.notModelled(); + return CProver.nondetBoolean(); + } + + /** + * Returns an array of arrays of {@code Annotation}s that + * represent the annotations on the formal parameters, in + * declaration order, of the {@code Executable} represented by + * this object. Synthetic and mandated parameters (see + * explanation below), such as the outer "this" parameter to an + * inner class constructor will be represented in the returned + * array. If the executable has no parameters (meaning no formal, + * no synthetic, and no mandated parameters), a zero-length array + * will be returned. If the {@code Executable} has one or more + * parameters, a nested array of length zero is returned for each + * parameter with no annotations. The annotation objects contained + * in the returned arrays are serializable. The caller of this + * method is free to modify the returned arrays; it will have no + * effect on the arrays returned to other callers. + * + * A compiler may add extra parameters that are implicitly + * declared in source ("mandated"), as well as parameters that + * are neither implicitly nor explicitly declared in source + * ("synthetic") to the parameter list for a method. See {@link + * java.lang.reflect.Parameter} for more information. + * + * @see java.lang.reflect.Parameter + * @see java.lang.reflect.Parameter#getAnnotations + * @return an array of arrays that represent the annotations on + * the formal and implicit parameters, in declaration order, of + * the executable represented by this object + */ + public abstract Annotation[][] getParameterAnnotations(); + + // DIFFBLUE MODEL LIBRARY - not used in model + // Annotation[][] sharedGetParameterAnnotations(Class[] parameterTypes, + // byte[] parameterAnnotations) { + // int numParameters = parameterTypes.length; + // if (parameterAnnotations == null) + // return new Annotation[numParameters][0]; + + // Annotation[][] result = parseParameterAnnotations(parameterAnnotations); + + // if (result.length != numParameters) + // handleParameterNumberMismatch(result.length, numParameters); + // return result; + // } + + abstract void handleParameterNumberMismatch(int resultLength, int numParameters); + + /** + * {@inheritDoc} + * @throws NullPointerException {@inheritDoc} + * + * @diffblue.untested + * @diffblue.noSupport + */ + public T getAnnotation(Class annotationClass) { + // Objects.requireNonNull(annotationClass); + // return annotationClass.cast(declaredAnnotations().get(annotationClass)); + CProver.notModelled(); + return CProver.nondetWithoutNullForNotModelled(); + } + + /** + * {@inheritDoc} + * @throws NullPointerException {@inheritDoc} + * + * @diffblue.untested + * @diffblue.noSupport + */ + @Override + public T[] getAnnotationsByType(Class annotationClass) { + // Objects.requireNonNull(annotationClass); + + // return AnnotationSupport.getDirectlyAndIndirectlyPresent(declaredAnnotations(), annotationClass); + CProver.notModelled(); + return CProver.nondetWithoutNullForNotModelled(); + } + + /** + * {@inheritDoc} + * + * @diffblue.untested + * @diffblue.noSupport + */ + public Annotation[] getDeclaredAnnotations() { + // return AnnotationParser.toArray(declaredAnnotations()); + CProver.notModelled(); + return CProver.nondetWithoutNullForNotModelled(); + } + + // DIFFBLUE MODEL LIBRARY - not used in model + // private transient Map, Annotation> declaredAnnotations; + + // DIFFBLUE MODEL LIBRARY - not used in model + // private synchronized Map, Annotation> declaredAnnotations() { + // if (declaredAnnotations == null) { + // Executable root = getRoot(); + // if (root != null) { + // declaredAnnotations = root.declaredAnnotations(); + // } else { + // declaredAnnotations = AnnotationParser.parseAnnotations( + // getAnnotationBytes(), + // sun.misc.SharedSecrets.getJavaLangAccess(). + // getConstantPool(getDeclaringClass()), + // getDeclaringClass()); + // } + // } + // return declaredAnnotations; + // } + + /** + * Returns an {@code AnnotatedType} object that represents the use of a type to + * specify the return type of the method/constructor represented by this + * Executable. + * + * If this {@code Executable} object represents a constructor, the {@code + * AnnotatedType} object represents the type of the constructed object. + * + * If this {@code Executable} object represents a method, the {@code + * AnnotatedType} object represents the use of a type to specify the return + * type of the method. + * + * @return an object representing the return type of the method + * or constructor represented by this {@code Executable} + */ + public abstract AnnotatedType getAnnotatedReturnType(); + + /* Helper for subclasses of Executable. + * + * Returns an AnnotatedType object that represents the use of a type to + * specify the return type of the method/constructor represented by this + * Executable. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // AnnotatedType getAnnotatedReturnType0(Type returnType) { + // return TypeAnnotationParser.buildAnnotatedType(getTypeAnnotationBytes0(), + // sun.misc.SharedSecrets.getJavaLangAccess(). + // getConstantPool(getDeclaringClass()), + // this, + // getDeclaringClass(), + // returnType, + // TypeAnnotation.TypeAnnotationTarget.METHOD_RETURN); + // } + + /** + * Returns an {@code AnnotatedType} object that represents the use of a + * type to specify the receiver type of the method/constructor represented + * by this Executable object. The receiver type of a method/constructor is + * available only if the method/constructor has a receiver + * parameter (JLS 8.4.1). + * + * If this {@code Executable} object represents a constructor or instance + * method that does not have a receiver parameter, or has a receiver + * parameter with no annotations on its type, then the return value is an + * {@code AnnotatedType} object representing an element with no + * annotations. + * + * If this {@code Executable} object represents a static method, then the + * return value is null. + * + * @return an object representing the receiver type of the method or + * constructor represented by this {@code Executable} + * + * @diffblue.untested + * @diffblue.noSupport + */ + public AnnotatedType getAnnotatedReceiverType() { + // if (Modifier.isStatic(this.getModifiers())) + // return null; + // return TypeAnnotationParser.buildAnnotatedType(getTypeAnnotationBytes0(), + // sun.misc.SharedSecrets.getJavaLangAccess(). + // getConstantPool(getDeclaringClass()), + // this, + // getDeclaringClass(), + // getDeclaringClass(), + // TypeAnnotation.TypeAnnotationTarget.METHOD_RECEIVER); + CProver.notModelled(); + return CProver.nondetWithoutNullForNotModelled(); + } + + /** + * Returns an array of {@code AnnotatedType} objects that represent the use + * of types to specify formal parameter types of the method/constructor + * represented by this Executable. The order of the objects in the array + * corresponds to the order of the formal parameter types in the + * declaration of the method/constructor. + * + * Returns an array of length 0 if the method/constructor declares no + * parameters. + * + * @return an array of objects representing the types of the + * formal parameters of the method or constructor represented by this + * {@code Executable} + * + * @diffblue.untested + * @diffblue.noSupport + */ + public AnnotatedType[] getAnnotatedParameterTypes() { + // return TypeAnnotationParser.buildAnnotatedTypes(getTypeAnnotationBytes0(), + // sun.misc.SharedSecrets.getJavaLangAccess(). + // getConstantPool(getDeclaringClass()), + // this, + // getDeclaringClass(), + // getAllGenericParameterTypes(), + // TypeAnnotation.TypeAnnotationTarget.METHOD_FORMAL_PARAMETER); + CProver.notModelled(); + return CProver.nondetWithoutNullForNotModelled(); + } + + /** + * Returns an array of {@code AnnotatedType} objects that represent the use + * of types to specify the declared exceptions of the method/constructor + * represented by this Executable. The order of the objects in the array + * corresponds to the order of the exception types in the declaration of + * the method/constructor. + * + * Returns an array of length 0 if the method/constructor declares no + * exceptions. + * + * @return an array of objects representing the declared + * exceptions of the method or constructor represented by this {@code + * Executable} + * + * @diffblue.untested + * @diffblue.noSupport + */ + public AnnotatedType[] getAnnotatedExceptionTypes() { + // return TypeAnnotationParser.buildAnnotatedTypes(getTypeAnnotationBytes0(), + // sun.misc.SharedSecrets.getJavaLangAccess(). + // getConstantPool(getDeclaringClass()), + // this, + // getDeclaringClass(), + // getGenericExceptionTypes(), + // TypeAnnotation.TypeAnnotationTarget.THROWS); + CProver.notModelled(); + return CProver.nondetWithoutNullForNotModelled(); + } + +} diff --git a/src/main/java/java/lang/reflect/Field.java b/src/main/java/java/lang/reflect/Field.java new file mode 100644 index 0000000..f4255cd --- /dev/null +++ b/src/main/java/java/lang/reflect/Field.java @@ -0,0 +1,1400 @@ +/* + * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang.reflect; + +import org.cprover.CProver; + +// DIFFBLUE MODEL LIBRARY +// removed for compatibility with Java 9 and newer +// import sun.reflect.CallerSensitive; +// import sun.reflect.Reflection; +// import sun.reflect.FieldAccessor; +// import sun.reflect.generics.repository.FieldRepository; +// import sun.reflect.generics.factory.CoreReflectionFactory; +// import sun.reflect.generics.factory.GenericsFactory; +// import sun.reflect.generics.scope.ClassScope; +import java.lang.annotation.Annotation; +import java.util.Map; +import java.util.Objects; +// DIFFBLUE MODEL LIBRARY +// removed for compatibility with Java 9 and newer +// import sun.reflect.annotation.AnnotationParser; +// import sun.reflect.annotation.AnnotationSupport; +// import sun.reflect.annotation.TypeAnnotation; +// import sun.reflect.annotation.TypeAnnotationParser; + +/** + * A {@code Field} provides information about, and dynamic access to, a + * single field of a class or an interface. The reflected field may + * be a class (static) field or an instance field. + * + *

A {@code Field} permits widening conversions to occur during a get or + * set access operation, but throws an {@code IllegalArgumentException} if a + * narrowing conversion would occur. + * + * @see Member + * @see java.lang.Class + * @see java.lang.Class#getFields() + * @see java.lang.Class#getField(String) + * @see java.lang.Class#getDeclaredFields() + * @see java.lang.Class#getDeclaredField(String) + * + * @author Kenneth Russell + * @author Nakul Saraiya + * + * @diffblue.untested + * @diffblue.noSupport + * This model was automatically generated by the JDK Processor tool. + */ +public final +class Field extends AccessibleObject implements Member { + + private Class clazz; + // DIFFBLUE MODEL LIBRARY - not used in model + // private int slot; + // This is guaranteed to be interned by the VM in the 1.4 + // reflection implementation + private String name; + // DIFFBLUE MODEL LIBRARY - not used in model + // private Class type; + // DIFFBLUE MODEL LIBRARY - not used in model + // private int modifiers; + // Generics and annotations support + // DIFFBLUE MODEL LIBRARY - not used in model + // private transient String signature; + // generic info repository; lazily initialized + // DIFFBLUE MODEL LIBRARY - not used in model + // private transient FieldRepository genericInfo; + // DIFFBLUE MODEL LIBRARY - not used in model + // private byte[] annotations; + // Cached field accessor created without override + // DIFFBLUE MODEL LIBRARY - not used in model + // private FieldAccessor fieldAccessor; + // Cached field accessor created with override + // DIFFBLUE MODEL LIBRARY - not used in model + // private FieldAccessor overrideFieldAccessor; + // For sharing of FieldAccessors. This branching structure is + // currently only two levels deep (i.e., one root Field and + // potentially many Field objects pointing to it.) + // + // If this branching structure would ever contain cycles, deadlocks can + // occur in annotation code. + // DIFFBLUE MODEL LIBRARY - not used in model + // private Field root; + + // Generics infrastructure + + // DIFFBLUE MODEL LIBRARY - not used in model + // private String getGenericSignature() {return signature;} + + // Accessor for factory + // DIFFBLUE MODEL LIBRARY - not used in model + // private GenericsFactory getFactory() { + // Class c = getDeclaringClass(); + // // create scope and factory + // return CoreReflectionFactory.make(c, ClassScope.make(c)); + // } + + // Accessor for generic info repository + // DIFFBLUE MODEL LIBRARY - not used in model + // private FieldRepository getGenericInfo() { + // // lazily initialize repository if necessary + // if (genericInfo == null) { + // // create and cache generic info repository + // genericInfo = FieldRepository.make(getGenericSignature(), + // getFactory()); + // } + // return genericInfo; //return cached repository + // } + + + /** + * Package-private constructor used by ReflectAccess to enable + * instantiation of these objects in Java code from the java.lang + * package via sun.reflect.LangReflectAccess. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // Field(Class declaringClass, + // String name, + // Class type, + // int modifiers, + // int slot, + // String signature, + // byte[] annotations) + // { + // this.clazz = declaringClass; + // this.name = name; + // this.type = type; + // this.modifiers = modifiers; + // this.slot = slot; + // this.signature = signature; + // this.annotations = annotations; + // } + + /** + * This constructor does not exist in the JDK, only in the model + */ + public Field( + Class declaringClass, + String name) + { + this.clazz = declaringClass; + this.name = name; + } + + /** + * Package-private routine (exposed to java.lang.Class via + * ReflectAccess) which returns a copy of this Field. The copy's + * "root" field points to this Field. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // Field copy() { + // // This routine enables sharing of FieldAccessor objects + // // among Field objects which refer to the same underlying + // // method in the VM. (All of this contortion is only necessary + // // because of the "accessibility" bit in AccessibleObject, + // // which implicitly requires that new java.lang.reflect + // // objects be fabricated for each reflective call on Class + // // objects.) + // if (this.root != null) + // throw new IllegalArgumentException("Can not copy a non-root Field"); + + // Field res = new Field(clazz, name, type, modifiers, slot, signature, annotations); + // res.root = this; + // // Might as well eagerly propagate this if already present + // res.fieldAccessor = fieldAccessor; + // res.overrideFieldAccessor = overrideFieldAccessor; + + // return res; + // } + + /** + * Returns the {@code Class} object representing the class or interface + * that declares the field represented by this {@code Field} object. + * + * @diffblue.fullSupport + */ + public Class getDeclaringClass() { + return clazz; + } + + /** + * Returns the name of the field represented by this {@code Field} object. + * + * @diffblue.fullSupport + */ + public String getName() { + return name; + } + + /** + * Returns the Java language modifiers for the field represented + * by this {@code Field} object, as an integer. The {@code Modifier} class should + * be used to decode the modifiers. + * + * @see Modifier + * + * @diffblue.untested + * @diffblue.noSupport + */ + public int getModifiers() { + // return modifiers; + CProver.notModelled(); + return CProver.nondetInt(); + } + + /** + * Returns {@code true} if this field represents an element of + * an enumerated type; returns {@code false} otherwise. + * + * @return {@code true} if and only if this field represents an element of + * an enumerated type. + * @since 1.5 + * + * @diffblue.untested + * @diffblue.noSupport + */ + public boolean isEnumConstant() { + // return (getModifiers() & Modifier.ENUM) != 0; + CProver.notModelled(); + return CProver.nondetBoolean(); + } + + /** + * Returns {@code true} if this field is a synthetic + * field; returns {@code false} otherwise. + * + * @return true if and only if this field is a synthetic + * field as defined by the Java Language Specification. + * @since 1.5 + * + * @diffblue.untested + * @diffblue.noSupport + */ + public boolean isSynthetic() { + // return Modifier.isSynthetic(getModifiers()); + CProver.notModelled(); + return CProver.nondetBoolean(); + } + + /** + * Returns a {@code Class} object that identifies the + * declared type for the field represented by this + * {@code Field} object. + * + * @return a {@code Class} object identifying the declared + * type of the field represented by this object + * + * @diffblue.untested + * @diffblue.noSupport + */ + public Class getType() { + // return type; + CProver.notModelled(); + return CProver.nondetWithoutNullForNotModelled(); + } + + /** + * Returns a {@code Type} object that represents the declared type for + * the field represented by this {@code Field} object. + * + *

If the {@code Type} is a parameterized type, the + * {@code Type} object returned must accurately reflect the + * actual type parameters used in the source code. + * + *

If the type of the underlying field is a type variable or a + * parameterized type, it is created. Otherwise, it is resolved. + * + * @return a {@code Type} object that represents the declared type for + * the field represented by this {@code Field} object + * @throws GenericSignatureFormatError if the generic field + * signature does not conform to the format specified in + * The Java™ Virtual Machine Specification + * @throws TypeNotPresentException if the generic type + * signature of the underlying field refers to a non-existent + * type declaration + * @throws MalformedParameterizedTypeException if the generic + * signature of the underlying field refers to a parameterized type + * that cannot be instantiated for any reason + * @since 1.5 + * + * @diffblue.untested + * @diffblue.noSupport + */ + public Type getGenericType() { + // if (getGenericSignature() != null) + // return getGenericInfo().getGenericType(); + // else + // return getType(); + CProver.notModelled(); + return CProver.nondetWithoutNullForNotModelled(); + } + + + /** + * Compares this {@code Field} against the specified object. Returns + * true if the objects are the same. Two {@code Field} objects are the same if + * they were declared by the same class and have the same name + * and type. + * + * @diffblue.limitedSupport + */ + public boolean equals(Object obj) { + if (obj != null && obj instanceof Field) { + Field other = (Field)obj; + return (getDeclaringClass() == other.getDeclaringClass()) + && (getName() == other.getName()); + } + return false; + } + + /** + * Returns a hashcode for this {@code Field}. This is computed as the + * exclusive-or of the hashcodes for the underlying field's + * declaring class name and its name. + * + * @diffblue.untested + * @diffblue.fullSupport + */ + public int hashCode() { + return getDeclaringClass().getName().hashCode() ^ getName().hashCode(); + } + + /** + * Returns a string describing this {@code Field}. The format is + * the access modifiers for the field, if any, followed + * by the field type, followed by a space, followed by + * the fully-qualified name of the class declaring the field, + * followed by a period, followed by the name of the field. + * For example: + *

+     *    public static final int java.lang.Thread.MIN_PRIORITY
+     *    private int java.io.FileDescriptor.fd
+     * 
+ * + *

The modifiers are placed in canonical order as specified by + * "The Java Language Specification". This is {@code public}, + * {@code protected} or {@code private} first, and then other + * modifiers in the following order: {@code static}, {@code final}, + * {@code transient}, {@code volatile}. + * + * @return a string describing this {@code Field} + * @jls 8.3.1 Field Modifiers + * + * @diffblue.untested + * @diffblue.noSupport + */ + public String toString() { + // int mod = getModifiers(); + // return (((mod == 0) ? "" : (Modifier.toString(mod) + " ")) + // + getType().getTypeName() + " " + // + getDeclaringClass().getTypeName() + "." + // + getName()); + CProver.notModelled(); + return CProver.nondetWithoutNullForNotModelled(); + } + + /** + * Returns a string describing this {@code Field}, including + * its generic type. The format is the access modifiers for the + * field, if any, followed by the generic field type, followed by + * a space, followed by the fully-qualified name of the class + * declaring the field, followed by a period, followed by the name + * of the field. + * + *

The modifiers are placed in canonical order as specified by + * "The Java Language Specification". This is {@code public}, + * {@code protected} or {@code private} first, and then other + * modifiers in the following order: {@code static}, {@code final}, + * {@code transient}, {@code volatile}. + * + * @return a string describing this {@code Field}, including + * its generic type + * + * @since 1.5 + * @jls 8.3.1 Field Modifiers + * + * @diffblue.untested + * @diffblue.noSupport + */ + public String toGenericString() { + // int mod = getModifiers(); + // Type fieldType = getGenericType(); + // return (((mod == 0) ? "" : (Modifier.toString(mod) + " ")) + // + fieldType.getTypeName() + " " + // + getDeclaringClass().getTypeName() + "." + // + getName()); + CProver.notModelled(); + return CProver.nondetWithoutNullForNotModelled(); + } + + /** + * Returns the value of the field represented by this {@code Field}, on + * the specified object. The value is automatically wrapped in an + * object if it has a primitive type. + * + *

The underlying field's value is obtained as follows: + * + *

If the underlying field is a static field, the {@code obj} argument + * is ignored; it may be null. + * + *

Otherwise, the underlying field is an instance field. If the + * specified {@code obj} argument is null, the method throws a + * {@code NullPointerException}. If the specified object is not an + * instance of the class or interface declaring the underlying + * field, the method throws an {@code IllegalArgumentException}. + * + *

If this {@code Field} object is enforcing Java language access control, and + * the underlying field is inaccessible, the method throws an + * {@code IllegalAccessException}. + * If the underlying field is static, the class that declared the + * field is initialized if it has not already been initialized. + * + *

Otherwise, the value is retrieved from the underlying instance + * or static field. If the field has a primitive type, the value + * is wrapped in an object before being returned, otherwise it is + * returned as is. + * + *

If the field is hidden in the type of {@code obj}, + * the field's value is obtained according to the preceding rules. + * + * @param obj object from which the represented field's value is + * to be extracted + * @return the value of the represented field in object + * {@code obj}; primitive values are wrapped in an appropriate + * object before being returned + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is inaccessible. + * @exception IllegalArgumentException if the specified object is not an + * instance of the class or interface declaring the underlying + * field (or a subclass or implementor thereof). + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * + * @diffblue.untested + * @diffblue.noSupport + */ + // DIFFBLUE MODEL LIBRARY + // removed for compatibility with Java 9 and newer + // @CallerSensitive + public Object get(Object obj) + throws IllegalArgumentException, IllegalAccessException + { + // if (!override) { + // if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + // Class caller = Reflection.getCallerClass(); + // checkAccess(caller, clazz, obj, modifiers); + // } + // } + // return getFieldAccessor(obj).get(obj); + CProver.notModelled(); + return CProver.nondetWithoutNullForNotModelled(); + } + + /** + * Gets the value of a static or instance {@code boolean} field. + * + * @param obj the object to extract the {@code boolean} value + * from + * @return the value of the {@code boolean} field + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is inaccessible. + * @exception IllegalArgumentException if the specified object is not + * an instance of the class or interface declaring the + * underlying field (or a subclass or implementor + * thereof), or if the field value cannot be + * converted to the type {@code boolean} by a + * widening conversion. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#get + * + * @diffblue.untested + * @diffblue.noSupport + */ + // DIFFBLUE MODEL LIBRARY + // removed for compatibility with Java 9 and newer + // @CallerSensitive + public boolean getBoolean(Object obj) + throws IllegalArgumentException, IllegalAccessException + { + // if (!override) { + // if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + // Class caller = Reflection.getCallerClass(); + // checkAccess(caller, clazz, obj, modifiers); + // } + // } + // return getFieldAccessor(obj).getBoolean(obj); + CProver.notModelled(); + return CProver.nondetBoolean(); + } + + /** + * Gets the value of a static or instance {@code byte} field. + * + * @param obj the object to extract the {@code byte} value + * from + * @return the value of the {@code byte} field + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is inaccessible. + * @exception IllegalArgumentException if the specified object is not + * an instance of the class or interface declaring the + * underlying field (or a subclass or implementor + * thereof), or if the field value cannot be + * converted to the type {@code byte} by a + * widening conversion. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#get + * + * @diffblue.untested + * @diffblue.noSupport + */ + // DIFFBLUE MODEL LIBRARY + // removed for compatibility with Java 9 and newer + // @CallerSensitive + public byte getByte(Object obj) + throws IllegalArgumentException, IllegalAccessException + { + // if (!override) { + // if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + // Class caller = Reflection.getCallerClass(); + // checkAccess(caller, clazz, obj, modifiers); + // } + // } + // return getFieldAccessor(obj).getByte(obj); + CProver.notModelled(); + return CProver.nondetByte(); + } + + /** + * Gets the value of a static or instance field of type + * {@code char} or of another primitive type convertible to + * type {@code char} via a widening conversion. + * + * @param obj the object to extract the {@code char} value + * from + * @return the value of the field converted to type {@code char} + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is inaccessible. + * @exception IllegalArgumentException if the specified object is not + * an instance of the class or interface declaring the + * underlying field (or a subclass or implementor + * thereof), or if the field value cannot be + * converted to the type {@code char} by a + * widening conversion. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#get + * + * @diffblue.untested + * @diffblue.noSupport + */ + // DIFFBLUE MODEL LIBRARY + // removed for compatibility with Java 9 and newer + // @CallerSensitive + public char getChar(Object obj) + throws IllegalArgumentException, IllegalAccessException + { + // if (!override) { + // if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + // Class caller = Reflection.getCallerClass(); + // checkAccess(caller, clazz, obj, modifiers); + // } + // } + // return getFieldAccessor(obj).getChar(obj); + CProver.notModelled(); + return CProver.nondetChar(); + } + + /** + * Gets the value of a static or instance field of type + * {@code short} or of another primitive type convertible to + * type {@code short} via a widening conversion. + * + * @param obj the object to extract the {@code short} value + * from + * @return the value of the field converted to type {@code short} + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is inaccessible. + * @exception IllegalArgumentException if the specified object is not + * an instance of the class or interface declaring the + * underlying field (or a subclass or implementor + * thereof), or if the field value cannot be + * converted to the type {@code short} by a + * widening conversion. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#get + * + * @diffblue.untested + * @diffblue.noSupport + */ + // DIFFBLUE MODEL LIBRARY + // removed for compatibility with Java 9 and newer + // @CallerSensitive + public short getShort(Object obj) + throws IllegalArgumentException, IllegalAccessException + { + // if (!override) { + // if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + // Class caller = Reflection.getCallerClass(); + // checkAccess(caller, clazz, obj, modifiers); + // } + // } + // return getFieldAccessor(obj).getShort(obj); + CProver.notModelled(); + return CProver.nondetShort(); + } + + /** + * Gets the value of a static or instance field of type + * {@code int} or of another primitive type convertible to + * type {@code int} via a widening conversion. + * + * @param obj the object to extract the {@code int} value + * from + * @return the value of the field converted to type {@code int} + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is inaccessible. + * @exception IllegalArgumentException if the specified object is not + * an instance of the class or interface declaring the + * underlying field (or a subclass or implementor + * thereof), or if the field value cannot be + * converted to the type {@code int} by a + * widening conversion. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#get + * + * @diffblue.untested + * @diffblue.noSupport + */ + // DIFFBLUE MODEL LIBRARY + // removed for compatibility with Java 9 and newer + // @CallerSensitive + public int getInt(Object obj) + throws IllegalArgumentException, IllegalAccessException + { + // if (!override) { + // if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + // Class caller = Reflection.getCallerClass(); + // checkAccess(caller, clazz, obj, modifiers); + // } + // } + // return getFieldAccessor(obj).getInt(obj); + CProver.notModelled(); + return CProver.nondetInt(); + } + + /** + * Gets the value of a static or instance field of type + * {@code long} or of another primitive type convertible to + * type {@code long} via a widening conversion. + * + * @param obj the object to extract the {@code long} value + * from + * @return the value of the field converted to type {@code long} + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is inaccessible. + * @exception IllegalArgumentException if the specified object is not + * an instance of the class or interface declaring the + * underlying field (or a subclass or implementor + * thereof), or if the field value cannot be + * converted to the type {@code long} by a + * widening conversion. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#get + * + * @diffblue.untested + * @diffblue.noSupport + */ + // DIFFBLUE MODEL LIBRARY + // removed for compatibility with Java 9 and newer + // @CallerSensitive + public long getLong(Object obj) + throws IllegalArgumentException, IllegalAccessException + { + // if (!override) { + // if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + // Class caller = Reflection.getCallerClass(); + // checkAccess(caller, clazz, obj, modifiers); + // } + // } + // return getFieldAccessor(obj).getLong(obj); + CProver.notModelled(); + return CProver.nondetLong(); + } + + /** + * Gets the value of a static or instance field of type + * {@code float} or of another primitive type convertible to + * type {@code float} via a widening conversion. + * + * @param obj the object to extract the {@code float} value + * from + * @return the value of the field converted to type {@code float} + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is inaccessible. + * @exception IllegalArgumentException if the specified object is not + * an instance of the class or interface declaring the + * underlying field (or a subclass or implementor + * thereof), or if the field value cannot be + * converted to the type {@code float} by a + * widening conversion. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#get + * + * @diffblue.untested + * @diffblue.noSupport + */ + // DIFFBLUE MODEL LIBRARY + // removed for compatibility with Java 9 and newer + // @CallerSensitive + public float getFloat(Object obj) + throws IllegalArgumentException, IllegalAccessException + { + // if (!override) { + // if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + // Class caller = Reflection.getCallerClass(); + // checkAccess(caller, clazz, obj, modifiers); + // } + // } + // return getFieldAccessor(obj).getFloat(obj); + CProver.notModelled(); + return CProver.nondetFloat(); + } + + /** + * Gets the value of a static or instance field of type + * {@code double} or of another primitive type convertible to + * type {@code double} via a widening conversion. + * + * @param obj the object to extract the {@code double} value + * from + * @return the value of the field converted to type {@code double} + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is inaccessible. + * @exception IllegalArgumentException if the specified object is not + * an instance of the class or interface declaring the + * underlying field (or a subclass or implementor + * thereof), or if the field value cannot be + * converted to the type {@code double} by a + * widening conversion. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#get + * + * @diffblue.untested + * @diffblue.noSupport + */ + // DIFFBLUE MODEL LIBRARY + // removed for compatibility with Java 9 and newer + // @CallerSensitive + public double getDouble(Object obj) + throws IllegalArgumentException, IllegalAccessException + { + // if (!override) { + // if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + // Class caller = Reflection.getCallerClass(); + // checkAccess(caller, clazz, obj, modifiers); + // } + // } + // return getFieldAccessor(obj).getDouble(obj); + CProver.notModelled(); + return CProver.nondetDouble(); + } + + /** + * Sets the field represented by this {@code Field} object on the + * specified object argument to the specified new value. The new + * value is automatically unwrapped if the underlying field has a + * primitive type. + * + *

The operation proceeds as follows: + * + *

If the underlying field is static, the {@code obj} argument is + * ignored; it may be null. + * + *

Otherwise the underlying field is an instance field. If the + * specified object argument is null, the method throws a + * {@code NullPointerException}. If the specified object argument is not + * an instance of the class or interface declaring the underlying + * field, the method throws an {@code IllegalArgumentException}. + * + *

If this {@code Field} object is enforcing Java language access control, and + * the underlying field is inaccessible, the method throws an + * {@code IllegalAccessException}. + * + *

If the underlying field is final, the method throws an + * {@code IllegalAccessException} unless {@code setAccessible(true)} + * has succeeded for this {@code Field} object + * and the field is non-static. Setting a final field in this way + * is meaningful only during deserialization or reconstruction of + * instances of classes with blank final fields, before they are + * made available for access by other parts of a program. Use in + * any other context may have unpredictable effects, including cases + * in which other parts of a program continue to use the original + * value of this field. + * + *

If the underlying field is of a primitive type, an unwrapping + * conversion is attempted to convert the new value to a value of + * a primitive type. If this attempt fails, the method throws an + * {@code IllegalArgumentException}. + * + *

If, after possible unwrapping, the new value cannot be + * converted to the type of the underlying field by an identity or + * widening conversion, the method throws an + * {@code IllegalArgumentException}. + * + *

If the underlying field is static, the class that declared the + * field is initialized if it has not already been initialized. + * + *

The field is set to the possibly unwrapped and widened new value. + * + *

If the field is hidden in the type of {@code obj}, + * the field's value is set according to the preceding rules. + * + * @param obj the object whose field should be modified + * @param value the new value for the field of {@code obj} + * being modified + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is either inaccessible or final. + * @exception IllegalArgumentException if the specified object is not an + * instance of the class or interface declaring the underlying + * field (or a subclass or implementor thereof), + * or if an unwrapping conversion fails. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * + * @diffblue.untested + * @diffblue.noSupport + */ + // DIFFBLUE MODEL LIBRARY + // removed for compatibility with Java 9 and newer + // @CallerSensitive + public void set(Object obj, Object value) + throws IllegalArgumentException, IllegalAccessException + { + // if (!override) { + // if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + // Class caller = Reflection.getCallerClass(); + // checkAccess(caller, clazz, obj, modifiers); + // } + // } + // getFieldAccessor(obj).set(obj, value); + CProver.notModelled(); + } + + /** + * Sets the value of a field as a {@code boolean} on the specified object. + * This method is equivalent to + * {@code set(obj, zObj)}, + * where {@code zObj} is a {@code Boolean} object and + * {@code zObj.booleanValue() == z}. + * + * @param obj the object whose field should be modified + * @param z the new value for the field of {@code obj} + * being modified + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is either inaccessible or final. + * @exception IllegalArgumentException if the specified object is not an + * instance of the class or interface declaring the underlying + * field (or a subclass or implementor thereof), + * or if an unwrapping conversion fails. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#set + * + * @diffblue.untested + * @diffblue.noSupport + */ + // DIFFBLUE MODEL LIBRARY + // removed for compatibility with Java 9 and newer + // @CallerSensitive + public void setBoolean(Object obj, boolean z) + throws IllegalArgumentException, IllegalAccessException + { + // if (!override) { + // if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + // Class caller = Reflection.getCallerClass(); + // checkAccess(caller, clazz, obj, modifiers); + // } + // } + // getFieldAccessor(obj).setBoolean(obj, z); + CProver.notModelled(); + } + + /** + * Sets the value of a field as a {@code byte} on the specified object. + * This method is equivalent to + * {@code set(obj, bObj)}, + * where {@code bObj} is a {@code Byte} object and + * {@code bObj.byteValue() == b}. + * + * @param obj the object whose field should be modified + * @param b the new value for the field of {@code obj} + * being modified + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is either inaccessible or final. + * @exception IllegalArgumentException if the specified object is not an + * instance of the class or interface declaring the underlying + * field (or a subclass or implementor thereof), + * or if an unwrapping conversion fails. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#set + * + * @diffblue.untested + * @diffblue.noSupport + */ + // DIFFBLUE MODEL LIBRARY + // removed for compatibility with Java 9 and newer + // @CallerSensitive + public void setByte(Object obj, byte b) + throws IllegalArgumentException, IllegalAccessException + { + // if (!override) { + // if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + // Class caller = Reflection.getCallerClass(); + // checkAccess(caller, clazz, obj, modifiers); + // } + // } + // getFieldAccessor(obj).setByte(obj, b); + CProver.notModelled(); + } + + /** + * Sets the value of a field as a {@code char} on the specified object. + * This method is equivalent to + * {@code set(obj, cObj)}, + * where {@code cObj} is a {@code Character} object and + * {@code cObj.charValue() == c}. + * + * @param obj the object whose field should be modified + * @param c the new value for the field of {@code obj} + * being modified + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is either inaccessible or final. + * @exception IllegalArgumentException if the specified object is not an + * instance of the class or interface declaring the underlying + * field (or a subclass or implementor thereof), + * or if an unwrapping conversion fails. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#set + * + * @diffblue.untested + * @diffblue.noSupport + */ + // DIFFBLUE MODEL LIBRARY + // removed for compatibility with Java 9 and newer + // @CallerSensitive + public void setChar(Object obj, char c) + throws IllegalArgumentException, IllegalAccessException + { + // if (!override) { + // if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + // Class caller = Reflection.getCallerClass(); + // checkAccess(caller, clazz, obj, modifiers); + // } + // } + // getFieldAccessor(obj).setChar(obj, c); + CProver.notModelled(); + } + + /** + * Sets the value of a field as a {@code short} on the specified object. + * This method is equivalent to + * {@code set(obj, sObj)}, + * where {@code sObj} is a {@code Short} object and + * {@code sObj.shortValue() == s}. + * + * @param obj the object whose field should be modified + * @param s the new value for the field of {@code obj} + * being modified + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is either inaccessible or final. + * @exception IllegalArgumentException if the specified object is not an + * instance of the class or interface declaring the underlying + * field (or a subclass or implementor thereof), + * or if an unwrapping conversion fails. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#set + * + * @diffblue.untested + * @diffblue.noSupport + */ + // DIFFBLUE MODEL LIBRARY + // removed for compatibility with Java 9 and newer + // @CallerSensitive + public void setShort(Object obj, short s) + throws IllegalArgumentException, IllegalAccessException + { + // if (!override) { + // if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + // Class caller = Reflection.getCallerClass(); + // checkAccess(caller, clazz, obj, modifiers); + // } + // } + // getFieldAccessor(obj).setShort(obj, s); + CProver.notModelled(); + } + + /** + * Sets the value of a field as an {@code int} on the specified object. + * This method is equivalent to + * {@code set(obj, iObj)}, + * where {@code iObj} is a {@code Integer} object and + * {@code iObj.intValue() == i}. + * + * @param obj the object whose field should be modified + * @param i the new value for the field of {@code obj} + * being modified + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is either inaccessible or final. + * @exception IllegalArgumentException if the specified object is not an + * instance of the class or interface declaring the underlying + * field (or a subclass or implementor thereof), + * or if an unwrapping conversion fails. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#set + * + * @diffblue.untested + * @diffblue.noSupport + */ + // DIFFBLUE MODEL LIBRARY + // removed for compatibility with Java 9 and newer + // @CallerSensitive + public void setInt(Object obj, int i) + throws IllegalArgumentException, IllegalAccessException + { + // if (!override) { + // if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + // Class caller = Reflection.getCallerClass(); + // checkAccess(caller, clazz, obj, modifiers); + // } + // } + // getFieldAccessor(obj).setInt(obj, i); + CProver.notModelled(); + } + + /** + * Sets the value of a field as a {@code long} on the specified object. + * This method is equivalent to + * {@code set(obj, lObj)}, + * where {@code lObj} is a {@code Long} object and + * {@code lObj.longValue() == l}. + * + * @param obj the object whose field should be modified + * @param l the new value for the field of {@code obj} + * being modified + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is either inaccessible or final. + * @exception IllegalArgumentException if the specified object is not an + * instance of the class or interface declaring the underlying + * field (or a subclass or implementor thereof), + * or if an unwrapping conversion fails. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#set + * + * @diffblue.untested + * @diffblue.noSupport + */ + // DIFFBLUE MODEL LIBRARY + // removed for compatibility with Java 9 and newer + // @CallerSensitive + public void setLong(Object obj, long l) + throws IllegalArgumentException, IllegalAccessException + { + // if (!override) { + // if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + // Class caller = Reflection.getCallerClass(); + // checkAccess(caller, clazz, obj, modifiers); + // } + // } + // getFieldAccessor(obj).setLong(obj, l); + CProver.notModelled(); + } + + /** + * Sets the value of a field as a {@code float} on the specified object. + * This method is equivalent to + * {@code set(obj, fObj)}, + * where {@code fObj} is a {@code Float} object and + * {@code fObj.floatValue() == f}. + * + * @param obj the object whose field should be modified + * @param f the new value for the field of {@code obj} + * being modified + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is either inaccessible or final. + * @exception IllegalArgumentException if the specified object is not an + * instance of the class or interface declaring the underlying + * field (or a subclass or implementor thereof), + * or if an unwrapping conversion fails. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#set + * + * @diffblue.untested + * @diffblue.noSupport + */ + // DIFFBLUE MODEL LIBRARY + // removed for compatibility with Java 9 and newer + // @CallerSensitive + public void setFloat(Object obj, float f) + throws IllegalArgumentException, IllegalAccessException + { + // if (!override) { + // if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + // Class caller = Reflection.getCallerClass(); + // checkAccess(caller, clazz, obj, modifiers); + // } + // } + // getFieldAccessor(obj).setFloat(obj, f); + CProver.notModelled(); + } + + /** + * Sets the value of a field as a {@code double} on the specified object. + * This method is equivalent to + * {@code set(obj, dObj)}, + * where {@code dObj} is a {@code Double} object and + * {@code dObj.doubleValue() == d}. + * + * @param obj the object whose field should be modified + * @param d the new value for the field of {@code obj} + * being modified + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is either inaccessible or final. + * @exception IllegalArgumentException if the specified object is not an + * instance of the class or interface declaring the underlying + * field (or a subclass or implementor thereof), + * or if an unwrapping conversion fails. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#set + * + * @diffblue.untested + * @diffblue.noSupport + */ + // DIFFBLUE MODEL LIBRARY + // removed for compatibility with Java 9 and newer + // @CallerSensitive + public void setDouble(Object obj, double d) + throws IllegalArgumentException, IllegalAccessException + { + // if (!override) { + // if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + // Class caller = Reflection.getCallerClass(); + // checkAccess(caller, clazz, obj, modifiers); + // } + // } + // getFieldAccessor(obj).setDouble(obj, d); + CProver.notModelled(); + } + + // security check is done before calling this method + // DIFFBLUE MODEL LIBRARY - not used in model + // private FieldAccessor getFieldAccessor(Object obj) + // throws IllegalAccessException + // { + // boolean ov = override; + // FieldAccessor a = (ov) ? overrideFieldAccessor : fieldAccessor; + // return (a != null) ? a : acquireFieldAccessor(ov); + // } + + // NOTE that there is no synchronization used here. It is correct + // (though not efficient) to generate more than one FieldAccessor + // for a given Field. However, avoiding synchronization will + // probably make the implementation more scalable. + // DIFFBLUE MODEL LIBRARY - not used in model + // private FieldAccessor acquireFieldAccessor(boolean overrideFinalCheck) { + // // First check to see if one has been created yet, and take it + // // if so + // FieldAccessor tmp = null; + // if (root != null) tmp = root.getFieldAccessor(overrideFinalCheck); + // if (tmp != null) { + // if (overrideFinalCheck) + // overrideFieldAccessor = tmp; + // else + // fieldAccessor = tmp; + // } else { + // // Otherwise fabricate one and propagate it up to the root + // tmp = reflectionFactory.newFieldAccessor(this, overrideFinalCheck); + // setFieldAccessor(tmp, overrideFinalCheck); + // } + + // return tmp; + // } + + // Returns FieldAccessor for this Field object, not looking up + // the chain to the root + // DIFFBLUE MODEL LIBRARY - not used in model + // private FieldAccessor getFieldAccessor(boolean overrideFinalCheck) { + // return (overrideFinalCheck)? overrideFieldAccessor : fieldAccessor; + // } + + // Sets the FieldAccessor for this Field object and + // (recursively) its root + // DIFFBLUE MODEL LIBRARY - not used in model + // private void setFieldAccessor(FieldAccessor accessor, boolean overrideFinalCheck) { + // if (overrideFinalCheck) + // overrideFieldAccessor = accessor; + // else + // fieldAccessor = accessor; + // // Propagate up + // if (root != null) { + // root.setFieldAccessor(accessor, overrideFinalCheck); + // } + // } + + /** + * @throws NullPointerException {@inheritDoc} + * @since 1.5 + * + * @diffblue.untested + * @diffblue.noSupport + */ + public T getAnnotation(Class annotationClass) { + // Objects.requireNonNull(annotationClass); + // return annotationClass.cast(declaredAnnotations().get(annotationClass)); + CProver.notModelled(); + return CProver.nondetWithoutNullForNotModelled(); + } + + /** + * {@inheritDoc} + * @throws NullPointerException {@inheritDoc} + * @since 1.8 + * + * @diffblue.untested + * @diffblue.noSupport + */ + @Override + public T[] getAnnotationsByType(Class annotationClass) { + // Objects.requireNonNull(annotationClass); + + // return AnnotationSupport.getDirectlyAndIndirectlyPresent(declaredAnnotations(), annotationClass); + CProver.notModelled(); + return CProver.nondetWithoutNullForNotModelled(); + } + + /** + * {@inheritDoc} + * + * @diffblue.untested + * @diffblue.noSupport + */ + public Annotation[] getDeclaredAnnotations() { + // return AnnotationParser.toArray(declaredAnnotations()); + CProver.notModelled(); + return CProver.nondetWithoutNullForNotModelled(); + } + + // DIFFBLUE MODEL LIBRARY - not used in model + // private transient Map, Annotation> declaredAnnotations; + + // DIFFBLUE MODEL LIBRARY - not used in model + // private synchronized Map, Annotation> declaredAnnotations() { + // if (declaredAnnotations == null) { + // Field root = this.root; + // if (root != null) { + // declaredAnnotations = root.declaredAnnotations(); + // } else { + // declaredAnnotations = AnnotationParser.parseAnnotations( + // annotations, + // sun.misc.SharedSecrets.getJavaLangAccess().getConstantPool(getDeclaringClass()), + // getDeclaringClass()); + // } + // } + // return declaredAnnotations; + // } + + // DIFFBLUE MODEL LIBRARY - not used in model + // private native byte[] getTypeAnnotationBytes0(); + + /** + * Returns an AnnotatedType object that represents the use of a type to specify + * the declared type of the field represented by this Field. + * @return an object representing the declared type of the field + * represented by this Field + * + * @since 1.8 + * + * @diffblue.untested + * @diffblue.noSupport + */ + public AnnotatedType getAnnotatedType() { + // return TypeAnnotationParser.buildAnnotatedType(getTypeAnnotationBytes0(), + // sun.misc.SharedSecrets.getJavaLangAccess(). + // getConstantPool(getDeclaringClass()), + // this, + // getDeclaringClass(), + // getGenericType(), + // TypeAnnotation.TypeAnnotationTarget.FIELD); + CProver.notModelled(); + return CProver.nondetWithoutNullForNotModelled(); + } +} diff --git a/src/main/java/java/lang/reflect/GenericSignatureFormatError.java b/src/main/java/java/lang/reflect/GenericSignatureFormatError.java new file mode 100644 index 0000000..eb130e7 --- /dev/null +++ b/src/main/java/java/lang/reflect/GenericSignatureFormatError.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang.reflect; + + +/** + * Thrown when a syntactically malformed signature attribute is + * encountered by a reflective method that needs to interpret the + * generic signature information for a type, method or constructor. + * + * @since 1.5 + */ +public class GenericSignatureFormatError extends ClassFormatError { + private static final long serialVersionUID = 6709919147137911034L; + + /** + * Constructs a new {@code GenericSignatureFormatError}. + * + */ + public GenericSignatureFormatError() { + super(); + } + + /** + * Constructs a new {@code GenericSignatureFormatError} with the + * specified message. + * + * @param message the detail message, may be {@code null} + */ + public GenericSignatureFormatError(String message) { + super(message); + } + + // DIFFBLUE MODEL LIBRARY + // While Object.getClass() is not modelled, we can get the same + // functionality by adding one toString() method per subclass of + // Throwable. + @Override + public String toString() { + String message = getLocalizedMessage(); + return (message != null) + ? ("java.lang.reflect.GenericSignatureFormatError: " + message) + : "java.lang.reflect.GenericSignatureFormatError"; + } +} diff --git a/src/main/java/java/lang/reflect/InvocationTargetException.java b/src/main/java/java/lang/reflect/InvocationTargetException.java new file mode 100644 index 0000000..3688822 --- /dev/null +++ b/src/main/java/java/lang/reflect/InvocationTargetException.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) 1996, 2004, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang.reflect; + +/** + * InvocationTargetException is a checked exception that wraps + * an exception thrown by an invoked method or constructor. + * + *

As of release 1.4, this exception has been retrofitted to conform to + * the general purpose exception-chaining mechanism. The "target exception" + * that is provided at construction time and accessed via the + * {@link #getTargetException()} method is now known as the cause, + * and may be accessed via the {@link Throwable#getCause()} method, + * as well as the aforementioned "legacy method." + * + * @see Method + * @see Constructor + */ +public class InvocationTargetException extends ReflectiveOperationException { + /** + * Use serialVersionUID from JDK 1.1.X for interoperability + */ + private static final long serialVersionUID = 4085088731926701167L; + + /** + * This field holds the target if the + * InvocationTargetException(Throwable target) constructor was + * used to instantiate the object + * + * @serial + * + */ + private Throwable target; + + /** + * Constructs an {@code InvocationTargetException} with + * {@code null} as the target exception. + */ + protected InvocationTargetException() { + super((Throwable)null); // Disallow initCause + } + + /** + * Constructs a InvocationTargetException with a target exception. + * + * @param target the target exception + */ + public InvocationTargetException(Throwable target) { + super((Throwable)null); // Disallow initCause + this.target = target; + } + + /** + * Constructs a InvocationTargetException with a target exception + * and a detail message. + * + * @param target the target exception + * @param s the detail message + */ + public InvocationTargetException(Throwable target, String s) { + super(s, null); // Disallow initCause + this.target = target; + } + + /** + * Get the thrown target exception. + * + *

This method predates the general-purpose exception chaining facility. + * The {@link Throwable#getCause()} method is now the preferred means of + * obtaining this information. + * + * @return the thrown target exception (cause of this exception). + */ + public Throwable getTargetException() { + return target; + } + + /** + * Returns the cause of this exception (the thrown target exception, + * which may be {@code null}). + * + * @return the cause of this exception. + * @since 1.4 + */ + public Throwable getCause() { + return target; + } + + // DIFFBLUE MODEL LIBRARY + // While Object.getClass() is not modelled, we can get the same + // functionality by adding one toString() method per subclass of + // Throwable. + @Override + public String toString() { + String message = getLocalizedMessage(); + return (message != null) + ? ("java.lang.reflect.InvocationTargetException: " + message) + : "java.lang.reflect.InvocationTargetException"; + } +} diff --git a/src/main/java/java/lang/reflect/MalformedParameterizedTypeException.java b/src/main/java/java/lang/reflect/MalformedParameterizedTypeException.java new file mode 100644 index 0000000..9c1eec5 --- /dev/null +++ b/src/main/java/java/lang/reflect/MalformedParameterizedTypeException.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +package java.lang.reflect; + +/** + * Thrown when a semantically malformed parameterized type is + * encountered by a reflective method that needs to instantiate it. + * For example, if the number of type arguments to a parameterized type + * is wrong. + * + * @since 1.5 + */ +public class MalformedParameterizedTypeException extends RuntimeException { + private static final long serialVersionUID = -5696557788586220964L; + + // DIFFBLUE MODEL LIBRARY + // While Object.getClass() is not modelled, we can get the same + // functionality by adding one toString() method per subclass of + // Throwable. + @Override + public String toString() { + String message = getLocalizedMessage(); + return (message != null) + ? ("java.lang.reflect.MalformedParameterizedTypeException: " + message) + : "java.lang.reflect.MalformedParameterizedTypeException"; + } +} diff --git a/src/main/java/java/lang/reflect/MalformedParametersException.java b/src/main/java/java/lang/reflect/MalformedParametersException.java new file mode 100644 index 0000000..7ce36ac --- /dev/null +++ b/src/main/java/java/lang/reflect/MalformedParametersException.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang.reflect; + +/** + * Thrown when {@link java.lang.reflect.Executable#getParameters the + * java.lang.reflect package} attempts to read method parameters from + * a class file and determines that one or more parameters are + * malformed. + * + *

The following is a list of conditions under which this exception + * can be thrown: + *

+ * + * See {@link java.lang.reflect.Executable#getParameters} for more + * information. + * + * @see java.lang.reflect.Executable#getParameters + * @since 1.8 + */ +public class MalformedParametersException extends RuntimeException { + + /** + * Version for serialization. + */ + private static final long serialVersionUID = 20130919L; + + /** + * Create a {@code MalformedParametersException} with an empty + * reason. + */ + public MalformedParametersException() {} + + /** + * Create a {@code MalformedParametersException}. + * + * @param reason The reason for the exception. + */ + public MalformedParametersException(String reason) { + super(reason); + } + + // DIFFBLUE MODEL LIBRARY + // While Object.getClass() is not modelled, we can get the same + // functionality by adding one toString() method per subclass of + // Throwable. + @Override + public String toString() { + String message = getLocalizedMessage(); + return (message != null) + ? ("java.lang.reflect.MalformedParametersException: " + message) + : "java.lang.reflect.MalformedParametersException"; + } +} diff --git a/src/main/java/java/lang/reflect/Method.java b/src/main/java/java/lang/reflect/Method.java new file mode 100644 index 0000000..fdab45c --- /dev/null +++ b/src/main/java/java/lang/reflect/Method.java @@ -0,0 +1,825 @@ +/* + * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang.reflect; + +import org.cprover.CProver; + +// DIFFBLUE MODEL LIBRARY +// removed for compatibility with Java 9 and newer +// import sun.reflect.CallerSensitive; +// import sun.reflect.MethodAccessor; +// import sun.reflect.Reflection; +import sun.reflect.generics.repository.MethodRepository; +import sun.reflect.generics.factory.CoreReflectionFactory; +import sun.reflect.generics.factory.GenericsFactory; +import sun.reflect.generics.scope.MethodScope; +import sun.reflect.annotation.AnnotationType; +import sun.reflect.annotation.AnnotationParser; +import java.lang.annotation.Annotation; +import java.lang.annotation.AnnotationFormatError; +import java.nio.ByteBuffer; + +/** + * A {@code Method} provides information about, and access to, a single method + * on a class or interface. The reflected method may be a class method + * or an instance method (including an abstract method). + * + *

A {@code Method} permits widening conversions to occur when matching the + * actual parameters to invoke with the underlying method's formal + * parameters, but it throws an {@code IllegalArgumentException} if a + * narrowing conversion would occur. + * + * @see Member + * @see java.lang.Class + * @see java.lang.Class#getMethods() + * @see java.lang.Class#getMethod(String, Class[]) + * @see java.lang.Class#getDeclaredMethods() + * @see java.lang.Class#getDeclaredMethod(String, Class[]) + * + * @author Kenneth Russell + * @author Nakul Saraiya + * + * @diffblue.untested + * @diffblue.noSupport + * This model was automatically generated by the JDK Processor tool. + */ +public final class Method extends Executable { + private Class clazz; + // DIFFBLUE MODEL LIBRARY - not used in model + // private int slot; + // This is guaranteed to be interned by the VM in the 1.4 + // reflection implementation + private String name; + // DIFFBLUE MODEL LIBRARY - not used in model + // private Class returnType; + private Class[] parameterTypes; + // DIFFBLUE MODEL LIBRARY - not used in model + // private Class[] exceptionTypes; + // DIFFBLUE MODEL LIBRARY - not used in model + // private int modifiers; + // Generics and annotations support + // DIFFBLUE MODEL LIBRARY - not used in model + // private transient String signature; + // generic info repository; lazily initialized + // DIFFBLUE MODEL LIBRARY - not used in model + // private transient MethodRepository genericInfo; + // DIFFBLUE MODEL LIBRARY - not used in model + // private byte[] annotations; + // DIFFBLUE MODEL LIBRARY - not used in model + // private byte[] parameterAnnotations; + // DIFFBLUE MODEL LIBRARY - not used in model + // private byte[] annotationDefault; + // DIFFBLUE MODEL LIBRARY - not used in model + // private volatile MethodAccessor methodAccessor; + // For sharing of MethodAccessors. This branching structure is + // currently only two levels deep (i.e., one root Method and + // potentially many Method objects pointing to it.) + // + // If this branching structure would ever contain cycles, deadlocks can + // occur in annotation code. + // DIFFBLUE MODEL LIBRARY - not used in model + // private Method root; + + // Generics infrastructure + // DIFFBLUE MODEL LIBRARY - not used in model + // private String getGenericSignature() {return signature;} + + // Accessor for factory + // DIFFBLUE MODEL LIBRARY - not used in model + // private GenericsFactory getFactory() { + // // create scope and factory + // return CoreReflectionFactory.make(this, MethodScope.make(this)); + // } + + /** + * Accessor for generic info repository + * + * @diffblue.untested + * @diffblue.noSupport + */ + @Override + // DIFFBLUE MODEL LIBRARY - not used in model + MethodRepository getGenericInfo() { + // // lazily initialize repository if necessary + // if (genericInfo == null) { + // // create and cache generic info repository + // genericInfo = MethodRepository.make(getGenericSignature(), + // getFactory()); + // } + // return genericInfo; //return cached repository + CProver.notModelled(); + return CProver.nondetWithoutNullForNotModelled(); + } + + /** + * Package-private constructor used by ReflectAccess to enable + * instantiation of these objects in Java code from the java.lang + * package via sun.reflect.LangReflectAccess. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // Method(Class declaringClass, + // String name, + // Class[] parameterTypes, + // Class returnType, + // Class[] checkedExceptions, + // int modifiers, + // int slot, + // String signature, + // byte[] annotations, + // byte[] parameterAnnotations, + // byte[] annotationDefault) { + // this.clazz = declaringClass; + // this.name = name; + // this.parameterTypes = parameterTypes; + // this.returnType = returnType; + // this.exceptionTypes = checkedExceptions; + // this.modifiers = modifiers; + // this.slot = slot; + // this.signature = signature; + // this.annotations = annotations; + // this.parameterAnnotations = parameterAnnotations; + // this.annotationDefault = annotationDefault; + // } + + /** + * This constructor does not exist in the JDK, only in the model + */ + public Method( + Class declaringClass, + String name, + Class[] parameterTypes) + { + this.clazz = declaringClass; + this.name = name; + this.parameterTypes = parameterTypes; + } + + /** + * Package-private routine (exposed to java.lang.Class via + * ReflectAccess) which returns a copy of this Method. The copy's + * "root" field points to this Method. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // Method copy() { + // // This routine enables sharing of MethodAccessor objects + // // among Method objects which refer to the same underlying + // // method in the VM. (All of this contortion is only necessary + // // because of the "accessibility" bit in AccessibleObject, + // // which implicitly requires that new java.lang.reflect + // // objects be fabricated for each reflective call on Class + // // objects.) + // if (this.root != null) + // throw new IllegalArgumentException("Can not copy a non-root Method"); + + // Method res = new Method(clazz, name, parameterTypes, returnType, + // exceptionTypes, modifiers, slot, signature, + // annotations, parameterAnnotations, annotationDefault); + // res.root = this; + // // Might as well eagerly propagate this if already present + // res.methodAccessor = methodAccessor; + // return res; + // } + + /** + * Used by Excecutable for annotation sharing. + * + * @diffblue.untested + * @diffblue.noSupport + */ + @Override + // DIFFBLUE MODEL LIBRARY - not used in model + Executable getRoot() { + // return root; + CProver.notModelled(); + return CProver.nondetWithoutNullForNotModelled(); + } + + /** + * @diffblue.untested + * @diffblue.noSupport + */ + @Override + // DIFFBLUE MODEL LIBRARY - not used in model + boolean hasGenericInformation() { + // return (getGenericSignature() != null); + CProver.notModelled(); + return CProver.nondetBoolean(); + } + + /** + * @diffblue.untested + * @diffblue.noSupport + */ + @Override + // DIFFBLUE MODEL LIBRARY - not used in model + byte[] getAnnotationBytes() { + // return annotations; + CProver.notModelled(); + return CProver.nondetWithoutNullForNotModelled(); + } + + /** + * {@inheritDoc} + * + * @diffblue.fullSupport + */ + @Override + public Class getDeclaringClass() { + return clazz; + } + + /** + * Returns the name of the method represented by this {@code Method} + * object, as a {@code String}. + * + * @diffblue.fullSupport + */ + @Override + public String getName() { + return name; + } + + /** + * {@inheritDoc} + * + * @diffblue.untested + * @diffblue.noSupport + */ + @Override + public int getModifiers() { + // return modifiers; + CProver.notModelled(); + return CProver.nondetInt(); + } + + /** + * {@inheritDoc} + * @throws GenericSignatureFormatError {@inheritDoc} + * @since 1.5 + */ + @Override + @SuppressWarnings({"rawtypes", "unchecked"}) + public TypeVariable[] getTypeParameters() { + // if (getGenericSignature() != null) + // return (TypeVariable[])getGenericInfo().getTypeParameters(); + // else + // return (TypeVariable[])new TypeVariable[0]; + CProver.notModelled(); + return CProver.nondetWithoutNullForNotModelled(); + } + + /** + * Returns a {@code Class} object that represents the formal return type + * of the method represented by this {@code Method} object. + * + * @return the return type for the method this object represents + * + * @diffblue.untested + * @diffblue.noSupport + */ + public Class getReturnType() { + // return returnType; + CProver.notModelled(); + return CProver.nondetWithoutNullForNotModelled(); + } + + /** + * Returns a {@code Type} object that represents the formal return + * type of the method represented by this {@code Method} object. + * + *

If the return type is a parameterized type, + * the {@code Type} object returned must accurately reflect + * the actual type parameters used in the source code. + * + *

If the return type is a type variable or a parameterized type, it + * is created. Otherwise, it is resolved. + * + * @return a {@code Type} object that represents the formal return + * type of the underlying method + * @throws GenericSignatureFormatError + * if the generic method signature does not conform to the format + * specified in + * The Java™ Virtual Machine Specification + * @throws TypeNotPresentException if the underlying method's + * return type refers to a non-existent type declaration + * @throws MalformedParameterizedTypeException if the + * underlying method's return typed refers to a parameterized + * type that cannot be instantiated for any reason + * @since 1.5 + * + * @diffblue.untested + * @diffblue.noSupport + */ + public Type getGenericReturnType() { +// if (getGenericSignature() != null) { + // return getGenericInfo().getReturnType(); +// } else { return getReturnType();} + CProver.notModelled(); + return CProver.nondetWithoutNullForNotModelled(); + } + + /** + * {@inheritDoc} + * + * @diffblue.untested + * @diffblue.fullSupport + */ + @Override + public Class[] getParameterTypes() { + return parameterTypes.clone(); + } + + /** + * {@inheritDoc} + * @since 1.8 + * + * @diffblue.untested + * @diffblue.fullSupport + */ + public int getParameterCount() { + return parameterTypes.length; + } + + + /** + * {@inheritDoc} + * @throws GenericSignatureFormatError {@inheritDoc} + * @throws TypeNotPresentException {@inheritDoc} + * @throws MalformedParameterizedTypeException {@inheritDoc} + * @since 1.5 + * + * @diffblue.untested + */ + @Override + public Type[] getGenericParameterTypes() { + return super.getGenericParameterTypes(); + } + + /** + * {@inheritDoc} + * + * @diffblue.untested + * @diffblue.noSupport + */ + @Override + public Class[] getExceptionTypes() { + // return exceptionTypes.clone(); + CProver.notModelled(); + return CProver.nondetWithoutNullForNotModelled(); + } + + /** + * {@inheritDoc} + * @throws GenericSignatureFormatError {@inheritDoc} + * @throws TypeNotPresentException {@inheritDoc} + * @throws MalformedParameterizedTypeException {@inheritDoc} + * @since 1.5 + * + * @diffblue.untested + */ + @Override + public Type[] getGenericExceptionTypes() { + return super.getGenericExceptionTypes(); + } + + /** + * Compares this {@code Method} against the specified object. Returns + * true if the objects are the same. Two {@code Methods} are the same if + * they were declared by the same class and have the same name + * and formal parameter types and return type. + * + * @diffblue.limitedSupport + */ + public boolean equals(Object obj) { + if (obj != null && obj instanceof Method) { + Method other = (Method)obj; + if ((getDeclaringClass() == other.getDeclaringClass()) + && (getName() == other.getName())) { + return equalParamTypes(parameterTypes, other.parameterTypes); + } + } + return false; + } + + /** + * Returns a hashcode for this {@code Method}. The hashcode is computed + * as the exclusive-or of the hashcodes for the underlying + * method's declaring class name and the method's name. + * + * @diffblue.untested + */ + public int hashCode() { + return getDeclaringClass().getName().hashCode() ^ getName().hashCode(); + } + + /** + * Returns a string describing this {@code Method}. The string is + * formatted as the method access modifiers, if any, followed by + * the method return type, followed by a space, followed by the + * class declaring the method, followed by a period, followed by + * the method name, followed by a parenthesized, comma-separated + * list of the method's formal parameter types. If the method + * throws checked exceptions, the parameter list is followed by a + * space, followed by the word throws followed by a + * comma-separated list of the thrown exception types. + * For example: + *

+     *    public boolean java.lang.Object.equals(java.lang.Object)
+     * 
+ * + *

The access modifiers are placed in canonical order as + * specified by "The Java Language Specification". This is + * {@code public}, {@code protected} or {@code private} first, + * and then other modifiers in the following order: + * {@code abstract}, {@code default}, {@code static}, {@code final}, + * {@code synchronized}, {@code native}, {@code strictfp}. + * + * @return a string describing this {@code Method} + * + * @jls 8.4.3 Method Modifiers + * + * @diffblue.untested + * @diffblue.noSupport + */ + public String toString() { + // return sharedToString(Modifier.methodModifiers(), + // isDefault(), + // parameterTypes, + // exceptionTypes); + CProver.notModelled(); + return CProver.nondetWithoutNullForNotModelled(); + } + + /** + * @diffblue.untested + * @diffblue.noSupport + */ + @Override + // DIFFBLUE MODEL LIBRARY - not used in model + void specificToStringHeader(StringBuilder sb) { + // sb.append(getReturnType().getTypeName()).append(' '); + // sb.append(getDeclaringClass().getTypeName()).append('.'); + // sb.append(getName()); + CProver.notModelled(); + } + + /** + * Returns a string describing this {@code Method}, including + * type parameters. The string is formatted as the method access + * modifiers, if any, followed by an angle-bracketed + * comma-separated list of the method's type parameters, if any, + * followed by the method's generic return type, followed by a + * space, followed by the class declaring the method, followed by + * a period, followed by the method name, followed by a + * parenthesized, comma-separated list of the method's generic + * formal parameter types. + * + * If this method was declared to take a variable number of + * arguments, instead of denoting the last parameter as + * "Type[]", it is denoted as + * "Type...". + * + * A space is used to separate access modifiers from one another + * and from the type parameters or return type. If there are no + * type parameters, the type parameter list is elided; if the type + * parameter list is present, a space separates the list from the + * class name. If the method is declared to throw exceptions, the + * parameter list is followed by a space, followed by the word + * throws followed by a comma-separated list of the generic thrown + * exception types. + * + *

The access modifiers are placed in canonical order as + * specified by "The Java Language Specification". This is + * {@code public}, {@code protected} or {@code private} first, + * and then other modifiers in the following order: + * {@code abstract}, {@code default}, {@code static}, {@code final}, + * {@code synchronized}, {@code native}, {@code strictfp}. + * + * @return a string describing this {@code Method}, + * include type parameters + * + * @since 1.5 + * + * @jls 8.4.3 Method Modifiers + * + * @diffblue.untested + */ + @Override + public String toGenericString() { + return sharedToGenericString(Modifier.methodModifiers(), isDefault()); + } + + /** + * @diffblue.untested + * @diffblue.noSupport + */ + @Override + // DIFFBLUE MODEL LIBRARY - not used in model + void specificToGenericStringHeader(StringBuilder sb) { + // Type genRetType = getGenericReturnType(); + // sb.append(genRetType.getTypeName()).append(' '); + // sb.append(getDeclaringClass().getTypeName()).append('.'); + // sb.append(getName()); + CProver.notModelled(); + } + + /** + * Invokes the underlying method represented by this {@code Method} + * object, on the specified object with the specified parameters. + * Individual parameters are automatically unwrapped to match + * primitive formal parameters, and both primitive and reference + * parameters are subject to method invocation conversions as + * necessary. + * + *

If the underlying method is static, then the specified {@code obj} + * argument is ignored. It may be null. + * + *

If the number of formal parameters required by the underlying method is + * 0, the supplied {@code args} array may be of length 0 or null. + * + *

If the underlying method is an instance method, it is invoked + * using dynamic method lookup as documented in The Java Language + * Specification, Second Edition, section 15.12.4.4; in particular, + * overriding based on the runtime type of the target object will occur. + * + *

If the underlying method is static, the class that declared + * the method is initialized if it has not already been initialized. + * + *

If the method completes normally, the value it returns is + * returned to the caller of invoke; if the value has a primitive + * type, it is first appropriately wrapped in an object. However, + * if the value has the type of an array of a primitive type, the + * elements of the array are not wrapped in objects; in + * other words, an array of primitive type is returned. If the + * underlying method return type is void, the invocation returns + * null. + * + * @param obj the object the underlying method is invoked from + * @param args the arguments used for the method call + * @return the result of dispatching the method represented by + * this object on {@code obj} with parameters + * {@code args} + * + * @exception IllegalAccessException if this {@code Method} object + * is enforcing Java language access control and the underlying + * method is inaccessible. + * @exception IllegalArgumentException if the method is an + * instance method and the specified object argument + * is not an instance of the class or interface + * declaring the underlying method (or of a subclass + * or implementor thereof); if the number of actual + * and formal parameters differ; if an unwrapping + * conversion for primitive arguments fails; or if, + * after possible unwrapping, a parameter value + * cannot be converted to the corresponding formal + * parameter type by a method invocation conversion. + * @exception InvocationTargetException if the underlying method + * throws an exception. + * @exception NullPointerException if the specified object is null + * and the method is an instance method. + * @exception ExceptionInInitializerError if the initialization + * provoked by this method fails. + * + * @diffblue.untested + * @diffblue.noSupport + */ + // DIFFBLUE MODEL LIBRARY + // removed for compatibility with Java 9 and newer + // @CallerSensitive + public Object invoke(Object obj, Object... args) + throws IllegalAccessException, IllegalArgumentException, + InvocationTargetException + { + // if (!override) { + // if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + // Class caller = Reflection.getCallerClass(); + // checkAccess(caller, clazz, obj, modifiers); + // } + // } + // MethodAccessor ma = methodAccessor; // read volatile + // if (ma == null) { + // ma = acquireMethodAccessor(); + // } + // return ma.invoke(obj, args); + CProver.notModelled(); + return CProver.nondetWithoutNullForNotModelled(); + } + + /** + * Returns {@code true} if this method is a bridge + * method; returns {@code false} otherwise. + * + * @return true if and only if this method is a bridge + * method as defined by the Java Language Specification. + * @since 1.5 + * + * @diffblue.untested + * @diffblue.noSupport + */ + public boolean isBridge() { + // return (getModifiers() & Modifier.BRIDGE) != 0; + CProver.notModelled(); + return CProver.nondetBoolean(); + } + + /** + * {@inheritDoc} + * @since 1.5 + * + * @diffblue.untested + */ + @Override + public boolean isVarArgs() { + return super.isVarArgs(); + } + + /** + * {@inheritDoc} + * @jls 13.1 The Form of a Binary + * @since 1.5 + * + * @diffblue.untested + */ + @Override + public boolean isSynthetic() { + return super.isSynthetic(); + } + + /** + * Returns {@code true} if this method is a default + * method; returns {@code false} otherwise. + * + * A default method is a public non-abstract instance method, that + * is, a non-static method with a body, declared in an interface + * type. + * + * @return true if and only if this method is a default + * method as defined by the Java Language Specification. + * @since 1.8 + * + * @diffblue.untested + * @diffblue.noSupport + */ + public boolean isDefault() { + // // Default methods are public non-abstract instance methods + // // declared in an interface. + // return ((getModifiers() & (Modifier.ABSTRACT | Modifier.PUBLIC | Modifier.STATIC)) == + // Modifier.PUBLIC) && getDeclaringClass().isInterface(); + CProver.notModelled(); + return CProver.nondetBoolean(); + } + + // NOTE that there is no synchronization used here. It is correct + // (though not efficient) to generate more than one MethodAccessor + // for a given Method. However, avoiding synchronization will + // probably make the implementation more scalable. + // DIFFBLUE MODEL LIBRARY - not used in model + // private MethodAccessor acquireMethodAccessor() { + // // First check to see if one has been created yet, and take it + // // if so + // MethodAccessor tmp = null; + // if (root != null) tmp = root.getMethodAccessor(); + // if (tmp != null) { + // methodAccessor = tmp; + // } else { + // // Otherwise fabricate one and propagate it up to the root + // tmp = reflectionFactory.newMethodAccessor(this); + // setMethodAccessor(tmp); + // } + + // return tmp; + // } + + // Returns MethodAccessor for this Method object, not looking up + // the chain to the root + // DIFFBLUE MODEL LIBRARY - not used in model + // MethodAccessor getMethodAccessor() { + // return methodAccessor; + // } + + // Sets the MethodAccessor for this Method object and + // (recursively) its root + // DIFFBLUE MODEL LIBRARY - not used in model + // void setMethodAccessor(MethodAccessor accessor) { + // methodAccessor = accessor; + // // Propagate up + // if (root != null) { + // root.setMethodAccessor(accessor); + // } + // } + + /** + * Returns the default value for the annotation member represented by + * this {@code Method} instance. If the member is of a primitive type, + * an instance of the corresponding wrapper type is returned. Returns + * null if no default is associated with the member, or if the method + * instance does not represent a declared member of an annotation type. + * + * @return the default value for the annotation member represented + * by this {@code Method} instance. + * @throws TypeNotPresentException if the annotation is of type + * {@link Class} and no definition can be found for the + * default class value. + * @since 1.5 + * + * @diffblue.untested + * @diffblue.noSupport + */ + public Object getDefaultValue() { + // if (annotationDefault == null) + // return null; + // Class memberType = AnnotationType.invocationHandlerReturnType( + // getReturnType()); + // Object result = AnnotationParser.parseMemberValue( + // memberType, ByteBuffer.wrap(annotationDefault), + // sun.misc.SharedSecrets.getJavaLangAccess(). + // getConstantPool(getDeclaringClass()), + // getDeclaringClass()); + // if (result instanceof sun.reflect.annotation.ExceptionProxy) + // throw new AnnotationFormatError("Invalid default: " + this); + // return result; + CProver.notModelled(); + return CProver.nondetWithoutNullForNotModelled(); + } + + /** + * {@inheritDoc} + * @throws NullPointerException {@inheritDoc} + * @since 1.5 + * + * @diffblue.untested + */ + public T getAnnotation(Class annotationClass) { + return super.getAnnotation(annotationClass); + } + + /** + * {@inheritDoc} + * @since 1.5 + * + * @diffblue.untested + */ + public Annotation[] getDeclaredAnnotations() { + return super.getDeclaredAnnotations(); + } + + /** + * {@inheritDoc} + * @since 1.5 + * + * @diffblue.untested + * @diffblue.noSupport + */ + @Override + public Annotation[][] getParameterAnnotations() { + // return sharedGetParameterAnnotations(parameterTypes, parameterAnnotations); + CProver.notModelled(); + return CProver.nondetWithoutNullForNotModelled(); + } + + /** + * {@inheritDoc} + * @since 1.8 + * + * @diffblue.untested + * @diffblue.noSupport + */ + @Override + public AnnotatedType getAnnotatedReturnType() { + // return getAnnotatedReturnType0(getGenericReturnType()); + CProver.notModelled(); + return CProver.nondetWithoutNullForNotModelled(); + } + + /** + * @diffblue.untested + */ + @Override + // DIFFBLUE MODEL LIBRARY - not used in model + void handleParameterNumberMismatch(int resultLength, int numParameters) { + throw new AnnotationFormatError("Parameter annotations don't match number of parameters"); + } +} diff --git a/src/main/java/java/lang/reflect/UndeclaredThrowableException.java b/src/main/java/java/lang/reflect/UndeclaredThrowableException.java new file mode 100644 index 0000000..e3e92e8 --- /dev/null +++ b/src/main/java/java/lang/reflect/UndeclaredThrowableException.java @@ -0,0 +1,131 @@ +/* + * Copyright (c) 1999, 2006, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang.reflect; + +/** + * Thrown by a method invocation on a proxy instance if its invocation + * handler's {@link InvocationHandler#invoke invoke} method throws a + * checked exception (a {@code Throwable} that is not assignable + * to {@code RuntimeException} or {@code Error}) that + * is not assignable to any of the exception types declared in the + * {@code throws} clause of the method that was invoked on the + * proxy instance and dispatched to the invocation handler. + * + *

An {@code UndeclaredThrowableException} instance contains + * the undeclared checked exception that was thrown by the invocation + * handler, and it can be retrieved with the + * {@code getUndeclaredThrowable()} method. + * {@code UndeclaredThrowableException} extends + * {@code RuntimeException}, so it is an unchecked exception + * that wraps a checked exception. + * + *

As of release 1.4, this exception has been retrofitted to + * conform to the general purpose exception-chaining mechanism. The + * "undeclared checked exception that was thrown by the invocation + * handler" that may be provided at construction time and accessed via + * the {@link #getUndeclaredThrowable()} method is now known as the + * cause, and may be accessed via the {@link + * Throwable#getCause()} method, as well as the aforementioned "legacy + * method." + * + * @author Peter Jones + * @see InvocationHandler + * @since 1.3 + */ +public class UndeclaredThrowableException extends RuntimeException { + static final long serialVersionUID = 330127114055056639L; + + /** + * the undeclared checked exception that was thrown + * @serial + */ + private Throwable undeclaredThrowable; + + /** + * Constructs an {@code UndeclaredThrowableException} with the + * specified {@code Throwable}. + * + * @param undeclaredThrowable the undeclared checked exception + * that was thrown + */ + public UndeclaredThrowableException(Throwable undeclaredThrowable) { + super((Throwable) null); // Disallow initCause + this.undeclaredThrowable = undeclaredThrowable; + } + + /** + * Constructs an {@code UndeclaredThrowableException} with the + * specified {@code Throwable} and a detail message. + * + * @param undeclaredThrowable the undeclared checked exception + * that was thrown + * @param s the detail message + */ + public UndeclaredThrowableException(Throwable undeclaredThrowable, + String s) + { + super(s, null); // Disallow initCause + this.undeclaredThrowable = undeclaredThrowable; + } + + /** + * Returns the {@code Throwable} instance wrapped in this + * {@code UndeclaredThrowableException}, which may be {@code null}. + * + *

This method predates the general-purpose exception chaining facility. + * The {@link Throwable#getCause()} method is now the preferred means of + * obtaining this information. + * + * @return the undeclared checked exception that was thrown + */ + public Throwable getUndeclaredThrowable() { + return undeclaredThrowable; + } + + /** + * Returns the cause of this exception (the {@code Throwable} + * instance wrapped in this {@code UndeclaredThrowableException}, + * which may be {@code null}). + * + * @return the cause of this exception. + * @since 1.4 + */ + public Throwable getCause() { + return undeclaredThrowable; + } + + // DIFFBLUE MODEL LIBRARY + // While Object.getClass() is not modelled, we can get the same + // functionality by adding one toString() method per subclass of + // Throwable. + @Override + public String toString() { + String message = getLocalizedMessage(); + return (message != null) + ? ("java.lang.reflect.UndeclaredThrowableException: " + message) + : "java.lang.reflect.UndeclaredThrowableException"; + } +} diff --git a/src/main/java/java/util/Random.java b/src/main/java/java/util/Random.java index 49a5597..ead9e2c 100644 --- a/src/main/java/java/util/Random.java +++ b/src/main/java/java/util/Random.java @@ -186,14 +186,13 @@ public Random(long seed) { * * @param seed the initial seed * - * @diffblue.noSupport - * Due to TG-2435.
+ * @diffblue.mock + * @diffblue.limitedSupport * We currently ignore seeds and make test-generator pick return values * for the methods in this class nondeterministically rather than * calculating them according to a probability distribution. So this * method is simply modelled as a no-op. * - * @diffblue.mock */ synchronized public void setSeed(long seed) { // this.seed.set(initialScramble(seed)); @@ -258,14 +257,9 @@ protected int next(int bits) { * @throws NullPointerException if the byte array is null * @since 1.1 * - * @diffblue.noSupport - * Due to TG-2435.
- * This method sets each entry of the argument to a nondeterministic - * {@code byte} value. - * The nondeterminism is introduced by test-generator itself, and - * probability distributions are ignored. - * * @diffblue.mock + * @diffblue.limitedSupport + * */ public void nextBytes(byte[] bytes) { // for (int i = 0, len = bytes.length; i < len; ) @@ -273,7 +267,6 @@ public void nextBytes(byte[] bytes) { // n = Math.min(len - i, Integer.SIZE/Byte.SIZE); // n-- > 0; rnd >>= Byte.SIZE) // bytes[i++] = (byte)rnd; - for (int i = 0; i < bytes.length; i++) { byte b = CProver.nondetByte(); bytes[i] = b; diff --git a/src/main/java/java/util/regex/Pattern.java b/src/main/java/java/util/regex/Pattern.java index 931bcf9..ae980dd 100644 --- a/src/main/java/java/util/regex/Pattern.java +++ b/src/main/java/java/util/regex/Pattern.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ package java.util.regex; import org.cprover.CProver; +import org.cprover.CProverString; import java.text.Normalizer; import java.util.Locale; @@ -937,8 +938,7 @@ public final class Pattern * * @serial */ - // DIFFBLUE MODEL LIBRARY - not used in model - // private String pattern; + private String pattern; /** * The original pattern flags. @@ -1046,13 +1046,13 @@ public final class Pattern * @throws PatternSyntaxException * If the expression's syntax is invalid * - * @diffblue.untested - * @diffblue.noSupport + * @diffblue.limitedSupport + * PatternSyntaxException is not thrown by the model, we only assume that + * the first character is not a '?' character. This should be sufficient + * for most cases, as `compile` is often used with String constants. */ public static Pattern compile(String regex) { - // return new Pattern(regex, 0); - CProver.notModelled(); - return CProver.nondetWithoutNullForNotModelled(); + return new Pattern(regex, 0); } /** @@ -1078,12 +1078,15 @@ public static Pattern compile(String regex) { * If the expression's syntax is invalid * * @diffblue.untested - * @diffblue.noSupport + * @diffblue.limitedSupport + * Argument `flags` is ignored. + * PatternSyntaxException is not thrown by the model, we only assume that + * the first character is not a '?' character. This should be sufficient + * for most cases, as `compile` is often used with String constants. + */ public static Pattern compile(String regex, int flags) { - // return new Pattern(regex, flags); - CProver.notModelled(); - return CProver.nondetWithoutNullForNotModelled(); + return new Pattern(regex, flags); } /** @@ -1091,13 +1094,10 @@ public static Pattern compile(String regex, int flags) { * * @return The source of this pattern * - * @diffblue.untested - * @diffblue.noSupport + * @diffblue.fullSupport */ public String pattern() { - // return pattern; - CProver.notModelled(); - return CProver.nondetWithoutNullForNotModelled(); + return pattern; } /** @@ -1108,13 +1108,10 @@ public String pattern() { * @return The string representation of this pattern * @since 1.5 * - * @diffblue.untested - * @diffblue.noSupport + * @diffblue.fullSupport */ public String toString() { - // return pattern; - CProver.notModelled(); - return CProver.nondetWithoutNullForNotModelled(); + return pattern; } /** @@ -1151,10 +1148,34 @@ public Matcher matcher(CharSequence input) { */ public int flags() { // return flags; - CProver.notModelled(); return CProver.nondetInt(); } + /** + * DIFFBLUE MODEL LIBRARY + * This method enforces an assumption that its argument contains + * no characters that has special meaning in regular expressions. + * This way we can then match the regex using String.equals(). + */ + private static void cproverAssumeIsPlainString(String regex) + { + CProver.assume( + regex.indexOf('[') == -1 && + regex.indexOf(']') == -1 && + regex.indexOf('{') == -1 && + regex.indexOf('}') == -1 && + regex.indexOf('(') == -1 && + regex.indexOf(')') == -1 && + regex.indexOf('?') == -1 && + regex.indexOf('.') == -1 && + regex.indexOf('+') == -1 && + regex.indexOf('\\') == -1 && + regex.indexOf('*') == -1 && + regex.indexOf('^') == -1 && + regex.indexOf('$') == -1 && + regex.indexOf('|') == -1); + } + /** * Compiles the given regular expression and attempts to match the given * input against it. @@ -1182,14 +1203,21 @@ public int flags() { * If the expression's syntax is invalid * * @diffblue.untested - * @diffblue.noSupport + * @diffblue.limitedSupport Regex can only be a plain string. */ public static boolean matches(String regex, CharSequence input) { // Pattern p = Pattern.compile(regex); // Matcher m = p.matcher(input); // return m.matches(); - CProver.notModelled(); - return CProver.nondetBoolean(); + + // DIFFBLUE MODEL LIBRARY + // We disallow special characters so that we can do matching using equals. + cproverAssumeIsPlainString(regex); + // + if (input == null) { + throw new NullPointerException(); // JDK throws NPE when the 2nd param is null + } + return regex.equals(input); } /** @@ -1377,4 +1405,4705 @@ public static String quote(String s) { CProver.notModelled(); return CProver.nondetWithoutNullForNotModelled(); } + + /** + * Recompile the Pattern instance from a stream. The original pattern + * string is read in and the object tree is recompiled from it. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private void readObject(java.io.ObjectInputStream s) + // throws java.io.IOException, ClassNotFoundException { + + // // Read in all fields + // s.defaultReadObject(); + + // // Initialize counts + // capturingGroupCount = 1; + // localCount = 0; + + // // if length > 0, the Pattern is lazily compiled + // compiled = false; + // if (pattern.length() == 0) { + // root = new Start(lastAccept); + // matchRoot = lastAccept; + // compiled = true; + // } + // } + + /** + * This private constructor is used to create all Patterns. The pattern + * string and match flags are all that is needed to completely describe + * a Pattern. An empty pattern string results in an object tree with + * only a Start node and a LastNode node. + */ + // DIFFBLUE MODEL LIBRARY - argument `f` is ignored for now but kept + // to stay closer to the original implementation + private Pattern(String p, int f) { + // DIFFBLUE MODEL LIBRARY + // We disallow special characters so that we can use equals for matching. + cproverAssumeIsPlainString(p); + pattern = p; + // pattern = p; + // flags = f; + + // // to use UNICODE_CASE if UNICODE_CHARACTER_CLASS present + // if ((flags & UNICODE_CHARACTER_CLASS) != 0) + // flags |= UNICODE_CASE; + + // // Reset group index count + // capturingGroupCount = 1; + // localCount = 0; + + // if (pattern.length() > 0) { + // compile(); + // } else { + // root = new Start(lastAccept); + // matchRoot = lastAccept; + // } + } + + /** + * The pattern is converted to normalizedD form and then a pure group + * is constructed to match canonical equivalences of the characters. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private void normalize() { + // boolean inCharClass = false; + // int lastCodePoint = -1; + + // // Convert pattern into normalizedD form + // normalizedPattern = Normalizer.normalize(pattern, Normalizer.Form.NFD); + // patternLength = normalizedPattern.length(); + + // // Modify pattern to match canonical equivalences + // StringBuilder newPattern = new StringBuilder(patternLength); + // for(int i=0; i= patternLength) + // break; + // c = normalizedPattern.codePointAt(i); + // sequenceBuffer.appendCodePoint(c); + // } + // String ea = produceEquivalentAlternation( + // sequenceBuffer.toString()); + // newPattern.setLength(newPattern.length()-Character.charCount(lastCodePoint)); + // newPattern.append("(?:").append(ea).append(")"); + // } else if (c == '[' && lastCodePoint != '\\') { + // i = normalizeCharClass(newPattern, i); + // } else { + // newPattern.appendCodePoint(c); + // } + // lastCodePoint = c; + // i += Character.charCount(c); + // } + // normalizedPattern = newPattern.toString(); + // } + + /** + * Complete the character class being parsed and add a set + * of alternations to it that will match the canonical equivalences + * of the characters within the class. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private int normalizeCharClass(StringBuilder newPattern, int i) { + // StringBuilder charClass = new StringBuilder(); + // StringBuilder eq = null; + // int lastCodePoint = -1; + // String result; + + // i++; + // charClass.append("["); + // while(true) { + // int c = normalizedPattern.codePointAt(i); + // StringBuilder sequenceBuffer; + + // if (c == ']' && lastCodePoint != '\\') { + // charClass.append((char)c); + // break; + // } else if (Character.getType(c) == Character.NON_SPACING_MARK) { + // sequenceBuffer = new StringBuilder(); + // sequenceBuffer.appendCodePoint(lastCodePoint); + // while(Character.getType(c) == Character.NON_SPACING_MARK) { + // sequenceBuffer.appendCodePoint(c); + // i += Character.charCount(c); + // if (i >= normalizedPattern.length()) + // break; + // c = normalizedPattern.codePointAt(i); + // } + // String ea = produceEquivalentAlternation( + // sequenceBuffer.toString()); + + // charClass.setLength(charClass.length()-Character.charCount(lastCodePoint)); + // if (eq == null) + // eq = new StringBuilder(); + // eq.append('|'); + // eq.append(ea); + // } else { + // charClass.appendCodePoint(c); + // i++; + // } + // if (i == normalizedPattern.length()) + // throw error("Unclosed character class"); + // lastCodePoint = c; + // } + + // if (eq != null) { + // result = "(?:"+charClass.toString()+eq.toString()+")"; + // } else { + // result = charClass.toString(); + // } + + // newPattern.append(result); + // return i; + // } + + /** + * Given a specific sequence composed of a regular character and + * combining marks that follow it, produce the alternation that will + * match all canonical equivalences of that sequence. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private String produceEquivalentAlternation(String source) { + // int len = countChars(source, 0, 1); + // if (source.length() == len) + // // source has one character. + // return source; + + // String base = source.substring(0,len); + // String combiningMarks = source.substring(len); + + // String[] perms = producePermutations(combiningMarks); + // StringBuilder result = new StringBuilder(source); + + // // Add combined permutations + // for(int x=0; x0) + // result.append("|"+next); + // next = composeOneStep(next); + // if (next != null) + // result.append("|"+produceEquivalentAlternation(next)); + // } + // return result.toString(); + // } + + /** + * Returns an array of strings that have all the possible + * permutations of the characters in the input string. + * This is used to get a list of all possible orderings + * of a set of combining marks. Note that some of the permutations + * are invalid because of combining class collisions, and these + * possibilities must be removed because they are not canonically + * equivalent. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private String[] producePermutations(String input) { + // if (input.length() == countChars(input, 0, 1)) + // return new String[] {input}; + + // if (input.length() == countChars(input, 0, 2)) { + // int c0 = Character.codePointAt(input, 0); + // int c1 = Character.codePointAt(input, Character.charCount(c0)); + // if (getClass(c1) == getClass(c0)) { + // return new String[] {input}; + // } + // String[] result = new String[2]; + // result[0] = input; + // StringBuilder sb = new StringBuilder(2); + // sb.appendCodePoint(c1); + // sb.appendCodePoint(c0); + // result[1] = sb.toString(); + // return result; + // } + + // int length = 1; + // int nCodePoints = countCodePoints(input); + // for(int x=1; x=0; y--) { + // if (combClass[y] == combClass[x]) { + // continue loop; + // } + // } + // StringBuilder sb = new StringBuilder(input); + // String otherChars = sb.delete(offset, offset+len).toString(); + // String[] subResult = producePermutations(otherChars); + + // String prefix = input.substring(offset, offset+len); + // for(int y=0; y= pLen - 1) // No \Q sequence found + // return; + // int j = i; + // i += 2; + // int[] newtemp = new int[j + 3*(pLen-i) + 2]; + // System.arraycopy(temp, 0, newtemp, 0, j); + + // boolean inQuote = true; + // boolean beginQuote = true; + // while (i < pLen) { + // int c = temp[i++]; + // if (!ASCII.isAscii(c) || ASCII.isAlpha(c)) { + // newtemp[j++] = c; + // } else if (ASCII.isDigit(c)) { + // if (beginQuote) { + // /* + // * A unicode escape \[0xu] could be before this quote, + // * and we don't want this numeric char to processed as + // * part of the escape. + // */ + // newtemp[j++] = '\\'; + // newtemp[j++] = 'x'; + // newtemp[j++] = '3'; + // } + // newtemp[j++] = c; + // } else if (c != '\\') { + // if (inQuote) newtemp[j++] = '\\'; + // newtemp[j++] = c; + // } else if (inQuote) { + // if (temp[i] == 'E') { + // i++; + // inQuote = false; + // } else { + // newtemp[j++] = '\\'; + // newtemp[j++] = '\\'; + // } + // } else { + // if (temp[i] == 'Q') { + // i++; + // inQuote = true; + // beginQuote = true; + // continue; + // } else { + // newtemp[j++] = c; + // if (i != pLen) + // newtemp[j++] = temp[i++]; + // } + // } + + // beginQuote = false; + // } + + // patternLength = j; + // temp = Arrays.copyOf(newtemp, j + 2); // double zero termination + // } + + /** + * Copies regular expression to an int array and invokes the parsing + * of the expression which will create the object tree. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private void compile() { + // // Handle canonical equivalences + // if (has(CANON_EQ) && !has(LITERAL)) { + // normalize(); + // } else { + // normalizedPattern = pattern; + // } + // patternLength = normalizedPattern.length(); + + // // Copy pattern to int array for convenience + // // Use double zero to terminate pattern + // temp = new int[patternLength + 2]; + + // hasSupplementary = false; + // int c, count = 0; + // // Convert all chars into code points + // for (int x = 0; x < patternLength; x += Character.charCount(c)) { + // c = normalizedPattern.codePointAt(x); + // if (isSupplementary(c)) { + // hasSupplementary = true; + // } + // temp[count++] = c; + // } + + // patternLength = count; // patternLength now in code points + + // if (! has(LITERAL)) + // RemoveQEQuoting(); + + // // Allocate all temporary objects here. + // buffer = new int[32]; + // groupNodes = new GroupHead[10]; + // namedGroups = null; + + // if (has(LITERAL)) { + // // Literal pattern handling + // matchRoot = newSlice(temp, patternLength, hasSupplementary); + // matchRoot.next = lastAccept; + // } else { + // // Start recursive descent parsing + // matchRoot = expr(lastAccept); + // // Check extra pattern characters + // if (patternLength != cursor) { + // if (peek() == ')') { + // throw error("Unmatched closing ')'"); + // } else { + // throw error("Unexpected internal error"); + // } + // } + // } + + // // Peephole optimization + // if (matchRoot instanceof Slice) { + // root = BnM.optimize(matchRoot); + // if (root == matchRoot) { + // root = hasSupplementary ? new StartS(matchRoot) : new Start(matchRoot); + // } + // } else if (matchRoot instanceof Begin || matchRoot instanceof First) { + // root = matchRoot; + // } else { + // root = hasSupplementary ? new StartS(matchRoot) : new Start(matchRoot); + // } + + // // Release temporary storage + // temp = null; + // buffer = null; + // groupNodes = null; + // patternLength = 0; + // compiled = true; + // } + + // DIFFBLUE MODEL LIBRARY - not used in model + // Map namedGroups() { + // if (namedGroups == null) + // namedGroups = new HashMap<>(2); + // return namedGroups; + // } + + /** + * Used to print out a subtree of the Pattern to help with debugging. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private static void printObjectTree(Node node) { + // while(node != null) { + // if (node instanceof Prolog) { + // System.out.println(node); + // printObjectTree(((Prolog)node).loop); + // System.out.println("**** end contents prolog loop"); + // } else if (node instanceof Loop) { + // System.out.println(node); + // printObjectTree(((Loop)node).body); + // System.out.println("**** end contents Loop body"); + // } else if (node instanceof Curly) { + // System.out.println(node); + // printObjectTree(((Curly)node).atom); + // System.out.println("**** end contents Curly body"); + // } else if (node instanceof GroupCurly) { + // System.out.println(node); + // printObjectTree(((GroupCurly)node).atom); + // System.out.println("**** end contents GroupCurly body"); + // } else if (node instanceof GroupTail) { + // System.out.println(node); + // System.out.println("Tail next is "+node.next); + // return; + // } else { + // System.out.println(node); + // } + // node = node.next; + // if (node != null) + // System.out.println("->next:"); + // if (node == Pattern.accept) { + // System.out.println("Accept Node"); + // node = null; + // } + // } + // } + + /** + * Used to accumulate information about a subtree of the object graph + * so that optimizations can be applied to the subtree. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static final class TreeInfo { + // int minLength; + // int maxLength; + // boolean maxValid; + // boolean deterministic; + + // TreeInfo() { + // reset(); + // } + // void reset() { + // minLength = 0; + // maxLength = 0; + // maxValid = true; + // deterministic = true; + // } + // } + + /* + * The following private methods are mainly used to improve the + * readability of the code. In order to let the Java compiler easily + * inline them, we should not put many assertions or error checks in them. + */ + + /** + * Indicates whether a particular flag is set or not. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private boolean has(int f) { + // return (flags & f) != 0; + // } + + /** + * Match next character, signal error if failed. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private void accept(int ch, String s) { + // int testChar = temp[cursor++]; + // if (has(COMMENTS)) + // testChar = parsePastWhitespace(testChar); + // if (ch != testChar) { + // throw error(s); + // } + // } + + /** + * Mark the end of pattern with a specific character. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private void mark(int c) { + // temp[patternLength] = c; + // } + + /** + * Peek the next character, and do not advance the cursor. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private int peek() { + // int ch = temp[cursor]; + // if (has(COMMENTS)) + // ch = peekPastWhitespace(ch); + // return ch; + // } + + /** + * Read the next character, and advance the cursor by one. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private int read() { + // int ch = temp[cursor++]; + // if (has(COMMENTS)) + // ch = parsePastWhitespace(ch); + // return ch; + // } + + /** + * Read the next character, and advance the cursor by one, + * ignoring the COMMENTS setting + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private int readEscaped() { + // int ch = temp[cursor++]; + // return ch; + // } + + /** + * Advance the cursor by one, and peek the next character. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private int next() { + // int ch = temp[++cursor]; + // if (has(COMMENTS)) + // ch = peekPastWhitespace(ch); + // return ch; + // } + + /** + * Advance the cursor by one, and peek the next character, + * ignoring the COMMENTS setting + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private int nextEscaped() { + // int ch = temp[++cursor]; + // return ch; + // } + + /** + * If in xmode peek past whitespace and comments. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private int peekPastWhitespace(int ch) { + // while (ASCII.isSpace(ch) || ch == '#') { + // while (ASCII.isSpace(ch)) + // ch = temp[++cursor]; + // if (ch == '#') { + // ch = peekPastLine(); + // } + // } + // return ch; + // } + + /** + * If in xmode parse past whitespace and comments. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private int parsePastWhitespace(int ch) { + // while (ASCII.isSpace(ch) || ch == '#') { + // while (ASCII.isSpace(ch)) + // ch = temp[cursor++]; + // if (ch == '#') + // ch = parsePastLine(); + // } + // return ch; + // } + + /** + * xmode parse past comment to end of line. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private int parsePastLine() { + // int ch = temp[cursor++]; + // while (ch != 0 && !isLineSeparator(ch)) + // ch = temp[cursor++]; + // return ch; + // } + + /** + * xmode peek past comment to end of line. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private int peekPastLine() { + // int ch = temp[++cursor]; + // while (ch != 0 && !isLineSeparator(ch)) + // ch = temp[++cursor]; + // return ch; + // } + + /** + * Determines if character is a line separator in the current mode + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private boolean isLineSeparator(int ch) { + // if (has(UNIX_LINES)) { + // return ch == '\n'; + // } else { + // return (ch == '\n' || + // ch == '\r' || + // (ch|1) == '\u2029' || + // ch == '\u0085'); + // } + // } + + /** + * Read the character after the next one, and advance the cursor by two. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private int skip() { + // int i = cursor; + // int ch = temp[i+1]; + // cursor = i + 2; + // return ch; + // } + + /** + * Unread one next character, and retreat cursor by one. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private void unread() { + // cursor--; + // } + + /** + * Internal method used for handling all syntax errors. The pattern is + * displayed with a pointer to aid in locating the syntax error. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private PatternSyntaxException error(String s) { + // return new PatternSyntaxException(s, normalizedPattern, cursor - 1); + // } + + /** + * Determines if there is any supplementary character or unpaired + * surrogate in the specified range. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private boolean findSupplementary(int start, int end) { + // for (int i = start; i < end; i++) { + // if (isSupplementary(temp[i])) + // return true; + // } + // return false; + // } + + /** + * Determines if the specified code point is a supplementary + * character or unpaired surrogate. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private static final boolean isSupplementary(int ch) { + // return ch >= Character.MIN_SUPPLEMENTARY_CODE_POINT || + // Character.isSurrogate((char)ch); + // } + + /** + * The following methods handle the main parsing. They are sorted + * according to their precedence order, the lowest one first. + */ + + /** + * The expression is parsed with branch nodes added for alternations. + * This may be called recursively to parse sub expressions that may + * contain alternations. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private Node expr(Node end) { + // Node prev = null; + // Node firstTail = null; + // Branch branch = null; + // Node branchConn = null; + + // for (;;) { + // Node node = sequence(end); + // Node nodeTail = root; //double return + // if (prev == null) { + // prev = node; + // firstTail = nodeTail; + // } else { + // // Branch + // if (branchConn == null) { + // branchConn = new BranchConn(); + // branchConn.next = end; + // } + // if (node == end) { + // // if the node returned from sequence() is "end" + // // we have an empty expr, set a null atom into + // // the branch to indicate to go "next" directly. + // node = null; + // } else { + // // the "tail.next" of each atom goes to branchConn + // nodeTail.next = branchConn; + // } + // if (prev == branch) { + // branch.add(node); + // } else { + // if (prev == end) { + // prev = null; + // } else { + // // replace the "end" with "branchConn" at its tail.next + // // when put the "prev" into the branch as the first atom. + // firstTail.next = branchConn; + // } + // prev = branch = new Branch(prev, node, branchConn); + // } + // } + // if (peek() != '|') { + // return prev; + // } + // next(); + // } + // } + + /** + * Parsing of sequences between alternations. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // @SuppressWarnings("fallthrough") + // private Node sequence(Node end) { + // Node head = null; + // Node tail = null; + // Node node = null; +// LOOP: + // for (;;) { + // int ch = peek(); + // switch (ch) { + // case '(': + // // Because group handles its own closure, + // // we need to treat it differently + // node = group0(); + // // Check for comment or flag group + // if (node == null) + // continue; + // if (head == null) + // head = node; + // else + // tail.next = node; + // // Double return: Tail was returned in root + // tail = root; + // continue; + // case '[': + // node = clazz(true); + // break; + // case '\\': + // ch = nextEscaped(); + // if (ch == 'p' || ch == 'P') { + // boolean oneLetter = true; + // boolean comp = (ch == 'P'); + // ch = next(); // Consume { if present + // if (ch != '{') { + // unread(); + // } else { + // oneLetter = false; + // } + // node = family(oneLetter, comp); + // } else { + // unread(); + // node = atom(); + // } + // break; + // case '^': + // next(); + // if (has(MULTILINE)) { + // if (has(UNIX_LINES)) + // node = new UnixCaret(); + // else + // node = new Caret(); + // } else { + // node = new Begin(); + // } + // break; + // case '$': + // next(); + // if (has(UNIX_LINES)) + // node = new UnixDollar(has(MULTILINE)); + // else + // node = new Dollar(has(MULTILINE)); + // break; + // case '.': + // next(); + // if (has(DOTALL)) { + // node = new All(); + // } else { + // if (has(UNIX_LINES)) + // node = new UnixDot(); + // else { + // node = new Dot(); + // } + // } + // break; + // case '|': + // case ')': + // break LOOP; + // case ']': // Now interpreting dangling ] and } as literals + // case '}': + // node = atom(); + // break; + // case '?': + // case '*': + // case '+': + // next(); + // throw error("Dangling meta character '" + ((char)ch) + "'"); + // case 0: + // if (cursor >= patternLength) { + // break LOOP; + // } + // // Fall through + // default: + // node = atom(); + // break; + // } + + // node = closure(node); + + // if (head == null) { + // head = tail = node; + // } else { + // tail.next = node; + // tail = node; + // } + // } + // if (head == null) { + // return end; + // } + // tail.next = end; + // root = tail; //double return + // return head; + // } + + /** + * Parse and add a new Single or Slice. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // @SuppressWarnings("fallthrough") + // private Node atom() { + // int first = 0; + // int prev = -1; + // boolean hasSupplementary = false; + // int ch = peek(); + // for (;;) { + // switch (ch) { + // case '*': + // case '+': + // case '?': + // case '{': + // if (first > 1) { + // cursor = prev; // Unwind one character + // first--; + // } + // break; + // case '$': + // case '.': + // case '^': + // case '(': + // case '[': + // case '|': + // case ')': + // break; + // case '\\': + // ch = nextEscaped(); + // if (ch == 'p' || ch == 'P') { // Property + // if (first > 0) { // Slice is waiting; handle it first + // unread(); + // break; + // } else { // No slice; just return the family node + // boolean comp = (ch == 'P'); + // boolean oneLetter = true; + // ch = next(); // Consume { if present + // if (ch != '{') + // unread(); + // else + // oneLetter = false; + // return family(oneLetter, comp); + // } + // } + // unread(); + // prev = cursor; + // ch = escape(false, first == 0, false); + // if (ch >= 0) { + // append(ch, first); + // first++; + // if (isSupplementary(ch)) { + // hasSupplementary = true; + // } + // ch = peek(); + // continue; + // } else if (first == 0) { + // return root; + // } + // // Unwind meta escape sequence + // cursor = prev; + // break; + // case 0: + // if (cursor >= patternLength) { + // break; + // } + // // Fall through + // default: + // prev = cursor; + // append(ch, first); + // first++; + // if (isSupplementary(ch)) { + // hasSupplementary = true; + // } + // ch = next(); + // continue; + // } + // break; + // } + // if (first == 1) { + // return newSingle(buffer[0]); + // } else { + // return newSlice(buffer, first, hasSupplementary); + // } + // } + + // DIFFBLUE MODEL LIBRARY - not used in model + // private void append(int ch, int len) { + // if (len >= buffer.length) { + // int[] tmp = new int[len+len]; + // System.arraycopy(buffer, 0, tmp, 0, len); + // buffer = tmp; + // } + // buffer[len] = ch; + // } + + /** + * Parses a backref greedily, taking as many numbers as it + * can. The first digit is always treated as a backref, but + * multi digit numbers are only treated as a backref if at + * least that many backrefs exist at this point in the regex. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private Node ref(int refNum) { + // boolean done = false; + // while(!done) { + // int ch = peek(); + // switch(ch) { + // case '0': + // case '1': + // case '2': + // case '3': + // case '4': + // case '5': + // case '6': + // case '7': + // case '8': + // case '9': + // int newRefNum = (refNum * 10) + (ch - '0'); + // // Add another number if it doesn't make a group + // // that doesn't exist + // if (capturingGroupCount - 1 < newRefNum) { + // done = true; + // break; + // } + // refNum = newRefNum; + // read(); + // break; + // default: + // done = true; + // break; + // } + // } + // if (has(CASE_INSENSITIVE)) + // return new CIBackRef(refNum, has(UNICODE_CASE)); + // else + // return new BackRef(refNum); + // } + + /** + * Parses an escape sequence to determine the actual value that needs + * to be matched. + * If -1 is returned and create was true a new object was added to the tree + * to handle the escape sequence. + * If the returned value is greater than zero, it is the value that + * matches the escape sequence. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private int escape(boolean inclass, boolean create, boolean isrange) { + // int ch = skip(); + // switch (ch) { + // case '0': + // return o(); + // case '1': + // case '2': + // case '3': + // case '4': + // case '5': + // case '6': + // case '7': + // case '8': + // case '9': + // if (inclass) break; + // if (create) { + // root = ref((ch - '0')); + // } + // return -1; + // case 'A': + // if (inclass) break; + // if (create) root = new Begin(); + // return -1; + // case 'B': + // if (inclass) break; + // if (create) root = new Bound(Bound.NONE, has(UNICODE_CHARACTER_CLASS)); + // return -1; + // case 'C': + // break; + // case 'D': + // if (create) root = has(UNICODE_CHARACTER_CLASS) + // ? new Utype(UnicodeProp.DIGIT).complement() + // : new Ctype(ASCII.DIGIT).complement(); + // return -1; + // case 'E': + // case 'F': + // break; + // case 'G': + // if (inclass) break; + // if (create) root = new LastMatch(); + // return -1; + // case 'H': + // if (create) root = new HorizWS().complement(); + // return -1; + // case 'I': + // case 'J': + // case 'K': + // case 'L': + // case 'M': + // case 'N': + // case 'O': + // case 'P': + // case 'Q': + // break; + // case 'R': + // if (inclass) break; + // if (create) root = new LineEnding(); + // return -1; + // case 'S': + // if (create) root = has(UNICODE_CHARACTER_CLASS) + // ? new Utype(UnicodeProp.WHITE_SPACE).complement() + // : new Ctype(ASCII.SPACE).complement(); + // return -1; + // case 'T': + // case 'U': + // break; + // case 'V': + // if (create) root = new VertWS().complement(); + // return -1; + // case 'W': + // if (create) root = has(UNICODE_CHARACTER_CLASS) + // ? new Utype(UnicodeProp.WORD).complement() + // : new Ctype(ASCII.WORD).complement(); + // return -1; + // case 'X': + // case 'Y': + // break; + // case 'Z': + // if (inclass) break; + // if (create) { + // if (has(UNIX_LINES)) + // root = new UnixDollar(false); + // else + // root = new Dollar(false); + // } + // return -1; + // case 'a': + // return '\007'; + // case 'b': + // if (inclass) break; + // if (create) root = new Bound(Bound.BOTH, has(UNICODE_CHARACTER_CLASS)); + // return -1; + // case 'c': + // return c(); + // case 'd': + // if (create) root = has(UNICODE_CHARACTER_CLASS) + // ? new Utype(UnicodeProp.DIGIT) + // : new Ctype(ASCII.DIGIT); + // return -1; + // case 'e': + // return '\033'; + // case 'f': + // return '\f'; + // case 'g': + // break; + // case 'h': + // if (create) root = new HorizWS(); + // return -1; + // case 'i': + // case 'j': + // break; + // case 'k': + // if (inclass) + // break; + // if (read() != '<') + // throw error("\\k is not followed by '<' for named capturing group"); + // String name = groupname(read()); + // if (!namedGroups().containsKey(name)) + // throw error("(named capturing group <"+ name+"> does not exit"); + // if (create) { + // if (has(CASE_INSENSITIVE)) + // root = new CIBackRef(namedGroups().get(name), has(UNICODE_CASE)); + // else + // root = new BackRef(namedGroups().get(name)); + // } + // return -1; + // case 'l': + // case 'm': + // break; + // case 'n': + // return '\n'; + // case 'o': + // case 'p': + // case 'q': + // break; + // case 'r': + // return '\r'; + // case 's': + // if (create) root = has(UNICODE_CHARACTER_CLASS) + // ? new Utype(UnicodeProp.WHITE_SPACE) + // : new Ctype(ASCII.SPACE); + // return -1; + // case 't': + // return '\t'; + // case 'u': + // return u(); + // case 'v': + // // '\v' was implemented as VT/0x0B in releases < 1.8 (though + // // undocumented). In JDK8 '\v' is specified as a predefined + // // character class for all vertical whitespace characters. + // // So [-1, root=VertWS node] pair is returned (instead of a + // // single 0x0B). This breaks the range if '\v' is used as + // // the start or end value, such as [\v-...] or [...-\v], in + // // which a single definite value (0x0B) is expected. For + // // compatibility concern '\013'/0x0B is returned if isrange. + // if (isrange) + // return '\013'; + // if (create) root = new VertWS(); + // return -1; + // case 'w': + // if (create) root = has(UNICODE_CHARACTER_CLASS) + // ? new Utype(UnicodeProp.WORD) + // : new Ctype(ASCII.WORD); + // return -1; + // case 'x': + // return x(); + // case 'y': + // break; + // case 'z': + // if (inclass) break; + // if (create) root = new End(); + // return -1; + // default: + // return ch; + // } + // throw error("Illegal/unsupported escape sequence"); + // } + + /** + * Parse a character class, and return the node that matches it. + * + * Consumes a ] on the way out if consume is true. Usually consume + * is true except for the case of [abc&&def] where def is a separate + * right hand node with "understood" brackets. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private CharProperty clazz(boolean consume) { + // CharProperty prev = null; + // CharProperty node = null; + // BitClass bits = new BitClass(); + // boolean include = true; + // boolean firstInClass = true; + // int ch = next(); + // for (;;) { + // switch (ch) { + // case '^': + // // Negates if first char in a class, otherwise literal + // if (firstInClass) { + // if (temp[cursor-1] != '[') + // break; + // ch = next(); + // include = !include; + // continue; + // } else { + // // ^ not first in class, treat as literal + // break; + // } + // case '[': + // firstInClass = false; + // node = clazz(true); + // if (prev == null) + // prev = node; + // else + // prev = union(prev, node); + // ch = peek(); + // continue; + // case '&': + // firstInClass = false; + // ch = next(); + // if (ch == '&') { + // ch = next(); + // CharProperty rightNode = null; + // while (ch != ']' && ch != '&') { + // if (ch == '[') { + // if (rightNode == null) + // rightNode = clazz(true); + // else + // rightNode = union(rightNode, clazz(true)); + // } else { // abc&&def + // unread(); + // rightNode = clazz(false); + // } + // ch = peek(); + // } + // if (rightNode != null) + // node = rightNode; + // if (prev == null) { + // if (rightNode == null) + // throw error("Bad class syntax"); + // else + // prev = rightNode; + // } else { + // prev = intersection(prev, node); + // } + // } else { + // // treat as a literal & + // unread(); + // break; + // } + // continue; + // case 0: + // firstInClass = false; + // if (cursor >= patternLength) + // throw error("Unclosed character class"); + // break; + // case ']': + // firstInClass = false; + // if (prev != null) { + // if (consume) + // next(); + // return prev; + // } + // break; + // default: + // firstInClass = false; + // break; + // } + // node = range(bits); + // if (include) { + // if (prev == null) { + // prev = node; + // } else { + // if (prev != node) + // prev = union(prev, node); + // } + // } else { + // if (prev == null) { + // prev = node.complement(); + // } else { + // if (prev != node) + // prev = setDifference(prev, node); + // } + // } + // ch = peek(); + // } + // } + + // DIFFBLUE MODEL LIBRARY - not used in model + // private CharProperty bitsOrSingle(BitClass bits, int ch) { + // /* Bits can only handle codepoints in [u+0000-u+00ff] range. + // Use "single" node instead of bits when dealing with unicode + // case folding for codepoints listed below. + // (1)Uppercase out of range: u+00ff, u+00b5 + // toUpperCase(u+00ff) -> u+0178 + // toUpperCase(u+00b5) -> u+039c + // (2)LatinSmallLetterLongS u+17f + // toUpperCase(u+017f) -> u+0053 + // (3)LatinSmallLetterDotlessI u+131 + // toUpperCase(u+0131) -> u+0049 + // (4)LatinCapitalLetterIWithDotAbove u+0130 + // toLowerCase(u+0130) -> u+0069 + // (5)KelvinSign u+212a + // toLowerCase(u+212a) ==> u+006B + // (6)AngstromSign u+212b + // toLowerCase(u+212b) ==> u+00e5 + // */ + // int d; + // if (ch < 256 && + // !(has(CASE_INSENSITIVE) && has(UNICODE_CASE) && + // (ch == 0xff || ch == 0xb5 || + // ch == 0x49 || ch == 0x69 || //I and i + // ch == 0x53 || ch == 0x73 || //S and s + // ch == 0x4b || ch == 0x6b || //K and k + // ch == 0xc5 || ch == 0xe5))) //A+ring + // return bits.add(ch, flags()); + // return newSingle(ch); + // } + + /** + * Parse a single character or a character range in a character class + * and return its representative node. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private CharProperty range(BitClass bits) { + // int ch = peek(); + // if (ch == '\\') { + // ch = nextEscaped(); + // if (ch == 'p' || ch == 'P') { // A property + // boolean comp = (ch == 'P'); + // boolean oneLetter = true; + // // Consume { if present + // ch = next(); + // if (ch != '{') + // unread(); + // else + // oneLetter = false; + // return family(oneLetter, comp); + // } else { // ordinary escape + // boolean isrange = temp[cursor+1] == '-'; + // unread(); + // ch = escape(true, true, isrange); + // if (ch == -1) + // return (CharProperty) root; + // } + // } else { + // next(); + // } + // if (ch >= 0) { + // if (peek() == '-') { + // int endRange = temp[cursor+1]; + // if (endRange == '[') { + // return bitsOrSingle(bits, ch); + // } + // if (endRange != ']') { + // next(); + // int m = peek(); + // if (m == '\\') { + // m = escape(true, false, true); + // } else { + // next(); + // } + // if (m < ch) { + // throw error("Illegal character range"); + // } + // if (has(CASE_INSENSITIVE)) + // return caseInsensitiveRangeFor(ch, m); + // else + // return rangeFor(ch, m); + // } + // } + // return bitsOrSingle(bits, ch); + // } + // throw error("Unexpected character '"+((char)ch)+"'"); + // } + + /** + * Parses a Unicode character family and returns its representative node. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private CharProperty family(boolean singleLetter, + // boolean maybeComplement) + // { + // next(); + // String name; + // CharProperty node = null; + + // if (singleLetter) { + // int c = temp[cursor]; + // if (!Character.isSupplementaryCodePoint(c)) { + // name = String.valueOf((char)c); + // } else { + // name = new String(temp, cursor, 1); + // } + // read(); + // } else { + // int i = cursor; + // mark('}'); + // while(read() != '}') { + // } + // mark('\000'); + // int j = cursor; + // if (j > patternLength) + // throw error("Unclosed character family"); + // if (i + 1 >= j) + // throw error("Empty character family"); + // name = new String(temp, i, j-i-1); + // } + + // int i = name.indexOf('='); + // if (i != -1) { + // // property construct \p{name=value} + // String value = name.substring(i + 1); + // name = name.substring(0, i).toLowerCase(Locale.ENGLISH); + // if ("sc".equals(name) || "script".equals(name)) { + // node = unicodeScriptPropertyFor(value); + // } else if ("blk".equals(name) || "block".equals(name)) { + // node = unicodeBlockPropertyFor(value); + // } else if ("gc".equals(name) || "general_category".equals(name)) { + // node = charPropertyNodeFor(value); + // } else { + // throw error("Unknown Unicode property {name=<" + name + ">, " + // + "value=<" + value + ">}"); + // } + // } else { + // if (name.startsWith("In")) { + // // \p{inBlockName} + // node = unicodeBlockPropertyFor(name.substring(2)); + // } else if (name.startsWith("Is")) { + // // \p{isGeneralCategory} and \p{isScriptName} + // name = name.substring(2); + // UnicodeProp uprop = UnicodeProp.forName(name); + // if (uprop != null) + // node = new Utype(uprop); + // if (node == null) + // node = CharPropertyNames.charPropertyFor(name); + // if (node == null) + // node = unicodeScriptPropertyFor(name); + // } else { + // if (has(UNICODE_CHARACTER_CLASS)) { + // UnicodeProp uprop = UnicodeProp.forPOSIXName(name); + // if (uprop != null) + // node = new Utype(uprop); + // } + // if (node == null) + // node = charPropertyNodeFor(name); + // } + // } + // if (maybeComplement) { + // if (node instanceof Category || node instanceof Block) + // hasSupplementary = true; + // node = node.complement(); + // } + // return node; + // } + + + /** + * Returns a CharProperty matching all characters belong to + * a UnicodeScript. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private CharProperty unicodeScriptPropertyFor(String name) { + // final Character.UnicodeScript script; + // try { + // script = Character.UnicodeScript.forName(name); + // } catch (IllegalArgumentException iae) { + // throw error("Unknown character script name {" + name + "}"); + // } + // return new Script(script); + // } + + /** + * Returns a CharProperty matching all characters in a UnicodeBlock. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private CharProperty unicodeBlockPropertyFor(String name) { + // final Character.UnicodeBlock block; + // try { + // block = Character.UnicodeBlock.forName(name); + // } catch (IllegalArgumentException iae) { + // throw error("Unknown character block name {" + name + "}"); + // } + // return new Block(block); + // } + + /** + * Returns a CharProperty matching all characters in a named property. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private CharProperty charPropertyNodeFor(String name) { + // CharProperty p = CharPropertyNames.charPropertyFor(name); + // if (p == null) + // throw error("Unknown character property name {" + name + "}"); + // return p; + // } + + /** + * Parses and returns the name of a "named capturing group", the trailing + * ">" is consumed after parsing. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private String groupname(int ch) { + // StringBuilder sb = new StringBuilder(); + // sb.append(Character.toChars(ch)); + // while (ASCII.isLower(ch=read()) || ASCII.isUpper(ch) || + // ASCII.isDigit(ch)) { + // sb.append(Character.toChars(ch)); + // } + // if (sb.length() == 0) + // throw error("named capturing group has 0 length name"); + // if (ch != '>') + // throw error("named capturing group is missing trailing '>'"); + // return sb.toString(); + // } + + /** + * Parses a group and returns the head node of a set of nodes that process + * the group. Sometimes a double return system is used where the tail is + * returned in root. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private Node group0() { + // boolean capturingGroup = false; + // Node head = null; + // Node tail = null; + // int save = flags; + // root = null; + // int ch = next(); + // if (ch == '?') { + // ch = skip(); + // switch (ch) { + // case ':': // (?:xxx) pure group + // head = createGroup(true); + // tail = root; + // head.next = expr(tail); + // break; + // case '=': // (?=xxx) and (?!xxx) lookahead + // case '!': + // head = createGroup(true); + // tail = root; + // head.next = expr(tail); + // if (ch == '=') { + // head = tail = new Pos(head); + // } else { + // head = tail = new Neg(head); + // } + // break; + // case '>': // (?>xxx) independent group + // head = createGroup(true); + // tail = root; + // head.next = expr(tail); + // head = tail = new Ques(head, INDEPENDENT); + // break; + // case '<': // (? is already defined"); + // capturingGroup = true; + // head = createGroup(false); + // tail = root; + // namedGroups().put(name, capturingGroupCount-1); + // head.next = expr(tail); + // break; + // } + // int start = cursor; + // head = createGroup(true); + // tail = root; + // head.next = expr(tail); + // tail.next = lookbehindEnd; + // TreeInfo info = new TreeInfo(); + // head.study(info); + // if (info.maxValid == false) { + // throw error("Look-behind group does not have " + // + "an obvious maximum length"); + // } + // boolean hasSupplementary = findSupplementary(start, patternLength); + // if (ch == '=') { + // head = tail = (hasSupplementary ? + // new BehindS(head, info.maxLength, + // info.minLength) : + // new Behind(head, info.maxLength, + // info.minLength)); + // } else if (ch == '!') { + // head = tail = (hasSupplementary ? + // new NotBehindS(head, info.maxLength, + // info.minLength) : + // new NotBehind(head, info.maxLength, + // info.minLength)); + // } else { + // throw error("Unknown look-behind group"); + // } + // break; + // case '$': + // case '@': + // throw error("Unknown group type"); + // default: // (?xxx:) inlined match flags + // unread(); + // addFlag(); + // ch = read(); + // if (ch == ')') { + // return null; // Inline modifier only + // } + // if (ch != ':') { + // throw error("Unknown inline modifier"); + // } + // head = createGroup(true); + // tail = root; + // head.next = expr(tail); + // break; + // } + // } else { // (xxx) a regular group + // capturingGroup = true; + // head = createGroup(false); + // tail = root; + // head.next = expr(tail); + // } + + // accept(')', "Unclosed group"); + // flags = save; + + // // Check for quantifiers + // Node node = closure(head); + // if (node == head) { // No closure + // root = tail; + // return node; // Dual return + // } + // if (head == tail) { // Zero length assertion + // root = node; + // return node; // Dual return + // } + + // if (node instanceof Ques) { + // Ques ques = (Ques) node; + // if (ques.type == POSSESSIVE) { + // root = node; + // return node; + // } + // tail.next = new BranchConn(); + // tail = tail.next; + // if (ques.type == GREEDY) { + // head = new Branch(head, null, tail); + // } else { // Reluctant quantifier + // head = new Branch(null, head, tail); + // } + // root = tail; + // return head; + // } else if (node instanceof Curly) { + // Curly curly = (Curly) node; + // if (curly.type == POSSESSIVE) { + // root = node; + // return node; + // } + // // Discover if the group is deterministic + // TreeInfo info = new TreeInfo(); + // if (head.study(info)) { // Deterministic + // GroupTail temp = (GroupTail) tail; + // head = root = new GroupCurly(head.next, curly.cmin, + // curly.cmax, curly.type, + // ((GroupTail)tail).localIndex, + // ((GroupTail)tail).groupIndex, + // capturingGroup); + // return head; + // } else { // Non-deterministic + // int temp = ((GroupHead) head).localIndex; + // Loop loop; + // if (curly.type == GREEDY) + // loop = new Loop(this.localCount, temp); + // else // Reluctant Curly + // loop = new LazyLoop(this.localCount, temp); + // Prolog prolog = new Prolog(loop); + // this.localCount += 1; + // loop.cmin = curly.cmin; + // loop.cmax = curly.cmax; + // loop.body = head; + // tail.next = loop; + // root = loop; + // return prolog; // Dual return + // } + // } + // throw error("Internal logic error"); + // } + + /** + * Create group head and tail nodes using double return. If the group is + * created with anonymous true then it is a pure group and should not + * affect group counting. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private Node createGroup(boolean anonymous) { + // int localIndex = localCount++; + // int groupIndex = 0; + // if (!anonymous) + // groupIndex = capturingGroupCount++; + // GroupHead head = new GroupHead(localIndex); + // root = new GroupTail(localIndex, groupIndex); + // if (!anonymous && groupIndex < 10) + // groupNodes[groupIndex] = head; + // return head; + // } + + /** + * Parses inlined match flags and set them appropriately. + */ + // @SuppressWarnings("fallthrough") + // DIFFBLUE MODEL LIBRARY - not used in model + // private void addFlag() { + // int ch = peek(); + // for (;;) { + // switch (ch) { + // case 'i': + // flags |= CASE_INSENSITIVE; + // break; + // case 'm': + // flags |= MULTILINE; + // break; + // case 's': + // flags |= DOTALL; + // break; + // case 'd': + // flags |= UNIX_LINES; + // break; + // case 'u': + // flags |= UNICODE_CASE; + // break; + // case 'c': + // flags |= CANON_EQ; + // break; + // case 'x': + // flags |= COMMENTS; + // break; + // case 'U': + // flags |= (UNICODE_CHARACTER_CLASS | UNICODE_CASE); + // break; + // case '-': // subFlag then fall through + // ch = next(); + // subFlag(); + // default: + // return; + // } + // ch = next(); + // } + // } + + @SuppressWarnings("fallthrough") + /** + * Parses the second part of inlined match flags and turns off + * flags appropriately. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private void subFlag() { + // int ch = peek(); + // for (;;) { + // switch (ch) { + // case 'i': + // flags &= ~CASE_INSENSITIVE; + // break; + // case 'm': + // flags &= ~MULTILINE; + // break; + // case 's': + // flags &= ~DOTALL; + // break; + // case 'd': + // flags &= ~UNIX_LINES; + // break; + // case 'u': + // flags &= ~UNICODE_CASE; + // break; + // case 'c': + // flags &= ~CANON_EQ; + // break; + // case 'x': + // flags &= ~COMMENTS; + // break; + // case 'U': + // flags &= ~(UNICODE_CHARACTER_CLASS | UNICODE_CASE); + // default: + // return; + // } + // ch = next(); + // } + // } + + // DIFFBLUE MODEL LIBRARY - not used in model + // static final int MAX_REPS = 0x7FFFFFFF; + + // DIFFBLUE MODEL LIBRARY - not used in model + // static final int GREEDY = 0; + + // DIFFBLUE MODEL LIBRARY - not used in model + // static final int LAZY = 1; + + // DIFFBLUE MODEL LIBRARY - not used in model + // static final int POSSESSIVE = 2; + + // DIFFBLUE MODEL LIBRARY - not used in model + // static final int INDEPENDENT = 3; + + /** + * Processes repetition. If the next character peeked is a quantifier + * then new nodes must be appended to handle the repetition. + * Prev could be a single or a group, so it could be a chain of nodes. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private Node closure(Node prev) { + // Node atom; + // int ch = peek(); + // switch (ch) { + // case '?': + // ch = next(); + // if (ch == '?') { + // next(); + // return new Ques(prev, LAZY); + // } else if (ch == '+') { + // next(); + // return new Ques(prev, POSSESSIVE); + // } + // return new Ques(prev, GREEDY); + // case '*': + // ch = next(); + // if (ch == '?') { + // next(); + // return new Curly(prev, 0, MAX_REPS, LAZY); + // } else if (ch == '+') { + // next(); + // return new Curly(prev, 0, MAX_REPS, POSSESSIVE); + // } + // return new Curly(prev, 0, MAX_REPS, GREEDY); + // case '+': + // ch = next(); + // if (ch == '?') { + // next(); + // return new Curly(prev, 1, MAX_REPS, LAZY); + // } else if (ch == '+') { + // next(); + // return new Curly(prev, 1, MAX_REPS, POSSESSIVE); + // } + // return new Curly(prev, 1, MAX_REPS, GREEDY); + // case '{': + // ch = temp[cursor+1]; + // if (ASCII.isDigit(ch)) { + // skip(); + // int cmin = 0; + // do { + // cmin = cmin * 10 + (ch - '0'); + // } while (ASCII.isDigit(ch = read())); + // int cmax = cmin; + // if (ch == ',') { + // ch = read(); + // cmax = MAX_REPS; + // if (ch != '}') { + // cmax = 0; + // while (ASCII.isDigit(ch)) { + // cmax = cmax * 10 + (ch - '0'); + // ch = read(); + // } + // } + // } + // if (ch != '}') + // throw error("Unclosed counted closure"); + // if (((cmin) | (cmax) | (cmax - cmin)) < 0) + // throw error("Illegal repetition range"); + // Curly curly; + // ch = peek(); + // if (ch == '?') { + // next(); + // curly = new Curly(prev, cmin, cmax, LAZY); + // } else if (ch == '+') { + // next(); + // curly = new Curly(prev, cmin, cmax, POSSESSIVE); + // } else { + // curly = new Curly(prev, cmin, cmax, GREEDY); + // } + // return curly; + // } else { + // throw error("Illegal repetition"); + // } + // default: + // return prev; + // } + // } + + /** + * Utility method for parsing control escape sequences. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private int c() { + // if (cursor < patternLength) { + // return read() ^ 64; + // } + // throw error("Illegal control escape sequence"); + // } + + /** + * Utility method for parsing octal escape sequences. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private int o() { + // int n = read(); + // if (((n-'0')|('7'-n)) >= 0) { + // int m = read(); + // if (((m-'0')|('7'-m)) >= 0) { + // int o = read(); + // if ((((o-'0')|('7'-o)) >= 0) && (((n-'0')|('3'-n)) >= 0)) { + // return (n - '0') * 64 + (m - '0') * 8 + (o - '0'); + // } + // unread(); + // return (n - '0') * 8 + (m - '0'); + // } + // unread(); + // return (n - '0'); + // } + // throw error("Illegal octal escape sequence"); + // } + + /** + * Utility method for parsing hexadecimal escape sequences. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private int x() { + // int n = read(); + // if (ASCII.isHexDigit(n)) { + // int m = read(); + // if (ASCII.isHexDigit(m)) { + // return ASCII.toDigit(n) * 16 + ASCII.toDigit(m); + // } + // } else if (n == '{' && ASCII.isHexDigit(peek())) { + // int ch = 0; + // while (ASCII.isHexDigit(n = read())) { + // ch = (ch << 4) + ASCII.toDigit(n); + // if (ch > Character.MAX_CODE_POINT) + // throw error("Hexadecimal codepoint is too big"); + // } + // if (n != '}') + // throw error("Unclosed hexadecimal escape sequence"); + // return ch; + // } + // throw error("Illegal hexadecimal escape sequence"); + // } + + /** + * Utility method for parsing unicode escape sequences. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private int cursor() { + // return cursor; + // } + + // DIFFBLUE MODEL LIBRARY - not used in model + // private void setcursor(int pos) { + // cursor = pos; + // } + + // DIFFBLUE MODEL LIBRARY - not used in model + // private int uxxxx() { + // int n = 0; + // for (int i = 0; i < 4; i++) { + // int ch = read(); + // if (!ASCII.isHexDigit(ch)) { + // throw error("Illegal Unicode escape sequence"); + // } + // n = n * 16 + ASCII.toDigit(ch); + // } + // return n; + // } + + // DIFFBLUE MODEL LIBRARY - not used in model + // private int u() { + // int n = uxxxx(); + // if (Character.isHighSurrogate((char)n)) { + // int cur = cursor(); + // if (read() == '\\' && read() == 'u') { + // int n2 = uxxxx(); + // if (Character.isLowSurrogate((char)n2)) + // return Character.toCodePoint((char)n, (char)n2); + // } + // setcursor(cur); + // } + // return n; + // } + + // + // Utility methods for code point support + // + + // DIFFBLUE MODEL LIBRARY - not used in model + // private static final int countChars(CharSequence seq, int index, + // int lengthInCodePoints) { + // // optimization + // if (lengthInCodePoints == 1 && !Character.isHighSurrogate(seq.charAt(index))) { + // assert (index >= 0 && index < seq.length()); + // return 1; + // } + // int length = seq.length(); + // int x = index; + // if (lengthInCodePoints >= 0) { + // assert (index >= 0 && index < length); + // for (int i = 0; x < length && i < lengthInCodePoints; i++) { + // if (Character.isHighSurrogate(seq.charAt(x++))) { + // if (x < length && Character.isLowSurrogate(seq.charAt(x))) { + // x++; + // } + // } + // } + // return x - index; + // } + + // assert (index >= 0 && index <= length); + // if (index == 0) { + // return 0; + // } + // int len = -lengthInCodePoints; + // for (int i = 0; x > 0 && i < len; i++) { + // if (Character.isLowSurrogate(seq.charAt(--x))) { + // if (x > 0 && Character.isHighSurrogate(seq.charAt(x-1))) { + // x--; + // } + // } + // } + // return index - x; + // } + + // DIFFBLUE MODEL LIBRARY - not used in model + // private static final int countCodePoints(CharSequence seq) { + // int length = seq.length(); + // int n = 0; + // for (int i = 0; i < length; ) { + // n++; + // if (Character.isHighSurrogate(seq.charAt(i++))) { + // if (i < length && Character.isLowSurrogate(seq.charAt(i))) { + // i++; + // } + // } + // } + // return n; + // } + + /** + * Creates a bit vector for matching Latin-1 values. A normal BitClass + * never matches values above Latin-1, and a complemented BitClass always + * matches values above Latin-1. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private static final class BitClass extends BmpCharProperty { + // final boolean[] bits; + // BitClass() { bits = new boolean[256]; } + // private BitClass(boolean[] bits) { this.bits = bits; } + // BitClass add(int c, int flags) { + // assert c >= 0 && c <= 255; + // if ((flags & CASE_INSENSITIVE) != 0) { + // if (ASCII.isAscii(c)) { + // bits[ASCII.toUpper(c)] = true; + // bits[ASCII.toLower(c)] = true; + // } else if ((flags & UNICODE_CASE) != 0) { + // bits[Character.toLowerCase(c)] = true; + // bits[Character.toUpperCase(c)] = true; + // } + // } + // bits[c] = true; + // return this; + // } + // boolean isSatisfiedBy(int ch) { + // return ch < 256 && bits[ch]; + // } + // } + + /** + * Returns a suitably optimized, single character matcher. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private CharProperty newSingle(final int ch) { + // if (has(CASE_INSENSITIVE)) { + // int lower, upper; + // if (has(UNICODE_CASE)) { + // upper = Character.toUpperCase(ch); + // lower = Character.toLowerCase(upper); + // if (upper != lower) + // return new SingleU(lower); + // } else if (ASCII.isAscii(ch)) { + // lower = ASCII.toLower(ch); + // upper = ASCII.toUpper(ch); + // if (lower != upper) + // return new SingleI(lower, upper); + // } + // } + // if (isSupplementary(ch)) + // return new SingleS(ch); // Match a given Unicode character + // return new Single(ch); // Match a given BMP character + // } + + /** + * Utility method for creating a string slice matcher. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private Node newSlice(int[] buf, int count, boolean hasSupplementary) { + // int[] tmp = new int[count]; + // if (has(CASE_INSENSITIVE)) { + // if (has(UNICODE_CASE)) { + // for (int i = 0; i < count; i++) { + // tmp[i] = Character.toLowerCase( + // Character.toUpperCase(buf[i])); + // } + // return hasSupplementary? new SliceUS(tmp) : new SliceU(tmp); + // } + // for (int i = 0; i < count; i++) { + // tmp[i] = ASCII.toLower(buf[i]); + // } + // return hasSupplementary? new SliceIS(tmp) : new SliceI(tmp); + // } + // for (int i = 0; i < count; i++) { + // tmp[i] = buf[i]; + // } + // return hasSupplementary ? new SliceS(tmp) : new Slice(tmp); + // } + + /** + * The following classes are the building components of the object + * tree that represents a compiled regular expression. The object tree + * is made of individual elements that handle constructs in the Pattern. + * Each type of object knows how to match its equivalent construct with + * the match() method. + */ + + /** + * Base class for all node classes. Subclasses should override the match() + * method as appropriate. This class is an accepting node, so its match() + * always returns true. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static class Node extends Object { + // Node next; + // Node() { + // next = Pattern.accept; + // } + // /** + // * This method implements the classic accept node. + // */ + // boolean match(Matcher matcher, int i, CharSequence seq) { + // matcher.last = i; + // matcher.groups[0] = matcher.first; + // matcher.groups[1] = matcher.last; + // return true; + // } + // /** + // * This method is good for all zero length assertions. + // */ + // boolean study(TreeInfo info) { + // if (next != null) { + // return next.study(info); + // } else { + // return info.deterministic; + // } + // } + // } + + // DIFFBLUE MODEL LIBRARY - not used in model + // static class LastNode extends Node { + // /** + // * This method implements the classic accept node with + // * the addition of a check to see if the match occurred + // * using all of the input. + // */ + // boolean match(Matcher matcher, int i, CharSequence seq) { + // if (matcher.acceptMode == Matcher.ENDANCHOR && i != matcher.to) + // return false; + // matcher.last = i; + // matcher.groups[0] = matcher.first; + // matcher.groups[1] = matcher.last; + // return true; + // } + // } + + /** + * Used for REs that can start anywhere within the input string. + * This basically tries to match repeatedly at each spot in the + * input string, moving forward after each try. An anchored search + * or a BnM will bypass this node completely. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static class Start extends Node { + // int minLength; + // Start(Node node) { + // this.next = node; + // TreeInfo info = new TreeInfo(); + // next.study(info); + // minLength = info.minLength; + // } + // boolean match(Matcher matcher, int i, CharSequence seq) { + // if (i > matcher.to - minLength) { + // matcher.hitEnd = true; + // return false; + // } + // int guard = matcher.to - minLength; + // for (; i <= guard; i++) { + // if (next.match(matcher, i, seq)) { + // matcher.first = i; + // matcher.groups[0] = matcher.first; + // matcher.groups[1] = matcher.last; + // return true; + // } + // } + // matcher.hitEnd = true; + // return false; + // } + // boolean study(TreeInfo info) { + // next.study(info); + // info.maxValid = false; + // info.deterministic = false; + // return false; + // } + // } + + /* + * StartS supports supplementary characters, including unpaired surrogates. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static final class StartS extends Start { + // StartS(Node node) { + // super(node); + // } + // boolean match(Matcher matcher, int i, CharSequence seq) { + // if (i > matcher.to - minLength) { + // matcher.hitEnd = true; + // return false; + // } + // int guard = matcher.to - minLength; + // while (i <= guard) { + // //if ((ret = next.match(matcher, i, seq)) || i == guard) + // if (next.match(matcher, i, seq)) { + // matcher.first = i; + // matcher.groups[0] = matcher.first; + // matcher.groups[1] = matcher.last; + // return true; + // } + // if (i == guard) + // break; + // // Optimization to move to the next character. This is + // // faster than countChars(seq, i, 1). + // if (Character.isHighSurrogate(seq.charAt(i++))) { + // if (i < seq.length() && + // Character.isLowSurrogate(seq.charAt(i))) { + // i++; + // } + // } + // } + // matcher.hitEnd = true; + // return false; + // } + // } + + /** + * Node to anchor at the beginning of input. This object implements the + * match for a \A sequence, and the caret anchor will use this if not in + * multiline mode. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static final class Begin extends Node { + // boolean match(Matcher matcher, int i, CharSequence seq) { + // int fromIndex = (matcher.anchoringBounds) ? + // matcher.from : 0; + // if (i == fromIndex && next.match(matcher, i, seq)) { + // matcher.first = i; + // matcher.groups[0] = i; + // matcher.groups[1] = matcher.last; + // return true; + // } else { + // return false; + // } + // } + // } + + /** + * Node to anchor at the end of input. This is the absolute end, so this + * should not match at the last newline before the end as $ will. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static final class End extends Node { + // boolean match(Matcher matcher, int i, CharSequence seq) { + // int endIndex = (matcher.anchoringBounds) ? + // matcher.to : matcher.getTextLength(); + // if (i == endIndex) { + // matcher.hitEnd = true; + // return next.match(matcher, i, seq); + // } + // return false; + // } + // } + + /** + * Node to anchor at the beginning of a line. This is essentially the + * object to match for the multiline ^. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static final class Caret extends Node { + // boolean match(Matcher matcher, int i, CharSequence seq) { + // int startIndex = matcher.from; + // int endIndex = matcher.to; + // if (!matcher.anchoringBounds) { + // startIndex = 0; + // endIndex = matcher.getTextLength(); + // } + // // Perl does not match ^ at end of input even after newline + // if (i == endIndex) { + // matcher.hitEnd = true; + // return false; + // } + // if (i > startIndex) { + // char ch = seq.charAt(i-1); + // if (ch != '\n' && ch != '\r' + // && (ch|1) != '\u2029' + // && ch != '\u0085' ) { + // return false; + // } + // // Should treat /r/n as one newline + // if (ch == '\r' && seq.charAt(i) == '\n') + // return false; + // } + // return next.match(matcher, i, seq); + // } + // } + + /** + * Node to anchor at the beginning of a line when in unixdot mode. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static final class UnixCaret extends Node { + // boolean match(Matcher matcher, int i, CharSequence seq) { + // int startIndex = matcher.from; + // int endIndex = matcher.to; + // if (!matcher.anchoringBounds) { + // startIndex = 0; + // endIndex = matcher.getTextLength(); + // } + // // Perl does not match ^ at end of input even after newline + // if (i == endIndex) { + // matcher.hitEnd = true; + // return false; + // } + // if (i > startIndex) { + // char ch = seq.charAt(i-1); + // if (ch != '\n') { + // return false; + // } + // } + // return next.match(matcher, i, seq); + // } + // } + + /** + * Node to match the location where the last match ended. + * This is used for the \G construct. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static final class LastMatch extends Node { + // boolean match(Matcher matcher, int i, CharSequence seq) { + // if (i != matcher.oldLast) + // return false; + // return next.match(matcher, i, seq); + // } + // } + + /** + * Node to anchor at the end of a line or the end of input based on the + * multiline mode. + * + * When not in multiline mode, the $ can only match at the very end + * of the input, unless the input ends in a line terminator in which + * it matches right before the last line terminator. + * + * Note that \r\n is considered an atomic line terminator. + * + * Like ^ the $ operator matches at a position, it does not match the + * line terminators themselves. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static final class Dollar extends Node { + // boolean multiline; + // Dollar(boolean mul) { + // multiline = mul; + // } + // boolean match(Matcher matcher, int i, CharSequence seq) { + // int endIndex = (matcher.anchoringBounds) ? + // matcher.to : matcher.getTextLength(); + // if (!multiline) { + // if (i < endIndex - 2) + // return false; + // if (i == endIndex - 2) { + // char ch = seq.charAt(i); + // if (ch != '\r') + // return false; + // ch = seq.charAt(i + 1); + // if (ch != '\n') + // return false; + // } + // } + // // Matches before any line terminator; also matches at the + // // end of input + // // Before line terminator: + // // If multiline, we match here no matter what + // // If not multiline, fall through so that the end + // // is marked as hit; this must be a /r/n or a /n + // // at the very end so the end was hit; more input + // // could make this not match here + // if (i < endIndex) { + // char ch = seq.charAt(i); + // if (ch == '\n') { + // // No match between \r\n + // if (i > 0 && seq.charAt(i-1) == '\r') + // return false; + // if (multiline) + // return next.match(matcher, i, seq); + // } else if (ch == '\r' || ch == '\u0085' || + // (ch|1) == '\u2029') { + // if (multiline) + // return next.match(matcher, i, seq); + // } else { // No line terminator, no match + // return false; + // } + // } + // // Matched at current end so hit end + // matcher.hitEnd = true; + // // If a $ matches because of end of input, then more input + // // could cause it to fail! + // matcher.requireEnd = true; + // return next.match(matcher, i, seq); + // } + // boolean study(TreeInfo info) { + // next.study(info); + // return info.deterministic; + // } + // } + + /** + * Node to anchor at the end of a line or the end of input based on the + * multiline mode when in unix lines mode. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static final class UnixDollar extends Node { + // boolean multiline; + // UnixDollar(boolean mul) { + // multiline = mul; + // } + // boolean match(Matcher matcher, int i, CharSequence seq) { + // int endIndex = (matcher.anchoringBounds) ? + // matcher.to : matcher.getTextLength(); + // if (i < endIndex) { + // char ch = seq.charAt(i); + // if (ch == '\n') { + // // If not multiline, then only possible to + // // match at very end or one before end + // if (multiline == false && i != endIndex - 1) + // return false; + // // If multiline return next.match without setting + // // matcher.hitEnd + // if (multiline) + // return next.match(matcher, i, seq); + // } else { + // return false; + // } + // } + // // Matching because at the end or 1 before the end; + // // more input could change this so set hitEnd + // matcher.hitEnd = true; + // // If a $ matches because of end of input, then more input + // // could cause it to fail! + // matcher.requireEnd = true; + // return next.match(matcher, i, seq); + // } + // boolean study(TreeInfo info) { + // next.study(info); + // return info.deterministic; + // } + // } + + /** + * Node class that matches a Unicode line ending '\R' + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static final class LineEnding extends Node { + // boolean match(Matcher matcher, int i, CharSequence seq) { + // // (u+000Du+000A|[u+000Au+000Bu+000Cu+000Du+0085u+2028u+2029]) + // if (i < matcher.to) { + // int ch = seq.charAt(i); + // if (ch == 0x0A || ch == 0x0B || ch == 0x0C || + // ch == 0x85 || ch == 0x2028 || ch == 0x2029) + // return next.match(matcher, i + 1, seq); + // if (ch == 0x0D) { + // i++; + // if (i < matcher.to && seq.charAt(i) == 0x0A) + // i++; + // return next.match(matcher, i, seq); + // } + // } else { + // matcher.hitEnd = true; + // } + // return false; + // } + // boolean study(TreeInfo info) { + // info.minLength++; + // info.maxLength += 2; + // return next.study(info); + // } + // } + + /** + * Abstract node class to match one character satisfying some + * boolean property. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private static abstract class CharProperty extends Node { + // abstract boolean isSatisfiedBy(int ch); + // CharProperty complement() { + // return new CharProperty() { + // boolean isSatisfiedBy(int ch) { + // return ! CharProperty.this.isSatisfiedBy(ch);}}; + // } + // boolean match(Matcher matcher, int i, CharSequence seq) { + // if (i < matcher.to) { + // int ch = Character.codePointAt(seq, i); + // return isSatisfiedBy(ch) + // && next.match(matcher, i+Character.charCount(ch), seq); + // } else { + // matcher.hitEnd = true; + // return false; + // } + // } + // boolean study(TreeInfo info) { + // info.minLength++; + // info.maxLength++; + // return next.study(info); + // } + // } + + /** + * Optimized version of CharProperty that works only for + * properties never satisfied by Supplementary characters. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private static abstract class BmpCharProperty extends CharProperty { + // boolean match(Matcher matcher, int i, CharSequence seq) { + // if (i < matcher.to) { + // return isSatisfiedBy(seq.charAt(i)) + // && next.match(matcher, i+1, seq); + // } else { + // matcher.hitEnd = true; + // return false; + // } + // } + // } + + /** + * Node class that matches a Supplementary Unicode character + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static final class SingleS extends CharProperty { + // final int c; + // SingleS(int c) { this.c = c; } + // boolean isSatisfiedBy(int ch) { + // return ch == c; + // } + // } + + /** + * Optimization -- matches a given BMP character + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static final class Single extends BmpCharProperty { + // final int c; + // Single(int c) { this.c = c; } + // boolean isSatisfiedBy(int ch) { + // return ch == c; + // } + // } + + /** + * Case insensitive matches a given BMP character + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static final class SingleI extends BmpCharProperty { + // final int lower; + // final int upper; + // SingleI(int lower, int upper) { + // this.lower = lower; + // this.upper = upper; + // } + // boolean isSatisfiedBy(int ch) { + // return ch == lower || ch == upper; + // } + // } + + /** + * Unicode case insensitive matches a given Unicode character + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static final class SingleU extends CharProperty { + // final int lower; + // SingleU(int lower) { + // this.lower = lower; + // } + // boolean isSatisfiedBy(int ch) { + // return lower == ch || + // lower == Character.toLowerCase(Character.toUpperCase(ch)); + // } + // } + + /** + * Node class that matches a Unicode block. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static final class Block extends CharProperty { + // final Character.UnicodeBlock block; + // Block(Character.UnicodeBlock block) { + // this.block = block; + // } + // boolean isSatisfiedBy(int ch) { + // return block == Character.UnicodeBlock.of(ch); + // } + // } + + /** + * Node class that matches a Unicode script + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static final class Script extends CharProperty { + // final Character.UnicodeScript script; + // Script(Character.UnicodeScript script) { + // this.script = script; + // } + // boolean isSatisfiedBy(int ch) { + // return script == Character.UnicodeScript.of(ch); + // } + // } + + /** + * Node class that matches a Unicode category. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static final class Category extends CharProperty { + // final int typeMask; + // Category(int typeMask) { this.typeMask = typeMask; } + // boolean isSatisfiedBy(int ch) { + // return (typeMask & (1 << Character.getType(ch))) != 0; + // } + // } + + /** + * Node class that matches a Unicode "type" + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static final class Utype extends CharProperty { + // final UnicodeProp uprop; + // Utype(UnicodeProp uprop) { this.uprop = uprop; } + // boolean isSatisfiedBy(int ch) { + // return uprop.is(ch); + // } + // } + + /** + * Node class that matches a POSIX type. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static final class Ctype extends BmpCharProperty { + // final int ctype; + // Ctype(int ctype) { this.ctype = ctype; } + // boolean isSatisfiedBy(int ch) { + // return ch < 128 && ASCII.isType(ch, ctype); + // } + // } + + /** + * Node class that matches a Perl vertical whitespace + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static final class VertWS extends BmpCharProperty { + // boolean isSatisfiedBy(int cp) { + // return (cp >= 0x0A && cp <= 0x0D) || + // cp == 0x85 || cp == 0x2028 || cp == 0x2029; + // } + // } + + /** + * Node class that matches a Perl horizontal whitespace + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static final class HorizWS extends BmpCharProperty { + // boolean isSatisfiedBy(int cp) { + // return cp == 0x09 || cp == 0x20 || cp == 0xa0 || + // cp == 0x1680 || cp == 0x180e || + // cp >= 0x2000 && cp <= 0x200a || + // cp == 0x202f || cp == 0x205f || cp == 0x3000; + // } + // } + + /** + * Base class for all Slice nodes + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static class SliceNode extends Node { + // int[] buffer; + // SliceNode(int[] buf) { + // buffer = buf; + // } + // boolean study(TreeInfo info) { + // info.minLength += buffer.length; + // info.maxLength += buffer.length; + // return next.study(info); + // } + // } + + /** + * Node class for a case sensitive/BMP-only sequence of literal + * characters. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static final class Slice extends SliceNode { + // Slice(int[] buf) { + // super(buf); + // } + // boolean match(Matcher matcher, int i, CharSequence seq) { + // int[] buf = buffer; + // int len = buf.length; + // for (int j=0; j= matcher.to) { + // matcher.hitEnd = true; + // return false; + // } + // if (buf[j] != seq.charAt(i+j)) + // return false; + // } + // return next.match(matcher, i+len, seq); + // } + // } + + /** + * Node class for a case_insensitive/BMP-only sequence of literal + * characters. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static class SliceI extends SliceNode { + // SliceI(int[] buf) { + // super(buf); + // } + // boolean match(Matcher matcher, int i, CharSequence seq) { + // int[] buf = buffer; + // int len = buf.length; + // for (int j=0; j= matcher.to) { + // matcher.hitEnd = true; + // return false; + // } + // int c = seq.charAt(i+j); + // if (buf[j] != c && + // buf[j] != ASCII.toLower(c)) + // return false; + // } + // return next.match(matcher, i+len, seq); + // } + // } + + /** + * Node class for a unicode_case_insensitive/BMP-only sequence of + * literal characters. Uses unicode case folding. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static final class SliceU extends SliceNode { + // SliceU(int[] buf) { + // super(buf); + // } + // boolean match(Matcher matcher, int i, CharSequence seq) { + // int[] buf = buffer; + // int len = buf.length; + // for (int j=0; j= matcher.to) { + // matcher.hitEnd = true; + // return false; + // } + // int c = seq.charAt(i+j); + // if (buf[j] != c && + // buf[j] != Character.toLowerCase(Character.toUpperCase(c))) + // return false; + // } + // return next.match(matcher, i+len, seq); + // } + // } + + /** + * Node class for a case sensitive sequence of literal characters + * including supplementary characters. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static final class SliceS extends SliceNode { + // SliceS(int[] buf) { + // super(buf); + // } + // boolean match(Matcher matcher, int i, CharSequence seq) { + // int[] buf = buffer; + // int x = i; + // for (int j = 0; j < buf.length; j++) { + // if (x >= matcher.to) { + // matcher.hitEnd = true; + // return false; + // } + // int c = Character.codePointAt(seq, x); + // if (buf[j] != c) + // return false; + // x += Character.charCount(c); + // if (x > matcher.to) { + // matcher.hitEnd = true; + // return false; + // } + // } + // return next.match(matcher, x, seq); + // } + // } + + /** + * Node class for a case insensitive sequence of literal characters + * including supplementary characters. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static class SliceIS extends SliceNode { + // SliceIS(int[] buf) { + // super(buf); + // } + // int toLower(int c) { + // return ASCII.toLower(c); + // } + // boolean match(Matcher matcher, int i, CharSequence seq) { + // int[] buf = buffer; + // int x = i; + // for (int j = 0; j < buf.length; j++) { + // if (x >= matcher.to) { + // matcher.hitEnd = true; + // return false; + // } + // int c = Character.codePointAt(seq, x); + // if (buf[j] != c && buf[j] != toLower(c)) + // return false; + // x += Character.charCount(c); + // if (x > matcher.to) { + // matcher.hitEnd = true; + // return false; + // } + // } + // return next.match(matcher, x, seq); + // } + // } + + /** + * Node class for a case insensitive sequence of literal characters. + * Uses unicode case folding. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static final class SliceUS extends SliceIS { + // SliceUS(int[] buf) { + // super(buf); + // } + // int toLower(int c) { + // return Character.toLowerCase(Character.toUpperCase(c)); + // } + // } + + // DIFFBLUE MODEL LIBRARY - not used in model + // private static boolean inRange(int lower, int ch, int upper) { + // return lower <= ch && ch <= upper; + // } + + /** + * Returns node for matching characters within an explicit value range. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private static CharProperty rangeFor(final int lower, + // final int upper) { + // return new CharProperty() { + // boolean isSatisfiedBy(int ch) { + // return inRange(lower, ch, upper);}}; + // } + + /** + * Returns node for matching characters within an explicit value + * range in a case insensitive manner. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private CharProperty caseInsensitiveRangeFor(final int lower, + // final int upper) { + // if (has(UNICODE_CASE)) + // return new CharProperty() { + // boolean isSatisfiedBy(int ch) { + // if (inRange(lower, ch, upper)) + // return true; + // int up = Character.toUpperCase(ch); + // return inRange(lower, up, upper) || + // inRange(lower, Character.toLowerCase(up), upper);}}; + // return new CharProperty() { + // boolean isSatisfiedBy(int ch) { + // return inRange(lower, ch, upper) || + // ASCII.isAscii(ch) && + // (inRange(lower, ASCII.toUpper(ch), upper) || + // inRange(lower, ASCII.toLower(ch), upper)); + // }}; + // } + + /** + * Implements the Unicode category ALL and the dot metacharacter when + * in dotall mode. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static final class All extends CharProperty { + // boolean isSatisfiedBy(int ch) { + // return true; + // } + // } + + /** + * Node class for the dot metacharacter when dotall is not enabled. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static final class Dot extends CharProperty { + // boolean isSatisfiedBy(int ch) { + // return (ch != '\n' && ch != '\r' + // && (ch|1) != '\u2029' + // && ch != '\u0085'); + // } + // } + + /** + * Node class for the dot metacharacter when dotall is not enabled + * but UNIX_LINES is enabled. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static final class UnixDot extends CharProperty { + // boolean isSatisfiedBy(int ch) { + // return ch != '\n'; + // } + // } + + /** + * The 0 or 1 quantifier. This one class implements all three types. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static final class Ques extends Node { + // Node atom; + // int type; + // Ques(Node node, int type) { + // this.atom = node; + // this.type = type; + // } + // boolean match(Matcher matcher, int i, CharSequence seq) { + // switch (type) { + // case GREEDY: + // return (atom.match(matcher, i, seq) && next.match(matcher, matcher.last, seq)) + // || next.match(matcher, i, seq); + // case LAZY: + // return next.match(matcher, i, seq) + // || (atom.match(matcher, i, seq) && next.match(matcher, matcher.last, seq)); + // case POSSESSIVE: + // if (atom.match(matcher, i, seq)) i = matcher.last; + // return next.match(matcher, i, seq); + // default: + // return atom.match(matcher, i, seq) && next.match(matcher, matcher.last, seq); + // } + // } + // boolean study(TreeInfo info) { + // if (type != INDEPENDENT) { + // int minL = info.minLength; + // atom.study(info); + // info.minLength = minL; + // info.deterministic = false; + // return next.study(info); + // } else { + // atom.study(info); + // return next.study(info); + // } + // } + // } + + /** + * Handles the curly-brace style repetition with a specified minimum and + * maximum occurrences. The * quantifier is handled as a special case. + * This class handles the three types. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static final class Curly extends Node { + // Node atom; + // int type; + // int cmin; + // int cmax; + + // Curly(Node node, int cmin, int cmax, int type) { + // this.atom = node; + // this.type = type; + // this.cmin = cmin; + // this.cmax = cmax; + // } + // boolean match(Matcher matcher, int i, CharSequence seq) { + // int j; + // for (j = 0; j < cmin; j++) { + // if (atom.match(matcher, i, seq)) { + // i = matcher.last; + // continue; + // } + // return false; + // } + // if (type == GREEDY) + // return match0(matcher, i, j, seq); + // else if (type == LAZY) + // return match1(matcher, i, j, seq); + // else + // return match2(matcher, i, j, seq); + // } + // // Greedy match. + // // i is the index to start matching at + // // j is the number of atoms that have matched + // boolean match0(Matcher matcher, int i, int j, CharSequence seq) { + // if (j >= cmax) { + // // We have matched the maximum... continue with the rest of + // // the regular expression + // return next.match(matcher, i, seq); + // } + // int backLimit = j; + // while (atom.match(matcher, i, seq)) { + // // k is the length of this match + // int k = matcher.last - i; + // if (k == 0) // Zero length match + // break; + // // Move up index and number matched + // i = matcher.last; + // j++; + // // We are greedy so match as many as we can + // while (j < cmax) { + // if (!atom.match(matcher, i, seq)) + // break; + // if (i + k != matcher.last) { + // if (match0(matcher, matcher.last, j+1, seq)) + // return true; + // break; + // } + // i += k; + // j++; + // } + // // Handle backing off if match fails + // while (j >= backLimit) { + // if (next.match(matcher, i, seq)) + // return true; + // i -= k; + // j--; + // } + // return false; + // } + // return next.match(matcher, i, seq); + // } + // // Reluctant match. At this point, the minimum has been satisfied. + // // i is the index to start matching at + // // j is the number of atoms that have matched + // boolean match1(Matcher matcher, int i, int j, CharSequence seq) { + // for (;;) { + // // Try finishing match without consuming any more + // if (next.match(matcher, i, seq)) + // return true; + // // At the maximum, no match found + // if (j >= cmax) + // return false; + // // Okay, must try one more atom + // if (!atom.match(matcher, i, seq)) + // return false; + // // If we haven't moved forward then must break out + // if (i == matcher.last) + // return false; + // // Move up index and number matched + // i = matcher.last; + // j++; + // } + // } + // boolean match2(Matcher matcher, int i, int j, CharSequence seq) { + // for (; j < cmax; j++) { + // if (!atom.match(matcher, i, seq)) + // break; + // if (i == matcher.last) + // break; + // i = matcher.last; + // } + // return next.match(matcher, i, seq); + // } + // boolean study(TreeInfo info) { + // // Save original info + // int minL = info.minLength; + // int maxL = info.maxLength; + // boolean maxV = info.maxValid; + // boolean detm = info.deterministic; + // info.reset(); + + // atom.study(info); + + // int temp = info.minLength * cmin + minL; + // if (temp < minL) { + // temp = 0xFFFFFFF; // arbitrary large number + // } + // info.minLength = temp; + + // if (maxV & info.maxValid) { + // temp = info.maxLength * cmax + maxL; + // info.maxLength = temp; + // if (temp < maxL) { + // info.maxValid = false; + // } + // } else { + // info.maxValid = false; + // } + + // if (info.deterministic && cmin == cmax) + // info.deterministic = detm; + // else + // info.deterministic = false; + // return next.study(info); + // } + // } + + /** + * Handles the curly-brace style repetition with a specified minimum and + * maximum occurrences in deterministic cases. This is an iterative + * optimization over the Prolog and Loop system which would handle this + * in a recursive way. The * quantifier is handled as a special case. + * If capture is true then this class saves group settings and ensures + * that groups are unset when backing off of a group match. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static final class GroupCurly extends Node { + // Node atom; + // int type; + // int cmin; + // int cmax; + // int localIndex; + // int groupIndex; + // boolean capture; + + // GroupCurly(Node node, int cmin, int cmax, int type, int local, + // int group, boolean capture) { + // this.atom = node; + // this.type = type; + // this.cmin = cmin; + // this.cmax = cmax; + // this.localIndex = local; + // this.groupIndex = group; + // this.capture = capture; + // } + // boolean match(Matcher matcher, int i, CharSequence seq) { + // int[] groups = matcher.groups; + // int[] locals = matcher.locals; + // int save0 = locals[localIndex]; + // int save1 = 0; + // int save2 = 0; + + // if (capture) { + // save1 = groups[groupIndex]; + // save2 = groups[groupIndex+1]; + // } + + // // Notify GroupTail there is no need to setup group info + // // because it will be set here + // locals[localIndex] = -1; + + // boolean ret = true; + // for (int j = 0; j < cmin; j++) { + // if (atom.match(matcher, i, seq)) { + // if (capture) { + // groups[groupIndex] = i; + // groups[groupIndex+1] = matcher.last; + // } + // i = matcher.last; + // } else { + // ret = false; + // break; + // } + // } + // if (ret) { + // if (type == GREEDY) { + // ret = match0(matcher, i, cmin, seq); + // } else if (type == LAZY) { + // ret = match1(matcher, i, cmin, seq); + // } else { + // ret = match2(matcher, i, cmin, seq); + // } + // } + // if (!ret) { + // locals[localIndex] = save0; + // if (capture) { + // groups[groupIndex] = save1; + // groups[groupIndex+1] = save2; + // } + // } + // return ret; + // } + // // Aggressive group match + // boolean match0(Matcher matcher, int i, int j, CharSequence seq) { + // // don't back off passing the starting "j" + // int min = j; + // int[] groups = matcher.groups; + // int save0 = 0; + // int save1 = 0; + // if (capture) { + // save0 = groups[groupIndex]; + // save1 = groups[groupIndex+1]; + // } + // for (;;) { + // if (j >= cmax) + // break; + // if (!atom.match(matcher, i, seq)) + // break; + // int k = matcher.last - i; + // if (k <= 0) { + // if (capture) { + // groups[groupIndex] = i; + // groups[groupIndex+1] = i + k; + // } + // i = i + k; + // break; + // } + // for (;;) { + // if (capture) { + // groups[groupIndex] = i; + // groups[groupIndex+1] = i + k; + // } + // i = i + k; + // if (++j >= cmax) + // break; + // if (!atom.match(matcher, i, seq)) + // break; + // if (i + k != matcher.last) { + // if (match0(matcher, i, j, seq)) + // return true; + // break; + // } + // } + // while (j > min) { + // if (next.match(matcher, i, seq)) { + // if (capture) { + // groups[groupIndex+1] = i; + // groups[groupIndex] = i - k; + // } + // return true; + // } + // // backing off + // i = i - k; + // if (capture) { + // groups[groupIndex+1] = i; + // groups[groupIndex] = i - k; + // } + // j--; + + // } + // break; + // } + // if (capture) { + // groups[groupIndex] = save0; + // groups[groupIndex+1] = save1; + // } + // return next.match(matcher, i, seq); + // } + // // Reluctant matching + // boolean match1(Matcher matcher, int i, int j, CharSequence seq) { + // for (;;) { + // if (next.match(matcher, i, seq)) + // return true; + // if (j >= cmax) + // return false; + // if (!atom.match(matcher, i, seq)) + // return false; + // if (i == matcher.last) + // return false; + // if (capture) { + // matcher.groups[groupIndex] = i; + // matcher.groups[groupIndex+1] = matcher.last; + // } + // i = matcher.last; + // j++; + // } + // } + // // Possessive matching + // boolean match2(Matcher matcher, int i, int j, CharSequence seq) { + // for (; j < cmax; j++) { + // if (!atom.match(matcher, i, seq)) { + // break; + // } + // if (capture) { + // matcher.groups[groupIndex] = i; + // matcher.groups[groupIndex+1] = matcher.last; + // } + // if (i == matcher.last) { + // break; + // } + // i = matcher.last; + // } + // return next.match(matcher, i, seq); + // } + // boolean study(TreeInfo info) { + // // Save original info + // int minL = info.minLength; + // int maxL = info.maxLength; + // boolean maxV = info.maxValid; + // boolean detm = info.deterministic; + // info.reset(); + + // atom.study(info); + + // int temp = info.minLength * cmin + minL; + // if (temp < minL) { + // temp = 0xFFFFFFF; // Arbitrary large number + // } + // info.minLength = temp; + + // if (maxV & info.maxValid) { + // temp = info.maxLength * cmax + maxL; + // info.maxLength = temp; + // if (temp < maxL) { + // info.maxValid = false; + // } + // } else { + // info.maxValid = false; + // } + + // if (info.deterministic && cmin == cmax) { + // info.deterministic = detm; + // } else { + // info.deterministic = false; + // } + // return next.study(info); + // } + // } + + /** + * A Guard node at the end of each atom node in a Branch. It + * serves the purpose of chaining the "match" operation to + * "next" but not the "study", so we can collect the TreeInfo + * of each atom node without including the TreeInfo of the + * "next". + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static final class BranchConn extends Node { + // BranchConn() {}; + // boolean match(Matcher matcher, int i, CharSequence seq) { + // return next.match(matcher, i, seq); + // } + // boolean study(TreeInfo info) { + // return info.deterministic; + // } + // } + + /** + * Handles the branching of alternations. Note this is also used for + * the ? quantifier to branch between the case where it matches once + * and where it does not occur. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static final class Branch extends Node { + // Node[] atoms = new Node[2]; + // int size = 2; + // Node conn; + // Branch(Node first, Node second, Node branchConn) { + // conn = branchConn; + // atoms[0] = first; + // atoms[1] = second; + // } + + // void add(Node node) { + // if (size >= atoms.length) { + // Node[] tmp = new Node[atoms.length*2]; + // System.arraycopy(atoms, 0, tmp, 0, atoms.length); + // atoms = tmp; + // } + // atoms[size++] = node; + // } + + // boolean match(Matcher matcher, int i, CharSequence seq) { + // for (int n = 0; n < size; n++) { + // if (atoms[n] == null) { + // if (conn.next.match(matcher, i, seq)) + // return true; + // } else if (atoms[n].match(matcher, i, seq)) { + // return true; + // } + // } + // return false; + // } + + // boolean study(TreeInfo info) { + // int minL = info.minLength; + // int maxL = info.maxLength; + // boolean maxV = info.maxValid; + + // int minL2 = Integer.MAX_VALUE; //arbitrary large enough num + // int maxL2 = -1; + // for (int n = 0; n < size; n++) { + // info.reset(); + // if (atoms[n] != null) + // atoms[n].study(info); + // minL2 = Math.min(minL2, info.minLength); + // maxL2 = Math.max(maxL2, info.maxLength); + // maxV = (maxV & info.maxValid); + // } + + // minL += minL2; + // maxL += maxL2; + + // info.reset(); + // conn.next.study(info); + + // info.minLength += minL; + // info.maxLength += maxL; + // info.maxValid &= maxV; + // info.deterministic = false; + // return false; + // } + // } + + /** + * The GroupHead saves the location where the group begins in the locals + * and restores them when the match is done. + * + * The matchRef is used when a reference to this group is accessed later + * in the expression. The locals will have a negative value in them to + * indicate that we do not want to unset the group if the reference + * doesn't match. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static final class GroupHead extends Node { + // int localIndex; + // GroupHead(int localCount) { + // localIndex = localCount; + // } + // boolean match(Matcher matcher, int i, CharSequence seq) { + // int save = matcher.locals[localIndex]; + // matcher.locals[localIndex] = i; + // boolean ret = next.match(matcher, i, seq); + // matcher.locals[localIndex] = save; + // return ret; + // } + // boolean matchRef(Matcher matcher, int i, CharSequence seq) { + // int save = matcher.locals[localIndex]; + // matcher.locals[localIndex] = ~i; // HACK + // boolean ret = next.match(matcher, i, seq); + // matcher.locals[localIndex] = save; + // return ret; + // } + // } + + /** + * Recursive reference to a group in the regular expression. It calls + * matchRef because if the reference fails to match we would not unset + * the group. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static final class GroupRef extends Node { + // GroupHead head; + // GroupRef(GroupHead head) { + // this.head = head; + // } + // boolean match(Matcher matcher, int i, CharSequence seq) { + // return head.matchRef(matcher, i, seq) + // && next.match(matcher, matcher.last, seq); + // } + // boolean study(TreeInfo info) { + // info.maxValid = false; + // info.deterministic = false; + // return next.study(info); + // } + // } + + /** + * The GroupTail handles the setting of group beginning and ending + * locations when groups are successfully matched. It must also be able to + * unset groups that have to be backed off of. + * + * The GroupTail node is also used when a previous group is referenced, + * and in that case no group information needs to be set. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static final class GroupTail extends Node { + // int localIndex; + // int groupIndex; + // GroupTail(int localCount, int groupCount) { + // localIndex = localCount; + // groupIndex = groupCount + groupCount; + // } + // boolean match(Matcher matcher, int i, CharSequence seq) { + // int tmp = matcher.locals[localIndex]; + // if (tmp >= 0) { // This is the normal group case. + // // Save the group so we can unset it if it + // // backs off of a match. + // int groupStart = matcher.groups[groupIndex]; + // int groupEnd = matcher.groups[groupIndex+1]; + + // matcher.groups[groupIndex] = tmp; + // matcher.groups[groupIndex+1] = i; + // if (next.match(matcher, i, seq)) { + // return true; + // } + // matcher.groups[groupIndex] = groupStart; + // matcher.groups[groupIndex+1] = groupEnd; + // return false; + // } else { + // // This is a group reference case. We don't need to save any + // // group info because it isn't really a group. + // matcher.last = i; + // return true; + // } + // } + // } + + /** + * This sets up a loop to handle a recursive quantifier structure. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static final class Prolog extends Node { + // Loop loop; + // Prolog(Loop loop) { + // this.loop = loop; + // } + // boolean match(Matcher matcher, int i, CharSequence seq) { + // return loop.matchInit(matcher, i, seq); + // } + // boolean study(TreeInfo info) { + // return loop.study(info); + // } + // } + + /** + * Handles the repetition count for a greedy Curly. The matchInit + * is called from the Prolog to save the index of where the group + * beginning is stored. A zero length group check occurs in the + * normal match but is skipped in the matchInit. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static class Loop extends Node { + // Node body; + // int countIndex; // local count index in matcher locals + // int beginIndex; // group beginning index + // int cmin, cmax; + // Loop(int countIndex, int beginIndex) { + // this.countIndex = countIndex; + // this.beginIndex = beginIndex; + // } + // boolean match(Matcher matcher, int i, CharSequence seq) { + // // Avoid infinite loop in zero-length case. + // if (i > matcher.locals[beginIndex]) { + // int count = matcher.locals[countIndex]; + + // // This block is for before we reach the minimum + // // iterations required for the loop to match + // if (count < cmin) { + // matcher.locals[countIndex] = count + 1; + // boolean b = body.match(matcher, i, seq); + // // If match failed we must backtrack, so + // // the loop count should NOT be incremented + // if (!b) + // matcher.locals[countIndex] = count; + // // Return success or failure since we are under + // // minimum + // return b; + // } + // // This block is for after we have the minimum + // // iterations required for the loop to match + // if (count < cmax) { + // matcher.locals[countIndex] = count + 1; + // boolean b = body.match(matcher, i, seq); + // // If match failed we must backtrack, so + // // the loop count should NOT be incremented + // if (!b) + // matcher.locals[countIndex] = count; + // else + // return true; + // } + // } + // return next.match(matcher, i, seq); + // } + // boolean matchInit(Matcher matcher, int i, CharSequence seq) { + // int save = matcher.locals[countIndex]; + // boolean ret = false; + // if (0 < cmin) { + // matcher.locals[countIndex] = 1; + // ret = body.match(matcher, i, seq); + // } else if (0 < cmax) { + // matcher.locals[countIndex] = 1; + // ret = body.match(matcher, i, seq); + // if (ret == false) + // ret = next.match(matcher, i, seq); + // } else { + // ret = next.match(matcher, i, seq); + // } + // matcher.locals[countIndex] = save; + // return ret; + // } + // boolean study(TreeInfo info) { + // info.maxValid = false; + // info.deterministic = false; + // return false; + // } + // } + + /** + * Handles the repetition count for a reluctant Curly. The matchInit + * is called from the Prolog to save the index of where the group + * beginning is stored. A zero length group check occurs in the + * normal match but is skipped in the matchInit. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static final class LazyLoop extends Loop { + // LazyLoop(int countIndex, int beginIndex) { + // super(countIndex, beginIndex); + // } + // boolean match(Matcher matcher, int i, CharSequence seq) { + // // Check for zero length group + // if (i > matcher.locals[beginIndex]) { + // int count = matcher.locals[countIndex]; + // if (count < cmin) { + // matcher.locals[countIndex] = count + 1; + // boolean result = body.match(matcher, i, seq); + // // If match failed we must backtrack, so + // // the loop count should NOT be incremented + // if (!result) + // matcher.locals[countIndex] = count; + // return result; + // } + // if (next.match(matcher, i, seq)) + // return true; + // if (count < cmax) { + // matcher.locals[countIndex] = count + 1; + // boolean result = body.match(matcher, i, seq); + // // If match failed we must backtrack, so + // // the loop count should NOT be incremented + // if (!result) + // matcher.locals[countIndex] = count; + // return result; + // } + // return false; + // } + // return next.match(matcher, i, seq); + // } + // boolean matchInit(Matcher matcher, int i, CharSequence seq) { + // int save = matcher.locals[countIndex]; + // boolean ret = false; + // if (0 < cmin) { + // matcher.locals[countIndex] = 1; + // ret = body.match(matcher, i, seq); + // } else if (next.match(matcher, i, seq)) { + // ret = true; + // } else if (0 < cmax) { + // matcher.locals[countIndex] = 1; + // ret = body.match(matcher, i, seq); + // } + // matcher.locals[countIndex] = save; + // return ret; + // } + // boolean study(TreeInfo info) { + // info.maxValid = false; + // info.deterministic = false; + // return false; + // } + // } + + /** + * Refers to a group in the regular expression. Attempts to match + * whatever the group referred to last matched. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static class BackRef extends Node { + // int groupIndex; + // BackRef(int groupCount) { + // super(); + // groupIndex = groupCount + groupCount; + // } + // boolean match(Matcher matcher, int i, CharSequence seq) { + // int j = matcher.groups[groupIndex]; + // int k = matcher.groups[groupIndex+1]; + + // int groupSize = k - j; + // // If the referenced group didn't match, neither can this + // if (j < 0) + // return false; + + // // If there isn't enough input left no match + // if (i + groupSize > matcher.to) { + // matcher.hitEnd = true; + // return false; + // } + // // Check each new char to make sure it matches what the group + // // referenced matched last time around + // for (int index=0; index matcher.to) { + // matcher.hitEnd = true; + // return false; + // } + + // // Check each new char to make sure it matches what the group + // // referenced matched last time around + // int x = i; + // for (int index=0; index matcher.to) { + // matcher.hitEnd = true; + // return false; + // } + // if (atom.match(matcher, i, seq)) { + // return next.match(matcher, matcher.last, seq); + // } + // i += countChars(seq, i, 1); + // matcher.first++; + // } + // } + // boolean study(TreeInfo info) { + // atom.study(info); + // info.maxValid = false; + // info.deterministic = false; + // return next.study(info); + // } + // } + + // DIFFBLUE MODEL LIBRARY - not used in model + // static final class Conditional extends Node { + // Node cond, yes, not; + // Conditional(Node cond, Node yes, Node not) { + // this.cond = cond; + // this.yes = yes; + // this.not = not; + // } + // boolean match(Matcher matcher, int i, CharSequence seq) { + // if (cond.match(matcher, i, seq)) { + // return yes.match(matcher, i, seq); + // } else { + // return not.match(matcher, i, seq); + // } + // } + // boolean study(TreeInfo info) { + // int minL = info.minLength; + // int maxL = info.maxLength; + // boolean maxV = info.maxValid; + // info.reset(); + // yes.study(info); + + // int minL2 = info.minLength; + // int maxL2 = info.maxLength; + // boolean maxV2 = info.maxValid; + // info.reset(); + // not.study(info); + + // info.minLength = minL + Math.min(minL2, info.minLength); + // info.maxLength = maxL + Math.max(maxL2, info.maxLength); + // info.maxValid = (maxV & maxV2 & info.maxValid); + // info.deterministic = false; + // return next.study(info); + // } + // } + + /** + * Zero width positive lookahead. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static final class Pos extends Node { + // Node cond; + // Pos(Node cond) { + // this.cond = cond; + // } + // boolean match(Matcher matcher, int i, CharSequence seq) { + // int savedTo = matcher.to; + // boolean conditionMatched = false; + + // // Relax transparent region boundaries for lookahead + // if (matcher.transparentBounds) + // matcher.to = matcher.getTextLength(); + // try { + // conditionMatched = cond.match(matcher, i, seq); + // } finally { + // // Reinstate region boundaries + // matcher.to = savedTo; + // } + // return conditionMatched && next.match(matcher, i, seq); + // } + // } + + /** + * Zero width negative lookahead. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static final class Neg extends Node { + // Node cond; + // Neg(Node cond) { + // this.cond = cond; + // } + // boolean match(Matcher matcher, int i, CharSequence seq) { + // int savedTo = matcher.to; + // boolean conditionMatched = false; + + // // Relax transparent region boundaries for lookahead + // if (matcher.transparentBounds) + // matcher.to = matcher.getTextLength(); + // try { + // if (i < matcher.to) { + // conditionMatched = !cond.match(matcher, i, seq); + // } else { + // // If a negative lookahead succeeds then more input + // // could cause it to fail! + // matcher.requireEnd = true; + // conditionMatched = !cond.match(matcher, i, seq); + // } + // } finally { + // // Reinstate region boundaries + // matcher.to = savedTo; + // } + // return conditionMatched && next.match(matcher, i, seq); + // } + // } + + /** + * For use with lookbehinds; matches the position where the lookbehind + * was encountered. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static Node lookbehindEnd = new Node() { + // boolean match(Matcher matcher, int i, CharSequence seq) { + // return i == matcher.lookbehindTo; + // } + // DIFFBLUE MODEL LIBRARY - not used in model + // }; + + /** + * Zero width positive lookbehind. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static class Behind extends Node { + // Node cond; + // int rmax, rmin; + // Behind(Node cond, int rmax, int rmin) { + // this.cond = cond; + // this.rmax = rmax; + // this.rmin = rmin; + // } + + // boolean match(Matcher matcher, int i, CharSequence seq) { + // int savedFrom = matcher.from; + // boolean conditionMatched = false; + // int startIndex = (!matcher.transparentBounds) ? + // matcher.from : 0; + // int from = Math.max(i - rmax, startIndex); + // // Set end boundary + // int savedLBT = matcher.lookbehindTo; + // matcher.lookbehindTo = i; + // // Relax transparent region boundaries for lookbehind + // if (matcher.transparentBounds) + // matcher.from = 0; + // for (int j = i - rmin; !conditionMatched && j >= from; j--) { + // conditionMatched = cond.match(matcher, j, seq); + // } + // matcher.from = savedFrom; + // matcher.lookbehindTo = savedLBT; + // return conditionMatched && next.match(matcher, i, seq); + // } + // } + + /** + * Zero width positive lookbehind, including supplementary + * characters or unpaired surrogates. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static final class BehindS extends Behind { + // BehindS(Node cond, int rmax, int rmin) { + // super(cond, rmax, rmin); + // } + // boolean match(Matcher matcher, int i, CharSequence seq) { + // int rmaxChars = countChars(seq, i, -rmax); + // int rminChars = countChars(seq, i, -rmin); + // int savedFrom = matcher.from; + // int startIndex = (!matcher.transparentBounds) ? + // matcher.from : 0; + // boolean conditionMatched = false; + // int from = Math.max(i - rmaxChars, startIndex); + // // Set end boundary + // int savedLBT = matcher.lookbehindTo; + // matcher.lookbehindTo = i; + // // Relax transparent region boundaries for lookbehind + // if (matcher.transparentBounds) + // matcher.from = 0; + + // for (int j = i - rminChars; + // !conditionMatched && j >= from; + // j -= j>from ? countChars(seq, j, -1) : 1) { + // conditionMatched = cond.match(matcher, j, seq); + // } + // matcher.from = savedFrom; + // matcher.lookbehindTo = savedLBT; + // return conditionMatched && next.match(matcher, i, seq); + // } + // } + + /** + * Zero width negative lookbehind. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static class NotBehind extends Node { + // Node cond; + // int rmax, rmin; + // NotBehind(Node cond, int rmax, int rmin) { + // this.cond = cond; + // this.rmax = rmax; + // this.rmin = rmin; + // } + + // boolean match(Matcher matcher, int i, CharSequence seq) { + // int savedLBT = matcher.lookbehindTo; + // int savedFrom = matcher.from; + // boolean conditionMatched = false; + // int startIndex = (!matcher.transparentBounds) ? + // matcher.from : 0; + // int from = Math.max(i - rmax, startIndex); + // matcher.lookbehindTo = i; + // // Relax transparent region boundaries for lookbehind + // if (matcher.transparentBounds) + // matcher.from = 0; + // for (int j = i - rmin; !conditionMatched && j >= from; j--) { + // conditionMatched = cond.match(matcher, j, seq); + // } + // // Reinstate region boundaries + // matcher.from = savedFrom; + // matcher.lookbehindTo = savedLBT; + // return !conditionMatched && next.match(matcher, i, seq); + // } + // } + + /** + * Zero width negative lookbehind, including supplementary + * characters or unpaired surrogates. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static final class NotBehindS extends NotBehind { + // NotBehindS(Node cond, int rmax, int rmin) { + // super(cond, rmax, rmin); + // } + // boolean match(Matcher matcher, int i, CharSequence seq) { + // int rmaxChars = countChars(seq, i, -rmax); + // int rminChars = countChars(seq, i, -rmin); + // int savedFrom = matcher.from; + // int savedLBT = matcher.lookbehindTo; + // boolean conditionMatched = false; + // int startIndex = (!matcher.transparentBounds) ? + // matcher.from : 0; + // int from = Math.max(i - rmaxChars, startIndex); + // matcher.lookbehindTo = i; + // // Relax transparent region boundaries for lookbehind + // if (matcher.transparentBounds) + // matcher.from = 0; + // for (int j = i - rminChars; + // !conditionMatched && j >= from; + // j -= j>from ? countChars(seq, j, -1) : 1) { + // conditionMatched = cond.match(matcher, j, seq); + // } + // //Reinstate region boundaries + // matcher.from = savedFrom; + // matcher.lookbehindTo = savedLBT; + // return !conditionMatched && next.match(matcher, i, seq); + // } + // } + + /** + * Returns the set union of two CharProperty nodes. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private static CharProperty union(final CharProperty lhs, + // final CharProperty rhs) { + // return new CharProperty() { + // boolean isSatisfiedBy(int ch) { + // return lhs.isSatisfiedBy(ch) || rhs.isSatisfiedBy(ch);}}; + // } + + /** + * Returns the set intersection of two CharProperty nodes. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private static CharProperty intersection(final CharProperty lhs, + // final CharProperty rhs) { + // return new CharProperty() { + // boolean isSatisfiedBy(int ch) { + // return lhs.isSatisfiedBy(ch) && rhs.isSatisfiedBy(ch);}}; + // } + + /** + * Returns the set difference of two CharProperty nodes. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private static CharProperty setDifference(final CharProperty lhs, + // final CharProperty rhs) { + // return new CharProperty() { + // boolean isSatisfiedBy(int ch) { + // return ! rhs.isSatisfiedBy(ch) && lhs.isSatisfiedBy(ch);}}; + // } + + /** + * Handles word boundaries. Includes a field to allow this one class to + * deal with the different types of word boundaries we can match. The word + * characters include underscores, letters, and digits. Non spacing marks + * can are also part of a word if they have a base character, otherwise + * they are ignored for purposes of finding word boundaries. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static final class Bound extends Node { + // static int LEFT = 0x1; + // static int RIGHT= 0x2; + // static int BOTH = 0x3; + // static int NONE = 0x4; + // int type; + // boolean useUWORD; + // Bound(int n, boolean useUWORD) { + // type = n; + // this.useUWORD = useUWORD; + // } + + // boolean isWord(int ch) { + // return useUWORD ? UnicodeProp.WORD.is(ch) + // : (ch == '_' || Character.isLetterOrDigit(ch)); + // } + + // int check(Matcher matcher, int i, CharSequence seq) { + // int ch; + // boolean left = false; + // int startIndex = matcher.from; + // int endIndex = matcher.to; + // if (matcher.transparentBounds) { + // startIndex = 0; + // endIndex = matcher.getTextLength(); + // } + // if (i > startIndex) { + // ch = Character.codePointBefore(seq, i); + // left = (isWord(ch) || + // ((Character.getType(ch) == Character.NON_SPACING_MARK) + // && hasBaseCharacter(matcher, i-1, seq))); + // } + // boolean right = false; + // if (i < endIndex) { + // ch = Character.codePointAt(seq, i); + // right = (isWord(ch) || + // ((Character.getType(ch) == Character.NON_SPACING_MARK) + // && hasBaseCharacter(matcher, i, seq))); + // } else { + // // Tried to access char past the end + // matcher.hitEnd = true; + // // The addition of another char could wreck a boundary + // matcher.requireEnd = true; + // } + // return ((left ^ right) ? (right ? LEFT : RIGHT) : NONE); + // } + // boolean match(Matcher matcher, int i, CharSequence seq) { + // return (check(matcher, i, seq) & type) > 0 + // && next.match(matcher, i, seq); + // } + // } + + /** + * Non spacing marks only count as word characters in bounds calculations + * if they have a base character. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // private static boolean hasBaseCharacter(Matcher matcher, int i, + // CharSequence seq) + // { + // int start = (!matcher.transparentBounds) ? + // matcher.from : 0; + // for (int x=i; x >= start; x--) { + // int ch = Character.codePointAt(seq, x); + // if (Character.isLetterOrDigit(ch)) + // return true; + // if (Character.getType(ch) == Character.NON_SPACING_MARK) + // continue; + // return false; + // } + // return false; + // } + + /** + * Attempts to match a slice in the input using the Boyer-Moore string + * matching algorithm. The algorithm is based on the idea that the + * pattern can be shifted farther ahead in the search text if it is + * matched right to left. + *

+ * The pattern is compared to the input one character at a time, from + * the rightmost character in the pattern to the left. If the characters + * all match the pattern has been found. If a character does not match, + * the pattern is shifted right a distance that is the maximum of two + * functions, the bad character shift and the good suffix shift. This + * shift moves the attempted match position through the input more + * quickly than a naive one position at a time check. + *

+ * The bad character shift is based on the character from the text that + * did not match. If the character does not appear in the pattern, the + * pattern can be shifted completely beyond the bad character. If the + * character does occur in the pattern, the pattern can be shifted to + * line the pattern up with the next occurrence of that character. + *

+ * The good suffix shift is based on the idea that some subset on the right + * side of the pattern has matched. When a bad character is found, the + * pattern can be shifted right by the pattern length if the subset does + * not occur again in pattern, or by the amount of distance to the + * next occurrence of the subset in the pattern. + * + * Boyer-Moore search methods adapted from code by Amy Yu. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static class BnM extends Node { + // int[] buffer; + // int[] lastOcc; + // int[] optoSft; + + // /** + // * Pre calculates arrays needed to generate the bad character + // * shift and the good suffix shift. Only the last seven bits + // * are used to see if chars match; This keeps the tables small + // * and covers the heavily used ASCII range, but occasionally + // * results in an aliased match for the bad character shift. + // */ + // static Node optimize(Node node) { + // if (!(node instanceof Slice)) { + // return node; + // } + + // int[] src = ((Slice) node).buffer; + // int patternLength = src.length; + // // The BM algorithm requires a bit of overhead; + // // If the pattern is short don't use it, since + // // a shift larger than the pattern length cannot + // // be used anyway. + // if (patternLength < 4) { + // return node; + // } + // int i, j, k; + // int[] lastOcc = new int[128]; + // int[] optoSft = new int[patternLength]; + // // Precalculate part of the bad character shift + // // It is a table for where in the pattern each + // // lower 7-bit value occurs + // for (i = 0; i < patternLength; i++) { + // lastOcc[src[i]&0x7F] = i + 1; + // } + // // Precalculate the good suffix shift + // // i is the shift amount being considered +// NEXT: for (i = patternLength; i > 0; i--) { + // // j is the beginning index of suffix being considered + // for (j = patternLength - 1; j >= i; j--) { + // // Testing for good suffix + // if (src[j] == src[j-i]) { + // // src[j..len] is a good suffix + // optoSft[j-1] = i; + // } else { + // // No match. The array has already been + // // filled up with correct values before. + // continue NEXT; + // } + // } + // // This fills up the remaining of optoSft + // // any suffix can not have larger shift amount + // // then its sub-suffix. Why??? + // while (j > 0) { + // optoSft[--j] = i; + // } + // } + // // Set the guard value because of unicode compression + // optoSft[patternLength-1] = 1; + // if (node instanceof SliceS) + // return new BnMS(src, lastOcc, optoSft, node.next); + // return new BnM(src, lastOcc, optoSft, node.next); + // } + // BnM(int[] src, int[] lastOcc, int[] optoSft, Node next) { + // this.buffer = src; + // this.lastOcc = lastOcc; + // this.optoSft = optoSft; + // this.next = next; + // } + // boolean match(Matcher matcher, int i, CharSequence seq) { + // int[] src = buffer; + // int patternLength = src.length; + // int last = matcher.to - patternLength; + + // // Loop over all possible match positions in text +// NEXT: while (i <= last) { + // // Loop over pattern from right to left + // for (int j = patternLength - 1; j >= 0; j--) { + // int ch = seq.charAt(i+j); + // if (ch != src[j]) { + // // Shift search to the right by the maximum of the + // // bad character shift and the good suffix shift + // i += Math.max(j + 1 - lastOcc[ch&0x7F], optoSft[j]); + // continue NEXT; + // } + // } + // // Entire pattern matched starting at i + // matcher.first = i; + // boolean ret = next.match(matcher, i + patternLength, seq); + // if (ret) { + // matcher.first = i; + // matcher.groups[0] = matcher.first; + // matcher.groups[1] = matcher.last; + // return true; + // } + // i++; + // } + // // BnM is only used as the leading node in the unanchored case, + // // and it replaced its Start() which always searches to the end + // // if it doesn't find what it's looking for, so hitEnd is true. + // matcher.hitEnd = true; + // return false; + // } + // boolean study(TreeInfo info) { + // info.minLength += buffer.length; + // info.maxValid = false; + // return next.study(info); + // } + // } + + /** + * Supplementary support version of BnM(). Unpaired surrogates are + * also handled by this class. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static final class BnMS extends BnM { + // int lengthInChars; + + // BnMS(int[] src, int[] lastOcc, int[] optoSft, Node next) { + // super(src, lastOcc, optoSft, next); + // for (int x = 0; x < buffer.length; x++) { + // lengthInChars += Character.charCount(buffer[x]); + // } + // } + // boolean match(Matcher matcher, int i, CharSequence seq) { + // int[] src = buffer; + // int patternLength = src.length; + // int last = matcher.to - lengthInChars; + + // // Loop over all possible match positions in text +// NEXT: while (i <= last) { + // // Loop over pattern from right to left + // int ch; + // for (int j = countChars(seq, i, patternLength), x = patternLength - 1; + // j > 0; j -= Character.charCount(ch), x--) { + // ch = Character.codePointBefore(seq, i+j); + // if (ch != src[x]) { + // // Shift search to the right by the maximum of the + // // bad character shift and the good suffix shift + // int n = Math.max(x + 1 - lastOcc[ch&0x7F], optoSft[x]); + // i += countChars(seq, i, n); + // continue NEXT; + // } + // } + // // Entire pattern matched starting at i + // matcher.first = i; + // boolean ret = next.match(matcher, i + lengthInChars, seq); + // if (ret) { + // matcher.first = i; + // matcher.groups[0] = matcher.first; + // matcher.groups[1] = matcher.last; + // return true; + // } + // i += countChars(seq, i, 1); + // } + // matcher.hitEnd = true; + // return false; + // } + // } + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + + /** + * This must be the very first initializer. + */ + // DIFFBLUE MODEL LIBRARY - not used in model + // static Node accept = new Node(); + + // DIFFBLUE MODEL LIBRARY - not used in model + // static Node lastAccept = new LastNode(); + + // DIFFBLUE MODEL LIBRARY - not used in model + // private static class CharPropertyNames { + + // static CharProperty charPropertyFor(String name) { + // CharPropertyFactory m = map.get(name); + // return m == null ? null : m.make(); + // } + + // private static abstract class CharPropertyFactory { + // abstract CharProperty make(); + // } + + // private static void defCategory(String name, + // final int typeMask) { + // map.put(name, new CharPropertyFactory() { + // CharProperty make() { return new Category(typeMask);}}); + // } + + // private static void defRange(String name, + // final int lower, final int upper) { + // map.put(name, new CharPropertyFactory() { + // CharProperty make() { return rangeFor(lower, upper);}}); + // } + + // private static void defCtype(String name, + // final int ctype) { + // map.put(name, new CharPropertyFactory() { + // CharProperty make() { return new Ctype(ctype);}}); + // } + + // private static abstract class CloneableProperty + // extends CharProperty implements Cloneable + // { + // public CloneableProperty clone() { + // try { + // return (CloneableProperty) super.clone(); + // } catch (CloneNotSupportedException e) { + // throw new AssertionError(e); + // } + // } + // } + + // private static void defClone(String name, + // final CloneableProperty p) { + // map.put(name, new CharPropertyFactory() { + // CharProperty make() { return p.clone();}}); + // } + + // private static final HashMap map + // = new HashMap<>(); + + // static { + // // Unicode character property aliases, defined in + // // http://www.unicode.org/Public/UNIDATA/PropertyValueAliases.txt + // defCategory("Cn", 1< asPredicate() { + // return s -> matcher(s).find(); + CProver.notModelled(); + return CProver.nondetWithoutNullForNotModelled(); + } + + /** + * Creates a stream from the given input sequence around matches of this + * pattern. + * + *

The stream returned by this method contains each substring of the + * input sequence that is terminated by another subsequence that matches + * this pattern or is terminated by the end of the input sequence. The + * substrings in the stream are in the order in which they occur in the + * input. Trailing empty strings will be discarded and not encountered in + * the stream. + * + *

If this pattern does not match any subsequence of the input then + * the resulting stream has just one element, namely the input sequence in + * string form. + * + *

When there is a positive-width match at the beginning of the input + * sequence then an empty leading substring is included at the beginning + * of the stream. A zero-width match at the beginning however never produces + * such empty leading substring. + * + *

If the input sequence is mutable, it must remain constant during the + * execution of the terminal stream operation. Otherwise, the result of the + * terminal stream operation is undefined. + * + * @param input + * The character sequence to be split + * + * @return The stream of strings computed by splitting the input + * around matches of this pattern + * @see #split(CharSequence) + * @since 1.8 + * + * @diffblue.untested + * @diffblue.noSupport + */ + public Stream splitAsStream(final CharSequence input) { + // class MatcherIterator implements Iterator { + // private final Matcher matcher; + // // The start position of the next sub-sequence of input + // // when current == input.length there are no more elements + // private int current; + // // null if the next element, if any, needs to obtained + // private String nextElement; + // // > 0 if there are N next empty elements + // private int emptyElementCount; + + // MatcherIterator() { + // this.matcher = matcher(input); + // } + + // public String next() { + // if (!hasNext()) + // throw new NoSuchElementException(); + + // if (emptyElementCount == 0) { + // String n = nextElement; + // nextElement = null; + // return n; + // } else { + // emptyElementCount--; + // return ""; + // } + // } + + // public boolean hasNext() { + // if (nextElement != null || emptyElementCount > 0) + // return true; + + // if (current == input.length()) + // return false; + + // // Consume the next matching element + // // Count sequence of matching empty elements + // while (matcher.find()) { + // nextElement = input.subSequence(current, matcher.start()).toString(); + // current = matcher.end(); + // if (!nextElement.isEmpty()) { + // return true; + // } else if (current > 0) { // no empty leading substring for zero-width + // // match at the beginning of the input + // emptyElementCount++; + // } + // } + + // // Consume last matching element + // nextElement = input.subSequence(current, input.length()).toString(); + // current = input.length(); + // if (!nextElement.isEmpty()) { + // return true; + // } else { + // // Ignore a terminal sequence of matching empty elements + // emptyElementCount = 0; + // nextElement = null; + // return false; + // } + // } + // } + // return StreamSupport.stream(Spliterators.spliteratorUnknownSize( + // new MatcherIterator(), Spliterator.ORDERED | Spliterator.NONNULL), false); + CProver.notModelled(); + return CProver.nondetWithoutNullForNotModelled(); + } } diff --git a/src/main/java/org/cprover/CProver.java b/src/main/java/org/cprover/CProver.java index 619be30..a1d96b0 100644 --- a/src/main/java/org/cprover/CProver.java +++ b/src/main/java/org/cprover/CProver.java @@ -316,7 +316,12 @@ public static int getMonitorCount(Object object) } /** - * Class identifier of an Object. For instance "java.lang.String", "java.lang.Interger". + * Class identifier of an Object. For instance "java.lang.String", + * "java.lang.Integer". This gives direct read access to the + * {@code @class_identifier} field used internally by JBMC and test-generator. + * The body of this function is replaced by preprocessing of the java + * bytecode, it is only meant to give meaningful output in case the model is + * executed. */ public static String classIdentifier(Object object) { @@ -342,7 +347,7 @@ public static String classIdentifier(Object object) public static float doubleToFloat(double d) { float converted = nondetFloat(); - assert(d == (double) converted); + CProver.assume(d == (double) converted); return converted; } } diff --git a/src/main/java/org/cprover/CProverString.java b/src/main/java/org/cprover/CProverString.java index f26624b..25bbeab 100644 --- a/src/main/java/org/cprover/CProverString.java +++ b/src/main/java/org/cprover/CProverString.java @@ -1,8 +1,10 @@ package org.cprover; -/// This class provides an interface with string functions modeled internally -/// in CProver, for which the CProver model differs from the JDK actual behavior. -/// This is in particular the case for functions that throw exceptions. +/** + * This class provides an interface with string functions modeled internally + * in CProver, for which the CProver model differs from the JDK actual behavior. + * This is in particular the case for functions that throw exceptions. + */ public final class CProverString { /** @@ -63,23 +65,29 @@ public static int offsetByCodePoints( return CProver.nondetInt(); } - /// Modeled internally in CBMC. - /// @return '\u0000' if index is out of bounds and behave as s.charAt(i) - /// otherwise. + /** + * Modeled internally in CBMC. + * @return '\u0000' if index is out of bounds and behave as s.charAt(i) + * otherwise. + */ public static char charAt(String s, int i) { return CProver.nondetChar(); } - /// Modeled internally in CBMC. - /// @return empty string if index is too large, s if index too small and - /// behave as s.substring(i) otherwise. + /** + * Modeled internally in CBMC. + * @return empty string if index is too large, s if index too small and + * behave as s.substring(i) otherwise. + */ public static String substring(String s, int i) { return CProver.nondetWithoutNullForNotModelled(); } - /// Modeled internally in CBMC. - /// @return empty string if i >= j, s.substring(k, l) where k = max(0, i) - /// and l = min(s.length() - 1, j) otherwise. + /** + * Modeled internally in CBMC. + * @return empty string if i >= j, s.substring(k, l) where k = max(0, i) + * and l = min(s.length() - 1, j) otherwise. + */ public static String substring(String s, int i, int j) { return CProver.nondetWithoutNullForNotModelled(); } @@ -93,7 +101,7 @@ public static String substring(String s, int i, int j) { * @return the specified subsequence. */ public static CharSequence subSequence( - String s, int beginIndex, int endIndex) { + String instance, int beginIndex, int endIndex) { return CProver.nondetWithoutNullForNotModelled(); } @@ -102,7 +110,7 @@ public static CharSequence subSequence( * sequence. * * @param instance the StringBuilder instance - * @param s the sequence to append. + * @param cs the sequence to append. * @param start the starting index of the subsequence to be appended. * @param end the end index of the subsequence to be appended. * @return the modified StringBuilder. @@ -198,7 +206,7 @@ public static StringBuilder insert( * * @param instance the StringBuilder instance * @param offset the offset. - * @param b a {@code int}. + * @param i a {@code int}. * @return the modified StringBuilder. */ public static StringBuilder insert( @@ -212,7 +220,7 @@ public static StringBuilder insert( * * @param instance the StringBuilder instance * @param offset the offset. - * @param b a {@code long}. + * @param l a {@code long}. * @return the modified StringBuilder. */ public static StringBuilder insert( @@ -226,7 +234,7 @@ public static StringBuilder insert( * * @param instance the StringBuilder instance * @param offset the offset. - * @param b a {@code float}. + * @param f a {@code float}. * @return the modified StringBuilder. */ public static StringBuilder insert( @@ -240,7 +248,7 @@ public static StringBuilder insert( * * @param instance the StringBuilder instance * @param offset the offset. - * @param b a {@code double}. + * @param d a {@code double}. * @return the modified StringBuilder. */ public static StringBuilder insert( @@ -273,7 +281,7 @@ public static char charAt(StringBuffer instance, int index) { * * @param instance the StringBuffer instance * @param index the index of the character to modify. - * @param ch the new character. + * @param c the new character. */ public static void setCharAt(StringBuffer instance, int index, char c) { } @@ -392,8 +400,9 @@ public static StringBuffer insert( * Converts an array of characters to a string. This uses a loop and * therefore in test-generation the {@code count} will be limited by the * unwind parameter. - * This constrains {@code value} to not be null, its length is greater or equal to - * {@code offset + count} and {@code offset} and {@code count} are non-negative. + * This constrains {@code value} to not be null, its length to be greater + * or equal to {@code offset + count} and {@code offset} and {@code count} + * to be non-negative. * * @param value array of characters which is the source to copy from * @param offset index in {@code value} of the first character to copy diff --git a/src/main/java/sun/misc/DoubleConsts.java b/src/main/java/sun/misc/DoubleConsts.java new file mode 100644 index 0000000..2c5964b --- /dev/null +++ b/src/main/java/sun/misc/DoubleConsts.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.misc; + +/** + * This class contains additional constants documenting limits of the + * double type. + * + * @author Joseph D. Darcy + */ + +public class DoubleConsts { + /** + * Don't let anyone instantiate this class. + */ + private DoubleConsts() {} + + public static final double POSITIVE_INFINITY = java.lang.Double.POSITIVE_INFINITY; + public static final double NEGATIVE_INFINITY = java.lang.Double.NEGATIVE_INFINITY; + public static final double NaN = java.lang.Double.NaN; + public static final double MAX_VALUE = java.lang.Double.MAX_VALUE; + public static final double MIN_VALUE = java.lang.Double.MIN_VALUE; + + /** + * A constant holding the smallest positive normal value of type + * double, 2-1022. It is equal to the + * value returned by + * Double.longBitsToDouble(0x0010000000000000L). + * + * @since 1.5 + */ + public static final double MIN_NORMAL = 2.2250738585072014E-308; + + + /** + * The number of logical bits in the significand of a + * double number, including the implicit bit. + */ + public static final int SIGNIFICAND_WIDTH = 53; + + /** + * Maximum exponent a finite double number may have. + * It is equal to the value returned by + * Math.ilogb(Double.MAX_VALUE). + */ + public static final int MAX_EXPONENT = 1023; + + /** + * Minimum exponent a normalized double number may + * have. It is equal to the value returned by + * Math.ilogb(Double.MIN_NORMAL). + */ + public static final int MIN_EXPONENT = -1022; + + /** + * The exponent the smallest positive double + * subnormal value would have if it could be normalized. It is + * equal to the value returned by + * FpUtils.ilogb(Double.MIN_VALUE). + */ + public static final int MIN_SUB_EXPONENT = MIN_EXPONENT - + (SIGNIFICAND_WIDTH - 1); + + /** + * Bias used in representing a double exponent. + */ + public static final int EXP_BIAS = 1023; + + /** + * Bit mask to isolate the sign bit of a double. + */ + public static final long SIGN_BIT_MASK = 0x8000000000000000L; + + /** + * Bit mask to isolate the exponent field of a + * double. + */ + public static final long EXP_BIT_MASK = 0x7FF0000000000000L; + + /** + * Bit mask to isolate the significand field of a + * double. + */ + public static final long SIGNIF_BIT_MASK = 0x000FFFFFFFFFFFFFL; + + static { + // verify bit masks cover all bit positions and that the bit + // masks are non-overlapping + assert(((SIGN_BIT_MASK | EXP_BIT_MASK | SIGNIF_BIT_MASK) == ~0L) && + (((SIGN_BIT_MASK & EXP_BIT_MASK) == 0L) && + ((SIGN_BIT_MASK & SIGNIF_BIT_MASK) == 0L) && + ((EXP_BIT_MASK & SIGNIF_BIT_MASK) == 0L))); + } +} diff --git a/src/main/java/sun/misc/FloatConsts.java b/src/main/java/sun/misc/FloatConsts.java new file mode 100644 index 0000000..4345c19 --- /dev/null +++ b/src/main/java/sun/misc/FloatConsts.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.misc; + +/** + * This class contains additional constants documenting limits of the + * float type. + * + * @author Joseph D. Darcy + */ + +public class FloatConsts { + /** + * Don't let anyone instantiate this class. + */ + private FloatConsts() {} + + public static final float POSITIVE_INFINITY = java.lang.Float.POSITIVE_INFINITY; + public static final float NEGATIVE_INFINITY = java.lang.Float.NEGATIVE_INFINITY; + public static final float NaN = java.lang.Float.NaN; + public static final float MAX_VALUE = java.lang.Float.MAX_VALUE; + public static final float MIN_VALUE = java.lang.Float.MIN_VALUE; + + /** + * A constant holding the smallest positive normal value of type + * float, 2-126. It is equal to the value + * returned by Float.intBitsToFloat(0x00800000). + */ + public static final float MIN_NORMAL = 1.17549435E-38f; + + /** + * The number of logical bits in the significand of a + * float number, including the implicit bit. + */ + public static final int SIGNIFICAND_WIDTH = 24; + + /** + * Maximum exponent a finite float number may have. + * It is equal to the value returned by + * Math.ilogb(Float.MAX_VALUE). + */ + public static final int MAX_EXPONENT = 127; + + /** + * Minimum exponent a normalized float number may + * have. It is equal to the value returned by + * Math.ilogb(Float.MIN_NORMAL). + */ + public static final int MIN_EXPONENT = -126; + + /** + * The exponent the smallest positive float subnormal + * value would have if it could be normalized. It is equal to the + * value returned by FpUtils.ilogb(Float.MIN_VALUE). + */ + public static final int MIN_SUB_EXPONENT = MIN_EXPONENT - + (SIGNIFICAND_WIDTH - 1); + + /** + * Bias used in representing a float exponent. + */ + public static final int EXP_BIAS = 127; + + /** + * Bit mask to isolate the sign bit of a float. + */ + public static final int SIGN_BIT_MASK = 0x80000000; + + /** + * Bit mask to isolate the exponent field of a + * float. + */ + public static final int EXP_BIT_MASK = 0x7F800000; + + /** + * Bit mask to isolate the significand field of a + * float. + */ + public static final int SIGNIF_BIT_MASK = 0x007FFFFF; + + static { + // verify bit masks cover all bit positions and that the bit + // masks are non-overlapping + assert(((SIGN_BIT_MASK | EXP_BIT_MASK | SIGNIF_BIT_MASK) == ~0) && + (((SIGN_BIT_MASK & EXP_BIT_MASK) == 0) && + ((SIGN_BIT_MASK & SIGNIF_BIT_MASK) == 0) && + ((EXP_BIT_MASK & SIGNIF_BIT_MASK) == 0))); + } +}