/* (c) 2014 LinkedIn Corp. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use
* this file except in compliance with the License. You may obtain a copy of the
* License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied.
*/
package com.linkedin.cubert.memory;
import java.io.IOException;
import java.io.InputStream;
/**
* PagedByteArrayInputStream
* Input Stream that reads from a PagedByteArray
* Warning: This Object is not thread safe
*
* Created by spyne on 7/29/14.
*/
public class PagedByteArrayInputStream extends InputStream
{
/**
* the data store from which the read occurs
*/
private final PagedByteArray pba;
/**
* Maintains the current read position
*/
private int offset = 0;
/**
* Create an Input Stream to read from a PagedByteArray
* @param pba the data source
*/
public PagedByteArrayInputStream(PagedByteArray pba)
{
this.pba = pba;
}
/**
* Read the next byte
*
* @return the next byte
* @throws IOException
*/
@Override
public int read() throws IOException
{
try
{
/**
* The & 0xff is necessary.
* It converts a negative number in byte (-129 to 127)
* into a positive number (0 - 255). Returning a positive byte is expected in
* classes like DataInputStream which OR (|) the stream data to retrieve the
* original data.
**/
return pba.read(offset++) & 0xff;
} catch (IndexOutOfBoundsException e)
{
throw new IOException(e);
}
}
/**
* Read the next sequence of bytes from the current position
*
* @param dest the destination byte array
* @param startOffset the start position of the dest array to which data is to be read
* @param len the number of bytes to be read
* @return the number of bytes read
*/
@Override
public int read(byte dest[], int startOffset, int len)
{
final int nBytes = pba.read(dest, startOffset, len, offset);
offset += nBytes;
return nBytes;
}
@Override
public synchronized void reset() throws IOException
{
offset = 0;
}
@Override
public long skip(long n) throws IOException
{
if (n < 0)
{
return 0;
}
final int size = pba.size();
if( offset + n >= size)
{
offset = size;
return size - offset;
}
else
{
offset += n;
return n;
}
}
@Override
public int available() throws IOException
{
return pba.size() - offset;
}
}