001    /*
002     *  This file is part of the Jikes RVM project (http://jikesrvm.org).
003     *
004     *  This file is licensed to You under the Eclipse Public License (EPL);
005     *  You may not use this file except in compliance with the License. You
006     *  may obtain a copy of the License at
007     *
008     *      http://www.opensource.org/licenses/eclipse-1.0.php
009     *
010     *  See the COPYRIGHT.txt file distributed with this work for information
011     *  regarding copyright ownership.
012     */
013    package org.jikesrvm.util;
014    
015    import java.io.InputStream;
016    import java.io.IOException;
017    import org.vmmagic.unboxed.Address;
018    import org.vmmagic.unboxed.Offset;
019    
020    /**
021     * Access raw memory region as an input stream.
022     */
023    public final class AddressInputStream extends InputStream {
024      /** Address of memory region to be read */
025      private final Address location;
026      /** Length of the memory region */
027      private final Offset length;
028      /** Offset to be read */
029      private Offset offset;
030      /** Mark offset */
031      private Offset markOffset;
032    
033      /** Constructor */
034      public AddressInputStream(Address location, Offset length) {
035        this.location = location;
036        this.length = length;
037        offset = Offset.zero();
038        markOffset = Offset.zero();
039      }
040    
041      /** @return number of bytes that can be read */
042      @Override
043      public int available() {
044        return length.minus(offset).toInt();
045      }
046      /** Mark location */
047      @Override
048      public void mark(int readLimit) {
049        markOffset = offset;
050      }
051      /** Is mark/reset supported */
052      @Override
053      public boolean markSupported() {
054        return true;
055      }
056      /** Read a byte */
057      @Override
058      public int read() throws IOException {
059        if (offset.sGE(length)) {
060          throw new IOException("Read beyond end of memory region");
061        }
062        byte result = location.loadByte(offset);
063        offset = offset.plus(1);
064        return result & 0xFF;
065      }
066      /** Reset to mark */
067      @Override
068      public void reset() {
069        offset = markOffset;
070      }
071      /** Skip bytes */
072      @Override
073      public long skip(long n) {
074        offset = offset.plus((int)n);
075        return ((int)n);
076      }
077    }