All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.github.karlatemp.mxlib.terminal.LinedOutputStream Maven / Gradle / Ivy

There is a newer version: 3.0-dev-20
Show newest version
/*
 * Copyright (c) 2018-2021 Karlatemp. All rights reserved.
 * @author Karlatemp  
 *
 * MXLib/MXLib.mxlib-terminal.main/LinedOutputStream.java
 *
 * Use of this source code is governed by the MIT license that can be found via the following link.
 *
 * https://github.com/Karlatemp/MxLib/blob/master/LICENSE
 */

package io.github.karlatemp.mxlib.terminal;

import org.jline.reader.LineReader;

import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;

public class LinedOutputStream extends OutputStream {

    public interface StringAllocator {
        String string(byte[] buffer, int offset, int size, Charset charset);
    }

    public static final StringAllocator DEFAULT_STRING_ALLOCATOR = String::new;

    private final byte[] buffer;
    private final LineReader reader;
    private final Charset charset;
    private final StringAllocator allocator;
    private int counter;
    private final int bufferLen1;

    public LinedOutputStream(LineReader reader, int size, Charset charset) {
        this(reader, size, charset, DEFAULT_STRING_ALLOCATOR);
    }

    public LinedOutputStream(LineReader reader, int size, Charset charset, StringAllocator allocator) {
        if (size < 1) throw new IllegalArgumentException();
        this.reader = reader;
        this.buffer = new byte[size];
        bufferLen1 = size - 1;
        this.charset = charset;
        this.allocator = allocator;
    }

    @Override
    public synchronized void write(int b) throws IOException {
        if ((b & 0xFF) == 10) {
            flush();
        } else if (counter == bufferLen1) {
            flush();
            buffer[counter++] = (byte) b;
        }
    }

    @Override
    public synchronized void write(byte[] b, int off, int len) throws IOException {
        int ed = off + len;
        if (off < 0 || len < 0 || ed > b.length) throw new IllegalArgumentException();
        while (off < ed) {
            int to = -1;
            for (int i = off; i < ed; i++) {
                if ((b[i] & 0xFF) == 10) {
                    to = i;
                    break;
                }
            }
            boolean newLine = false;
            boolean skipLn = false;
            if (to == -1) {
                to = ed;
            } else {
                newLine = true;
                skipLn = true;
            }
            int writeSize = to - off;
            int overloads = counter + writeSize - buffer.length;
            if (overloads > 0) {
                newLine = true;
                skipLn = false;
                to = off + buffer.length - counter;
            }
            if (to > off) {
                int cpc = to - off;
                System.arraycopy(b, off, buffer, counter, cpc);
                counter += cpc;
            }
            if (newLine) flush();
            off = to;
            if (skipLn) {
                off++;
            }
        }
    }

    @Override
    public synchronized void flush() throws IOException {
        if (counter == 0) return;
        reader.printAbove(allocator.string(buffer, 0, counter, charset));
        counter = 0;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy