2 * Copyright (C) 2014, United States Government, as represented by the
3 * Administrator of the National Aeronautics and Space Administration.
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
10 * http://www.apache.org/licenses/LICENSE-2.0.
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.
18 package gov.nasa.jpf.vm;
20 import gov.nasa.jpf.annotation.MJI;
21 import gov.nasa.jpf.vm.CharArrayFields;
22 import gov.nasa.jpf.vm.ElementInfo;
23 import gov.nasa.jpf.vm.Fields;
24 import gov.nasa.jpf.vm.Heap;
25 import gov.nasa.jpf.vm.MJIEnv;
26 import gov.nasa.jpf.vm.NativePeer;
28 import java.io.UnsupportedEncodingException;
29 import java.util.Locale;
32 * MJI NativePeer class for java.lang.String library abstraction
34 public class JPF_java_lang_String extends NativePeer {
38 public int init___3CII__Ljava_lang_String_2 (MJIEnv env, int objRef, int valueRef, int offset, int count) {
39 char[] value = env.getCharArrayObject(valueRef);
40 String result = new String(value, offset, count);
41 return env.newString(result);
45 public int init___3III__Ljava_lang_String_2 (MJIEnv env, int objRef, int codePointsRef, int offset, int count) {
46 int[] codePoints = env.getIntArrayObject(codePointsRef);
47 String result = new String(codePoints, offset, count);
48 return env.newString(result);
51 @SuppressWarnings("deprecation")
53 public int init___3BIII__Ljava_lang_String_2 (MJIEnv env, int objRef, int asciiRef, int hibyte, int offset, int count) {
54 byte[] ascii = env.getByteArrayObject(asciiRef);
55 String result = new String(ascii, hibyte, offset, count);
56 return env.newString(result);
60 public int init___3BIILjava_lang_String_2__Ljava_lang_String_2 (MJIEnv env, int objRef, int bytesRef, int offset, int length, int charsetNameRef) throws UnsupportedEncodingException {
61 byte[] bytes = env.getByteArrayObject(bytesRef);
62 String charsetName = env.getStringObject(charsetNameRef);
63 String result = new String(bytes, offset, length, charsetName);
64 return env.newString(result);
68 public int init___3BII__Ljava_lang_String_2 (MJIEnv env, int objRef, int bytesRef, int offset, int length) {
69 byte[] bytes = env.getByteArrayObject(bytesRef);
70 String result = new String(bytes, offset, length);
71 return env.newString(result);
75 public int codePointAt__I__I (MJIEnv env, int objRef, int index) {
76 String obj = env.getStringObject(objRef);
77 return obj.codePointAt(index);
81 public int codePointBefore__I__I (MJIEnv env, int objRef, int index) {
82 String obj = env.getStringObject(objRef);
83 return obj.codePointBefore(index);
87 public int codePointCount__II__I (MJIEnv env, int objRef, int beginIndex, int endIndex) {
88 String obj = env.getStringObject(objRef);
89 return obj.codePointCount(beginIndex, endIndex);
93 public int offsetByCodePoints__II__I (MJIEnv env, int objRef, int index, int codePointOffset) {
94 String obj = env.getStringObject(objRef);
95 return obj.offsetByCodePoints(index, codePointOffset);
99 public void getChars__II_3CI__V (MJIEnv env, int objRef, int srcBegin, int srcEnd, int dstRef, int dstBegin) {
100 String obj = env.getStringObject(objRef);
101 char[] dst = env.getCharArrayObject(dstRef);
102 obj.getChars(srcBegin, srcEnd, dst, dstBegin);
106 public void getChars___3CI__V(MJIEnv env, int objRef, int dstRef, int dstBegin) {
107 String obj = env.getStringObject(objRef);
108 char[] dst = env.getCharArrayObject(dstRef);
109 obj.getChars(0, obj.length(), dst, dstBegin);
112 @SuppressWarnings("deprecation")
114 public void getBytes__II_3BI__V (MJIEnv env, int objRef, int srcBegin, int srcEnd, int dstRef, int dstBegin) {
115 String obj = env.getStringObject(objRef);
116 byte[] dst = env.getByteArrayObject(dstRef);
117 obj.getBytes(srcBegin, srcEnd, dst, dstBegin);
121 public int getBytes__Ljava_lang_String_2___3B (MJIEnv env, int objRef, int charSetRef) {
122 String string = env.getStringObject(objRef);
123 String charset = env.getStringObject(charSetRef);
126 byte[] b = string.getBytes(charset);
127 return env.newByteArray(b);
129 } catch (UnsupportedEncodingException uex) {
130 env.throwException(uex.getClass().getName(), uex.getMessage());
136 public int getBytes_____3B (MJIEnv env, int objRef) {
137 String obj = env.getStringObject(objRef);
138 byte[] bytes = obj.getBytes();
139 return env.newByteArray(bytes);
143 public char charAt__I__C (MJIEnv env, int objRef, int index){
144 char[] data = env.getStringChars(objRef);
150 public boolean equals0___3C_3CI__Z (MJIEnv env, int clsObjRef, int charsRef1, int charsRef2, int len) {
152 if ((charsRef1 == MJIEnv.NULL) || (charsRef2 == MJIEnv.NULL)) { return false; }
154 char[] a = env.getCharArrayObject(charsRef1);
155 char[] b = env.getCharArrayObject(charsRef2);
157 if (a.length < len || b.length < len) { return false; }
159 for (int i = 0; i < len; i++) {
160 if (a[i] != b[i]) { return false; }
167 public boolean equals__Ljava_lang_Object_2__Z (MJIEnv env, int objRef, int argRef) {
168 if (argRef == MJIEnv.NULL) {
172 Heap heap = env.getHeap();
173 ElementInfo s1 = heap.get(objRef);
174 ClassInfo ci1 = s1.getClassInfo();
176 ElementInfo s2 = heap.get(argRef);
177 ClassInfo ci2 = s2.getClassInfo();
179 if (!ci2.isInstanceOf(ci1)) {
183 Fields f1 = heap.get(s1.getReferenceField("value")).getFields();
184 Fields f2 = heap.get(s2.getReferenceField("value")).getFields();
186 char[] c1 = ((CharArrayFields) f1).asCharArray();
187 char[] c2 = ((CharArrayFields) f2).asCharArray();
189 if (c1.length != c2.length) {
193 for (int i = 0; i < c1.length; i++) {
194 if (c1[i] != c2[i]) {
203 public boolean equalsIgnoreCase__Ljava_lang_String_2__Z (MJIEnv env, int objref, int anotherString) {
204 String thisString = env.getStringObject(objref);
205 if (anotherString != MJIEnv.NULL) {
206 return thisString.equalsIgnoreCase(env.getStringObject(anotherString));
213 public int compareTo__Ljava_lang_String_2__I (MJIEnv env, int objRef, int anotherStringRef) {
214 String obj = env.getStringObject(objRef);
215 String anotherString = env.getStringObject(anotherStringRef);
216 return obj.compareTo(anotherString);
220 public int MJIcompare__Ljava_lang_String_2Ljava_lang_String_2__I (MJIEnv env, int clsRef, int s1Ref, int s2Ref) {
221 // Is there a way to reflect?
222 String a = env.getStringObject(s1Ref);
223 String s2 = env.getStringObject(s2Ref);
225 int n2 = s2.length();
226 int min = Math.min(n1, n2);
227 for (int i = 0; i < min; i++) {
228 char x = a.charAt(i);
229 char y = s2.charAt(i);
231 x = Character.toUpperCase(x);
232 y = Character.toUpperCase(y);
234 x = Character.toLowerCase(x);
235 y = Character.toLowerCase(y);
236 if (x != y) { return x - y; }
244 public boolean regionMatches__ILjava_lang_String_2II__Z (MJIEnv env, int objRef, int toffset, int otherRef, int ooffset, int len) {
245 String obj = env.getStringObject(objRef);
246 String other = env.getStringObject(otherRef);
247 return obj.regionMatches(toffset, other, ooffset, len);
252 public boolean regionMatches__ZILjava_lang_String_2II__Z (MJIEnv env, int objRef, boolean ignoreCase, int toffset, int otherRef, int ooffset, int len) {
253 String obj = env.getStringObject(objRef);
254 String other = env.getStringObject(otherRef);
255 return obj.regionMatches(ignoreCase, toffset, other, ooffset, len);
260 public boolean startsWith__Ljava_lang_String_2I__Z (MJIEnv env, int objRef, int prefixRef, int toffset) {
261 String thisStr = env.getStringObject(objRef);
262 String prefix = env.getStringObject(prefixRef);
263 return thisStr.startsWith(prefix, toffset);
267 public boolean startsWith__Ljava_lang_String_2__Z (MJIEnv env, int objRef, int prefixRef) {
268 String thisStr = env.getStringObject(objRef);
269 String prefix = env.getStringObject(prefixRef);
270 return thisStr.startsWith(prefix);
274 public int hashCode____I (MJIEnv env, int objref) {
275 return computeStringHashCode(env, objref);
278 public static int computeStringHashCode(MJIEnv env, int objref) {
279 ElementInfo ei = env.getElementInfo(objref);
280 int h = ei.getIntField("hash");
283 int vref = env.getReferenceField(objref, "value");
285 // now get the char array data, but be aware they are stored as ints
286 ElementInfo eiVal = env.getElementInfo(vref);
287 char[] values = eiVal.asCharArray();
289 for (int i = 0; i < values.length; i++) {
290 h = 31 * h + values[i];
293 ei = ei.getModifiableInstance();
294 ei.setIntField("hash", h);
301 public int indexOf__I__I (MJIEnv env, int objref, int c) {
302 return indexOf__II__I(env, objref, c, 0);
306 public int indexOf__II__I (MJIEnv env, int objref, int c, int fromIndex) {
307 int vref = env.getReferenceField(objref, "value");
308 ElementInfo ei = env.getElementInfo(vref);
309 char[] values = ((CharArrayFields) ei.getFields()).asCharArray();
311 int len = values.length;
313 if (fromIndex >= len) { return -1; }
318 for (int i = fromIndex; i < len; i++) {
319 if (values[i] == c) { return i; }
326 public int lastIndexOf__I__I (MJIEnv env, int objref, int c) {
327 return lastIndexOf__II__I(env, objref, c, Integer.MAX_VALUE);
331 public int lastIndexOf__II__I (MJIEnv env, int objref, int c, int fromIndex) {
332 int vref = env.getReferenceField(objref, "value");
333 ElementInfo ei = env.getElementInfo(vref);
334 char[] values = ((CharArrayFields) ei.getFields()).asCharArray();
336 int len = values.length;
338 if (fromIndex < 0) { return -1; }
339 if (fromIndex > len - 1) {
343 for (int i = fromIndex; i > 0; i--) {
344 if (values[i] == c) { return i; }
351 public int indexOf__Ljava_lang_String_2__I (MJIEnv env, int objref, int str) {
352 String thisStr = env.getStringObject(objref);
353 String indexStr = env.getStringObject(str);
355 return thisStr.indexOf(indexStr);
359 public int indexOf__Ljava_lang_String_2I__I (MJIEnv env, int objref, int str, int fromIndex) {
360 String thisStr = env.getStringObject(objref);
361 String indexStr = env.getStringObject(str);
363 return thisStr.indexOf(indexStr, fromIndex);
367 public int lastIndexOf__Ljava_lang_String_2I__I (MJIEnv env, int objref, int str, int fromIndex) {
368 String thisStr = env.getStringObject(objref);
369 String indexStr = env.getStringObject(str);
371 return thisStr.lastIndexOf(indexStr, fromIndex);
375 public int substring__I__Ljava_lang_String_2 (MJIEnv env, int objRef, int beginIndex) {
376 String obj = env.getStringObject(objRef);
377 String result = obj.substring(beginIndex);
378 return env.newString(result);
383 public int substring__II__Ljava_lang_String_2 (MJIEnv env, int objRef, int beginIndex, int endIndex) {
384 String obj = env.getStringObject(objRef);
385 String result = obj.substring(beginIndex, endIndex);
386 return env.newString(result);
391 public int concat__Ljava_lang_String_2__Ljava_lang_String_2 (MJIEnv env, int objRef, int strRef) {
392 Heap heap = env.getHeap();
394 ElementInfo thisStr = heap.get(objRef);
395 CharArrayFields thisFields = (CharArrayFields) heap.get(thisStr.getReferenceField("value")).getFields();
396 char[] thisChars = thisFields.asCharArray();
397 int thisLength = thisChars.length;
399 ElementInfo otherStr = heap.get(strRef);
400 CharArrayFields otherFields = (CharArrayFields) heap.get(otherStr.getReferenceField("value")).getFields();
401 char[] otherChars = otherFields.asCharArray();
402 int otherLength = otherChars.length;
404 if (otherLength == 0) { return objRef; }
406 char resultChars[] = new char[thisLength + otherLength];
407 System.arraycopy(thisChars, 0, resultChars, 0, thisLength);
408 System.arraycopy(otherChars, 0, resultChars, thisLength, otherLength);
410 return env.newString(new String(resultChars));
413 // --- the various replaces
416 public int replace__CC__Ljava_lang_String_2 (MJIEnv env, int objRef, char oldChar, char newChar) {
418 if (oldChar == newChar) { // nothing to replace
422 int vref = env.getReferenceField(objRef, "value");
423 ElementInfo ei = env.getModifiableElementInfo(vref);
424 char[] values = ((CharArrayFields) ei.getFields()).asCharArray();
425 int len = values.length;
427 char[] newValues = null;
429 for (int i = 0, j = 0; j < len; i++, j++) {
432 if (newValues == null) {
433 newValues = new char[len];
435 System.arraycopy(values, 0, newValues, 0, j);
438 newValues[j] = newChar;
440 if (newValues != null) {
446 if (newValues != null) {
447 String s = new String(newValues);
448 return env.newString(s);
450 } else { // oldChar not found, return the original string
456 public boolean matches__Ljava_lang_String_2__Z (MJIEnv env, int objRef, int regexRef) {
457 String s = env.getStringObject(objRef);
458 String r = env.getStringObject(regexRef);
464 public int replaceFirst__Ljava_lang_String_2Ljava_lang_String_2__Ljava_lang_String_2 (MJIEnv env, int objRef, int regexRef, int replacementRef) {
465 String thisStr = env.getStringObject(objRef);
466 String regexStr = env.getStringObject(regexRef);
467 String replacementStr = env.getStringObject(replacementRef);
469 String result = thisStr.replaceFirst(regexStr, replacementStr);
470 return (result != thisStr) ? env.newString(result) : objRef;
474 public int replaceAll__Ljava_lang_String_2Ljava_lang_String_2__Ljava_lang_String_2 (MJIEnv env, int objRef, int regexRef, int replacementRef) {
475 String thisStr = env.getStringObject(objRef);
476 String regexStr = env.getStringObject(regexRef);
477 String replacementStr = env.getStringObject(replacementRef);
479 String result = thisStr.replaceAll(regexStr, replacementStr);
480 return (result != thisStr) ? env.newString(result) : objRef;
484 public int split__Ljava_lang_String_2I___3Ljava_lang_String_2 (MJIEnv env, int clsObjRef, int strRef, int limit) {
485 String s = env.getStringObject(strRef);
486 String obj = env.getStringObject(clsObjRef);
488 String[] result = obj.split(s, limit);
490 return env.newStringArray(result);
494 public int split__Ljava_lang_String_2___3Ljava_lang_String_2 (MJIEnv env, int clsObjRef, int strRef) {
495 String s = env.getStringObject(strRef);
496 String obj = env.getStringObject(clsObjRef);
498 String[] result = obj.split(s);
500 return env.newStringArray(result);
504 public int toLowerCase__Ljava_util_Locale_2__Ljava_lang_String_2 (MJIEnv env, int objRef, int locRef) {
505 String s = env.getStringObject(objRef);
506 Locale loc = JPF_java_util_Locale.getLocale(env, locRef);
508 String lower = s.toLowerCase(loc);
510 return (s == lower) ? objRef : env.newString(lower);
514 public int toLowerCase____Ljava_lang_String_2 (MJIEnv env, int objRef) {
515 String s = env.getStringObject(objRef);
516 String lower = s.toLowerCase();
518 return (s == lower) ? objRef : env.newString(lower);
522 public int toUpperCase__Ljava_util_Locale_2__Ljava_lang_String_2 (MJIEnv env, int objRef, int locRef) {
523 String s = env.getStringObject(objRef);
524 Locale loc = JPF_java_util_Locale.getLocale(env, locRef);
526 String upper = s.toUpperCase(loc);
528 return (s == upper) ? objRef : env.newString(upper);
532 public int toUpperCase____Ljava_lang_String_2 (MJIEnv env, int objRef) {
533 String s = env.getStringObject(objRef);
534 String upper = s.toUpperCase();
536 return (s == upper) ? objRef : env.newString(upper);
540 public int trim____Ljava_lang_String_2 (MJIEnv env, int objRef) {
541 Heap heap = env.getHeap();
542 ElementInfo thisStr = heap.get(objRef);
544 CharArrayFields thisFields = (CharArrayFields) heap.get(thisStr.getReferenceField("value")).getFields();
545 char[] thisChars = thisFields.asCharArray();
546 int thisLength = thisChars.length;
549 int end = thisLength;
551 while ((start < end) && (thisChars[start] <= ' ')) {
555 while ((start < end) && (thisChars[end - 1] <= ' ')) {
559 if (start == 0 && end == thisLength) {
560 // if there was no white space, return the string itself
564 String result = new String(thisChars, start, end - start);
565 return env.newString(result);
569 public int toCharArray_____3C (MJIEnv env, int objref) {
570 int vref = env.getReferenceField(objref, "value");
571 char[] v = env.getCharArrayObject(vref);
573 int cref = env.newCharArray(v);
579 public int format__Ljava_lang_String_2_3Ljava_lang_Object_2__Ljava_lang_String_2 (MJIEnv env, int clsObjRef, int fmtRef, int argRef) {
580 return env.newString(env.format(fmtRef, argRef));
584 public int format__Ljava_util_Locale_2Ljava_lang_String_2_3Ljava_lang_Object_2__Ljava_lang_String_2 (MJIEnv env, int clsObjRef, int locRef, int fmtRef, int argRef) {
585 Locale loc = JPF_java_util_Locale.getLocale(env, locRef);
586 return env.newString(env.format(loc, fmtRef, argRef));
590 public int intern____Ljava_lang_String_2 (MJIEnv env, int robj) {
591 // <2do> Replace this with a JPF space HashSet once we have a String model
592 Heap heap = env.getHeap();
594 String s = env.getStringObject(robj);
595 ElementInfo ei = heap.newInternString(s, env.getThreadInfo());
597 return ei.getObjectRef();
601 public int valueOf__I__Ljava_lang_String_2 (MJIEnv env, int clsref, int i) {
602 String result = String.valueOf(i);
603 return env.newString(result);
607 public int valueOf__J__Ljava_lang_String_2 (MJIEnv env, int clsref, long l) {
608 String result = String.valueOf(l);
609 return env.newString(result);
613 public int valueOf__F__Ljava_lang_String_2 (MJIEnv env, int clsref, float f) {
614 String result = String.valueOf(f);
615 return env.newString(result);
619 public int valueOf__D__Ljava_lang_String_2 (MJIEnv env, int clsref, double d) {
620 String result = String.valueOf(d);
621 return env.newString(result);