diff --git a/src/main/java/java/lang/String.java b/src/main/java/java/lang/String.java index 0ac8bad..2881dbe 100644 --- a/src/main/java/java/lang/String.java +++ b/src/main/java/java/lang/String.java @@ -3089,11 +3089,13 @@ 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 test can be generated for these characters. */ public String[] split(String regex, int limit) { - CProver.notModelled(); - return CProver.nondetWithNullForNotModelled(); // /* fastpath if the regex is a // (1)one-char String and this character is not one of the // RegEx's meta characters ".$|()[{^?*+\\", or @@ -3145,6 +3147,74 @@ public String[] split(String regex, int limit) { // return list.subList(0, resultSize).toArray(result); // } // return Pattern.compile(regex).split(this, limit); + + // DIFFBLUE MODELS LIBRARY + if (limit == 0) { + return split(regex); + } + + int size = CProver.nondetInt(); + CProver.assume(size >= 0); + String[] result = new String[size]; + + int tokenStart = 0; + int tokenIndex = 0; + + if (regex.length() == 0) { + do { + CProver.assume(size > tokenIndex); + if (tokenStart == length() || tokenIndex == limit - 1) { + // extract the remainder of the string + result[tokenIndex++] = + CProverString.substring(this, tokenStart, length()); + // stop here + tokenStart = -1; + } else { + // extract the token prior to the delimiter + result[tokenIndex++] = + CProverString.substring(this, tokenStart, tokenStart + 1); + tokenStart = tokenStart + 1; + } + } while (tokenStart >= 0 && (limit <= 0 || tokenIndex < limit)); + + // Ensure the size of the array corresponds to the number of tokens + CProver.assume(tokenIndex == size); + return result; + } + + // We only handle single character delimiters + CProver.assume(regex.length() <= 1); + char delimiter = CProverString.charAt(regex, 0); + + // We don't handle special regex characters \.[{()<>*+-=?^$| + CProver.assume(delimiter != '\\' && delimiter != '.' && delimiter != '[' + && delimiter != '{' && delimiter != '(' + && delimiter != ')' && delimiter != '<' + && delimiter != '>' && delimiter != '*' + && delimiter != '+' && delimiter != '-' + && delimiter != '=' && delimiter != '?' + && delimiter != '^' && delimiter != '$'); + + do { + int tokenEnd = indexOf(delimiter, tokenStart); + CProver.assume(size > tokenIndex); + if (tokenEnd == -1 || tokenIndex == limit - 1) { + // extract the remainder of the string + result[tokenIndex++] = + CProverString.substring(this, tokenStart, length()); + // stop here + tokenStart = -1; + } else { + // extract the token prior to the delimiter + result[tokenIndex++] = + CProverString.substring(this, tokenStart, tokenEnd); + tokenStart = tokenEnd + 1; + } + } while (tokenStart >= 0 && (limit <= 0 || tokenIndex < limit)); + + // Ensure the size of the array corresponds to the number of tokens + CProver.assume(tokenIndex == size); + return result; } /** @@ -3185,12 +3255,79 @@ 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 test can be generated for these characters. */ public String[] split(String regex) { - CProver.notModelled(); - return CProver.nondetWithNullForNotModelled(); // return split(regex, 0); + + // DIFFBLUE MODELS LIBRARY + int size = CProver.nondetInt(); + CProver.assume(size >= 0); + String[] result = new String[size]; + int tokenIndex = 0; + int tokenStart = 0; + + if (regex.length() == 0) { + CProver.assume(size > tokenIndex); + if (length() == 0) { + result[tokenIndex++] = ""; + } + while (tokenStart < length()) { + result[tokenIndex++] = + CProverString.substring(this, tokenStart, tokenStart + 1); + tokenStart = tokenStart + 1; + } + // Ensure the size of the array corresponds to the number of tokens + CProver.assume(tokenIndex == size); + return result; + } + + // We only handle single character delimiters + CProver.assume(regex.length() == 1); + char delimiter = CProverString.charAt(regex, 0); + + // We don't handle special regex characters \.[{()<>*+-=?^$| + CProver.assume(delimiter != '\\' && delimiter != '.' && delimiter != '[' + && delimiter != '{' && delimiter != '(' + && delimiter != ')' && delimiter != '<' + && delimiter != '>' && delimiter != '*' + && delimiter != '+' && delimiter != '-' + && delimiter != '=' && delimiter != '?' + && delimiter != '^' && delimiter != '$'); + + do { + int tokenEnd = indexOf(delimiter, tokenStart); + if (tokenIndex >= size && tokenIndex >= 1) { + // Ignore trailing empty strings + CProver.assume(tokenEnd == tokenStart); + tokenStart++; + } else if (tokenEnd >= 0) { + // extract the token prior to the delimiter + CProver.assume(size > tokenIndex); + result[tokenIndex++] = + CProverString.substring(this, tokenStart, tokenEnd); + // Ensure trailing empty strings are skipped + CProver.assume(tokenEnd != tokenStart || tokenIndex != size); + tokenStart = tokenEnd + 1; + } else { + // extract the remainder of the string + CProver.assume(size > tokenIndex); + result[tokenIndex++] = + CProverString.substring(this, tokenStart, length()); + // Ensure trailing empty strings are skipped + CProver.assume(length() > tokenStart); + // stop here + tokenStart = -1; + } + } while (tokenStart >= 0 && tokenStart < length()); + + // Ensure the size of the array corresponds to the number of tokens + CProver.assume(tokenIndex == size); + return result; } /** diff --git a/src/main/java/java/lang/StringBuilder.java b/src/main/java/java/lang/StringBuilder.java index d583dad..84d0ecd 100644 --- a/src/main/java/java/lang/StringBuilder.java +++ b/src/main/java/java/lang/StringBuilder.java @@ -611,14 +611,22 @@ public int lastIndexOf(String str, int fromIndex) { } /** - * @diffblue.noSupport + * @diffblue.fullSupport + * @diffblue.untested */ @Override public StringBuilder reverse() { // super.reverse(); // return this; - CProver.notModelled(); - return CProver.nondetWithNullForNotModelled(); + int size = this.length(); + if (size < 2) + return this; + String tmp = this.toString(); + CProverString.delete(this, 0, size); + for (int i=size-1; i>=0; --i) { + this.append(CProverString.charAt(tmp, i)); + } + return this; } /**