net.sf.robocode.host.io.RobotOutputStream Maven / Gradle / Ivy
/*
* Copyright (c) 2001-2023 Mathew A. Nelson and Robocode contributors
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://robocode.sourceforge.io/license/epl-v10.html
*/
package net.sf.robocode.host.io;
import java.io.PrintWriter;
import java.io.StringWriter;
import net.sf.robocode.io.RobocodeProperties;
/**
* @author Mathew A. Nelson (original)
* @author Flemming N. Larsen (contributor)
*/
public class RobotOutputStream extends java.io.PrintStream {
private static final int MAX_CHARS = 50000;
private int count = 0;
private boolean messaged = false;
private final StringBuilder text;
private final Object syncRoot = new Object();
public RobotOutputStream() {
super(new BufferedPipedOutputStream(128, true));
this.text = new StringBuilder(8192);
}
public String readAndReset() {
synchronized (syncRoot) {
// Out's counter must be reset before processing event.
// Otherwise, it will not be reset when printing in the onScannedEvent()
// before a scan() call, which will potentially cause a new onScannedEvent()
// and therefore not be able to reset the counter.
count = 0;
if (text.length() > 0) {
final String result = text.toString();
text.setLength(0);
return result;
}
return "";
}
}
private boolean isOkToPrint() {
synchronized (syncRoot) {
if (RobocodeProperties.isDebuggingOn()) { // It is always allowed to print when debugging is enabled.
return true;
}
if (count > MAX_CHARS) {
if (!messaged) {
text.append(
"\nSYSTEM: This robot is printing too much between actions. Output stopped until next action.\n");
messaged = true;
}
return false;
}
messaged = false;
return true;
}
}
@Override
public void print(char[] s) {
synchronized (syncRoot) {
if (isOkToPrint()) {
int origLen = text.length();
text.append(s);
count += text.length() - origLen;
}
}
}
@Override
public void print(char c) {
synchronized (syncRoot) {
if (isOkToPrint()) {
text.append(c);
count++;
}
}
}
@Override
public void print(double d) {
synchronized (syncRoot) {
if (isOkToPrint()) {
int origLen = text.length();
text.append(d);
count += text.length() - origLen;
}
}
}
@Override
public void print(float f) {
synchronized (syncRoot) {
if (isOkToPrint()) {
int origLen = text.length();
text.append(f);
count += text.length() - origLen;
}
}
}
@Override
public void print(int i) {
synchronized (syncRoot) {
if (isOkToPrint()) {
int origLen = text.length();
text.append(i);
count += text.length() - origLen;
}
}
}
@Override
public void print(long l) {
synchronized (syncRoot) {
if (isOkToPrint()) {
int origLen = text.length();
text.append(l);
count += text.length() - origLen;
}
}
}
@Override
public void print(Object obj) {
synchronized (syncRoot) {
if (isOkToPrint()) {
int origLen = text.length();
if (obj != null) {
String s = obj.toString();
text.append(s);
} else {
text.append((Object) null);
}
count += text.length() - origLen;
}
}
}
@Override
public void print(String s) {
synchronized (syncRoot) {
if (isOkToPrint()) {
int origLen = text.length();
text.append(s);
count += text.length() - origLen;
}
}
}
@Override
public void print(boolean b) {
synchronized (syncRoot) {
if (isOkToPrint()) {
int origLen = text.length();
text.append(b);
count += text.length() - origLen;
}
}
}
@Override
public void println() {
print('\n');
}
@Override
public void println(char[] x) {
print(x);
print('\n');
}
@Override
public void println(char x) {
print(x);
print('\n');
}
@Override
public void println(double x) {
print(x);
print('\n');
}
@Override
public void println(float x) {
print(x);
print('\n');
}
@Override
public void println(int x) {
print(x);
print('\n');
}
@Override
public void println(long x) {
print(x);
print('\n');
}
@Override
public void println(Object x) {
print(x);
print('\n');
}
@Override
public void println(String x) {
print(x);
print('\n');
}
@Override
public void println(boolean x) {
print(x);
print('\n');
}
@Override
public void write(byte[] buf) {
write(buf, 0, buf.length);
}
@Override
public void write(byte[] buf, int off, int len) {
synchronized (syncRoot) {
if (isOkToPrint()) {
if (buf != null) {
int origLen = text.length();
for (int i = 0; i < len; i++) {
text.append((char) buf[off + i]);
}
count += text.length() - origLen;
}
}
}
}
@Override
public void write(int b) {
synchronized (syncRoot) {
if (isOkToPrint()) {
int origLen = text.length();
text.append((char) b);
count += text.length() - origLen;
}
}
}
public void printStackTrace(Throwable t) {
if (t != null) {
synchronized (syncRoot) {
if (isOkToPrint()) {
StringWriter sw = new StringWriter();
final PrintWriter writer = new PrintWriter(sw);
t.printStackTrace(writer);
writer.flush();
int origLen = text.length();
text.append(sw);
count += text.length() - origLen;
}
}
}
}
}