001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.io; 019 020import java.io.InputStream; 021import java.nio.ByteBuffer; 022 023import org.apache.hadoop.hbase.util.ByteBufferUtils; 024import org.apache.yetus.audience.InterfaceAudience; 025 026/** 027 * Not thread safe! 028 * <p> 029 * Please note that the reads will cause position movement on wrapped ByteBuffer. 030 */ 031@InterfaceAudience.Private 032public class ByteBufferInputStream extends InputStream { 033 034 private ByteBuffer buf; 035 036 public ByteBufferInputStream(ByteBuffer buf) { 037 this.buf = buf; 038 } 039 040 /** 041 * Reads the next byte of data from this input stream. The value byte is returned as an 042 * <code>int</code> in the range <code>0</code> to <code>255</code>. If no byte is available 043 * because the end of the stream has been reached, the value <code>-1</code> is returned. 044 * @return the next byte of data, or <code>-1</code> if the end of the stream has been reached. 045 */ 046 @Override 047 public int read() { 048 if (this.buf.hasRemaining()) { 049 return (this.buf.get() & 0xff); 050 } 051 return -1; 052 } 053 054 /** 055 * Reads up to next <code>len</code> bytes of data from buffer into passed array(starting from 056 * given offset). 057 * @param b the array into which the data is read. 058 * @param off the start offset in the destination array <code>b</code> 059 * @param len the maximum number of bytes to read. 060 * @return the total number of bytes actually read into the buffer, or <code>-1</code> if not even 061 * 1 byte can be read because the end of the stream has been reached. 062 */ 063 @Override 064 public int read(byte[] b, int off, int len) { 065 int avail = available(); 066 if (avail <= 0) { 067 return -1; 068 } 069 070 if (len > avail) { 071 len = avail; 072 } 073 if (len <= 0) { 074 return 0; 075 } 076 077 ByteBufferUtils.copyFromBufferToArray(b, this.buf, this.buf.position(), off, len); 078 this.buf.position(this.buf.position() + len); // we should advance the buffer position 079 return len; 080 } 081 082 /** 083 * Skips <code>n</code> bytes of input from this input stream. Fewer bytes might be skipped if the 084 * end of the input stream is reached. The actual number <code>k</code> of bytes to be skipped is 085 * equal to the smaller of <code>n</code> and remaining bytes in the stream. 086 * @param n the number of bytes to be skipped. 087 * @return the actual number of bytes skipped. 088 */ 089 @Override 090 public long skip(long n) { 091 long k = Math.min(n, available()); 092 if (k < 0) { 093 k = 0; 094 } 095 this.buf.position((int) (this.buf.position() + k)); 096 return k; 097 } 098 099 /** 100 * @return the number of remaining bytes that can be read (or skipped 101 * over) from this input stream. 102 */ 103 @Override 104 public int available() { 105 return this.buf.remaining(); 106 } 107}