2222
2323package processing .app ;
2424
25- import jssc .SerialPort ;
26- import jssc .SerialPortEvent ;
27- import jssc .SerialPortEventListener ;
28- import jssc .SerialPortException ;
25+ import static processing .app .I18n .format ;
26+ import static processing .app .I18n .tr ;
2927
3028import java .io .IOException ;
31- import java .nio .ByteBuffer ;
32- import java .nio .CharBuffer ;
29+ import java .io .InputStreamReader ;
30+ import java .io .PipedInputStream ;
31+ import java .io .PipedOutputStream ;
3332import java .nio .charset .Charset ;
34- import java .nio .charset .CharsetDecoder ;
35- import java .nio .charset .CodingErrorAction ;
3633import java .nio .charset .StandardCharsets ;
3734import java .util .Arrays ;
3835import java .util .List ;
3936
40- import static processing .app .I18n .format ;
41- import static processing .app .I18n .tr ;
37+ import jssc .SerialPort ;
38+ import jssc .SerialPortEvent ;
39+ import jssc .SerialPortEventListener ;
40+ import jssc .SerialPortException ;
4241
4342public class Serial implements SerialPortEventListener {
4443
@@ -53,11 +52,8 @@ public class Serial implements SerialPortEventListener {
5352
5453 private SerialPort port ;
5554
56- private CharsetDecoder bytesToStrings ;
57- private static final int IN_BUFFER_CAPACITY = 128 ;
58- private static final int OUT_BUFFER_CAPACITY = 128 ;
59- private ByteBuffer inFromSerial = ByteBuffer .allocate (IN_BUFFER_CAPACITY );
60- private CharBuffer outToMessage = CharBuffer .allocate (OUT_BUFFER_CAPACITY );
55+ private PipedOutputStream decoderInRaw ;
56+ private InputStreamReader decoderOutputUTF8 ;
6157
6258 public Serial () throws SerialException {
6359 this (PreferencesData .get ("serial.port" ),
@@ -189,42 +185,18 @@ public synchronized void serialEvent(SerialPortEvent serialEvent) {
189185
190186 public void processSerialEvent (byte [] buf ) {
191187 int next = 0 ;
192- // This uses a CharsetDecoder to convert from bytes to UTF-8 in
193- // a streaming fashion (i.e. where characters might be split
194- // over multiple reads). This needs the data to be in a
195- // ByteBuffer (inFromSerial, which we also use to store leftover
196- // incomplete characters for the nexst run) and produces a
197- // CharBuffer (outToMessage), which we then convert to char[] to
198- // pass onwards.
199- // Note that these buffers switch from input to output mode
200- // using flip/compact/clear
201- while (next < buf .length || inFromSerial .position () > 0 ) {
202- do {
203- // This might be 0 when all data was already read from buf
204- // (but then there will be data in inFromSerial left to
205- // decode).
206- int copyNow = Math .min (buf .length - next , inFromSerial .remaining ());
207- inFromSerial .put (buf , next , copyNow );
208- next += copyNow ;
209-
210- inFromSerial .flip ();
211- bytesToStrings .decode (inFromSerial , outToMessage , false );
212- inFromSerial .compact ();
213-
214- // When there are multi-byte characters, outToMessage might
215- // still have room, so add more bytes if we have any.
216- } while (next < buf .length && outToMessage .hasRemaining ());
217-
218- // If no output was produced, the input only contained
219- // incomplete characters, so we're done processing
220- if (outToMessage .position () == 0 )
221- break ;
222-
223- outToMessage .flip ();
224- char [] chars = new char [outToMessage .remaining ()];
225- outToMessage .get (chars );
226- message (chars , chars .length );
227- outToMessage .clear ();
188+ int max = buf .length ;
189+ char chars [] = new char [512 ];
190+ try {
191+ while (next < max ) {
192+ int w = Integer .min (max - next , 128 );
193+ decoderInRaw .write (buf , next , w );
194+ next += w ;
195+ int n = decoderOutputUTF8 .read (chars );
196+ message (chars , n );
197+ }
198+ } catch (IOException e ) {
199+ e .printStackTrace ();
228200 }
229201 }
230202
@@ -295,10 +267,13 @@ public void setRTS(boolean state) {
295267 * before they are handed as Strings to {@Link #message(char[], int)}.
296268 */
297269 public synchronized void resetDecoding (Charset charset ) {
298- bytesToStrings = charset .newDecoder ()
299- .onMalformedInput (CodingErrorAction .REPLACE )
300- .onUnmappableCharacter (CodingErrorAction .REPLACE )
301- .replaceWith ("\u2e2e " );
270+ try {
271+ decoderInRaw = new PipedOutputStream ();
272+ decoderOutputUTF8 = new InputStreamReader (new PipedInputStream (decoderInRaw ), charset );
273+ } catch (IOException e ) {
274+ // Should never happen...
275+ e .printStackTrace ();
276+ }
302277 }
303278
304279 static public List <String > list () {
0 commit comments