mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-23 00:24:11 -08:00
classlib: add PrintStream.format
This commit is contained in:
parent
b792f48b55
commit
403da28830
|
@ -17,17 +17,18 @@
|
||||||
package org.teavm.classlib.java.io;
|
package org.teavm.classlib.java.io;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
public class TBufferedOutputStream extends TFilterOutputStream {
|
public class TBufferedOutputStream extends TFilterOutputStream {
|
||||||
protected byte[] buf;
|
protected byte[] buf;
|
||||||
protected int count;
|
protected int count;
|
||||||
|
|
||||||
public TBufferedOutputStream(TOutputStream out) {
|
public TBufferedOutputStream(OutputStream out) {
|
||||||
super(out);
|
super(out);
|
||||||
buf = new byte[8192];
|
buf = new byte[8192];
|
||||||
}
|
}
|
||||||
|
|
||||||
public TBufferedOutputStream(TOutputStream out, int size) {
|
public TBufferedOutputStream(OutputStream out, int size) {
|
||||||
super(out);
|
super(out);
|
||||||
if (size <= 0) {
|
if (size <= 0) {
|
||||||
throw new IllegalArgumentException("size must be > 0");
|
throw new IllegalArgumentException("size must be > 0");
|
||||||
|
|
|
@ -18,6 +18,7 @@ package org.teavm.classlib.java.io;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import org.teavm.classlib.java.lang.TMath;
|
import org.teavm.classlib.java.lang.TMath;
|
||||||
import org.teavm.classlib.java.lang.TString;
|
import org.teavm.classlib.java.lang.TString;
|
||||||
|
import org.teavm.classlib.java.nio.charset.TCharset;
|
||||||
import org.teavm.classlib.java.util.TArrays;
|
import org.teavm.classlib.java.util.TArrays;
|
||||||
|
|
||||||
public class TByteArrayOutputStream extends TOutputStream {
|
public class TByteArrayOutputStream extends TOutputStream {
|
||||||
|
@ -66,6 +67,10 @@ public class TByteArrayOutputStream extends TOutputStream {
|
||||||
return new TString(buf, 0, count, charsetName);
|
return new TString(buf, 0, count, charsetName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TString toString(TCharset charset) {
|
||||||
|
return new TString(buf, 0, count, charset);
|
||||||
|
}
|
||||||
|
|
||||||
public void writeTo(TOutputStream out) throws IOException {
|
public void writeTo(TOutputStream out) throws IOException {
|
||||||
out.write(buf, 0, count);
|
out.write(buf, 0, count);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,8 +14,14 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.teavm.classlib.java.io;
|
package org.teavm.classlib.java.io;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import org.teavm.classlib.java.lang.*;
|
import java.io.OutputStream;
|
||||||
|
import org.teavm.classlib.java.lang.TDouble;
|
||||||
|
import org.teavm.classlib.java.lang.TFloat;
|
||||||
|
import org.teavm.classlib.java.lang.TInteger;
|
||||||
|
import org.teavm.classlib.java.lang.TNullPointerException;
|
||||||
|
import org.teavm.classlib.java.lang.TString;
|
||||||
|
|
||||||
public class TDataOutputStream extends TFilterOutputStream implements TDataOutput {
|
public class TDataOutputStream extends TFilterOutputStream implements TDataOutput {
|
||||||
/**
|
/**
|
||||||
|
@ -24,7 +30,7 @@ public class TDataOutputStream extends TFilterOutputStream implements TDataOutpu
|
||||||
protected int written;
|
protected int written;
|
||||||
byte[] buff;
|
byte[] buff;
|
||||||
|
|
||||||
public TDataOutputStream(TOutputStream out) {
|
public TDataOutputStream(OutputStream out) {
|
||||||
super(out);
|
super(out);
|
||||||
buff = new byte[8];
|
buff = new byte[8];
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,11 +16,12 @@
|
||||||
package org.teavm.classlib.java.io;
|
package org.teavm.classlib.java.io;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
public class TFilterOutputStream extends TOutputStream {
|
public class TFilterOutputStream extends TOutputStream {
|
||||||
protected TOutputStream out;
|
protected OutputStream out;
|
||||||
|
|
||||||
public TFilterOutputStream(TOutputStream out) {
|
public TFilterOutputStream(OutputStream out) {
|
||||||
this.out = out;
|
this.out = out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
package org.teavm.classlib.java.io;
|
package org.teavm.classlib.java.io;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.Locale;
|
||||||
import org.teavm.classlib.java.lang.TMath;
|
import org.teavm.classlib.java.lang.TMath;
|
||||||
import org.teavm.classlib.java.lang.TObject;
|
import org.teavm.classlib.java.lang.TObject;
|
||||||
import org.teavm.classlib.java.lang.TStringBuilder;
|
import org.teavm.classlib.java.lang.TStringBuilder;
|
||||||
|
@ -27,6 +29,7 @@ import org.teavm.classlib.java.nio.charset.TCodingErrorAction;
|
||||||
import org.teavm.classlib.java.nio.charset.TIllegalCharsetNameException;
|
import org.teavm.classlib.java.nio.charset.TIllegalCharsetNameException;
|
||||||
import org.teavm.classlib.java.nio.charset.TUnsupportedCharsetException;
|
import org.teavm.classlib.java.nio.charset.TUnsupportedCharsetException;
|
||||||
import org.teavm.classlib.java.nio.charset.impl.TUTF8Charset;
|
import org.teavm.classlib.java.nio.charset.impl.TUTF8Charset;
|
||||||
|
import org.teavm.classlib.java.util.TFormatter;
|
||||||
|
|
||||||
public class TPrintStream extends TFilterOutputStream {
|
public class TPrintStream extends TFilterOutputStream {
|
||||||
private boolean autoFlush;
|
private boolean autoFlush;
|
||||||
|
@ -35,7 +38,7 @@ public class TPrintStream extends TFilterOutputStream {
|
||||||
private char[] buffer = new char[32];
|
private char[] buffer = new char[32];
|
||||||
private TCharset charset;
|
private TCharset charset;
|
||||||
|
|
||||||
public TPrintStream(TOutputStream out, boolean autoFlush, String encoding) throws TUnsupportedEncodingException {
|
public TPrintStream(OutputStream out, boolean autoFlush, String encoding) throws TUnsupportedEncodingException {
|
||||||
super(out);
|
super(out);
|
||||||
this.autoFlush = autoFlush;
|
this.autoFlush = autoFlush;
|
||||||
try {
|
try {
|
||||||
|
@ -45,13 +48,23 @@ public class TPrintStream extends TFilterOutputStream {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public TPrintStream(TOutputStream out, boolean autoFlush) {
|
public TPrintStream(OutputStream out, boolean autoFlush) {
|
||||||
super(out);
|
super(out);
|
||||||
this.autoFlush = autoFlush;
|
this.autoFlush = autoFlush;
|
||||||
this.charset = TUTF8Charset.INSTANCE;
|
this.charset = TUTF8Charset.INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TPrintStream(TOutputStream out) {
|
public TPrintStream(OutputStream out, boolean autoFlush, TCharset charset) {
|
||||||
|
super(out);
|
||||||
|
this.autoFlush = autoFlush;
|
||||||
|
this.charset = charset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TPrintStream(OutputStream out, TCharset charset) {
|
||||||
|
this(out, false, charset);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TPrintStream(OutputStream out) {
|
||||||
this(out, false);
|
this(out, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,6 +170,31 @@ public class TPrintStream extends TFilterOutputStream {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void print(CharSequence s, int begin, int end) {
|
||||||
|
TCharBuffer src = TCharBuffer.wrap(s, begin, end - begin);
|
||||||
|
byte[] destBytes = new byte[TMath.max(16, TMath.min(end - begin, 1024))];
|
||||||
|
TByteBuffer dest = TByteBuffer.wrap(destBytes);
|
||||||
|
TCharsetEncoder encoder = charset.newEncoder()
|
||||||
|
.onMalformedInput(TCodingErrorAction.REPLACE)
|
||||||
|
.onUnmappableCharacter(TCodingErrorAction.REPLACE);
|
||||||
|
while (true) {
|
||||||
|
boolean overflow = encoder.encode(src, dest, true).isOverflow();
|
||||||
|
write(destBytes, 0, dest.position());
|
||||||
|
dest.clear();
|
||||||
|
if (!overflow) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (true) {
|
||||||
|
boolean overflow = encoder.flush(dest).isOverflow();
|
||||||
|
write(destBytes, 0, dest.position());
|
||||||
|
dest.clear();
|
||||||
|
if (!overflow) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void print(char c) {
|
public void print(char c) {
|
||||||
buffer[0] = c;
|
buffer[0] = c;
|
||||||
print(buffer, 0, 1);
|
print(buffer, 0, 1);
|
||||||
|
@ -231,10 +269,54 @@ public class TPrintStream extends TFilterOutputStream {
|
||||||
print('\n');
|
print('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TPrintStream format(String format, Object... args) {
|
||||||
|
return format(Locale.getDefault(), format, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TPrintStream format(Locale locale, String format, Object... args) {
|
||||||
|
if (args == null) {
|
||||||
|
args = new Object[1];
|
||||||
|
}
|
||||||
|
try (var formatter = new TFormatter(getAppendable(), locale)) {
|
||||||
|
formatter.format(format, args);
|
||||||
|
if (formatter.ioException() != null) {
|
||||||
|
errorState = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
private void printSB() {
|
private void printSB() {
|
||||||
char[] buffer = sb.length() > this.buffer.length ? new char[sb.length()] : this.buffer;
|
char[] buffer = sb.length() > this.buffer.length ? new char[sb.length()] : this.buffer;
|
||||||
sb.getChars(0, sb.length(), buffer, 0);
|
sb.getChars(0, sb.length(), buffer, 0);
|
||||||
print(buffer, 0, sb.length());
|
print(buffer, 0, sb.length());
|
||||||
sb.setLength(0);
|
sb.setLength(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Appendable appendable;
|
||||||
|
|
||||||
|
private Appendable getAppendable() {
|
||||||
|
if (appendable == null) {
|
||||||
|
appendable = new Appendable() {
|
||||||
|
@Override
|
||||||
|
public Appendable append(CharSequence csq) {
|
||||||
|
print(csq, 0, csq.length());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Appendable append(CharSequence csq, int start, int end) {
|
||||||
|
print(csq, start, end);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Appendable append(char c) {
|
||||||
|
print(c);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return appendable;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,6 @@ import org.teavm.classlib.impl.console.StderrOutputStream;
|
||||||
import org.teavm.classlib.impl.console.StdoutOutputStream;
|
import org.teavm.classlib.impl.console.StdoutOutputStream;
|
||||||
import org.teavm.classlib.java.io.TConsole;
|
import org.teavm.classlib.java.io.TConsole;
|
||||||
import org.teavm.classlib.java.io.TInputStream;
|
import org.teavm.classlib.java.io.TInputStream;
|
||||||
import org.teavm.classlib.java.io.TOutputStream;
|
|
||||||
import org.teavm.classlib.java.io.TPrintStream;
|
import org.teavm.classlib.java.io.TPrintStream;
|
||||||
import org.teavm.classlib.java.lang.reflect.TArray;
|
import org.teavm.classlib.java.lang.reflect.TArray;
|
||||||
import org.teavm.dependency.PluggableDependency;
|
import org.teavm.dependency.PluggableDependency;
|
||||||
|
@ -60,7 +59,7 @@ public final class TSystem extends TObject {
|
||||||
if (PlatformDetector.isJavaScript()) {
|
if (PlatformDetector.isJavaScript()) {
|
||||||
outCache = (TPrintStream) (Object) new JSStdoutPrintStream();
|
outCache = (TPrintStream) (Object) new JSStdoutPrintStream();
|
||||||
} else {
|
} else {
|
||||||
outCache = new TPrintStream((TOutputStream) (Object) StdoutOutputStream.INSTANCE, false);
|
outCache = new TPrintStream(StdoutOutputStream.INSTANCE, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return outCache;
|
return outCache;
|
||||||
|
@ -71,7 +70,7 @@ public final class TSystem extends TObject {
|
||||||
if (PlatformDetector.isJavaScript()) {
|
if (PlatformDetector.isJavaScript()) {
|
||||||
errCache = (TPrintStream) (Object) new JSStderrPrintStream();
|
errCache = (TPrintStream) (Object) new JSStderrPrintStream();
|
||||||
} else {
|
} else {
|
||||||
errCache = new TPrintStream((TOutputStream) (Object) StderrOutputStream.INSTANCE, false);
|
errCache = new TPrintStream(StderrOutputStream.INSTANCE, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return errCache;
|
return errCache;
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.classlib.java.io;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.PrintStream;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.teavm.junit.TeaVMTestRunner;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
@RunWith(TeaVMTestRunner.class)
|
||||||
|
public class PrintStreamTest {
|
||||||
|
@Test
|
||||||
|
public void format() {
|
||||||
|
var bytes = new ByteArrayOutputStream();
|
||||||
|
var stream = new PrintStream(bytes, false, StandardCharsets.UTF_8);
|
||||||
|
stream.format("n=%d; ", 23);
|
||||||
|
stream.format("s=%s", null);
|
||||||
|
stream.flush();
|
||||||
|
assertEquals("n=23; s=null", bytes.toString(StandardCharsets.UTF_8));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user