Skip to content

Commit 7296197

Browse files
Merge branch 'fix-serial-lingering-bytes' into combined
2 parents 08cb6a7 + 1f3819c commit 7296197

File tree

1 file changed

+29
-10
lines changed

1 file changed

+29
-10
lines changed

arduino-core/src/processing/app/Serial.java

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -176,22 +176,41 @@ public synchronized void serialEvent(SerialPortEvent serialEvent) {
176176
try {
177177
byte[] buf = port.readBytes(serialEvent.getEventValue());
178178
int next = 0;
179-
while(next < buf.length) {
180-
while(next < buf.length && outToMessage.hasRemaining()) {
181-
int spaceInIn = inFromSerial.remaining();
182-
int copyNow = buf.length - next < spaceInIn ? buf.length - next : spaceInIn;
179+
// This uses a CharsetDecoder to convert from bytes to UTF-8 in
180+
// a streaming fashion (i.e. where characters might be split
181+
// over multiple reads). This needs the data to be in a
182+
// ByteBuffer (inFromSerial, which we also use to store leftover
183+
// incomplete characters for the nexst run) and produces a
184+
// CharBuffer (outToMessage), which we then convert to char[] to
185+
// pass onwards.
186+
// Note that these buffers switch from input to output mode
187+
// using flip/compact/clear
188+
while(next < buf.length || inFromSerial.position() > 0) {
189+
do {
190+
// This might be 0 when all data was already read from buf
191+
// (but then there will be data in inFromSerial left to
192+
// decode).
193+
int copyNow = Math.min(buf.length - next, inFromSerial.remaining());
183194
inFromSerial.put(buf, next, copyNow);
184195
next += copyNow;
196+
185197
inFromSerial.flip();
186198
bytesToStrings.decode(inFromSerial, outToMessage, false);
187199
inFromSerial.compact();
188-
}
200+
201+
// When there are multi-byte characters, outToMessage might
202+
// still have room, so add more bytes if we have any.
203+
} while (next < buf.length && outToMessage.hasRemaining());
204+
205+
// If no output was produced, the input only contained
206+
// incomplete characters, so we're done processing
207+
if (outToMessage.position() == 0)
208+
break;
209+
189210
outToMessage.flip();
190-
if(outToMessage.hasRemaining()) {
191-
char[] chars = new char[outToMessage.remaining()];
192-
outToMessage.get(chars);
193-
message(chars, chars.length);
194-
}
211+
char[] chars = new char[outToMessage.remaining()];
212+
outToMessage.get(chars);
213+
message(chars, chars.length);
195214
outToMessage.clear();
196215
}
197216
} catch (SerialPortException e) {

0 commit comments

Comments
 (0)