From 890d73e8aa7703d9fb7cf9641f21c94612d992b0 Mon Sep 17 00:00:00 2001
From: nathan
Date: Fri, 17 Oct 2014 00:10:49 +0200
Subject: [PATCH] Cleaned up input console to use my own growing-byte buffers.
Also made one that is fast (but unsynchronized)
---
.../src/dorkbox/util/bytes/ByteBuffer2.java | 124 ++++---
.../dorkbox/util/bytes/ByteBuffer2Fast.java | 338 ++++++++++++++++++
.../src/dorkbox/util/input/InputConsole.java | 258 +++++++------
.../util/input/windows/WindowsTerminal.java | 1 -
4 files changed, 549 insertions(+), 172 deletions(-)
create mode 100644 Dorkbox-Util/src/dorkbox/util/bytes/ByteBuffer2Fast.java
diff --git a/Dorkbox-Util/src/dorkbox/util/bytes/ByteBuffer2.java b/Dorkbox-Util/src/dorkbox/util/bytes/ByteBuffer2.java
index 5f31b8c..1455774 100644
--- a/Dorkbox-Util/src/dorkbox/util/bytes/ByteBuffer2.java
+++ b/Dorkbox-Util/src/dorkbox/util/bytes/ByteBuffer2.java
@@ -34,23 +34,23 @@ public class ByteBuffer2 {
public ByteBuffer2(byte[] bytes) {
this.bytes = bytes;
clear();
- position = bytes.length;
+ this.position = bytes.length;
}
public byte getByte() {
- if (position > limit) {
+ if (this.position > this.limit) {
throw new BufferUnderflowException();
}
- return bytes[position++];
+ return this.bytes[this.position++];
}
public byte getByte(int i) {
- if (i > limit) {
+ if (i > this.limit) {
throw new BufferUnderflowException();
}
- return bytes[i];
+ return this.bytes[i];
}
public void getBytes(byte[] buffer) {
@@ -62,12 +62,12 @@ public class ByteBuffer2 {
}
public void getBytes(byte[] buffer, int offset, int length) {
- if (position + length - offset > limit) {
+ if (this.position + length - offset > this.limit) {
throw new BufferUnderflowException();
}
- System.arraycopy(bytes, position, buffer, 0, length-offset);
- position += length-offset;
+ System.arraycopy(this.bytes, this.position, buffer, 0, length-offset);
+ this.position += length-offset;
}
/**
@@ -76,18 +76,18 @@ public class ByteBuffer2 {
* NOT PROTECTED
*/
private final void _put(byte b) {
- bytes[position++] = b;
+ this.bytes[this.position++] = b;
}
/** NOT PROTECTED! */
private final void checkBuffer(int threshold) {
- if (bytes.length < threshold) {
+ if (this.bytes.length < threshold) {
byte[] t = new byte[threshold];
// grow at back of array
- System.arraycopy(bytes, 0, t, 0, bytes.length);
- limit = t.length;
+ System.arraycopy(this.bytes, 0, t, 0, this.bytes.length);
+ this.limit = t.length;
- bytes = t;
+ this.bytes = t;
}
}
@@ -101,16 +101,16 @@ public class ByteBuffer2 {
}
public final synchronized ByteBuffer2 putBytes(byte[] src, int offset, int length) {
- checkBuffer(position + length - offset);
+ checkBuffer(this.position + length - offset);
- System.arraycopy(src, offset, bytes, position, length);
- position += length;
+ System.arraycopy(src, offset, this.bytes, this.position, length);
+ this.position += length;
return this;
}
public final synchronized ByteBuffer2 putByte(byte b) {
- checkBuffer(position + 1);
+ checkBuffer(this.position + 1);
_put(b);
return this;
@@ -122,7 +122,7 @@ public class ByteBuffer2 {
}
public final synchronized void putChar(char c) {
- checkBuffer(position + 2);
+ checkBuffer(this.position + 2);
putBytes(BigEndian.Char_.toBytes(c));
}
@@ -131,8 +131,19 @@ public class ByteBuffer2 {
return BigEndian.Char_.fromBytes(getByte(), getByte());
}
+ public final char getChar(int i) {
+ return BigEndian.Char_.fromBytes(getByte(i++), getByte(i));
+ }
+
+ public void getChars(int srcStart, int srcLength, char[] dest, int destStart) {
+ for (int i=srcStart;i bytes.length || position < 0) {
+ if (position > this.bytes.length || position < 0) {
throw new IllegalArgumentException();
}
this.position = position;
- if (mark > position) {
- mark = -1;
+ if (this.mark > position) {
+ this.mark = -1;
}
return this;
@@ -212,7 +232,7 @@ public class ByteBuffer2 {
* limit.
*/
public final synchronized int remaining() {
- return limit - position;
+ return this.limit - this.position;
}
/**
@@ -220,7 +240,7 @@ public class ByteBuffer2 {
* the limit.
*/
public final synchronized boolean hasRemaining() {
- return position < limit;
+ return this.position < this.limit;
}
/**
@@ -228,11 +248,11 @@ public class ByteBuffer2 {
*/
public final synchronized void limit(int limit) {
this.limit = limit;
- if (position > limit) {
- position = limit;
+ if (this.position > limit) {
+ this.position = limit;
}
- if (mark > limit) {
- mark = -1;
+ if (this.mark > limit) {
+ this.mark = -1;
}
}
@@ -240,14 +260,14 @@ public class ByteBuffer2 {
* Returns this buffer's limit.
*/
public int limit() {
- return limit;
+ return this.limit;
}
/**
* Returns this buffer's capacity.
*/
public int capacity() {
- return bytes.length;
+ return this.bytes.length;
}
/**
@@ -260,8 +280,8 @@ public class ByteBuffer2 {
* can be followed immediately by an invocation of another relative put method.
*/
public final synchronized void compact() {
- mark = -1;
- System.arraycopy(bytes, position, bytes, 0, remaining());
+ this.mark = -1;
+ System.arraycopy(this.bytes, this.position, this.bytes, 0, remaining());
position(remaining());
limit(capacity());
@@ -275,9 +295,9 @@ public class ByteBuffer2 {
* discarded.
*/
public final synchronized void flip() {
- limit = position;
- position = 0;
- mark = -1;
+ this.limit = this.position;
+ this.position = 0;
+ this.mark = -1;
}
/**
@@ -285,9 +305,9 @@ public class ByteBuffer2 {
* the capacity, and the mark is discarded.
*/
public final synchronized void clear() {
- position = 0;
- limit = capacity();
- mark = -1;
+ this.position = 0;
+ this.limit = capacity();
+ this.mark = -1;
}
/**
@@ -295,15 +315,15 @@ public class ByteBuffer2 {
* discarded.
*/
public final synchronized void rewind() {
- position = 0;
- mark = -1;
+ this.position = 0;
+ this.mark = -1;
}
/**
* Sets this buffer's mark at its position.
*/
public final synchronized void mark() {
- mark = position;
+ this.mark = this.position;
}
/**
@@ -313,6 +333,6 @@ public class ByteBuffer2 {
* value.
*/
public void reset() {
- position = mark;
+ this.position = this.mark;
}
}
\ No newline at end of file
diff --git a/Dorkbox-Util/src/dorkbox/util/bytes/ByteBuffer2Fast.java b/Dorkbox-Util/src/dorkbox/util/bytes/ByteBuffer2Fast.java
new file mode 100644
index 0000000..0e26bd5
--- /dev/null
+++ b/Dorkbox-Util/src/dorkbox/util/bytes/ByteBuffer2Fast.java
@@ -0,0 +1,338 @@
+package dorkbox.util.bytes;
+
+import java.nio.BufferUnderflowException;
+
+/**
+ * Cleanroom implementation of a self-growing bytebuffer. NOT SYNCHRONIZED!
+ */
+public class ByteBuffer2Fast {
+
+ private byte[] bytes;
+
+ private int position = 0;
+ private int mark = -1;
+ private int limit = 0;
+
+ public static ByteBuffer2Fast wrap(byte[] buffer) {
+ return new ByteBuffer2Fast(buffer);
+ }
+
+ public static ByteBuffer2Fast allocate(int capacity) {
+ ByteBuffer2Fast byteBuffer2 = new ByteBuffer2Fast(new byte[capacity]);
+ byteBuffer2.clear();
+ return byteBuffer2;
+ }
+
+ public ByteBuffer2Fast() {
+ this(0);
+ }
+
+ public ByteBuffer2Fast(int size) {
+ this(new byte[size]);
+ }
+
+ public ByteBuffer2Fast(byte[] bytes) {
+ this.bytes = bytes;
+ clear();
+ this.position = bytes.length;
+ }
+
+ public byte getByte() {
+ if (this.position > this.limit) {
+ throw new BufferUnderflowException();
+ }
+
+ return this.bytes[this.position++];
+ }
+
+ public byte getByte(int i) {
+ if (i > this.limit) {
+ throw new BufferUnderflowException();
+ }
+
+ return this.bytes[i];
+ }
+
+ public void getBytes(byte[] buffer) {
+ getBytes(buffer, 0, buffer.length);
+ }
+
+ public void getBytes(byte[] buffer, int length) {
+ getBytes(buffer, 0, length);
+ }
+
+ public void getBytes(byte[] buffer, int offset, int length) {
+ if (this.position + length - offset > this.limit) {
+ throw new BufferUnderflowException();
+ }
+
+ System.arraycopy(this.bytes, this.position, buffer, 0, length-offset);
+ this.position += length-offset;
+ }
+
+ /**
+ * MUST call checkBuffer before calling this!
+ *
+ * NOT PROTECTED
+ */
+ private final void _put(byte b) {
+ this.bytes[this.position++] = b;
+ }
+
+ /** NOT PROTECTED! */
+ private final void checkBuffer(int threshold) {
+ if (this.bytes.length < threshold) {
+ byte[] t = new byte[threshold];
+ // grow at back of array
+ System.arraycopy(this.bytes, 0, t, 0, this.bytes.length);
+ this.limit = t.length;
+
+ this.bytes = t;
+ }
+ }
+
+ public final void put(ByteBuffer2Fast buffer) {
+ putBytes(buffer.array(), buffer.position, buffer.limit);
+ buffer.position = buffer.limit;
+ }
+
+ public final ByteBuffer2Fast putBytes(byte[] src) {
+ return putBytes(src, 0, src.length);
+ }
+
+ public final ByteBuffer2Fast putBytes(byte[] src, int offset, int length) {
+ checkBuffer(this.position + length - offset);
+
+ System.arraycopy(src, offset, this.bytes, this.position, length);
+ this.position += length;
+
+ return this;
+ }
+
+ public final ByteBuffer2Fast putByte(byte b) {
+ checkBuffer(this.position + 1);
+
+ _put(b);
+ return this;
+ }
+
+ public final void putByte(int position, byte b) {
+ this.position = position;
+ putByte(b);
+ }
+
+ public final void putChar(char c) {
+ checkBuffer(this.position + 2);
+
+ putBytes(BigEndian.Char_.toBytes(c));
+ }
+
+ public final char getChar() {
+ return BigEndian.Char_.fromBytes(getByte(), getByte());
+ }
+
+ public final char getChar(int i) {
+ return BigEndian.Char_.fromBytes(getByte(i++), getByte(i));
+ }
+
+ public void getChars(int srcStart, int srcLength, char[] dest, int destStart) {
+ for (int i=srcStart;i this.bytes.length || position < 0) {
+ throw new IllegalArgumentException();
+ }
+
+ this.position = position;
+ if (this.mark > position) {
+ this.mark = -1;
+ }
+
+ return this;
+ }
+
+ /**
+ * Returns the number of elements between the current position and the
+ * limit.
+ */
+ public final int remaining() {
+ return this.limit - this.position;
+ }
+
+ /**
+ * Tells whether there are any elements between the current position and
+ * the limit.
+ */
+ public final boolean hasRemaining() {
+ return this.position < this.limit;
+ }
+
+ /**
+ * Sets this buffer's limit.
+ */
+ public final void limit(int limit) {
+ this.limit = limit;
+ if (this.position > limit) {
+ this.position = limit;
+ }
+ if (this.mark > limit) {
+ this.mark = -1;
+ }
+ }
+
+ /**
+ * Returns this buffer's limit.
+ */
+ public int limit() {
+ return this.limit;
+ }
+
+ /**
+ * Returns this buffer's capacity.
+ */
+ public int capacity() {
+ return this.bytes.length;
+ }
+
+ /**
+ * The bytes between the buffer's current position and its limit, if any, are copied to the beginning of the buffer.
+ * That is, the byte at index p = position() is copied to index zero, the byte at index p + 1 is copied to index one,
+ * and so forth until the byte at index limit() - 1 is copied to index n = limit() - 1 - p. The buffer's position is
+ * then set to n+1 and its limit is set to its capacity. The mark, if defined, is discarded.
+ *
+ * The buffer's position is set to the number of bytes copied, rather than to zero, so that an invocation of this method
+ * can be followed immediately by an invocation of another relative put method.
+ */
+ public final void compact() {
+ this.mark = -1;
+ System.arraycopy(this.bytes, this.position, this.bytes, 0, remaining());
+
+ position(remaining());
+ limit(capacity());
+ }
+
+ /**
+ * Readies the buffer for reading.
+ *
+ * Flips this buffer. The limit is set to the current position and then
+ * the position is set to zero. If the mark is defined then it is
+ * discarded.
+ */
+ public final void flip() {
+ this.limit = this.position;
+ this.position = 0;
+ this.mark = -1;
+ }
+
+ /**
+ * Clears this buffer. The position is set to zero, the limit is set to
+ * the capacity, and the mark is discarded.
+ */
+ public final void clear() {
+ this.position = 0;
+ this.limit = capacity();
+ this.mark = -1;
+ }
+
+ /**
+ * Rewinds this buffer. The position is set to zero and the mark is
+ * discarded.
+ */
+ public final void rewind() {
+ this.position = 0;
+ this.mark = -1;
+ }
+
+ /**
+ * Sets this buffer's mark at its position.
+ */
+ public final void mark() {
+ this.mark = this.position;
+ }
+
+ /**
+ * Resets this buffer's position to the previously-marked position.
+ *
+ * Invoking this method neither changes nor discards the mark's
+ * value.
+ */
+ public void reset() {
+ this.position = this.mark;
+ }
+}
\ No newline at end of file
diff --git a/Dorkbox-Util/src/dorkbox/util/input/InputConsole.java b/Dorkbox-Util/src/dorkbox/util/input/InputConsole.java
index e664cdc..c50784c 100644
--- a/Dorkbox-Util/src/dorkbox/util/input/InputConsole.java
+++ b/Dorkbox-Util/src/dorkbox/util/input/InputConsole.java
@@ -5,18 +5,21 @@ import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
+import java.io.PrintStream;
import java.io.Reader;
import java.net.URL;
import java.nio.charset.Charset;
import java.security.CodeSource;
import java.security.ProtectionDomain;
-import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.CopyOnWriteArrayList;
import org.fusesource.jansi.Ansi;
import org.fusesource.jansi.AnsiConsole;
import org.slf4j.Logger;
import dorkbox.util.OS;
+import dorkbox.util.Sys;
+import dorkbox.util.bytes.ByteBuffer2Fast;
import dorkbox.util.input.posix.UnixTerminal;
import dorkbox.util.input.unsupported.UnsupportedTerminal;
import dorkbox.util.input.windows.WindowsTerminal;
@@ -36,20 +39,31 @@ public class InputConsole {
{
AnsiConsole.systemInstall();
+ Thread consoleThread = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ consoleProxyReader.run();
+ }
+ });
+ consoleThread.setDaemon(true);
+ consoleThread.setName("Console Input Reader");
+
+ consoleThread.start();
+
+ // has to be NOT DAEMON thread, since it must run before the app closes.
+
// don't forget we have to shut down the ansi console as well
// alternatively, shut everything down when the JVM closes.
- Runtime.getRuntime().addShutdownHook(new Thread() {
+ Thread shutdownThread = new Thread() {
@Override
public void run() {
AnsiConsole.systemUninstall();
- InputConsole.destroy();
- }
- });
- }
- // called by our shutdown thread
- private static final void destroy() {
- consoleProxyReader.destroy0();
+ consoleProxyReader.shutdown0();
+ }
+ };
+ shutdownThread.setName("Console Input Shutdown");
+ Runtime.getRuntime().addShutdownHook(shutdownThread);
}
/** return null if no data */
@@ -94,9 +108,17 @@ public class InputConsole {
private final Object inputLockSingle = new Object();
private final Object inputLockLine = new Object();
- private AtomicBoolean isRunning = new AtomicBoolean(false);
- private AtomicBoolean isInShutdown = new AtomicBoolean(false);
- private volatile char[] readLine = null;
+ private ThreadLocal threadBufferForRead = new ThreadLocal();
+ private CopyOnWriteArrayList threadBuffersForRead = new CopyOnWriteArrayList();
+
+ ThreadLocal indexOfStringForReadChar = new ThreadLocal() {
+ @Override
+ protected Integer initialValue() {
+ return -1;
+ }
+ };
+
+
private volatile int readChar = -1;
private final boolean unsupported;
@@ -119,7 +141,7 @@ public class InputConsole {
logger.debug("Creating terminal; type={}", type);
- Terminal t;
+ Terminal t;
try {
if (type.equals(TerminalType.UNIX)) {
t = new UnixTerminal();
@@ -182,36 +204,8 @@ public class InputConsole {
logger.debug("Created Terminal: {}", this.terminal);
}
- /**
- * make sure the input console reader thread is started.
- */
- private void startInputConsole() {
- // protected by atomic!
- if (!this.isRunning.compareAndSet(false, true) || this.isInShutdown.get()) {
- return;
- }
-
- Thread consoleThread = new Thread(new Runnable() {
- @Override
- public void run() {
- consoleProxyReader.run();
- }
- });
- consoleThread.setDaemon(true);
- consoleThread.setName("Console Input Reader");
-
- consoleThread.start();
- }
-
- private void destroy0() {
- // Don't change this, because we don't want to enable reading, etc from this once it's destroyed.
- // so we pretend that it's still running
- // isRunning.set(false);
-
- if (this.isInShutdown.compareAndSet(true, true)) {
- return;
- }
-
+ // called when the JVM is shutting down.
+ private void shutdown0() {
synchronized (this.inputLockSingle) {
this.inputLockSingle.notifyAll();
}
@@ -224,7 +218,8 @@ public class InputConsole {
InputConsole inputConsole = InputConsole.this;
inputConsole.terminal.restore();
- inputConsole.reader.close();
+ // this will 'hang' our shutdown, and honestly, who cares? We're shutting down anyways.
+ // inputConsole.reader.close(); // hangs on shutdown
} catch (IOException ignored) {
ignored.printStackTrace();
}
@@ -241,7 +236,11 @@ public class InputConsole {
/** return null if no data */
private final char[] readLine0() {
- startInputConsole();
+ if (this.threadBufferForRead.get() == null) {
+ ByteBuffer2Fast buffer = ByteBuffer2Fast.allocate(0);
+ this.threadBufferForRead.set(buffer);
+ this.threadBuffersForRead.add(buffer);
+ }
synchronized (this.inputLockLine) {
try {
@@ -250,34 +249,53 @@ public class InputConsole {
return emptyLine;
}
}
- return this.readLine;
+
+ ByteBuffer2Fast stringBuffer = this.threadBufferForRead.get();
+ int len = stringBuffer.position();
+ if (len == 0) {
+ return emptyLine;
+ }
+
+ char[] chars = new char[len/2]; // because 2 chars is 1 bytes
+ stringBuffer.getChars(0, len, chars, 0);
+
+ // dump the chars in the buffer (safer for passwords, etc)
+ stringBuffer.clear();
+ stringBuffer.putBytes(new byte[0]);
+
+ this.threadBufferForRead.set(null);
+ this.threadBuffersForRead.remove(stringBuffer); // TODO: use object pool!
+
+ return chars;
}
/** return null if no data */
private final char[] readLinePassword0() {
- // don't bother in an IDE. it won't work.
- return readLine0();
- }
-
- ThreadLocal indexOfStringForReadChar = new ThreadLocal() {
- @Override
- protected Integer initialValue() {
- return -1;
+ if (this.threadBufferForRead.get() == null) {
+ ByteBuffer2Fast buffer = ByteBuffer2Fast.allocate(0);
+ this.threadBufferForRead.set(buffer);
+ this.threadBuffersForRead.add(buffer);
}
- };
+
+ // don't bother in an IDE. it won't work.
+ boolean echoEnabled = this.terminal.isEchoEnabled();
+ this.terminal.setEchoEnabled(false);
+ char[] readLine0 = readLine0();
+ this.terminal.setEchoEnabled(echoEnabled);
+
+ return readLine0;
+ }
/** return -1 if no data */
private final int read0() {
- startInputConsole();
-
// if we are reading data (because we are in IDE mode), we want to return ALL
// the chars of the line!
// so, readChar is REALLY the index at which we return letters (until the whole string is returned
if (this.unsupported) {
- int integer = this.indexOfStringForReadChar.get();
+ int readerCount = this.indexOfStringForReadChar.get();
- if (integer == -1) {
+ if (readerCount == -1) {
// we have to wait for more data.
synchronized (this.inputLockLine) {
try {
@@ -285,24 +303,23 @@ public class InputConsole {
} catch (InterruptedException e) {
return -1;
}
- integer = 0;
+ readerCount = 0;
this.indexOfStringForReadChar.set(0);
}
}
- // EACH thread will have it's own count!
- char[] readLine2 = this.readLine;
- if (readLine2 == null) {
- return -1;
- } else if (integer == readLine2.length) {
+ // EACH thread will have it's own count!
+ ByteBuffer2Fast stringBuffer = this.threadBufferForRead.get();
+
+ if (readerCount == stringBuffer.position()) {
this.indexOfStringForReadChar.set(-1);
return '\n';
} else {
- this.indexOfStringForReadChar.set(integer+1);
+ this.indexOfStringForReadChar.set(readerCount+1);
}
- char c = readLine2[integer];
+ char c = stringBuffer.getChar(readerCount);
return c;
}
else {
@@ -339,19 +356,30 @@ public class InputConsole {
// it just waits until \n until it triggers
if (this.unsupported) {
BufferedReader reader = (BufferedReader) this.reader;
+ String line = null;
+ char[] readLine = null;
try {
- while ((this.readLine = reader.readLine().toCharArray()) != null) {
+ while ((line = reader.readLine()) != null) {
+ readLine = line.toCharArray();
+
// notify everyone waiting for a line of text.
synchronized (this.inputLockSingle) {
- if (this.readLine.length > 0) {
- this.readChar = this.readLine[0];
+ if (readLine.length > 0) {
+ this.readChar = readLine[0];
} else {
this.readChar = -1;
}
this.inputLockSingle.notifyAll();
}
synchronized (this.inputLockLine) {
+ byte[] charToBytes = Sys.charToBytes(readLine);
+
+ for (ByteBuffer2Fast buffer : this.threadBuffersForRead) {
+ buffer.clear();
+ buffer.putBytes(charToBytes);
+ }
+
this.inputLockLine.notifyAll();
}
}
@@ -360,12 +388,13 @@ public class InputConsole {
}
}
else {
+ // from a 'regular' console
try {
final boolean ansiEnabled = Ansi.isEnabled();
Ansi ansi = Ansi.ansi();
+ PrintStream out = AnsiConsole.out;
int typedChar;
- StringBuilder buf = new StringBuilder();
// don't type ; in a bash shell, it quits everything
// \n is replaced by \r in unix terminal?
@@ -388,65 +417,57 @@ public class InputConsole {
// clear ourself + one extra.
if (ansiEnabled) {
- // size of the buffer BEFORE our backspace was typed
- int length = buf.length();
- int amtToOverwrite = 2; // backspace is always 2 chars (^?)
+ for (ByteBuffer2Fast buffer : this.threadBuffersForRead) {
+ // size of the buffer BEFORE our backspace was typed
+ int length = buffer.position();
+ int amtToOverwrite = 2 * 2; // backspace is always 2 chars (^?) * 2 because it's bytes
- if (length > 1) {
- char charAt = buf.charAt(length-1);
- amtToOverwrite += getPrintableCharacters(charAt);
+ if (length > 1) {
+ char charAt = buffer.getChar(length-2);
+ amtToOverwrite += getPrintableCharacters(charAt);
- // delete last item in our buffer
- buf.setLength(--length);
+ // delete last item in our buffer
+ length -= 2;
+ buffer.position(length);
- // now figure out where the cursor is really at.
- // this is more memory friendly than buf.toString.length
- for (int i=0;i 0) {
- this.readLine = new char[length];
- buf.getChars(0, length, this.readLine, 0);
- } else {
- this.readLine = emptyLine;
- }
-
this.inputLockLine.notifyAll();
}
-
- // dump the characters in the backing array (slightly safer for passwords when using this method)
- if (length > 0) {
- buf.delete(0, buf.length());
- }
} else if (asChar != '\r') {
// only append if we are not a new line.
- buf.append(asChar);
+ for (ByteBuffer2Fast buffer : this.threadBuffersForRead) {
+ buffer.putChar(asChar);
+ }
}
}
} catch (IOException ignored) {
@@ -455,11 +476,11 @@ public class InputConsole {
}
/**
- + * Get the default encoding. Will first look at the LC_CTYPE environment variable, then the input.encoding
- + * system property, then the default charset according to the JVM.
- + *
- + * @return The default encoding to use when none is specified.
- + */
+ * Get the default encoding. Will first look at the LC_CTYPE environment variable, then the input.encoding
+ * system property, then the default charset according to the JVM.
+ *
+ * @return The default encoding to use when none is specified.
+ */
public static String getEncoding() {
// LC_CTYPE is usually in the form en_US.UTF-8
String envEncoding = extractEncodingFromCtype(System.getenv("LC_CTYPE"));
@@ -481,9 +502,8 @@ public class InputConsole {
String encodingAndModifier = ctype.substring(ctype.indexOf('.') + 1);
if (encodingAndModifier.indexOf('@') > 0) {
return encodingAndModifier.substring(0, encodingAndModifier.indexOf('@'));
- } else {
- return encodingAndModifier;
}
+ return encodingAndModifier;
}
return null;
}
diff --git a/Dorkbox-Util/src/dorkbox/util/input/windows/WindowsTerminal.java b/Dorkbox-Util/src/dorkbox/util/input/windows/WindowsTerminal.java
index 25cc950..4fece85 100644
--- a/Dorkbox-Util/src/dorkbox/util/input/windows/WindowsTerminal.java
+++ b/Dorkbox-Util/src/dorkbox/util/input/windows/WindowsTerminal.java
@@ -54,7 +54,6 @@ public class WindowsTerminal extends Terminal
public void init() throws IOException {
this.originalMode = WindowsSupport.getConsoleMode();
WindowsSupport.setConsoleMode(this.originalMode & ~ConsoleMode.ENABLE_ECHO_INPUT.code);
- setEchoEnabled(false);
}
/**