//
// Copyright (C) 2006 United States Government as represented by the
// Administrator of the National Aeronautics and Space Administration
// (NASA). All Rights Reserved.
//
// This software is distributed under the NASA Open Source Agreement
// (NOSA), version 1.3. The NOSA has been approved by the Open Source
// Initiative. See the file NOSA-1.3-JPF at the top of the distribution
// directory tree for the complete NOSA document.
//
// THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY
// KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT
// LIMITED TO, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL CONFORM TO
// SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
// A PARTICULAR PURPOSE, OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT
// THE SUBJECT SOFTWARE WILL BE ERROR FREE, OR ANY WARRANTY THAT
// DOCUMENTATION, IF PROVIDED, WILL CONFORM TO THE SUBJECT SOFTWARE.
//
package gov.nasa.jpf.vm;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Function;
import cmu.conditional.Conditional;
import cmu.conditional.One;
import de.fosd.typechef.featureexpr.FeatureExpr;
import gov.nasa.jpf.annotation.MJI;
public class JPF_java_lang_StringBuilder extends NativePeer {
@Deprecated
int appendString(FeatureExpr ctx, MJIEnv env, int objref, String s) {
return appendString(ctx, env, objref, new One<>(s));
}
Conditional<Integer> appendString(FeatureExpr ctx, final MJIEnv env, final Conditional<Integer> objref, final Conditional<String> conditionalS) {
return objref.mapf(ctx, new BiFunction<FeatureExpr, Integer, Conditional<Integer>>() {
@Override
public Conditional<Integer> apply(FeatureExpr ctx, Integer objref) {
return new One<>(appendString(ctx, env, objref, conditionalS));
}
});
}
int appendString(FeatureExpr ctx, final MJIEnv env, final int objref, final Conditional<String> conditionalS) {
Conditional<Integer> condAref = env.getReferenceField(ctx, objref, "value");
condAref.mapf(ctx, new BiConsumer<FeatureExpr, Integer>() {
@Override
public void accept(FeatureExpr ctx, final Integer aref) {
conditionalS.mapf(ctx, new BiConsumer<FeatureExpr, String>() {
@Override
public void accept(FeatureExpr ctx, final String s) {
final int slen = s.length();
final int alen = env.getArrayLength(ctx, aref);
Conditional<Integer> count = env.getIntField(objref, "count");
count.mapf(ctx, new BiConsumer<FeatureExpr, Integer>() {
@Override
public void accept(FeatureExpr ctx, Integer count) {
if (Conditional.isContradiction(ctx)) {
return;
}
int i, j;
int n = count + slen;
if (n < alen) {
for (i = count, j = 0; i < n; i++, j++) {
env.setCharArrayElement(ctx, aref, i, new One<>(s.charAt(j)));
}
} else {
int m = 3 * alen / 2;
if (m < n) {
m = n;
}
int arefNew = env.newCharArray(ctx, m);
for (i = 0; i < count; i++) {
env.setCharArrayElement(ctx, arefNew, i, env.getCharArrayElement(aref, i));
}
for (j = 0; i < n; i++, j++) {
env.setCharArrayElement(ctx, arefNew, i, new One<>(s.charAt(j)));
}
env.setReferenceField(ctx, objref, "value", arefNew);
}
env.setIntField(ctx, objref, "count", new One<>(n));
}
});
}
});
}
});
return objref;
}
// we skip the AbstractStringBuilder ctor here, which is a bit dangerous
// This is only justified because StringBuilders are used everywhere (implicitly)
@MJI
public void $init____V(MJIEnv env, int objref, FeatureExpr ctx) {
int aref = env.newCharArray(ctx, 16);
env.setReferenceField(ctx, objref, "value", aref);
}
@MJI
public void $init__I__V(final MJIEnv env, final int objref, Conditional<Integer> len, FeatureExpr ctx) {
len.mapf(ctx, new BiConsumer<FeatureExpr, Integer>() {
@Override
public void accept(FeatureExpr ctx, Integer len) {
int aref = env.newCharArray(ctx, len);
env.setReferenceField(ctx, objref, "value", aref);
}
});
}
@MJI
// TODO can be improved
public void $init__Ljava_lang_String_2__V(final MJIEnv env, final int objref, Conditional<Integer> sRef, FeatureExpr ctx) {
sRef.mapf(ctx, new BiConsumer<FeatureExpr, Integer>() {
@Override
public void accept(FeatureExpr ctx, Integer sRef) {
if (sRef.intValue() == MJIEnv.NULL) {
env.throwException(ctx, "java.lang.NullPointerException");
return;
}
Conditional<char[]> src = env.getStringChars(sRef);
src.mapf(ctx, new BiConsumer<FeatureExpr, char[]>() {
@Override
public void accept(final FeatureExpr ctx, final char[] src) {
if (Conditional.isContradiction(ctx)) {
return;
}
int aref = env.newCharArray(ctx, src.length + 16);
// char[] dst = env.getCharArrayObject(aref).getValue();
for (int i = 0; i < src.length; i++) {
env.setCharArrayElement(ctx, aref, i, new One<>(src[i]));
}
// System.arraycopy(src, 0, dst, 0, src.length);
env.setReferenceField(ctx, objref, "value", aref);
env.setIntField(ctx, objref, "count", new One<>(src.length));
}
});
}
});
}
@MJI
public Conditional<Integer> append__Ljava_lang_String_2__Ljava_lang_StringBuilder_2(final MJIEnv env, Conditional<Integer> objref, Conditional<Integer> sref, FeatureExpr ctx) {
Conditional<String> s = sref.mapr(new Function<Integer, Conditional<String>>() {
@Override
public Conditional<String> apply(Integer sref) {
return env.getConditionalStringObject(sref);
}
});
s = s.simplify(ctx).map(new Function<String, String>() {
@Override
public String apply(final String s) {
if (s == null) {
return "null";
}
return s;
}
}).simplifyValues();
return appendString(ctx, env, objref, s);
}
@MJI
public int append__I__Ljava_lang_StringBuilder_2(MJIEnv env, int objref, Conditional<Integer> i, FeatureExpr ctx) {
Conditional<String> s = i.map(new Function<Integer, String>() {
@Override
public String apply(Integer i) {
return Integer.toString(i);
}
});
return appendString(ctx, env, objref, s);
}
@MJI
public int append__F__Ljava_lang_StringBuilder_2(MJIEnv env, int objref, float f, FeatureExpr ctx) {
String s = Float.toString(f);
return appendString(ctx, env, objref, s);
}
@MJI
public int append__D__Ljava_lang_StringBuilder_2(MJIEnv env, int objref, Conditional<Double> d, FeatureExpr ctx) {
Conditional<String> s = d.map(new Function<Double, String>() {
@Override
public String apply(Double d) {
return Double.toString(d);
}
});
return appendString(ctx, env, objref, s);
}
@MJI
public int append__J__Ljava_lang_StringBuilder_2(MJIEnv env, int objref, Conditional<Long> l, FeatureExpr ctx) {
Conditional<String> s = l.map(new Function<Long, String>() {
@Override
public String apply(Long l) {
return Long.toString(l);
}
});
return appendString(ctx, env, objref, s);
}
@MJI
public int append__Z__Ljava_lang_StringBuilder_2(MJIEnv env, int objref, Conditional<Boolean> b, FeatureExpr ctx) {
Conditional<String> s = b.map(new Function<Boolean, String>() {
@Override
public String apply(Boolean b) {
return b ? "true" : "false";
}
});
return appendString(ctx, env, objref, s);
}
@MJI
public int append__C__Ljava_lang_StringBuilder_2(MJIEnv env, Conditional<Integer> objref, Conditional<Character> c, FeatureExpr ctx) {
Conditional<String> s = c.map(new Function<Character, String>() {
@Override
public String apply(Character c) {
return c + "";
}
});
return appendString(ctx, env, objref.getValue(), s);
//
// int aref = env.getReferenceField(ctx, objref, "value").getValue();
// int alen = env.getArrayLength(aref);
//
// int count = env.getIntField(ctx, objref, "count").getValue().intValue();
// int i;
// int n = count +1;
//
// if (n < alen) {
// env.setCharArrayElement(ctx, aref, count, c);
// } else {
// int m = 3 * alen / 2;
// int arefNew = env.newCharArray(ctx, m);
// for (i=0; i<count; i++) {
// env.setCharArrayElement(ctx, arefNew, i, env.getCharArrayElement(aref, i).getValue());
// }
// env.setCharArrayElement(ctx, arefNew, count, c);
// env.setReferenceField(ctx, objref, "value", arefNew);
// }
//
// env.setIntField(ctx, objref, "count", n);
//
// return objref;
}
@MJI
public int toString____Ljava_lang_String_2(final MJIEnv env, final int objref, FeatureExpr ctx) {
Conditional<Integer> aref = env.getReferenceField(ctx, objref, "value");
Conditional<String> s = aref.mapf(ctx, new BiFunction<FeatureExpr, Integer, Conditional<String>>() {
@Override
public Conditional<String> apply(FeatureExpr ctx, Integer aref) {
Conditional<char[]> buf = env.getCharArrayObject(aref).simplify(ctx);
return buf.mapf(ctx, new BiFunction<FeatureExpr, char[], Conditional<String>>() {
@Override
public Conditional<String> apply(FeatureExpr ctx, final char[] buf) {
final Conditional<Integer> count = env.getIntField(objref, "count").simplify(ctx);
return count.mapf(ctx, new BiFunction<FeatureExpr, Integer, Conditional<String>>() {
@Override
public Conditional<String> apply(FeatureExpr ctx, Integer count) {
return new One<>(new String(buf, 0, count));
}
});
}
});
}
}).simplify();
return env.newString(ctx, s);
}
@SuppressWarnings("deprecation")
@MJI
public Conditional<Integer> indexOf__Ljava_lang_String_2I__I(final MJIEnv env, int objref, final int str, final int fromIndex, FeatureExpr ctx) {
Integer aref = env.getReferenceField(ctx, objref, "value").getValue();
Conditional<char[]> buf = env.getCharArrayObject(aref);
return buf.mapf(ctx, new BiFunction<FeatureExpr, char[], Conditional<Integer>>() {
@Override
public Conditional<Integer> apply(FeatureExpr ctx, char[] buf) {
String indexStr = env.getStringObject(ctx, str);
return new One<>(new String(buf).indexOf(indexStr, fromIndex));
}
});
}
@MJI
public int substring__I__Ljava_lang_String_2(MJIEnv env, int objRef, int beginIndex, FeatureExpr ctx) {
Integer aref = env.getReferenceField(ctx, objRef, "value").getValue();
char[] buf = env.getCharArrayObject(aref).getValue();
String obj = new String(buf);
String result = obj.substring(beginIndex);
return env.newString(ctx, result);
}
@MJI
public int substring__II__Ljava_lang_String_2(MJIEnv env, int objRef, final Conditional<Integer> beginIndex, final Conditional<Integer> endIndex, FeatureExpr ctx) {
Integer aref = env.getReferenceField(ctx, objRef, "value").getValue();
Conditional<char[]> buf = env.getCharArrayObject(aref);
Conditional<String> result = buf.mapf(ctx, new BiFunction<FeatureExpr, char[], Conditional<String>>() {
@Override
public Conditional<String> apply(FeatureExpr ctx, char[] buf) {
String obj = new String(buf);
return new One<>(obj.substring(beginIndex.getValue(), endIndex.getValue()));
}
});
return env.newString(ctx, result);
}
@MJI
public int delete__II__Ljava_lang_StringBuilder_2(final MJIEnv env, final int objref, final Integer beginIndex, final Integer endIndex, FeatureExpr ctx) {
final Integer aref = env.getReferenceField(ctx, objref, "value").getValue();
Conditional<Integer> count = env.getIntField(objref, "count");
final int diff = endIndex - beginIndex;
count.mapf(ctx, new BiConsumer<FeatureExpr, Integer>() {
@Override
public void accept(FeatureExpr ctx, Integer count) {
for (int i = beginIndex, j = endIndex; i < count; i++, j++) {
if (j < count) {
env.setCharArrayElement(ctx, aref, i, env.getCharArrayElement(aref, j));
} else {
env.setCharArrayElement(ctx, aref, i, new One<>(' '));
}
}
env.setIntField(ctx, objref, "count", new One<>(count - diff));
}
});
return objref;
}
}