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      public int available() {
043        return length.minus(offset).toInt();
044      }
045      /** Mark location */
046      public void mark(int readLimit) {
047        markOffset = offset;
048      }
049      /** Is mark/reset supported */
050      public boolean markSupported() {
051        return true;
052      }
053      /** Read a byte */
054      public int read() throws IOException {
055        if (offset.sGE(length)) {
056          throw new IOException("Read beyond end of memory region");
057        }
058        byte result = location.loadByte(offset);
059        offset = offset.plus(1);
060        return result;
061      }
062      /** Reset to mark */
063      public void reset() {
064        offset = markOffset;
065      }
066      /** Skip bytes */
067      public long skip(long n) {
068        offset = offset.plus((int)n);
069        return (long)((int)n);
070      }
071    }