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

com.github.marschall.lineparser.DecodingLineReader Maven / Gradle / Ivy

There is a newer version: 0.5.0
Show newest version
package com.github.marschall.lineparser;

import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CoderResult;

/**
 * Decodes lines into a {@link CharBuffer}.
 */
final class DecodingLineReader implements LineReader {

  private final CharsetDecoder decoder;
  private CharBuffer out;

  DecodingLineReader(Charset charset, int bufferSize) {
    this.decoder = charset.newDecoder();
    this.out = CharBuffer.allocate(bufferSize);
  }

  DecodingLineReader(Charset charset) {
    this(charset, 2048);
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public CharSequence readLine(ByteBuffer buffer, int start, int length) {
    // reset the buffer limit
    buffer.position(start).limit(start + length);
    this.decode(buffer);
    // undo buffer limit, position doesn't matter because we only do absolute gets
    buffer.limit(buffer.capacity());
    // CharBufferCharSequence could be used, more memory usage indirection initially
    // but less after a few #subSequence calls
    return this.out;
  }

  /**
   * Gets the current buffer. Only for testing.
   *
   * @return the current buffer
   */
  CharBuffer getOut() {
    return out;
  }

  private void decode(ByteBuffer in) {
    int originalPosition = in.position();
    this.out.clear();
    CoderResult result = decoder.decode(in, this.out, true);
    if (result.isOverflow()) {
      int newCapacity = this.out.capacity() * 2;
      // double until it fits
      // this is not ideal be there isn't a good general way to estimate the required buffer size
      // using the line length in bytes would wasteful for UTF-16 or UTF-32
      // we could get creative with #averageCharsPerByte and #maxCharsPerByte
      // but would have to track if we got it wrong
      this.out = CharBuffer.allocate(newCapacity);
      in.position(originalPosition);
      decode(in);
    } else {
      out.flip();
    }
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy