Package at.jku.sii.sqlitereader.io

Source Code of at.jku.sii.sqlitereader.io.ChainedArrayDataInput

/*$Id$*/
package at.jku.sii.sqlitereader.io;

import java.io.DataInput;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;

import at.jku.sii.sqlitereader.annotator.AnnotatedAdvancedDataInputBase;
import at.jku.sii.sqlitereader.annotator.Annotator;
import at.jku.sii.sqlitereader.annotator.OffsetAnnotator;


public class ChainedArrayDataInput extends AnnotatedAdvancedDataInputBase implements Sizeable {

  private final ArrayDataInput[] ins;
  private final int size;
  private final long[] offsets;
  private int current;
  private int currentIn;
  private final Annotator annotator;
  private final DataInputStream din;

  public ChainedArrayDataInput(Collection<ArrayDataInput> inputs) {
    this(inputs.toArray(new ArrayDataInput[0]));
  }

  public ChainedArrayDataInput(ArrayDataInput... inputs) {
    this.ins = inputs;
    int sum = 0;
    this.offsets = new long[this.ins.length];
    for (int i = 0; i < this.ins.length; ++i) {
      this.offsets[i] = sum;
      sum += this.ins[i].size();
    }
    this.size = sum;

    this.annotator = new Annotator() {
      @Override
      public Annotator createSubAnnotator(long offset) {
        return new OffsetAnnotator(offset, this);
      }
      @Override
      public void annotate(long pos, int length, String text, Object... value) {
        ChainedArrayDataInput.this.annotateChained(pos, length, text, value);
      }
    };

    this.din = new DataInputStream(new InputStream() {
      @Override
      public int read() throws IOException {
        return ChainedArrayDataInput.this.readChained();
      }
    });
  }

  protected int readChained() {
    ArrayDataInput in = this.ins[this.currentIn];
    this.current++;
    long relative = this.current - this.offsets[this.currentIn];
    while (relative > in.size() && this.currentIn < this.ins.length) { // switch
      this.currentIn++;
      in = this.ins[this.currentIn];
      in.seek(0);
      relative = this.current - this.offsets[this.currentIn];
    }
    if (relative > in.size())
      return -1; // EOF
    return in.read();
  }

  protected void annotateChained(long pos, int length, String annotation, Object... value) {
    int input = this.findStart(pos);
    pos -= this.offsets[input]; // to relative
    while (length > 0) {
      ArrayDataInput block = this.ins[input];
      final int blockSize = block.size();
      block.annotate(pos, Math.min(length, blockSize), annotation, value);
      pos -= blockSize;
      length -= blockSize;
    }
  }

  private int findStart(long pos) {
    // fast version, its the current one
    if (pos >= this.offsets[this.currentIn] && (this.currentIn >= this.offsets.length - 1 || pos < this.offsets[this.currentIn + 1]))
      return this.currentIn;
    for (int i = 1; i < this.offsets.length; ++i)
      if (pos < this.offsets[i]) // too big -> within the last one
        return i - 1;
    return this.offsets.length - 1;
  }

  @Override
  public final int size() {
    return this.size;
  }


  @Override
  public long currentPosition() {
    return this.current;
  }

  @Override
  protected final DataInput get() {
    return this.din;
  }

  public final void seek(long pos) {
    this.current += pos;
    this.currentIn = this.findStart(pos);
    this.ins[this.currentIn].seek(this.currentRelative());
  }

  private long currentRelative() {
    return this.current - this.offsets[this.currentIn];
  }

  @Override
  protected Annotator getAnnotator() {
    return this.annotator;
  }
}
TOP

Related Classes of at.jku.sii.sqlitereader.io.ChainedArrayDataInput

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.