diff --git a/approximations/src/main/java/decoders/java/util/ArrayList_Decoder.java b/approximations/src/main/java/decoders/java/util/ArrayList_Decoder.java index 162bde35..81962838 100644 --- a/approximations/src/main/java/decoders/java/util/ArrayList_Decoder.java +++ b/approximations/src/main/java/decoders/java/util/ArrayList_Decoder.java @@ -46,7 +46,6 @@ public T createInstance(final JcClassOrInterface approx, List params = m.getParameters(); if (params.size() != 1) continue; - if (!"java.lang.Object".equals(params.get(0).getType().getTypeName())) continue; cached_ArrayList_add = m_add = m; } @@ -60,6 +59,16 @@ public T createInstance(final JcClassOrInterface approx, return decoder.invokeMethod(m_ctor, (List) Collections.EMPTY_LIST); } + private static List getAllFields(JcClassOrInterface clazz) { + JcClassOrInterface superclass = clazz.getSuperClass(); + if (superclass == null) { + return clazz.getDeclaredFields(); + } + List declaredFields = clazz.getDeclaredFields(); + declaredFields.addAll(getAllFields(superclass)); + return declaredFields; + } + @Override public void initializeInstance(final JcClassOrInterface approx, final ObjectData approxData, @@ -68,7 +77,7 @@ public void initializeInstance(final JcClassOrInterface approx, JcField f_storage = cached_ArrayList_storage; // TODO: add synchronization if needed if (f_storage == null) { - final List fields = approx.getDeclaredFields(); + final List fields = getAllFields(approx); for (int i = 0, c = fields.size(); i < c; i++) { JcField f = fields.get(i); if ("storage".equals(f.getName())) { diff --git a/approximations/src/main/java/generated/java/lang/StringBuilderImpl.java b/approximations/src/main/java/generated/java/lang/StringBuilderImpl.java index 98d52929..f3d88759 100644 --- a/approximations/src/main/java/generated/java/lang/StringBuilderImpl.java +++ b/approximations/src/main/java/generated/java/lang/StringBuilderImpl.java @@ -30,273 +30,379 @@ public final class StringBuilderImpl implements Serializable, Comparable 1073741823) throw new OutOfMemoryError("Requested array size exceeds VM limit"); - this.value = new char[STRING_BUILDER_LENGTH_MAX]; + + this.value = new byte[STRING_BUILDER_LENGTH_MAX]; + this.byteCount = 0; } - private void _appendCharSequence(CharSequence seq, int seqStart, int seqEnd) { - if (seqStart < 0 || seqStart > seqEnd || seqEnd > seq.length()) + private static String _getString(CharSequence seq) { + if (seq instanceof String) + return (String) seq; + + return LibSLRuntime.toString(seq); + } + + private static CharSequence _getCharSequence(CharSequence seq) { + if (seq == null) + return "null"; + + return seq; + } + + private static CharSequence _getCharSequence(Object obj) { + if (obj == null) + return "null"; + + return LibSLRuntime.toString(obj); + } + + private static CharSequence _getCharSequence(boolean b) { + if (b) + return "true"; + + return "false"; + } + + private int _charPosToBytePos(int charPos) { + return charPos << coder; + } + + private int _bytePosToCharPos(int charPos) { + return charPos >> coder; + } + + private static void _checkRangeBounds(int start, int end, int rightBound) { + if (start < 0 || start > end || end > rightBound) throw new IndexOutOfBoundsException(); - int available = this.value.length - this.count; - int len = seqEnd - seqStart; - if (len > available) - len = available; - if (len <= 0) - return; + } - String str; - if (seq instanceof String) { - str = (String) seq; - } else { - str = LibSLRuntime.toString(seq); - } - char[] chars = str.toCharArray(); - LibSLRuntime.ArrayActions.copy(chars, seqStart, this.value, this.count, len); - this.count += len; + private static void _checkSeqBounds(CharSequence seq, int seqStart, int seqEnd) { + _checkRangeBounds(seqStart, seqEnd, seq.length()); } - private String _asString(int posStart, int posEnd) { - int len = posEnd - posStart; - if (len == 0) - return ""; + private void _checkByteOffset(int byteOffset) { + if (byteOffset < 0 || byteOffset > this.byteCount) + throw new IndexOutOfBoundsException(); + } - char[] symbols = new char[len]; - LibSLRuntime.ArrayActions.copy(this.value, posStart, symbols, 0, len); - return LibSLRuntime.toString(this.value); + private void _checkCharOffset(int charOffset) { + _checkByteOffset(_charPosToBytePos(charOffset)); } - public String _asString() { - int len = this.count; - if (len == 0) - return ""; + private int _getByteSeqLength(int byteOffset, int byteSeqStart, int byteSeqEnd) { + int availableBytes = this.value.length - byteOffset; + int byteSeqLength = byteSeqEnd - byteSeqStart; + if (byteSeqLength > availableBytes) + byteSeqLength = availableBytes; + + return byteSeqLength; + } - if (len == this.value.length) - return LibSLRuntime.toString(this.value); + // TODO: unify _appendCharSequence with _appendChars #Approx + private void _appendCharSequence(CharSequence seq, int seqStart, int seqEnd) { + _checkSeqBounds(seq, seqStart, seqEnd); - char[] symbols = new char[len]; - LibSLRuntime.ArrayActions.copy(this.value, 0, symbols, 0, len); - return LibSLRuntime.toString(this.value); + int byteSeqStart = _charPosToBytePos(seqStart); + int byteSeqEnd = _charPosToBytePos(seqEnd); + int byteSeqLength = _getByteSeqLength(byteCount, byteSeqStart, byteSeqEnd); + String str = _getString(seq); + byte[] bytes = str.getBytes(); + LibSLRuntime.ArrayActions.copy(bytes, byteSeqStart, this.value, byteCount, byteSeqLength); + this.byteCount += byteSeqLength; } + private void _appendChars(char[] seq, int seqStart, int seqEnd) { + _checkRangeBounds(seqStart, seqEnd, seq.length); + + int byteSeqStart = _charPosToBytePos(seqStart); + int byteSeqEnd = _charPosToBytePos(seqEnd); + int byteSeqLength = _getByteSeqLength(byteCount, byteSeqStart, byteSeqEnd); + byte[] bytes = StringImpl._getBytes(seq); + LibSLRuntime.ArrayActions.copy(bytes, byteSeqStart, this.value, byteCount, byteSeqLength); + this.byteCount += byteSeqLength; + } + + private void _appendCharSequence(CharSequence seq) { + _appendCharSequence(seq, 0, seq.length()); + } + + private StringImpl _asString(int posStart, int posEnd) { + int bytePosStart = _charPosToBytePos(posStart); + int bytePosEnd = _charPosToBytePos(posEnd); + int byteLength = bytePosEnd - bytePosStart; + if (byteLength == 0) + return StringImpl._emptyString; + + if (bytePosStart == 0 && bytePosEnd == this.value.length) + return new StringImpl(this.value); + + byte[] bytes = new byte[byteLength]; + LibSLRuntime.ArrayActions.copy(this.value, bytePosStart, bytes, 0, byteLength); + return new StringImpl(bytes); + } + + public StringImpl _asString() { + return _asString(0, this.byteCount); + } + + // TODO: unify _insertCharSequence with _insertChars #Approx private void _insertCharSequence(int offset, CharSequence seq, int seqStart, int seqEnd) { - if (seqStart < 0 || seqStart > seqEnd || seqEnd > seq.length() || offset > this.count) - throw new IndexOutOfBoundsException(); + _checkSeqBounds(seq, seqStart, seqEnd); + + int byteOffset = _charPosToBytePos(offset); + _checkByteOffset(byteOffset); - int available = this.value.length - offset; - int len = seqEnd - seqStart; - if (len > available) - len = available; + int byteSeqStart = _charPosToBytePos(seqStart); + int byteSeqEnd = _charPosToBytePos(seqEnd); + int availableBytes = this.value.length - byteOffset; + int byteLength = byteSeqEnd - byteSeqStart; + if (byteLength > availableBytes) + byteLength = availableBytes; - if (len <= 0) + if (byteLength <= 0) return; - int availableForLeftovers = available - len; + int availableForLeftovers = availableBytes - byteLength; if (availableForLeftovers > 0) { - int rightLeftovers = this.count - offset; - if (rightLeftovers > availableForLeftovers) { + int rightLeftovers = this.byteCount - byteOffset; + if (rightLeftovers > availableForLeftovers) rightLeftovers = availableForLeftovers; - } - if (rightLeftovers > 0) { - int rightIndex = offset + 1; - LibSLRuntime.ArrayActions.copy(this.value, rightIndex, this.value, rightIndex + len, rightLeftovers); - } + + if (rightLeftovers > 0) + // Moving bytes, that would be replaced, beyond right bound of insertion + LibSLRuntime.ArrayActions.copy(this.value, byteOffset, this.value, byteOffset + byteLength, rightLeftovers); } - String str; - if (seq instanceof String) { - str = (String) seq; - } else { - str = LibSLRuntime.toString(seq); + + String str = _getString(seq); + byte[] bytes = str.getBytes(); + LibSLRuntime.ArrayActions.copy(bytes, byteSeqStart, this.value, byteOffset, byteLength); + this.byteCount += byteLength; + } + + @SuppressWarnings("SameParameterValue") + private void _insertChars(int offset, char[] chars, int seqStart, int seqEnd) { + _checkRangeBounds(seqStart, seqEnd, chars.length); + + int byteOffset = _charPosToBytePos(offset); + _checkByteOffset(byteOffset); + + int byteSeqStart = _charPosToBytePos(seqStart); + int byteSeqEnd = _charPosToBytePos(seqEnd); + int availableBytes = this.value.length - byteOffset; + int byteLength = byteSeqEnd - byteSeqStart; + if (byteLength > availableBytes) + byteLength = availableBytes; + + if (byteLength <= 0) + return; + + int availableForLeftovers = availableBytes - byteLength; + if (availableForLeftovers > 0) { + int rightLeftovers = this.byteCount - byteOffset; + if (rightLeftovers > availableForLeftovers) + rightLeftovers = availableForLeftovers; + + if (rightLeftovers > 0) + // Moving bytes, that would be replaced, beyond right bound of insertion + LibSLRuntime.ArrayActions.copy(this.value, byteOffset, this.value, byteOffset + byteLength, rightLeftovers); } - char[] chars = str.toCharArray(); - LibSLRuntime.ArrayActions.copy(chars, seqStart, this.value, offset, len); - this.count += len; + + byte[] bytes = StringImpl._getBytes(chars); + LibSLRuntime.ArrayActions.copy(bytes, byteSeqStart, this.value, byteOffset, byteLength); + this.byteCount += byteLength; + } + + private void _insertCharSequence(int offset, CharSequence seq) { + _insertCharSequence(offset, seq, 0, seq.length()); } private void _deleteChars(int start, int end) { - if (start < 0 || start > end || end > this.count) - throw new IndexOutOfBoundsException(); + int byteStart = _charPosToBytePos(start); + int byteEnd = _charPosToBytePos(end); + _checkRangeBounds(byteStart, byteEnd, this.byteCount); - int leftovers = this.count - end; + int leftovers = this.byteCount - byteEnd; if (leftovers > 0) - LibSLRuntime.ArrayActions.copy(this.value, end, this.value, start, leftovers); - this.count -= end - start; + LibSLRuntime.ArrayActions.copy(this.value, byteEnd, this.value, byteStart, leftovers); + int deletedBytesSize = byteEnd - byteStart; + this.byteCount -= deletedBytesSize; } @SuppressWarnings("DataFlowIssue") private void _assumeInvariants() { Engine.assume(this.value != null); Engine.assume(this.value.length <= STRING_BUILDER_LENGTH_MAX); - Engine.assume(this.count <= this.value.length); - Engine.assume(this.count >= 0); + Engine.assume(this.byteCount <= this.value.length); + Engine.assume(this.byteCount >= 0); + Engine.assume(this.coder == StringImpl._currentCoder()); } public StringBuilderImpl append(CharSequence seq) { _assumeInvariants(); - if (seq == null) { - _appendCharSequence("null", 0, 4); - } else { - _appendCharSequence(seq, 0, seq.length()); - } + seq = _getCharSequence(seq); + _appendCharSequence(seq); return this; } - @SuppressWarnings("ReplaceNullCheck") public StringBuilderImpl append(CharSequence seq, int start, int end) { _assumeInvariants(); - if (seq == null) { - _appendCharSequence("null", start, end); - } else { - _appendCharSequence(seq, start, end); - } + seq = _getCharSequence(seq); + _appendCharSequence(seq, start, end); + return this; } public StringBuilderImpl append(Object obj) { _assumeInvariants(); - if (obj == null) { - _appendCharSequence("null", 0, 4); - } else { - String seq = LibSLRuntime.toString(obj); - _appendCharSequence(seq, 0, seq.length()); - } + CharSequence seq = _getCharSequence(obj); + _appendCharSequence(seq); + return this; } public StringBuilderImpl append(String str) { _assumeInvariants(); - if (str == null) { - _appendCharSequence("null", 0, 4); - } else { - _appendCharSequence(str, 0, str.length()); - } + CharSequence seq = _getCharSequence(str); + _appendCharSequence(seq); + return this; } public StringBuilderImpl append(StringBuffer sb) { _assumeInvariants(); - if (sb == null) { - _appendCharSequence("null", 0, 4); - } else { - String seq = LibSLRuntime.toString(sb); - _appendCharSequence(seq, 0, seq.length()); - } + CharSequence seq = _getCharSequence(sb); + _appendCharSequence(seq); + return this; } public StringBuilderImpl append(boolean x) { _assumeInvariants(); - if (x) { - _appendCharSequence("true", 0, 4); - } else { - _appendCharSequence("false", 0, 5); - } + CharSequence seq = _getCharSequence(x); + _appendCharSequence(seq); + return this; } public StringBuilderImpl append(char x) { _assumeInvariants(); - if (this.count < this.value.length) { - value[this.count] = x; - this.count++; + if (this.byteCount < this.value.length) { + StringImpl._addCharToBytes(value, byteCount, x); + this.byteCount++; } + return this; } - public StringBuilderImpl append(char[] str) { + public StringBuilderImpl append(char[] chars) { _assumeInvariants(); - String seq = LibSLRuntime.toString(str); - _appendCharSequence(seq, 0, seq.length()); + _appendChars(chars, 0, chars.length); + return this; } - public StringBuilderImpl append(char[] str, int offset, int len) { + public StringBuilderImpl append(char[] chars, int offset, int len) { _assumeInvariants(); - String seq = LibSLRuntime.toString(str); - _appendCharSequence(seq, offset, len); + _appendChars(chars, offset, len); + return this; } public StringBuilderImpl append(double x) { _assumeInvariants(); String seq = LibSLRuntime.toString(x); - _appendCharSequence(seq, 0, seq.length()); + _appendCharSequence(seq); + return this; } public StringBuilderImpl append(float x) { _assumeInvariants(); String seq = LibSLRuntime.toString(x); - _appendCharSequence(seq, 0, seq.length()); + _appendCharSequence(seq); + return this; } public StringBuilderImpl append(int x) { _assumeInvariants(); String seq = LibSLRuntime.toString(x); - _appendCharSequence(seq, 0, seq.length()); + _appendCharSequence(seq); + return this; } public StringBuilderImpl append(long x) { _assumeInvariants(); String seq = LibSLRuntime.toString(x); - _appendCharSequence(seq, 0, seq.length()); + _appendCharSequence(seq); + return this; } public StringBuilderImpl appendCodePoint(int codePoint) { + // TODO: fix #Approx _assumeInvariants(); - int cnt = this.count; + int cnt = this.byteCount; int len = this.value.length; if (Character.isBmpCodePoint(codePoint)) { if (cnt + 1 <= len) { - value[cnt] = ((char) codePoint); - this.count = cnt + 1; + value[cnt] = (byte) codePoint; + this.byteCount = cnt + 1; } } else { if (Character.isValidCodePoint(codePoint)) { if (cnt + 2 <= len) { - value[cnt + 1] = Character.lowSurrogate(codePoint); - value[cnt] = Character.highSurrogate(codePoint); - this.count = cnt + 2; + value[cnt + 1] = (byte) Character.lowSurrogate(codePoint); + value[cnt] = (byte) Character.highSurrogate(codePoint); + this.byteCount = cnt + 2; } } else { throw new IllegalArgumentException(); @@ -307,21 +413,24 @@ public StringBuilderImpl appendCodePoint(int codePoint) { public int capacity() { _assumeInvariants(); - return this.value.length; + return _bytePosToCharPos(this.value.length); } public char charAt(int index) { + // TODO: fix #Approx _assumeInvariants(); - if (index < 0 || index >= this.count) + index = _charPosToBytePos(index); + if (index < 0 || index >= this.byteCount) throw new StringIndexOutOfBoundsException(); - return value[index]; + return (char) value[index]; } @NotNull public IntStream chars() { + // TODO: fix #Approx _assumeInvariants(); - int len = this.count; + int len = this.byteCount; int[] intValues = new int[len]; for (int i = 0; i < len; i++) { intValues[i] = value[i]; @@ -332,33 +441,37 @@ public IntStream chars() { public int codePointAt(int index) { _assumeInvariants(); - if (index < 0 || index >= this.count) + if (index < 0 || index >= this.byteCount) throw new StringIndexOutOfBoundsException(index); - return Character.codePointAt(this.value, index, this.count); + // TODO: support code points #Approx + return 0; } public int codePointBefore(int index) { _assumeInvariants(); int i = index - 1; - if (i < 0 || i >= this.count) + if (i < 0 || i >= this.byteCount) throw new StringIndexOutOfBoundsException(index); - return Character.codePointBefore(this.value, index, 0); + // TODO: support code points #Approx + return 0; } public int codePointCount(int beginIndex, int endIndex) { _assumeInvariants(); - if (beginIndex < 0 || beginIndex > endIndex || endIndex > this.count) + if (beginIndex < 0 || beginIndex > endIndex || endIndex > this.byteCount) throw new IndexOutOfBoundsException(); - return Character.codePointCount(this.value, beginIndex, endIndex - beginIndex); + // TODO: support code points #Approx + return 0; } @NotNull public IntStream codePoints() { + // TODO: support code points #Approx _assumeInvariants(); - int len = this.count; + int len = this.byteCount; int[] intValues = new int[len]; for (int i = 0; i < len; i++) { intValues[i] = value[i]; @@ -371,20 +484,23 @@ public int compareTo(@NotNull StringBuilderImpl another) { if (another == this) return 0; - String thisString = _asString(); - String anotherString = another._asString(); + // TODO: implement compareTo in StringImpl #Approx + String thisString = _asString().toString(); + String anotherString = another._asString().toString(); return thisString.compareTo(anotherString); } public StringBuilderImpl delete(int start, int end) { _assumeInvariants(); _deleteChars(start, end); + return this; } public StringBuilderImpl deleteCharAt(int index) { _assumeInvariants(); _deleteChars(index, index + 1); + return this; } @@ -393,8 +509,9 @@ public void ensureCapacity(int minimumCapacity) { } public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) { + // TODO: fix #Approx _assumeInvariants(); - if (srcBegin < 0 || srcBegin > srcEnd || srcEnd > this.count) + if (srcBegin < 0 || srcBegin > srcEnd || srcEnd > this.byteCount) throw new StringIndexOutOfBoundsException(); int len = srcEnd - srcBegin; if (dst == null) @@ -407,79 +524,70 @@ public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) { public char[] getValue() { _assumeInvariants(); - return this.value; + return StringImpl._getChars(this.value); } public int indexOf(String str) { _assumeInvariants(); - return _asString().indexOf(str); + // TODO: implement indexOf in StringImpl #Approx + return _asString().toString().indexOf(str); } public int indexOf(String str, int fromIndex) { _assumeInvariants(); - return _asString().indexOf(str, fromIndex); + // TODO: implement indexOf in StringImpl #Approx + return _asString().toString().indexOf(str, fromIndex); } public StringBuilderImpl insert(int dstOffset, CharSequence s) { _assumeInvariants(); - if (s == null) { - _insertCharSequence(dstOffset, "null", 0, 4); - } else { - _insertCharSequence(dstOffset, s, 0, s.length()); - } + _insertCharSequence(dstOffset, s); + return this; } - @SuppressWarnings("ReplaceNullCheck") public StringBuilderImpl insert(int dstOffset, CharSequence s, int start, int end) { _assumeInvariants(); - if (s == null) { - _insertCharSequence(dstOffset, "null", start, end); - } else { - _insertCharSequence(dstOffset, s, start, end); - } + _insertCharSequence(dstOffset, s, start, end); + return this; } public StringBuilderImpl insert(int dstOffset, Object obj) { _assumeInvariants(); - if (obj == null) { - _insertCharSequence(dstOffset, "null", 0, 4); - } else { - String s = LibSLRuntime.toString(obj); - _insertCharSequence(dstOffset, s, 0, s.length()); - } + CharSequence seq = _getCharSequence(obj); + _insertCharSequence(dstOffset, seq); + return this; } public StringBuilderImpl insert(int dstOffset, String s) { _assumeInvariants(); - if (s == null) { - _insertCharSequence(dstOffset, "null", 0, 4); - } else { - _insertCharSequence(dstOffset, s, 0, s.length()); - } + _insertCharSequence(dstOffset, s); + return this; } public StringBuilderImpl insert(int dstOffset, boolean x) { _assumeInvariants(); - String s = LibSLRuntime.toString(x); - _insertCharSequence(dstOffset, s, 0, s.length()); + CharSequence seq = _getCharSequence(x); + _insertCharSequence(dstOffset, seq); + return this; } public StringBuilderImpl insert(int dstOffset, char x) { _assumeInvariants(); - String s = LibSLRuntime.toString(x); - _insertCharSequence(dstOffset, s, 0, 1); + CharSequence seq = _getCharSequence(x); + _insertCharSequence(dstOffset, seq, 0, 1); + return this; } public StringBuilderImpl insert(int dstOffset, char[] x) { _assumeInvariants(); - String s = LibSLRuntime.toString(x); - _insertCharSequence(dstOffset, s, 0, s.length()); + _insertChars(dstOffset, x, 0, x.length); + return this; } @@ -487,118 +595,122 @@ public StringBuilderImpl insert(int index, char[] str, int offset, int len) { _assumeInvariants(); char[] arr = new char[len]; LibSLRuntime.ArrayActions.copy(str, offset, arr, 0, len); - String s = LibSLRuntime.toString(arr); - _insertCharSequence(index, s, 0, len); + _insertChars(index, arr, 0, len); + return this; } public StringBuilderImpl insert(int dstOffset, double x) { _assumeInvariants(); String s = LibSLRuntime.toString(x); - _insertCharSequence(dstOffset, s, 0, s.length()); + _insertCharSequence(dstOffset, s); + return this; } public StringBuilderImpl insert(int dstOffset, float x) { _assumeInvariants(); String s = LibSLRuntime.toString(x); - _insertCharSequence(dstOffset, s, 0, s.length()); + _insertCharSequence(dstOffset, s); + return this; } public StringBuilderImpl insert(int dstOffset, int x) { _assumeInvariants(); String s = LibSLRuntime.toString(x); - _insertCharSequence(dstOffset, s, 0, s.length()); + _insertCharSequence(dstOffset, s); + return this; } public StringBuilderImpl insert(int dstOffset, long x) { _assumeInvariants(); String s = LibSLRuntime.toString(x); - _insertCharSequence(dstOffset, s, 0, s.length()); + _insertCharSequence(dstOffset, s); + return this; } public int lastIndexOf(String str) { _assumeInvariants(); - return _asString().lastIndexOf(str, this.count); + return _asString().toString().lastIndexOf(str, this.byteCount); } public int lastIndexOf(String str, int fromIndex) { _assumeInvariants(); - return _asString().lastIndexOf(str, fromIndex); + return _asString().toString().lastIndexOf(str, fromIndex); } public int length() { _assumeInvariants(); - return this.count; + return this.byteCount; } public int offsetByCodePoints(int index, int codePointOffset) { _assumeInvariants(); - if (index < 0 || index > this.count) + if (index < 0 || index > this.byteCount) throw new IndexOutOfBoundsException(); - return Character.offsetByCodePoints(this.value, 0, this.count, index, codePointOffset); + // TODO: support code points #Approx + return 0; } public StringBuilderImpl replace(int start, int end, String s) { _assumeInvariants(); _deleteChars(start, end); - if (s == null) { - _insertCharSequence(start, "null", 0, 4); - } else { - _insertCharSequence(start, s, 0, s.length()); - } + _insertCharSequence(start, s); + return this; } public StringBuilderImpl reverse() { _assumeInvariants(); - if (this.count == 0) - return this; - - boolean hasSurrogates = false; - int n = this.count - 1; - for (int i = (n - 1) >> 1; i > -1; i--) { - int k = n - i; - char cj = value[i]; - char ck = value[k]; - value[i] = ck; - value[k] = cj; - if (Character.isSurrogate(cj) || Character.isSurrogate(ck)) { - hasSurrogates = true; - } - } - if (!hasSurrogates) + if (this.byteCount == 0) return this; - for (int i = 0; i < n; i++) { - char c2 = value[i]; - if (Character.isLowSurrogate(c2)) { - char c1 = value[i + 1]; - if (Character.isHighSurrogate(c1)) { - value[i] = c1; - i++; - value[i] = c2; - } - } - } + // TODO: implement #Approx +// boolean hasSurrogates = false; +// int n = this.byteCount - 1; +// for (int i = (n - 1) >> 1; i > -1; i--) { +// int k = n - i; +// byte cj = value[i]; +// byte ck = value[k]; +// value[i] = ck; +// value[k] = cj; +// if (Character.isSurrogate(cj) || Character.isSurrogate(ck)) { +// hasSurrogates = true; +// } +// } +// if (!hasSurrogates) +// return this; +// +// for (int i = 0; i < n; i++) { +// char c2 = value[i]; +// if (Character.isLowSurrogate(c2)) { +// char c1 = value[i + 1]; +// if (Character.isHighSurrogate(c1)) { +// value[i] = c1; +// i++; +// value[i] = c2; +// } +// } +// } return this; } public void setCharAt(int index, char x) { _assumeInvariants(); - if (index < 0 || index >= this.count) + if (index < 0 || index >= this.byteCount) throw new StringIndexOutOfBoundsException(); - value[index] = x; + StringImpl._addCharToBytes(value, index, x); } public void setLength(int newLength) { _assumeInvariants(); + newLength = _charPosToBytePos(newLength); int maxLength = this.value.length; if (newLength > maxLength) newLength = maxLength; @@ -606,46 +718,49 @@ public void setLength(int newLength) { if (newLength < 0) throw new StringIndexOutOfBoundsException(); - if (newLength < this.count) { - this.count = newLength; + if (newLength < this.byteCount) { + this.byteCount = newLength; return; } - if (newLength > this.count) { - LibSLRuntime.ArrayActions.fillRange(this.value, this.count, newLength, ((char) 0)); - this.count = newLength; + if (newLength > this.byteCount) { + LibSLRuntime.ArrayActions.fillRange(this.value, this.byteCount, newLength, ((byte) 0)); + this.byteCount = newLength; } } @NotNull public CharSequence subSequence(int start, int end) { _assumeInvariants(); - if (start < 0 || start > end || end > this.count) + // TODO: fix #Approx + if (start < 0 || start > end || end > this.byteCount) throw new StringIndexOutOfBoundsException(); - return _asString(start, end); + return _asString(start, end).toString(); } public String substring(int start) { _assumeInvariants(); - if (start < 0 || start > this.count) + // TODO: fix #Approx + if (start < 0 || start > this.byteCount) throw new StringIndexOutOfBoundsException(); - return _asString(start, this.count); + return _asString(start, this.byteCount).toString(); } public String substring(int start, int end) { _assumeInvariants(); - if (start < 0 || start > end || end > this.count) + // TODO: fix #Approx + if (start < 0 || start > end || end > this.byteCount) throw new StringIndexOutOfBoundsException(); - return _asString(start, end); + return _asString(start, end).toString(); } @NotNull public String toString() { _assumeInvariants(); - return _asString(); + return _asString().toString(); } public void trimToSize() { diff --git a/approximations/src/main/java/generated/java/lang/StringImpl.java b/approximations/src/main/java/generated/java/lang/StringImpl.java index c730a8a7..e5f9f128 100644 --- a/approximations/src/main/java/generated/java/lang/StringImpl.java +++ b/approximations/src/main/java/generated/java/lang/StringImpl.java @@ -17,27 +17,95 @@ public class StringImpl implements Serializable { private static final int STRING_LENGTH_MAX = 50; - public byte[] value; + static final byte UTF16 = 1; - public int length; + static final byte LATIN1 = 0; - public StringImpl(byte[] value, int length) { + // Enforce coder == UTF8 + static boolean COMPACT_STRINGS; + + static { + COMPACT_STRINGS = true; + } + + private final byte[] value; + + // TODO: everywhere add assume 'coder == LATIN1' #Approx + private final byte coder; + + public static StringImpl _emptyString = new StringImpl(new byte[] {}); + + public static byte _currentCoder() { + return COMPACT_STRINGS ? LATIN1 : UTF16; + } + + public static void _addCharToBytes(byte[] bytes, int index, char value) { + if (COMPACT_STRINGS) { + Engine.assume(value <= 0xFF); + bytes[index] = (byte) value; + } else { + bytes[index++] = (byte) value; + bytes[index] = (byte) (value >> 8); + } + } + + public static byte[] _getBytes(char[] chars) { + int size = chars.length << _currentCoder(); + byte[] bytes = new byte[size]; + if (COMPACT_STRINGS) { + for (int i = 0; i < chars.length; i++) { + char c = chars[i]; + Engine.assume(c <= 0xFF); + bytes[i] = (byte) chars[i]; + } + } else { + int byteIndex = 0; + for (char c : chars) { + bytes[byteIndex++] = (byte) c; + bytes[byteIndex] = (byte) (c >> 8); + byteIndex++; + } + } + + return bytes; + } + + public static char[] _getChars(byte[] bytes) { + int size = bytes.length >> _currentCoder(); + char[] chars = new char[size]; + if (COMPACT_STRINGS) { + for (int i = 0; i < bytes.length; i++) { + byte c = bytes[i]; + chars[i] = (char) bytes[i]; + } + } else { + int byteIndex = 0; + for (int i = 0; i < chars.length; i++) { + char c = (char) (((char) bytes[byteIndex++]) | (((char) bytes[byteIndex++]) << 8)); + } + } + + return chars; + } + + private StringImpl(byte[] value, byte coder) { + Engine.assume(coder == _currentCoder()); this.value = value; - this.length = length; + this.coder = coder; } public StringImpl() { - this(new byte[0], 0); + this(new byte[0], _currentCoder()); } public StringImpl(StringImpl original) { - this(original.value, original.length); + this(original.value, original.coder); } public StringImpl(byte[] bytes) { int len = bytes.length; - this.length = len; this.value = new byte[len]; + this.coder = _currentCoder(); LibSLRuntime.ArrayActions.copy(bytes, 0, this.value, 0, len); } @@ -90,50 +158,42 @@ public static java.lang.String valueOf(long x) { } @SuppressWarnings("DataFlowIssue") - public StringImpl concat(StringImpl str) { + private void _assumeInvariants() { Engine.assume(this.value != null); Engine.assume(this.value.length <= STRING_LENGTH_MAX); - Engine.assume(this.length == this.value.length); + Engine.assume(this.coder == _currentCoder()); + } + + public StringImpl concat(StringImpl str) { + _assumeInvariants(); + byte[] otherVal = str.value; int otherLen = otherVal.length; if (otherLen == 0) return this; - int newLength = this.length + otherLen; + int newLength = this.value.length + otherLen; byte[] newValue = new byte[newLength]; - LibSLRuntime.ArrayActions.copy(this.value, 0, newValue, 0, this.length); - LibSLRuntime.ArrayActions.copy(otherVal, 0, newValue, this.length, otherLen); - return new StringImpl(newValue, newLength); + LibSLRuntime.ArrayActions.copy(this.value, 0, newValue, 0, this.value.length); + LibSLRuntime.ArrayActions.copy(otherVal, 0, newValue, this.value.length, otherLen); + return new StringImpl(newValue, _currentCoder()); } - @SuppressWarnings("DataFlowIssue") public byte[] getBytes() { - Engine.assume(this.value != null); - Engine.assume(this.value.length <= STRING_LENGTH_MAX); - Engine.assume(this.length == this.value.length); + _assumeInvariants(); + return this.value; } - @SuppressWarnings("DataFlowIssue") public void getBytes(int srcBegin, int srcEnd, byte[] dst, int dstBegin) { if (srcBegin < 0) throw new StringIndexOutOfBoundsException(srcBegin); - if (this.length < srcEnd) + if (this.value.length < srcEnd) throw new StringIndexOutOfBoundsException(srcEnd); int count = srcEnd - srcBegin; if (count < 0) throw new StringIndexOutOfBoundsException(count); - Engine.assume(this.value != null); - Engine.assume(this.value.length <= STRING_LENGTH_MAX); - Engine.assume(this.length == this.value.length); + _assumeInvariants(); LibSLRuntime.ArrayActions.copy(this.value, srcBegin, dst, dstBegin, count); } - - public boolean isEmpty() { - return this.length == 0; - } - - public int length() { - return this.length; - } } diff --git a/approximations/src/main/java/generated/java/lang/SystemImpl.java b/approximations/src/main/java/generated/java/lang/SystemImpl.java index b91d594a..4e09e54e 100644 --- a/approximations/src/main/java/generated/java/lang/SystemImpl.java +++ b/approximations/src/main/java/generated/java/lang/SystemImpl.java @@ -12,6 +12,7 @@ import java.lang.SecurityException; import java.lang.String; import java.lang.UnsatisfiedLinkError; +import java.util.Map; import java.util.Properties; import jdk.internal.misc.VM; import org.jacodb.approximation.annotation.Approximate; @@ -21,12 +22,10 @@ @SuppressWarnings({"unused", "removal"}) @Approximate(java.lang.System.class) public final class SystemImpl { - private static final LibSLRuntime.Map propsMap = new LibSLRuntime.Map<>(new LibSLRuntime.HashMapContainer<>()); + private static Properties props; private static volatile SecurityManager security = null; - private static Properties props = null; - @SuppressWarnings("FieldMayBeFinal") private static Console console = null; @@ -51,70 +50,69 @@ public final class SystemImpl { private SystemImpl() { } private static void _initProperties() { - LibSLRuntime.Map pm = propsMap; + props = new Properties(); int javaVersion = 8; String userName = "Admin"; - pm.set("file.encoding", "Cp1251"); - pm.set("sun.io.unicode.encoding", "UnicodeLittle"); - pm.set("sun.jnu.encoding", "Cp1251"); - pm.set("sun.stderr.encoding", "cp866"); - pm.set("sun.stdout.encoding", "cp866"); + props.setProperty("file.encoding", "Cp1251"); + props.setProperty("sun.io.unicode.encoding", "UnicodeLittle"); + props.setProperty("sun.jnu.encoding", "Cp1251"); + props.setProperty("sun.stderr.encoding", "cp866"); + props.setProperty("sun.stdout.encoding", "cp866"); String[] versionStrings = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15" }; String versionString = versionStrings[javaVersion]; - pm.set("java.specification.name", "Java Platform API Specification"); - pm.set("java.specification.vendor", "Oracle Corporation"); - pm.set("java.specification.version", versionString); - pm.set("java.vm.info", "mixed mode"); - pm.set("java.vm.name", "OpenJDK 64-Bit Server VM"); - pm.set("java.vm.specification.name", "Java Virtual Machine Specification"); - pm.set("java.vm.specification.vendor", "Oracle Corporation"); - pm.set("java.vm.specification.version", versionString); - pm.set("java.vm.vendor", "Eclipse Adoptium"); - pm.set("java.vm.version", versionString.concat(".0.362+9")); - pm.set("java.library.path", "C:\\Program Files\\Eclipse Adoptium\\jdk-8.0.362.9-hotspot\\bin;C:\\Windows\\Sun\\Java\\bin;C:\\Windows\\system32;."); - pm.set("java.home", "C:\\Program Files\\Eclipse Adoptium\\jdk-8.0.362.9-hotspot"); - pm.set("sun.boot.library.path", "C:\\Program Files\\Eclipse Adoptium\\jdk-8.0.362.9-hotspot\\bin"); - pm.set("java.io.tmpdir", "T:\\Temp\\"); - pm.set("java.class.path", "."); + props.setProperty("java.specification.name", "Java Platform API Specification"); + props.setProperty("java.specification.vendor", "Oracle Corporation"); + props.setProperty("java.specification.version", versionString); + props.setProperty("java.vm.info", "mixed mode"); + props.setProperty("java.vm.name", "OpenJDK 64-Bit Server VM"); + props.setProperty("java.vm.specification.name", "Java Virtual Machine Specification"); + props.setProperty("java.vm.specification.vendor", "Oracle Corporation"); + props.setProperty("java.vm.specification.version", versionString); + props.setProperty("java.vm.vendor", "Eclipse Adoptium"); + props.setProperty("java.vm.version", versionString.concat(".0.362+9")); + props.setProperty("java.library.path", "C:\\Program Files\\Eclipse Adoptium\\jdk-8.0.362.9-hotspot\\bin;C:\\Windows\\Sun\\Java\\bin;C:\\Windows\\system32;."); + props.setProperty("java.home", "C:\\Program Files\\Eclipse Adoptium\\jdk-8.0.362.9-hotspot"); + props.setProperty("sun.boot.library.path", "C:\\Program Files\\Eclipse Adoptium\\jdk-8.0.362.9-hotspot\\bin"); + props.setProperty("java.io.tmpdir", "T:\\Temp\\"); + props.setProperty("java.class.path", "."); if (LibSLGlobals.SYSTEM_IS_WINDOWS) { - pm.set("file.separator", "\\"); - pm.set("line.separator", "\r\n"); - pm.set("path.separator", ";"); + props.setProperty( "file.separator", "\\"); + props.setProperty("line.separator", "\r\n"); + props.setProperty( "path.separator", ";"); } else { - pm.set("file.separator", "/"); - pm.set("line.separator", "\n"); - pm.set("path.separator", ":"); + props.setProperty("file.separator", "/"); + props.setProperty("line.separator", "\n"); + props.setProperty("path.separator", ":"); } - pm.set("user.country", "RU"); - pm.set("user.country.format", "US"); - pm.set("user.language", "ru"); + props.setProperty("user.country", "RU"); + props.setProperty("user.country.format", "US"); + props.setProperty("user.language", "ru"); String[] bytecodeVersions = { "?", "?", "?", "?", "?", "49.0", "50.0", "51.0", "52.0", "53.0", "54.0", "55.0", "?", "?", "?", "?" }; - pm.set("java.class.version", bytecodeVersions[javaVersion]); - pm.set("os.arch", "amd64"); - pm.set("os.name", "Windows 10"); - pm.set("os.version", "10.0"); - pm.set("sun.arch.data.model", "64"); - pm.set("sun.cpu.endian", "little"); - pm.set("sun.cpu.isalist", "amd64"); - pm.set("sun.desktop", "windows"); - pm.set("user.dir", "D:\\Company\\Prod\\Service"); - pm.set("user.home", "C:\\Users\\".concat(userName)); - pm.set("user.name", userName); - pm.set("user.script", ""); - pm.set("user.timezone", ""); - pm.set("user.variant", ""); - pm.set("sun.java.command", "org.example.MainClass"); - pm.set("awt.toolkit", "sun.awt.windows.WToolkit"); - pm.set("java.awt.graphicsenv", "sun.awt.Win32GraphicsEnvironment"); - pm.set("java.awt.printerjob", "sun.awt.windows.WPrinterJob"); - pm.set("sun.java.launcher", "SUN_STANDARD"); - pm.set("sun.management.compiler", "HotSpot 64-Bit Tiered Compilers"); - pm.set("sun.nio.MaxDirectMemorySize", "-1"); - pm.set("sun.os.patch.level", ""); - pm.set("java.vm.compressedOopsMode", "Zero based"); - pm.set("jdk.boot.class.path.append", ""); - pm.set("jdk.debug", "release"); - props = null; + props.setProperty("java.class.version", bytecodeVersions[javaVersion]); + props.setProperty("os.arch", "amd64"); + props.setProperty("os.name", "Windows 10"); + props.setProperty("os.version", "10.0"); + props.setProperty("sun.arch.data.model", "64"); + props.setProperty("sun.cpu.endian", "little"); + props.setProperty("sun.cpu.isalist", "amd64"); + props.setProperty("sun.desktop", "windows"); + props.setProperty("user.dir", "D:\\Company\\Prod\\Service"); + props.setProperty("user.home", "C:\\Users\\".concat(userName)); + props.setProperty("user.name", userName); + props.setProperty("user.script", ""); + props.setProperty("user.timezone", ""); + props.setProperty("user.variant", ""); + props.setProperty("sun.java.command", "org.example.MainClass"); + props.setProperty("awt.toolkit", "sun.awt.windows.WToolkit"); + props.setProperty("java.awt.graphicsenv", "sun.awt.Win32GraphicsEnvironment"); + props.setProperty("java.awt.printerjob", "sun.awt.windows.WPrinterJob"); + props.setProperty("sun.java.launcher", "SUN_STANDARD"); + props.setProperty("sun.management.compiler", "HotSpot 64-Bit Tiered Compilers"); + props.setProperty("sun.nio.MaxDirectMemorySize", "-1"); + props.setProperty("sun.os.patch.level", ""); + props.setProperty("java.vm.compressedOopsMode", "Zero based"); + props.setProperty("jdk.boot.class.path.append", ""); + props.setProperty("jdk.debug", "release"); } @SuppressWarnings("DataFlowIssue") @@ -150,12 +148,11 @@ public static String clearProperty(String key) { SecurityManager sm = security; if (sm != null) sm.checkPermission(new java.util.PropertyPermission(key, "write")); - LibSLRuntime.Map pm = propsMap; - if (!pm.hasKey(key)) + if (!props.containsKey(key)) return null; - String result = pm.get(key); - pm.remove(key); + String result = props.getProperty(key); + props.remove(key); return result; } @@ -181,11 +178,7 @@ public static String getProperty(String key) { SecurityManager sm = security; if (sm != null) sm.checkPropertyAccess(key); - LibSLRuntime.Map pm = propsMap; - if (!pm.hasKey(key)) - return null; - - return pm.get(key); + return props.getProperty(key); } public static String getProperty(String key, String def) { @@ -194,9 +187,8 @@ public static String getProperty(String key, String def) { if (sm != null) { sm.checkPropertyAccess(key); } - LibSLRuntime.Map pm = propsMap; - if (pm.hasKey(key)) - return pm.get(key); + if (props.containsKey(key)) + return props.getProperty(key); return def; } @@ -235,7 +227,7 @@ public static int identityHashCode(Object x) { } public static String lineSeparator() { - return propsMap.get("line.separator"); + return props.getProperty("line.separator"); } @SuppressWarnings({"DuplicateCondition", "ConstantValue"}) @@ -310,15 +302,7 @@ public static String setProperty(String key, String value) { throw new NullPointerException("key can't be empty"); if (security != null) security.checkPermission(new java.util.PropertyPermission(key, "write")); - LibSLRuntime.Map pm = propsMap; - String result; - if (pm.hasKey(key)) { - result = pm.get(key); - } else { - result = null; - } - pm.set(key, value); - return result; + return (String)props.setProperty(key, value); } public static void setSecurityManager(SecurityManager s) { diff --git a/approximations/src/main/java/generated/java/util/PropertiesImpl.java b/approximations/src/main/java/generated/java/util/PropertiesImpl.java new file mode 100644 index 00000000..b364eb09 --- /dev/null +++ b/approximations/src/main/java/generated/java/util/PropertiesImpl.java @@ -0,0 +1,21 @@ +package generated.java.util; + +import generated.java.util.map.AbstractMapImpl; +import generated.java.util.map.ConcurrentHashMapImpl; +import org.jacodb.approximation.annotation.Approximate; +import org.usvm.api.Engine; + +import java.util.Map; +import java.util.Properties; +import java.util.Set; + +@Approximate(Properties.class) +public class PropertiesImpl { + private final ConcurrentHashMapImpl map; + protected Properties defaults; + + private PropertiesImpl(Properties defaults, int initialCapacity) { + this.map = new ConcurrentHashMapImpl<>(initialCapacity); + this.defaults = defaults; + } +} diff --git a/approximations/src/main/java/generated/java/util/array/ArraysImpl.java b/approximations/src/main/java/generated/java/util/array/ArraysImpl.java new file mode 100644 index 00000000..3dc9941b --- /dev/null +++ b/approximations/src/main/java/generated/java/util/array/ArraysImpl.java @@ -0,0 +1,23 @@ +package generated.java.util.array; + +import generated.java.util.list.ArrayListImpl; +import org.jacodb.approximation.annotation.Approximate; + +import java.util.Arrays; +import java.util.List; + +@Approximate(Arrays.class) +public class ArraysImpl { + + @SafeVarargs + @SuppressWarnings("varargs") + public static List asList(T... a) { + ArrayListImpl list = new ArrayListImpl(); + int index = 0; + for (T item : a) { + list.add(index, item); + index++; + } + return list; + } +} diff --git a/approximations/src/main/java/generated/java/util/stream/BaseStreamImpl.java b/approximations/src/main/java/generated/java/util/stream/BaseStreamImpl.java index df1dbe22..656bea4c 100644 --- a/approximations/src/main/java/generated/java/util/stream/BaseStreamImpl.java +++ b/approximations/src/main/java/generated/java/util/stream/BaseStreamImpl.java @@ -39,19 +39,19 @@ protected SymbolicList _getCloseHandlers() { } protected StreamStubImpl _copyToObjStream(T[] storage) { - return new StreamStubImpl<>(storage, _getCloseHandlers(), isParallel, linkedOrConsumed); + return new StreamStubImpl<>(storage, _getCloseHandlers(), isParallel, false); } protected IntStreamImpl _copyToIntStream(int[] storage) { - return new IntStreamImpl(storage, _getCloseHandlers(), isParallel, linkedOrConsumed); + return new IntStreamImpl(storage, _getCloseHandlers(), isParallel, false); } protected LongStreamImpl _copyToLongStream(long[] storage) { - return new LongStreamImpl(storage, _getCloseHandlers(), isParallel, linkedOrConsumed); + return new LongStreamImpl(storage, _getCloseHandlers(), isParallel, false); } protected DoubleStreamImpl _copyToDoubleStream(double[] storage) { - return new DoubleStreamImpl(storage, _getCloseHandlers(), isParallel, linkedOrConsumed); + return new DoubleStreamImpl(storage, _getCloseHandlers(), isParallel, false); } public void evaluate() { diff --git a/approximations/src/main/java/generated/java/util/stream/DoubleStreamImpl.java b/approximations/src/main/java/generated/java/util/stream/DoubleStreamImpl.java index c5779c9b..f9bd64a0 100644 --- a/approximations/src/main/java/generated/java/util/stream/DoubleStreamImpl.java +++ b/approximations/src/main/java/generated/java/util/stream/DoubleStreamImpl.java @@ -68,7 +68,7 @@ protected int _getLength() { } private DoubleStreamImpl _copy(double[] storage) { - return new DoubleStreamImpl(storage, _getCloseHandlers(), isParallel, linkedOrConsumed); + return new DoubleStreamImpl(storage, _getCloseHandlers(), isParallel, false); } private DoubleStreamImpl _copy() { diff --git a/approximations/src/main/java/generated/java/util/stream/IntStreamImpl.java b/approximations/src/main/java/generated/java/util/stream/IntStreamImpl.java index 04f57a43..d00243ff 100644 --- a/approximations/src/main/java/generated/java/util/stream/IntStreamImpl.java +++ b/approximations/src/main/java/generated/java/util/stream/IntStreamImpl.java @@ -66,7 +66,7 @@ protected int _getLength() { } private IntStreamImpl _copy(int[] storage) { - return new IntStreamImpl(storage, _getCloseHandlers(), isParallel, linkedOrConsumed); + return new IntStreamImpl(storage, _getCloseHandlers(), isParallel, false); } private IntStreamImpl _copy() { diff --git a/approximations/src/main/java/generated/java/util/stream/LongStreamImpl.java b/approximations/src/main/java/generated/java/util/stream/LongStreamImpl.java index b7ba0843..9628acd3 100644 --- a/approximations/src/main/java/generated/java/util/stream/LongStreamImpl.java +++ b/approximations/src/main/java/generated/java/util/stream/LongStreamImpl.java @@ -66,7 +66,7 @@ protected int _getLength() { } private LongStreamImpl _copy(long[] storage) { - return new LongStreamImpl(storage, _getCloseHandlers(), isParallel, linkedOrConsumed); + return new LongStreamImpl(storage, _getCloseHandlers(), isParallel, false); } private LongStreamImpl _copy() { diff --git a/approximations/src/main/java/generated/java/util/stream/StreamStubImpl.java b/approximations/src/main/java/generated/java/util/stream/StreamStubImpl.java index c404dd87..6fb83caf 100644 --- a/approximations/src/main/java/generated/java/util/stream/StreamStubImpl.java +++ b/approximations/src/main/java/generated/java/util/stream/StreamStubImpl.java @@ -78,7 +78,7 @@ protected int _getLength() { } private StreamStubImpl _copy(T[] storage) { - return new StreamStubImpl<>(storage, _getCloseHandlers(), isParallel, linkedOrConsumed); + return new StreamStubImpl<>(storage, _getCloseHandlers(), isParallel, false); } private StreamStubImpl _copy() { diff --git a/approximations/src/main/java/runtime/LibSLRuntime.java b/approximations/src/main/java/runtime/LibSLRuntime.java index fb03400d..38b334aa 100644 --- a/approximations/src/main/java/runtime/LibSLRuntime.java +++ b/approximations/src/main/java/runtime/LibSLRuntime.java @@ -234,7 +234,7 @@ public static String toString(long v) { } public static String toString(final char v) { - return String.valueOf(v); + return new String(new char[] { v }); } // TODO: do we need more variants for other primitive array types? diff --git a/tests/src/main/java/approximations/java/lang/System_Tests.java b/tests/src/main/java/approximations/java/lang/System_Tests.java index e6371555..5f9d78d5 100644 --- a/tests/src/main/java/approximations/java/lang/System_Tests.java +++ b/tests/src/main/java/approximations/java/lang/System_Tests.java @@ -7,10 +7,12 @@ import java.lang.Object; import java.lang.SecurityManager; import java.lang.String; +import java.util.Objects; import java.util.Properties; import java.util.ResourceBundle; import java.lang.System; +import java.util.concurrent.ConcurrentHashMap; @Test @SuppressWarnings({"unused", "UnnecessaryBoxing", "JavadocReference"}) @@ -92,34 +94,50 @@ public static int test_arraycopy_0(final int execution) { /** * {@link java.lang.System#clearProperty(String)} */ - @Test(executionMax = 1) + @Test public static int test_clearProperty_0(final int execution) { - switch (execution) { - case 0: { - System.setProperty("abc.xyz", "321"); - String oldValue = System.clearProperty("abc.xyz"); + System.setProperty("abc.xyz", "321"); + String oldValue = System.clearProperty("abc.xyz"); - if (!"321".equals(oldValue)) - return -1; - break; - } + if (!"321".equals(oldValue)) + return -1; - case 1: { - String oldValue = System.clearProperty("user.home"); + return 0; + } - if (oldValue == null) - return -1; - break; - } + @Test + public static int test_clearProperty_1(final int execution) { + String oldValue = System.clearProperty("user.home"); - // TODO: more tests + if (oldValue == null) + return -1; - default: - return 0; - } - return execution; + return 0; } + @Test + public static int test_clearProperty_2(final int execution) { + String oldValue = System.clearProperty("file.encoding"); + + if (!oldValue.equals("Cp1251")) + return -1; + + return 0; + } + + @Test + public static int test_clearProperty_3(final int execution) { + String propKey = "abc.xyz"; + System.setProperty(propKey, "321"); + if (System.getProperty(propKey) == null) { + return -1; + } + System.clearProperty(propKey); + if (System.getProperty(propKey) != null) { + return -1; + } + return 0; + } /** * {@link java.lang.System#console()} @@ -184,9 +202,27 @@ public static int test_getLogger_1(final int execution) { /** * {@link java.lang.System#getProperties()} */ - @Test(disabled = true) + @Test public static int test_getProperties_0(final int execution) { - return -1; + Properties properties = System.getProperties(); + if (properties.getProperty("file.separator") == null) { + return -1; + } + + return 0; + } + + @Test + public static int test_getProperties_1(final int execution) { + Properties properties = System.getProperties(); + if (properties.getProperty("file.separator") == null) { + return -1; + } + Properties newProperties = new Properties(properties); + if (newProperties.getProperty("file.separator") == null) { + return -1; + } + return 0; }