Preparing for tracking the object creation etc.
[jpf-core.git] / src / peers / gov / nasa / jpf / vm / JPF_java_lang_StringBuffer.java
1 /*
2  * Copyright (C) 2014, United States Government, as represented by the
3  * Administrator of the National Aeronautics and Space Administration.
4  * All rights reserved.
5  *
6  * The Java Pathfinder core (jpf-core) platform is licensed under the
7  * Apache License, Version 2.0 (the "License"); you may not use this file except
8  * in compliance with the License. You may obtain a copy of the License at
9  * 
10  *        http://www.apache.org/licenses/LICENSE-2.0. 
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and 
16  * limitations under the License.
17  */
18 package gov.nasa.jpf.vm;
19
20 import gov.nasa.jpf.annotation.MJI;
21 import gov.nasa.jpf.vm.ClassInfo;
22 import gov.nasa.jpf.vm.MJIEnv;
23 import gov.nasa.jpf.vm.NativePeer;
24
25
26 /**
27  * MJI NativePeer class for java.lang.StringBuffer library abstraction
28  */
29 public class JPF_java_lang_StringBuffer extends NativePeer {
30   
31   boolean hasSharedField = false; // Java 1.4 has, 1.5 doesn't
32
33   @MJI
34   public void $clinit____V (MJIEnv env, int clsObjRef) {
35     // apparently, Java 1.5 has changed the implementation of class
36     // StringBuffer so that it doesn't use the 'shared' state anymore
37     // (which was a performance hack to avoid copying the char array
38     // data when creating String objects from subsequently unmodified
39     // StringBuffers
40     // adding this little extra logic here also serves the purpose of
41     // avoiding a native ObjectStreamClass method which is called during
42     // the static StringBuffer init
43     ClassInfo ci = env.getClassInfo();
44     if (ci.getInstanceField("shared") != null) {
45       hasSharedField = true;
46     }
47   }
48   
49   int appendString (MJIEnv env, int objref, String s) {
50     int slen = s.length();
51     int aref = env.getReferenceField(objref, "value");
52     int alen = env.getArrayLength(aref);
53     int count = env.getIntField(objref, "count");
54     int i, j;
55     int n = count + slen;
56     
57     if (n < alen) {
58       for (i=count, j=0; i<n; i++, j++) {
59         env.setCharArrayElement(aref, i, s.charAt(j));
60       }
61     } else {
62       int m = 3 * alen / 2;
63       if (m < n) {
64         m = n;
65       }
66       int arefNew = env.newCharArray(m);
67       for (i=0; i<count; i++) {
68         env.setCharArrayElement(arefNew, i, env.getCharArrayElement(aref, i));
69       }
70       for (j=0; i<n; i++, j++) {
71         env.setCharArrayElement(arefNew, i, s.charAt(j));
72       }
73       env.setReferenceField(objref, "value", arefNew);
74     }
75     
76     if (hasSharedField) {
77       env.setBooleanField(objref, "shared", false);
78     }
79     env.setIntField(objref, "count", n);
80     
81     return objref;
82   }
83
84 /*
85   public static int append__Ljava_lang_StringBuffer_2 (MJIEnv env, int objref, int sbref) {
86     int vref = env.getReferenceField(sbref, "value");
87     int sbCount = env.getIntField(sbref, "count");
88
89     // how braindead, how lazy
90     char[] b = env.getCharArrayObject(vref);
91     String s = new String(b, 0, sbCount);
92     
93     return appendString(env, objref, s);
94   }
95 */
96
97   @MJI
98   public int append__Ljava_lang_String_2__Ljava_lang_StringBuffer_2 (MJIEnv env, int objref, int sref) {
99     String s = env.getStringObject(sref);    
100     if (s == null) s = "null";
101     
102     return appendString(env, objref, s);
103   }
104   
105   @MJI
106   public int append__I__Ljava_lang_StringBuffer_2 (MJIEnv env, int objref, int i) {
107     String s = Integer.toString(i);
108     
109     return appendString(env, objref, s);
110   }
111
112   @MJI
113   public int append__F__Ljava_lang_StringBuffer_2 (MJIEnv env, int objref, float f) {
114     String s = Float.toString(f);
115     
116     return appendString(env, objref, s);
117   }
118
119   @MJI
120   public int append__D__Ljava_lang_StringBuffer_2 (MJIEnv env, int objref, double d) {
121     String s = Double.toString(d);
122     
123     return appendString(env, objref, s);
124   }
125   
126   @MJI
127   public int append__J__Ljava_lang_StringBuffer_2 (MJIEnv env, int objref, long l) {
128     String s = Long.toString(l);
129     
130     return appendString(env, objref, s);
131   }
132
133   @MJI
134   public int append__Z__Ljava_lang_StringBuffer_2 (MJIEnv env, int objref, boolean b) {
135     String s = b ? "true" : "false";
136     
137     return appendString(env, objref, s);
138   }
139  
140 /*
141   public static int append__B__Ljava_lang_StringBuffer_2 (MJIEnv env, int objref, byte b) {
142     return append__C__Ljava_lang_StringBuffer_2(env, objref, (char)b);
143   }
144 */
145  
146   @MJI
147   public int append__C__Ljava_lang_StringBuffer_2 (MJIEnv env, int objref, char c) {
148     int aref = env.getReferenceField(objref, "value");
149     int alen = env.getArrayLength(aref);
150     int count = env.getIntField(objref, "count");
151     int n = count +1;
152     
153     if (n < alen) {
154       env.setCharArrayElement(aref, count, c);
155     } else {
156       int m = 3 * alen / 2;
157       int arefNew = env.newCharArray(m);
158       for (int i=0; i<count; i++) {
159         env.setCharArrayElement(arefNew, i, env.getCharArrayElement(aref, i));
160       }
161       env.setCharArrayElement(arefNew, count, c);
162       env.setReferenceField(objref, "value", arefNew);
163     }
164     
165     if (hasSharedField) {
166       env.setBooleanField(objref, "shared", false);
167     }
168     env.setIntField(objref, "count", n);
169     
170     return objref;
171     
172   }
173 }
174