/*
 *  This file is part of the Jikes RVM project (http://jikesrvm.org).
 *
 *  This file is licensed to You under the Common Public License (CPL);
 *  You may not use this file except in compliance with the License. You
 *  may obtain a copy of the License at
 *
 *      http://www.opensource.org/licenses/cpl1.0.php
 *
 *  See the COPYRIGHT.txt file distributed with this work for information
 *  regarding copyright ownership.
 */
package org.jikesrvm.util;

import java.io.InputStream;
import java.io.IOException;
import org.vmmagic.unboxed.Address;
import org.vmmagic.unboxed.Offset;

/**
 * Access raw memory region as an input stream
 */
public final class AddressInputStream extends InputStream {
  /** Address of memory region to be read */
  private final Address location;
  /** Length of the memory region */
  private final Offset length;
  /** Offset to be read */
  private Offset offset;
  /** Mark offset */
  private Offset markOffset;

  /** Constructor */
  public AddressInputStream(Address location, Offset length) {
    this.location = location;
    this.length = length;
    offset = Offset.zero();
    markOffset = Offset.zero();
  }

  /** @return number of bytes that can be read */
  public int available() {
    return length.minus(offset).toInt();
  }
  /** Mark location */
  public void mark(int readLimit) {
    markOffset = offset;
  }
  /** Is mark/reset supported */
  public boolean markSupported() {
    return true;
  }
  /** Read a byte */
  public int read() throws IOException {
    if (offset.sGE(length)) {
      throw new IOException("Read beyond end of memory region");
    }
    byte result = location.loadByte(offset);
    offset = offset.plus(1);
    return result;
  }
  /** Reset to mark */
  public void reset() {
    offset = markOffset;
  }
  /** Skip bytes */
  public long skip(long n) {
    offset = offset.plus((int)n);
    return (long)((int)n);
  }
}
