Skip to content

Commit e2cd3ed

Browse files
Add a model of String.format
This uses CProverString.format which is builtin in the string solver.
1 parent c2fdd88 commit e2cd3ed

File tree

1 file changed

+66
-2
lines changed

1 file changed

+66
-2
lines changed

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

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3884,6 +3884,59 @@ 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+
{
3894+
if(obj == null)
3895+
return "";
3896+
if(obj instanceof String)
3897+
return (String)obj;
3898+
if(obj instanceof Integer)
3899+
{
3900+
int intValue = (Integer)obj;
3901+
// Fixed width translation
3902+
String result = cproverNonDet();
3903+
CProver.assume(result.length() == 4);
3904+
CProver.assume(CProverString.charAt(result, 0) == (char) 0);
3905+
CProver.assume(CProverString.charAt(result, 0) == (char) 0);
3906+
CProver.assume(CProverString.charAt(result, 2) == (char) (intValue & 0xFFFF));
3907+
CProver.assume(CProverString.charAt(result, 3) == (char) (intValue & 0xFFFF));
3908+
return result;
3909+
}
3910+
if(obj instanceof Character)
3911+
return String.valueOf(((Character) obj).charValue());
3912+
if(obj instanceof Byte)
3913+
return String.valueOf((char)((Byte) obj).byteValue());
3914+
if(obj instanceof Long) {
3915+
long longValue = (Long) obj;
3916+
// Fixed width translation
3917+
// Fixed width translation
3918+
String result = cproverNonDet();
3919+
CProver.assume(result.length() == 4);
3920+
CProver.assume(CProverString.charAt(result, 0) == (char) 0);
3921+
CProver.assume(CProverString.charAt(result, 0) == (char) 0);
3922+
CProver.assume(CProverString.charAt(result, 2) == (char) (longValue & 0xFFFF));
3923+
CProver.assume(CProverString.charAt(result, 3) == (char) (longValue & 0xFFFF));
3924+
return result;
3925+
}
3926+
if(obj instanceof Boolean)
3927+
return ((Boolean) obj) ? "true" : "false";
3928+
if(obj instanceof Float || obj instanceof Double) {
3929+
double doubleValue = obj instanceof Float
3930+
? ((Float)obj).doubleValue() :(Double) obj;
3931+
// Fixed width translation
3932+
char charArray[] = {
3933+
(char) ((long)doubleValue >> 24), (char) ((long)doubleValue >> 16 & 0xFFFF),
3934+
(char) ((long)doubleValue >> 8 & 0xFFFF), (char) ((long)doubleValue & 0xFFFF)};
3935+
return new String(charArray);
3936+
}
3937+
return "";
3938+
}
3939+
38873940
/**
38883941
* Returns a formatted string using the specified format string and
38893942
* arguments.
@@ -3946,9 +3999,20 @@ public char[] toCharArray() {
39463999
* @diffblue.untested
39474000
*/
39484001
public static String format(String format, Object... args) {
3949-
// DIFFBLUE MODEL LIBRARY This is treated internally in CBMC
3950-
return CProver.nondetWithoutNullForNotModelled();
4002+
// DIFFBLUE MODEL LIBRARY
39514003
// return new Formatter().format(format, args).toString();
4004+
String arg1 = args.length > 0 ? cproverFormatArgument(args[0]) : "";
4005+
String arg2 = args.length > 1 ? cproverFormatArgument(args[1]) : "";
4006+
String arg3 = args.length > 2 ? cproverFormatArgument(args[2]) : "";
4007+
String arg4 = args.length > 3 ? cproverFormatArgument(args[3]) : "";
4008+
String arg5 = args.length > 4 ? cproverFormatArgument(args[4]) : "";
4009+
String arg6 = args.length > 5 ? cproverFormatArgument(args[5]) : "";
4010+
String arg7 = args.length > 6 ? cproverFormatArgument(args[6]) : "";
4011+
String arg8 = args.length > 7 ? cproverFormatArgument(args[7]) : "";
4012+
String arg9 = args.length > 8 ? cproverFormatArgument(args[8]) : "";
4013+
String arg10 = args.length > 9 ? cproverFormatArgument(args[9]) : "";
4014+
return CProverString.format(format, arg1, arg2, arg3, arg4, arg5, arg6,
4015+
arg7, arg8, arg9, arg10);
39524016
}
39534017

39544018
/**

0 commit comments

Comments
 (0)