// // 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.Function; import cmu.conditional.Conditional; import cmu.conditional.One; import de.fosd.typechef.featureexpr.FeatureExpr; import gov.nasa.jpf.annotation.MJI; /** * MJI NativePeer class for java.lang.StringBuffer library abstraction */ public class JPF_java_lang_StringBuffer extends NativePeer { boolean hasSharedField = false; // Java 1.4 has, 1.5 doesn't @MJI public void $clinit____V(MJIEnv env, int clsObjRef, FeatureExpr ctx) { // apparently, Java 1.5 has changed the implementation of class // StringBuffer so that it doesn't use the 'shared' state anymore // (which was a performance hack to avoid copying the char array // data when creating String objects from subsequently unmodified // StringBuffers // adding this little extra logic here also serves the purpose of // avoiding a native ObjectStreamClass method which is called during // the static StringBuffer init ClassInfo ci = env.getClassInfo(); if (ci.getInstanceField("shared") != null) { hasSharedField = true; } } @Deprecated int appendString(MJIEnv env, int objref, String s, FeatureExpr ctx) { return appendString(env, objref, new One<>(s), ctx); } int appendString(final MJIEnv env, final int objref, final Conditional<String> s, FeatureExpr ctx) { try { final Conditional<Integer> aref = env.getReferenceField(ctx, objref, "value"); aref.mapf(ctx, new BiConsumer<FeatureExpr, Integer>() { @Override public void accept(FeatureExpr ctx, final Integer aref) { final int alen = env.getArrayLength(ctx, aref); s.mapf(ctx, new BiConsumer<FeatureExpr, String>() { @Override public void accept(FeatureExpr ctx, final String s) { final int slen = s.length(); 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); } if (hasSharedField) { env.setBooleanField(ctx, objref, "shared", One.FALSE); } env.setIntField(ctx, objref, "count", new One<>(n)); } }); } }); } }); } catch (Exception e) { System.out.println("JPF_java_lang_StringBuffer.appendString()"); System.out.println(e); for (StackTraceElement t : e.getStackTrace()) { System.out.println(t); } } return objref; } /* * public static int append__Ljava_lang_StringBuffer_2 (MJIEnv env, int objref, int sbref) { * int vref = env.getReferenceField(sbref, "value"); * int sbCount = env.getIntField(sbref, "count"); * // how braindead, how lazy * char[] b = env.getCharArrayObject(vref); * String s = new String(b, 0, sbCount); * return appendString(env, objref, s); * } */ @MJI public int append__Ljava_lang_String_2__Ljava_lang_StringBuffer_2(final MJIEnv env, int 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(env, objref, s, ctx); } @MJI public int append__I__Ljava_lang_StringBuffer_2(MJIEnv env, int objref, int i, FeatureExpr ctx) { String s = Integer.toString(i); return appendString(env, objref, s, ctx); } @MJI public int append__F__Ljava_lang_StringBuffer_2(MJIEnv env, int objref, float f, FeatureExpr ctx) { String s = Float.toString(f); return appendString(env, objref, s, ctx); } @MJI public int append__D__Ljava_lang_StringBuffer_2(MJIEnv env, int objref, double d, FeatureExpr ctx) { String s = Double.toString(d); return appendString(env, objref, s, ctx); } @MJI public int append__J__Ljava_lang_StringBuffer_2(MJIEnv env, int objref, long l, FeatureExpr ctx) { String s = Long.toString(l); return appendString(env, objref, s, ctx); } @MJI public int append__Z__Ljava_lang_StringBuffer_2(MJIEnv env, int objref, boolean b, FeatureExpr ctx) { String s = b ? "true" : "false"; return appendString(env, objref, s, ctx); } /* * public static int append__B__Ljava_lang_StringBuffer_2 (MJIEnv env, int objref, byte b) { * return append__C__Ljava_lang_StringBuffer_2(env, objref, (char)b); * } */ @MJI public int append__C__Ljava_lang_StringBuffer_2(MJIEnv env, int objref, char c, FeatureExpr ctx) { return appendString(env, objref, "" + c, ctx); // int aref = env.getReferenceField(ctx, objref, "value").getValue(); // int alen = env.getArrayLength(ctx, aref); // // int count = env.getIntField(objref, "count").getValue().intValue(); // int n = count + 1; // // if (n < alen) { // env.setCharArrayElement(ctx, aref, count, new One<>(c)); // } else { // int m = 3 * alen / 2; // int arefNew = env.newCharArray(ctx, m); // for (int i = 0; i < count; i++) { // env.setCharArrayElement(ctx, arefNew, i, env.getCharArrayElement(aref, i)); // } // env.setCharArrayElement(ctx, arefNew, count, new One<>(c)); // env.setReferenceField(ctx, objref, "value", arefNew); // } // // if (hasSharedField) { // env.setBooleanField(ctx, objref, "shared", new One<>(false)); // } // env.setIntField(ctx, objref, "count", new One<>(n)); // // return objref; } }