Skip to content

Commit

Permalink
applied several suggestions by @DavyLandman; incuding avoiding the co…
Browse files Browse the repository at this point in the history
…pying of byte arrays that will be printed immediately anyway. The code now only buffers unfinished lines.
  • Loading branch information
jurgenvinju committed May 24, 2024
1 parent fb16802 commit 6a30669
Showing 1 changed file with 45 additions and 51 deletions.
96 changes: 45 additions & 51 deletions src/org/rascalmpl/repl/TerminalProgressBarMonitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

Expand Down Expand Up @@ -117,87 +118,80 @@ public void write(String str, int off, int len) throws IOException {
}
}

private class UnfinishedLine {
private static class UnfinishedLine {
final long threadId;
int curCapacity = 512;
byte[] buffer = new byte[curCapacity];
int curEnd = 0;
int lastNewLine = 0;
private int curCapacity = 512;
private byte[] buffer = new byte[curCapacity];
private int curEnd = 0;

Check warning on line 125 in src/org/rascalmpl/repl/TerminalProgressBarMonitor.java

View check run for this annotation

Codecov / codecov/patch

src/org/rascalmpl/repl/TerminalProgressBarMonitor.java#L123-L125

Added lines #L123 - L125 were not covered by tests

public UnfinishedLine() {
this.threadId = Thread.currentThread().getId();
}

Check warning on line 129 in src/org/rascalmpl/repl/TerminalProgressBarMonitor.java

View check run for this annotation

Codecov / codecov/patch

src/org/rascalmpl/repl/TerminalProgressBarMonitor.java#L127-L129

Added lines #L127 - L129 were not covered by tests

/**
* Adding input combines previously unfinished sentences with possible
* new sentences. A number of cases come together here that otherwise
* should be diligently separated.
*
* - An unfinished line can already exist or not
* - The new input can contain newlines or not
* - The new input can end with a newline character or not
*
* By concatenating the previous unfinished line with the new input
* all we have to do now is figure out where the last newline character is.
* new (unfinished) sentences.
*
* The resulting buffer nevers contain any newline character.
*/
private void add(byte[] newInput, int offset, int len) {
private void store(byte[] newInput, int offset, int len) {
// first ensure capacity of the array
if (curEnd + len >= curCapacity) {
var oldCapacity = curCapacity;
curCapacity *= 2; // this should not happen to often. we're talking a few lines of text.
byte[] tmp = new byte[curCapacity];
System.arraycopy(buffer, 0, tmp, 0, oldCapacity);
buffer = tmp;
curCapacity *= 2;
buffer = Arrays.copyOf(buffer, curCapacity);

Check warning on line 141 in src/org/rascalmpl/repl/TerminalProgressBarMonitor.java

View check run for this annotation

Codecov / codecov/patch

src/org/rascalmpl/repl/TerminalProgressBarMonitor.java#L140-L141

Added lines #L140 - L141 were not covered by tests
}

System.arraycopy(newInput, offset, buffer, curEnd, len);
curEnd += len;
lastNewLine = startOfLastLine();
}

Check warning on line 146 in src/org/rascalmpl/repl/TerminalProgressBarMonitor.java

View check run for this annotation

Codecov / codecov/patch

src/org/rascalmpl/repl/TerminalProgressBarMonitor.java#L144-L146

Added lines #L144 - L146 were not covered by tests

public void write(byte[] n, OutputStream out) throws IOException {
add(n, 0, n.length);
flushToLastLine(out);
write(n, 0, n.length, out);
}

Check warning on line 150 in src/org/rascalmpl/repl/TerminalProgressBarMonitor.java

View check run for this annotation

Codecov / codecov/patch

src/org/rascalmpl/repl/TerminalProgressBarMonitor.java#L149-L150

Added lines #L149 - L150 were not covered by tests

/**
* Main workhorse looks for newline characters in the new input.
* - if there are newlines, than whatever is in the buffer can be flushed.
* - all the characters up to the last new new line are flushed immediately.
* - all the new characters after the last newline are buffered.
*/
public void write(byte[] n, int offset, int len, OutputStream out) throws IOException {
add(n, offset, len);
flushToLastLine(out);
}

private void flushToLastLine(OutputStream out) throws IOException {
if (lastNewLine != -1) {
// write everything out (except the last unfinished line), but including the last newline
out.write(buffer, 0, lastNewLine + 1);

if (lastNewLine + 1 == curEnd) {
// nothing left
curEnd = 0;
lastNewLine = -1;
}
else {
// copy the last line that does not end with a newline
curEnd -= lastNewLine;
System.arraycopy(buffer, lastNewLine + 1, buffer, 0, curEnd);
lastNewLine = -1; // no newline anymore
}
}
int lastNL = startOfLastLine(n, offset, len);

Check warning on line 159 in src/org/rascalmpl/repl/TerminalProgressBarMonitor.java

View check run for this annotation

Codecov / codecov/patch

src/org/rascalmpl/repl/TerminalProgressBarMonitor.java#L159

Added line #L159 was not covered by tests

// otherwise we wait until the next input comes to be able to complete a line.
if (lastNL == -1) {
store(n, offset, len);

Check warning on line 162 in src/org/rascalmpl/repl/TerminalProgressBarMonitor.java

View check run for this annotation

Codecov / codecov/patch

src/org/rascalmpl/repl/TerminalProgressBarMonitor.java#L162

Added line #L162 was not covered by tests
}
else {
flush(out);
out.write(n, offset, lastNL + 1);
store(n, offset, lastNL - offset);

Check warning on line 167 in src/org/rascalmpl/repl/TerminalProgressBarMonitor.java

View check run for this annotation

Codecov / codecov/patch

src/org/rascalmpl/repl/TerminalProgressBarMonitor.java#L165-L167

Added lines #L165 - L167 were not covered by tests
}
}

Check warning on line 169 in src/org/rascalmpl/repl/TerminalProgressBarMonitor.java

View check run for this annotation

Codecov / codecov/patch

src/org/rascalmpl/repl/TerminalProgressBarMonitor.java#L169

Added line #L169 was not covered by tests

public void writeLeftOvers(OutputStream out) throws IOException {
/**
* This empties the current buffer onto the stream,
* and resets the cursor.
*/
private void flush(OutputStream out) throws IOException {
if (curEnd != 0) {
out.write(buffer, 0, curEnd);
out.write('\n');
curEnd = 0;

Check warning on line 178 in src/org/rascalmpl/repl/TerminalProgressBarMonitor.java

View check run for this annotation

Codecov / codecov/patch

src/org/rascalmpl/repl/TerminalProgressBarMonitor.java#L177-L178

Added lines #L177 - L178 were not covered by tests
lastNewLine = -1;
}
}

Check warning on line 180 in src/org/rascalmpl/repl/TerminalProgressBarMonitor.java

View check run for this annotation

Codecov / codecov/patch

src/org/rascalmpl/repl/TerminalProgressBarMonitor.java#L180

Added line #L180 was not covered by tests

/**
* Prints whatever is the last line in the buffer,
* and adds a newline.
*/
public void flushLastLine(OutputStream out) throws IOException {
if (curEnd != 0) {
flush(out);
out.write('\n');

Check warning on line 189 in src/org/rascalmpl/repl/TerminalProgressBarMonitor.java

View check run for this annotation

Codecov / codecov/patch

src/org/rascalmpl/repl/TerminalProgressBarMonitor.java#L188-L189

Added lines #L188 - L189 were not covered by tests
}
}

Check warning on line 191 in src/org/rascalmpl/repl/TerminalProgressBarMonitor.java

View check run for this annotation

Codecov / codecov/patch

src/org/rascalmpl/repl/TerminalProgressBarMonitor.java#L191

Added line #L191 was not covered by tests

private int startOfLastLine() {
for (int i = curEnd - 1; i >= 0; i--) {
private int startOfLastLine(byte[] buffer, int offset, int len) {
for (int i = offset + len - 1; i >= 0; i--) {
if (buffer[i] == '\n') {
return i;

Check warning on line 196 in src/org/rascalmpl/repl/TerminalProgressBarMonitor.java

View check run for this annotation

Codecov / codecov/patch

src/org/rascalmpl/repl/TerminalProgressBarMonitor.java#L196

Added line #L196 was not covered by tests
}
Expand Down Expand Up @@ -662,7 +656,7 @@ public synchronized void endAllJobs() {
bars.clear();
for (UnfinishedLine l : unfinishedLines) {
try {
l.writeLeftOvers(out);
l.flushLastLine(out);

Check warning on line 659 in src/org/rascalmpl/repl/TerminalProgressBarMonitor.java

View check run for this annotation

Codecov / codecov/patch

src/org/rascalmpl/repl/TerminalProgressBarMonitor.java#L659

Added line #L659 was not covered by tests
}
catch (IOException e) {

Check warning on line 661 in src/org/rascalmpl/repl/TerminalProgressBarMonitor.java

View check run for this annotation

Codecov / codecov/patch

src/org/rascalmpl/repl/TerminalProgressBarMonitor.java#L661

Added line #L661 was not covered by tests
// might happen if the terminal crashes before we stop running
Expand Down

0 comments on commit 6a30669

Please sign in to comment.