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 {
35 final static String sioobe = "java.lang.StringIndexOutOfBoundsException";
36 final static String sioor = "String index out of range: ";
39 public int init___3CII__Ljava_lang_String_2 (MJIEnv env, int objRef, int valueRef, int offset, int count) {
40 char[] value = env.getCharArrayObject(valueRef);
41 String result = new String(value, offset, count);
42 return env.newString(result);
46 public int init___3III__Ljava_lang_String_2 (MJIEnv env, int objRef, int codePointsRef, int offset, int count) {
47 int[] codePoints = env.getIntArrayObject(codePointsRef);
48 String result = new String(codePoints, offset, count);
49 return env.newString(result);
52 @SuppressWarnings("deprecation")
54 public int init___3BIII__Ljava_lang_String_2 (MJIEnv env, int objRef, int asciiRef, int hibyte, int offset, int count) {
55 byte[] ascii = env.getByteArrayObject(asciiRef);
56 String result = new String(ascii, hibyte, offset, count);
57 return env.newString(result);
61 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 {
62 byte[] bytes = env.getByteArrayObject(bytesRef);
63 String charsetName = env.getStringObject(charsetNameRef);
64 String result = new String(bytes, offset, length, charsetName);
65 return env.newString(result);
69 public int init___3BII__Ljava_lang_String_2 (MJIEnv env, int objRef, int bytesRef, int offset, int length) {
70 byte[] bytes = env.getByteArrayObject(bytesRef);
71 String result = new String(bytes, offset, length);
72 return env.newString(result);
76 public int codePointAt__I__I (MJIEnv env, int objRef, int index) {
77 String obj = env.getStringObject(objRef);
78 return obj.codePointAt(index);
82 public int codePointBefore__I__I (MJIEnv env, int objRef, int index) {
83 String obj = env.getStringObject(objRef);
84 return obj.codePointBefore(index);
88 public int codePointCount__II__I (MJIEnv env, int objRef, int beginIndex, int endIndex) {
89 String obj = env.getStringObject(objRef);
90 return obj.codePointCount(beginIndex, endIndex);
94 public int offsetByCodePoints__II__I (MJIEnv env, int objRef, int index, int codePointOffset) {
95 String obj = env.getStringObject(objRef);
96 return obj.offsetByCodePoints(index, codePointOffset);
100 public void getChars__II_3CI__V (MJIEnv env, int objRef, int srcBegin, int srcEnd, int dstRef, int dstBegin) {
101 String obj = env.getStringObject(objRef);
102 char[] dst = env.getCharArrayObject(dstRef);
103 obj.getChars(srcBegin, srcEnd, dst, dstBegin);
107 public void getChars___3CI__V(MJIEnv env, int objRef, int dstRef, int dstBegin) {
108 String obj = env.getStringObject(objRef);
109 char[] dst = env.getCharArrayObject(dstRef);
110 obj.getChars(0, obj.length(), dst, dstBegin);
113 @SuppressWarnings("deprecation")
115 public void getBytes__II_3BI__V (MJIEnv env, int objRef, int srcBegin, int srcEnd, int dstRef, int dstBegin) {
116 String obj = env.getStringObject(objRef);
117 byte[] dst = env.getByteArrayObject(dstRef);
118 obj.getBytes(srcBegin, srcEnd, dst, dstBegin);
122 public int getBytes__Ljava_lang_String_2___3B (MJIEnv env, int objRef, int charSetRef) {
123 String string = env.getStringObject(objRef);
124 String charset = env.getStringObject(charSetRef);
127 byte[] b = string.getBytes(charset);
128 return env.newByteArray(b);
130 } catch (UnsupportedEncodingException uex) {
131 env.throwException(uex.getClass().getName(), uex.getMessage());
137 public int getBytes_____3B (MJIEnv env, int objRef) {
138 String obj = env.getStringObject(objRef);
139 byte[] bytes = obj.getBytes();
140 return env.newByteArray(bytes);
144 public char charAt__I__C (MJIEnv env, int objRef, int index){
145 char[] data = env.getStringChars(objRef);
146 if (index >= 0 && index < data.length) {
149 env.throwException(sioobe, sioor + index);
155 public boolean equals0___3C_3CI__Z (MJIEnv env, int clsObjRef, int charsRef1, int charsRef2, int len) {
157 if ((charsRef1 == MJIEnv.NULL) || (charsRef2 == MJIEnv.NULL)) { return false; }
159 char[] a = env.getCharArrayObject(charsRef1);
160 char[] b = env.getCharArrayObject(charsRef2);
162 if (a.length < len || b.length < len) { return false; }
164 for (int i = 0; i < len; i++) {
165 if (a[i] != b[i]) { return false; }
172 public boolean equals__Ljava_lang_Object_2__Z (MJIEnv env, int objRef, int argRef) {
173 if (argRef == MJIEnv.NULL) {
177 Heap heap = env.getHeap();
178 ElementInfo s1 = heap.get(objRef);
179 ClassInfo ci1 = s1.getClassInfo();
181 ElementInfo s2 = heap.get(argRef);
182 ClassInfo ci2 = s2.getClassInfo();
184 if (!ci2.isInstanceOf(ci1)) {
188 Fields f1 = heap.get(s1.getReferenceField("value")).getFields();
189 Fields f2 = heap.get(s2.getReferenceField("value")).getFields();
191 char[] c1 = ((CharArrayFields) f1).asCharArray();
192 char[] c2 = ((CharArrayFields) f2).asCharArray();
194 if (c1.length != c2.length) {
198 for (int i = 0; i < c1.length; i++) {
199 if (c1[i] != c2[i]) {
208 public boolean equalsIgnoreCase__Ljava_lang_String_2__Z (MJIEnv env, int objref, int anotherString) {
209 String thisString = env.getStringObject(objref);
210 if (anotherString != MJIEnv.NULL) {
211 return thisString.equalsIgnoreCase(env.getStringObject(anotherString));
218 public int compareTo__Ljava_lang_String_2__I (MJIEnv env, int objRef, int anotherStringRef) {
219 String obj = env.getStringObject(objRef);
220 String anotherString = env.getStringObject(anotherStringRef);
221 return obj.compareTo(anotherString);
225 public int MJIcompare__Ljava_lang_String_2Ljava_lang_String_2__I (MJIEnv env, int clsRef, int s1Ref, int s2Ref) {
226 // Is there a way to reflect?
227 String a = env.getStringObject(s1Ref);
228 String s2 = env.getStringObject(s2Ref);
230 int n2 = s2.length();
231 int min = Math.min(n1, n2);
232 for (int i = 0; i < min; i++) {
233 char x = a.charAt(i);
234 char y = s2.charAt(i);
236 x = Character.toUpperCase(x);
237 y = Character.toUpperCase(y);
239 x = Character.toLowerCase(x);
240 y = Character.toLowerCase(y);
241 if (x != y) { return x - y; }
249 public boolean regionMatches__ILjava_lang_String_2II__Z (MJIEnv env, int objRef, int toffset, int otherRef, int ooffset, int len) {
250 String obj = env.getStringObject(objRef);
251 String other = env.getStringObject(otherRef);
252 return obj.regionMatches(toffset, other, ooffset, len);
257 public boolean regionMatches__ZILjava_lang_String_2II__Z (MJIEnv env, int objRef, boolean ignoreCase, int toffset, int otherRef, int ooffset, int len) {
258 String obj = env.getStringObject(objRef);
259 String other = env.getStringObject(otherRef);
260 return obj.regionMatches(ignoreCase, toffset, other, ooffset, len);
265 public boolean startsWith__Ljava_lang_String_2I__Z (MJIEnv env, int objRef, int prefixRef, int toffset) {
266 String thisStr = env.getStringObject(objRef);
267 String prefix = env.getStringObject(prefixRef);
268 return thisStr.startsWith(prefix, toffset);
272 public boolean startsWith__Ljava_lang_String_2__Z (MJIEnv env, int objRef, int prefixRef) {
273 String thisStr = env.getStringObject(objRef);
274 String prefix = env.getStringObject(prefixRef);
275 return thisStr.startsWith(prefix);
279 public int hashCode____I (MJIEnv env, int objref) {
280 return computeStringHashCode(env, objref);
283 public static int computeStringHashCode(MJIEnv env, int objref) {
284 ElementInfo ei = env.getElementInfo(objref);
285 int h = ei.getIntField("hash");
288 int vref = env.getReferenceField(objref, "value");
290 // now get the char array data, but be aware they are stored as ints
291 ElementInfo eiVal = env.getElementInfo(vref);
292 char[] values = eiVal.asCharArray();
294 for (int i = 0; i < values.length; i++) {
295 h = 31 * h + values[i];
298 ei = ei.getModifiableInstance();
299 ei.setIntField("hash", h);
306 public int indexOf__I__I (MJIEnv env, int objref, int c) {
307 return indexOf__II__I(env, objref, c, 0);
311 public int indexOf__II__I (MJIEnv env, int objref, int c, int fromIndex) {
312 int vref = env.getReferenceField(objref, "value");
313 ElementInfo ei = env.getElementInfo(vref);
314 char[] values = ((CharArrayFields) ei.getFields()).asCharArray();
316 int len = values.length;
318 if (fromIndex >= len) { return -1; }
323 for (int i = fromIndex; i < len; i++) {
324 if (values[i] == c) { return i; }
331 public int lastIndexOf__I__I (MJIEnv env, int objref, int c) {
332 return lastIndexOf__II__I(env, objref, c, Integer.MAX_VALUE);
336 public int lastIndexOf__II__I (MJIEnv env, int objref, int c, int fromIndex) {
337 int vref = env.getReferenceField(objref, "value");
338 ElementInfo ei = env.getElementInfo(vref);
339 char[] values = ((CharArrayFields) ei.getFields()).asCharArray();
341 int len = values.length;
343 if (fromIndex < 0) { return -1; }
344 if (fromIndex > len - 1) {
348 for (int i = fromIndex; i >= 0; i--) {
349 if (values[i] == c) { return i; }
356 public int indexOf__Ljava_lang_String_2__I (MJIEnv env, int objref, int str) {
357 String thisStr = env.getStringObject(objref);
358 String indexStr = env.getStringObject(str);
360 return thisStr.indexOf(indexStr);
364 public int indexOf__Ljava_lang_String_2I__I (MJIEnv env, int objref, int str, int fromIndex) {
365 String thisStr = env.getStringObject(objref);
366 String indexStr = env.getStringObject(str);
368 return thisStr.indexOf(indexStr, fromIndex);
372 public int lastIndexOf__Ljava_lang_String_2I__I (MJIEnv env, int objref, int str, int fromIndex) {
373 String thisStr = env.getStringObject(objref);
374 String indexStr = env.getStringObject(str);
376 return thisStr.lastIndexOf(indexStr, fromIndex);
380 public int substring__I__Ljava_lang_String_2 (MJIEnv env, int objRef, int beginIndex) {
381 String obj = env.getStringObject(objRef);
382 return substring__II__Ljava_lang_String_2(env, objRef, beginIndex, obj.length());
386 public int substring__II__Ljava_lang_String_2 (MJIEnv env, int objRef, int beginIndex, int endIndex) {
387 if (beginIndex > endIndex) {
388 env.throwException(sioobe, sioor + (endIndex - beginIndex));
391 if (beginIndex < 0) {
392 env.throwException(sioobe, sioor + beginIndex);
395 String obj = env.getStringObject(objRef);
396 if (endIndex > obj.length()) {
397 env.throwException(sioobe, sioor + endIndex);
400 String result = obj.substring(beginIndex, endIndex);
401 return env.newString(result);
406 public int concat__Ljava_lang_String_2__Ljava_lang_String_2 (MJIEnv env, int objRef, int strRef) {
407 Heap heap = env.getHeap();
409 ElementInfo thisStr = heap.get(objRef);
410 CharArrayFields thisFields = (CharArrayFields) heap.get(thisStr.getReferenceField("value")).getFields();
411 char[] thisChars = thisFields.asCharArray();
412 int thisLength = thisChars.length;
414 ElementInfo otherStr = heap.get(strRef);
415 CharArrayFields otherFields = (CharArrayFields) heap.get(otherStr.getReferenceField("value")).getFields();
416 char[] otherChars = otherFields.asCharArray();
417 int otherLength = otherChars.length;
419 if (otherLength == 0) { return objRef; }
421 char resultChars[] = new char[thisLength + otherLength];
422 System.arraycopy(thisChars, 0, resultChars, 0, thisLength);
423 System.arraycopy(otherChars, 0, resultChars, thisLength, otherLength);
425 return env.newString(new String(resultChars));
428 // --- the various replaces
431 public int replace__CC__Ljava_lang_String_2 (MJIEnv env, int objRef, char oldChar, char newChar) {
433 if (oldChar == newChar) { // nothing to replace
437 int vref = env.getReferenceField(objRef, "value");
438 ElementInfo ei = env.getModifiableElementInfo(vref);
439 char[] values = ((CharArrayFields) ei.getFields()).asCharArray();
440 int len = values.length;
442 char[] newValues = null;
444 for (int i = 0, j = 0; j < len; i++, j++) {
447 if (newValues == null) {
448 newValues = new char[len];
450 System.arraycopy(values, 0, newValues, 0, j);
453 newValues[j] = newChar;
455 if (newValues != null) {
461 if (newValues != null) {
462 String s = new String(newValues);
463 return env.newString(s);
465 } else { // oldChar not found, return the original string
471 public boolean matches__Ljava_lang_String_2__Z (MJIEnv env, int objRef, int regexRef) {
472 String s = env.getStringObject(objRef);
473 String r = env.getStringObject(regexRef);
479 public int replaceFirst__Ljava_lang_String_2Ljava_lang_String_2__Ljava_lang_String_2 (MJIEnv env, int objRef, int regexRef, int replacementRef) {
480 String thisStr = env.getStringObject(objRef);
481 String regexStr = env.getStringObject(regexRef);
482 String replacementStr = env.getStringObject(replacementRef);
484 String result = thisStr.replaceFirst(regexStr, replacementStr);
485 return (result != thisStr) ? env.newString(result) : objRef;
489 public int replaceAll__Ljava_lang_String_2Ljava_lang_String_2__Ljava_lang_String_2 (MJIEnv env, int objRef, int regexRef, int replacementRef) {
490 String thisStr = env.getStringObject(objRef);
491 String regexStr = env.getStringObject(regexRef);
492 String replacementStr = env.getStringObject(replacementRef);
494 String result = thisStr.replaceAll(regexStr, replacementStr);
495 return (result != thisStr) ? env.newString(result) : objRef;
499 public int split__Ljava_lang_String_2I___3Ljava_lang_String_2 (MJIEnv env, int clsObjRef, int strRef, int limit) {
500 String s = env.getStringObject(strRef);
501 String obj = env.getStringObject(clsObjRef);
503 String[] result = obj.split(s, limit);
505 return env.newStringArray(result);
509 public int split__Ljava_lang_String_2___3Ljava_lang_String_2 (MJIEnv env, int clsObjRef, int strRef) {
510 String s = env.getStringObject(strRef);
511 String obj = env.getStringObject(clsObjRef);
513 String[] result = obj.split(s);
515 return env.newStringArray(result);
519 public int toLowerCase__Ljava_util_Locale_2__Ljava_lang_String_2 (MJIEnv env, int objRef, int locRef) {
520 String s = env.getStringObject(objRef);
521 Locale loc = JPF_java_util_Locale.getLocale(env, locRef);
523 String lower = s.toLowerCase(loc);
525 return (s == lower) ? objRef : env.newString(lower);
529 public int toLowerCase____Ljava_lang_String_2 (MJIEnv env, int objRef) {
530 String s = env.getStringObject(objRef);
531 String lower = s.toLowerCase();
533 return (s == lower) ? objRef : env.newString(lower);
537 public int toUpperCase__Ljava_util_Locale_2__Ljava_lang_String_2 (MJIEnv env, int objRef, int locRef) {
538 String s = env.getStringObject(objRef);
539 Locale loc = JPF_java_util_Locale.getLocale(env, locRef);
541 String upper = s.toUpperCase(loc);
543 return (s == upper) ? objRef : env.newString(upper);
547 public int toUpperCase____Ljava_lang_String_2 (MJIEnv env, int objRef) {
548 String s = env.getStringObject(objRef);
549 String upper = s.toUpperCase();
551 return (s == upper) ? objRef : env.newString(upper);
555 public int trim____Ljava_lang_String_2 (MJIEnv env, int objRef) {
556 Heap heap = env.getHeap();
557 ElementInfo thisStr = heap.get(objRef);
559 CharArrayFields thisFields = (CharArrayFields) heap.get(thisStr.getReferenceField("value")).getFields();
560 char[] thisChars = thisFields.asCharArray();
561 int thisLength = thisChars.length;
564 int end = thisLength;
566 while ((start < end) && (thisChars[start] <= ' ')) {
570 while ((start < end) && (thisChars[end - 1] <= ' ')) {
574 if (start == 0 && end == thisLength) {
575 // if there was no white space, return the string itself
579 String result = new String(thisChars, start, end - start);
580 return env.newString(result);
584 public int toCharArray_____3C (MJIEnv env, int objref) {
585 int vref = env.getReferenceField(objref, "value");
586 char[] v = env.getCharArrayObject(vref);
588 int cref = env.newCharArray(v);
594 public int format__Ljava_lang_String_2_3Ljava_lang_Object_2__Ljava_lang_String_2 (MJIEnv env, int clsObjRef, int fmtRef, int argRef) {
595 return env.newString(env.format(fmtRef, argRef));
599 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) {
600 Locale loc = JPF_java_util_Locale.getLocale(env, locRef);
601 return env.newString(env.format(loc, fmtRef, argRef));
605 public int intern____Ljava_lang_String_2 (MJIEnv env, int robj) {
606 // <2do> Replace this with a JPF space HashSet once we have a String model
607 Heap heap = env.getHeap();
609 String s = env.getStringObject(robj);
610 ElementInfo ei = heap.newInternString(s, env.getThreadInfo());
612 return ei.getObjectRef();
616 public int valueOf__I__Ljava_lang_String_2 (MJIEnv env, int clsref, int i) {
617 String result = String.valueOf(i);
618 return env.newString(result);
622 public int valueOf__J__Ljava_lang_String_2 (MJIEnv env, int clsref, long l) {
623 String result = String.valueOf(l);
624 return env.newString(result);
628 public int valueOf__F__Ljava_lang_String_2 (MJIEnv env, int clsref, float f) {
629 String result = String.valueOf(f);
630 return env.newString(result);
634 public int valueOf__D__Ljava_lang_String_2 (MJIEnv env, int clsref, double d) {
635 String result = String.valueOf(d);
636 return env.newString(result);