Skip to content

Commit 9f561d9

Browse files
Add a model of String.format
This uses CProverString.format which is builtin in the string solver.
1 parent 59cfa41 commit 9f561d9

File tree

1 file changed

+56
-5
lines changed

1 file changed

+56
-5
lines changed

src/main/java/java/lang/String.java

Lines changed: 56 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3884,6 +3884,44 @@ public char[] toCharArray() {
38843884
return result;
38853885
}
38863886

3887+
/**
3888+
* Helper function for the {@code format} function.
3889+
* Serialize potential String.format argument to a String.
3890+
* The returned String is never null.
3891+
*/
3892+
static String cproverFormatArgument(Object obj) {
3893+
if (obj == null) return "null";
3894+
if (obj instanceof String) return (String) obj;
3895+
3896+
// All primitive types are cast to a long
3897+
long longValue = 0;
3898+
if (obj instanceof Integer) {
3899+
longValue = (Integer) obj;
3900+
} else if (obj instanceof Long) {
3901+
longValue = (Long) obj;
3902+
} else if (obj instanceof Float) {
3903+
longValue = (long) ((Float) obj).doubleValue();
3904+
} else if (obj instanceof Double) {
3905+
longValue = (long) ((Double) obj).doubleValue();
3906+
} else if (obj instanceof Character) {
3907+
char charValue = (Character) obj;
3908+
longValue = (long) charValue;
3909+
} else if (obj instanceof Byte) {
3910+
byte byteValue = ((Byte) obj);
3911+
longValue = (long) byteValue;
3912+
} else if (obj instanceof Boolean) {
3913+
longValue = ((Boolean) obj) ? 1 : 0;
3914+
}
3915+
3916+
// The long value is encoded using a string of 4 characters
3917+
StringBuilder builder = new StringBuilder();
3918+
builder.append((char) (longValue >> 48 & 0xFFFF));
3919+
builder.append((char) (longValue >> 32 & 0xFFFF));
3920+
builder.append((char) (longValue >> 16 & 0xFFFF));
3921+
builder.append((char) (longValue & 0xFFFF));
3922+
return builder.toString();
3923+
}
3924+
38873925
/**
38883926
* Returns a formatted string using the specified format string and
38893927
* arguments.
@@ -3946,9 +3984,23 @@ public char[] toCharArray() {
39463984
* @diffblue.untested
39473985
*/
39483986
public static String format(String format, Object... args) {
3949-
// DIFFBLUE MODEL LIBRARY This is treated internally in CBMC
3950-
return CProver.nondetWithoutNullForNotModelled();
39513987
// return new Formatter().format(format, args).toString();
3988+
// DIFFBLUE MODEL LIBRARY
3989+
if (args.length > 10) {
3990+
return CProver.nondetWithoutNull("");
3991+
}
3992+
String arg0 = args.length > 0 ? cproverFormatArgument(args[0]) : "";
3993+
String arg1 = args.length > 1 ? cproverFormatArgument(args[1]) : "";
3994+
String arg2 = args.length > 2 ? cproverFormatArgument(args[2]) : "";
3995+
String arg3 = args.length > 3 ? cproverFormatArgument(args[3]) : "";
3996+
String arg4 = args.length > 4 ? cproverFormatArgument(args[4]) : "";
3997+
String arg5 = args.length > 5 ? cproverFormatArgument(args[5]) : "";
3998+
String arg6 = args.length > 6 ? cproverFormatArgument(args[6]) : "";
3999+
String arg7 = args.length > 7 ? cproverFormatArgument(args[7]) : "";
4000+
String arg8 = args.length > 8 ? cproverFormatArgument(args[8]) : "";
4001+
String arg9 = args.length > 9 ? cproverFormatArgument(args[9]) : "";
4002+
return CProverString.format(format, arg0, arg1, arg2, arg3, arg4, arg5,
4003+
arg6, arg7, arg8, arg9);
39524004
}
39534005

39544006
/**
@@ -3988,12 +4040,11 @@ public static String format(String format, Object... args) {
39884040
* @see java.util.Formatter
39894041
* @since 1.5
39904042
*
3991-
* @diffblue.noSupport
4043+
* @diffblue.limitedSupport The locale argument is ignored
39924044
*/
39934045
public static String format(Locale l, String format, Object... args) {
39944046
// return new Formatter(l).format(format, args).toString();
3995-
CProver.notModelled();
3996-
return CProver.nondetWithoutNullForNotModelled();
4047+
return format(format, args);
39974048
}
39984049

39994050
/**

0 commit comments

Comments
 (0)