public ByteFragment next() throws IOException {
        // if sent out all that have read
        if (posNext >= posRead) {
            // need to read more from the stream
            int readBytes = readFromStream();
            if (readBytes <= 0) {
                // if everything was sent out and there is nothing left in the stream
                return null;
            }
        }
        // looking for the separator
        int positionSep;
        while ((positionSep = indexOf(buf, sep, posNext, posRead)) < posNext) {
            // read from stream till we find the separator
            int readBytes = readFromStream();
            if (readBytes <= 0) {
                // if there is nothing to read, return everything left as a result
                positionSep = posRead;
                break;
            }
        }
        // if the separator is found, return the fragment
        int fragmentStart = posNext;
        posNext = positionSep + 1;
        return new ByteFragment(buf, fragmentStart, positionSep - fragmentStart);
    }
We have a stream of bytes and a separator as an input. We split the stream by
the separator and pass the byte arrays to output.
clickhouse-data/src/main/java/com/clickhouse/data/format/tsv/StreamSplitter.java