diff options
author | Andreas Loth | 2017-02-28 06:04:14 +0000 |
---|---|---|
committer | Sarika Sinha | 2017-03-01 04:21:34 +0000 |
commit | b880d44d7e2ff505bfed40ca37b130b24e60993d (patch) | |
tree | 65a0b01f8dae9a06228135ac78a77cae771b60b9 /org.eclipse.ui.console/src/org/eclipse/ui/internal/console/StreamDecoder.java | |
parent | 3014f2fdbe89cfb3ab8923d73fc8702ed0fcb4cb (diff) | |
download | eclipse.platform.debug-b880d44d7e2ff505bfed40ca37b130b24e60993d.tar.gz eclipse.platform.debug-b880d44d7e2ff505bfed40ca37b130b24e60993d.tar.xz eclipse.platform.debug-b880d44d7e2ff505bfed40ca37b130b24e60993d.zip |
Bug 507664 - IOConsoleOutputStream does not handle multi-byte charactersI20170301-2000
at buffer boundaries correctly
Change-Id: Ib1651069ab6a1a09d26e0b33bfae2dc3aef2fd77
Signed-off-by: Andreas Loth <andy_2639@justmail.de>
Diffstat (limited to 'org.eclipse.ui.console/src/org/eclipse/ui/internal/console/StreamDecoder.java')
-rw-r--r-- | org.eclipse.ui.console/src/org/eclipse/ui/internal/console/StreamDecoder.java | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/org.eclipse.ui.console/src/org/eclipse/ui/internal/console/StreamDecoder.java b/org.eclipse.ui.console/src/org/eclipse/ui/internal/console/StreamDecoder.java new file mode 100644 index 000000000..dde14fdcd --- /dev/null +++ b/org.eclipse.ui.console/src/org/eclipse/ui/internal/console/StreamDecoder.java @@ -0,0 +1,96 @@ +/******************************************************************************* + * Copyright (c) 2017 Andreas Loth and others. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andreas Loth - initial API and implementation + *******************************************************************************/ + +package org.eclipse.ui.internal.console; + +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.Charset; +import java.nio.charset.CharsetDecoder; +import java.nio.charset.CoderResult; +import java.nio.charset.CodingErrorAction; + + +/** + * @since 3.7 + */ +public class StreamDecoder { + + static private final int BUFFER_SIZE = 4096; + + private final CharsetDecoder decoder; + private final ByteBuffer inputBuffer; + private final CharBuffer outputBuffer; + + public StreamDecoder(Charset charset) { + this.decoder = charset.newDecoder(); + this.decoder.onMalformedInput(CodingErrorAction.REPLACE); + this.decoder.onUnmappableCharacter(CodingErrorAction.REPLACE); + this.inputBuffer = ByteBuffer.allocate(StreamDecoder.BUFFER_SIZE); + this.inputBuffer.flip(); + this.outputBuffer = CharBuffer.allocate(StreamDecoder.BUFFER_SIZE); + } + + private void consume(StringBuilder consumer) { + this.outputBuffer.flip(); + consumer.append(this.outputBuffer); + this.outputBuffer.clear(); + } + + private void internalDecode(StringBuilder consumer, byte[] buffer, int offset, int length, boolean last) { + assert (offset >= 0); + assert (length >= 0); + int position = offset; + int end = offset + length; + assert (end <= buffer.length); + boolean finished = false; + do { + CoderResult result = this.decoder.decode(this.inputBuffer, this.outputBuffer, last); + if (result.isOverflow()) { + this.consume(consumer); + } else if (result.isUnderflow()) { + this.inputBuffer.compact(); + int remaining = this.inputBuffer.remaining(); + assert (remaining > 0); + int read = Math.min(remaining, end - position); + if (read > 0) { + this.inputBuffer.put(buffer, position, read); + position += read; + } else { + finished = true; + } + this.inputBuffer.flip(); + } else { + assert false; + } + } while (!finished); + } + + public void decode(StringBuilder consumer, byte[] buffer, int offset, int length) { + this.internalDecode(consumer, buffer, offset, length, false); + this.consume(consumer); + } + + public void finish(StringBuilder consumer) { + this.internalDecode(consumer, new byte[0], 0, 0, true); + CoderResult result; + do { + result = this.decoder.flush(this.outputBuffer); + if (result.isOverflow()) { + this.consume(consumer); + } else { + assert result.isUnderflow(); + } + } while (!result.isUnderflow()); + this.consume(consumer); + } + +} |