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 */ 013package org.jikesrvm.util; 014 015import java.io.InputStream; 016import java.io.IOException; 017 018import org.vmmagic.unboxed.Address; 019import org.vmmagic.unboxed.Extent; 020 021/** 022 * Access raw memory region as an input stream. 023 */ 024public final class AddressInputStream extends InputStream { 025 /** Start address of memory region to be read */ 026 private final Address startAddress; 027 /** Length of the memory region */ 028 private final Extent length; 029 /** Offset to be read. Uses an Extent because the offset is always non-negative. */ 030 private Extent offset; 031 /** Mark offset. Uses an Extent because the offset is always non-negative. */ 032 private Extent markOffset; 033 034 /** 035 * 036 * @param startAddress start address of the memory region 037 * @param length length of the region in bytes 038 */ 039 public AddressInputStream(Address startAddress, Extent length) { 040 this.startAddress = startAddress; 041 this.length = length; 042 043 offset = Extent.zero(); 044 markOffset = Extent.zero(); 045 } 046 047 /** @return number of bytes that can be read */ 048 @Override 049 public int available() { 050 int available = length.minus(offset).toInt(); 051 available = (available > 0) ? available : 0; 052 return available; 053 } 054 055 /** 056 * Closing an AddressInputStream has no effect. 057 */ 058 @Override 059 public void close() throws IOException { 060 } 061 062 /** Marks location. Read limit has no effect. */ 063 @Override 064 public void mark(int readLimit) { 065 markOffset = offset; 066 } 067 068 /** Is mark/reset supported */ 069 @Override 070 public boolean markSupported() { 071 return true; 072 } 073 074 /** Reads a byte */ 075 @Override 076 public int read() { 077 if (offset.GE(length)) { 078 return -1; 079 } 080 081 Address readLocation = startAddress.plus(offset); 082 byte result = readLocation.loadByte(); 083 offset = offset.plus(1); 084 return result & 0xFF; 085 } 086 087 /** Resets to mark */ 088 @Override 089 public void reset() { 090 offset = markOffset; 091 } 092 093 /** Skips bytes (at most @code{Integer.MAX_VALUE} bytes) */ 094 @Override 095 public long skip(long n) { 096 if (n < 0) { 097 return 0; 098 } 099 100 long maxInt = Integer.MAX_VALUE; 101 int skipAmount = (n > maxInt) ? Integer.MAX_VALUE : (int) n; 102 int available = available(); 103 skipAmount = (skipAmount > available) ? available : skipAmount; 104 105 offset = offset.plus(skipAmount); 106 return skipAmount; 107 } 108}