package com.fasterxml.aalto.in;
import java.io.*;
/**
* Simple {@link InputStream} implementation that is used to "unwind" some
* data previously read from an input stream; so that as long as some of
* that data remains, it's returned; but as long as it's read, we'll
* just use data from the underlying original stream.
* This is similar to {@link java.io.PushbackInputStream}, but here there's
* only one implicit pushback, when instance is constructed.
*/
public final class
MergedStream
extends
InputStream
{
final
ReaderConfig mConfig;
final
InputStream mIn;
byte[]
mData;
int
mPtr;
final int
mEnd;
public
MergedStream(
ReaderConfig cfg,
InputStream in, byte[]
buf, int
start, int
end)
{
mConfig =
cfg;
mIn =
in;
mData =
buf;
mPtr =
start;
mEnd =
end;
}
@
Override
public int
available() throws
IOException
{
if (
mData != null) {
return
mEnd -
mPtr;
}
return
mIn.
available();
}
@
Override
public void
close() throws
IOException
{
freeBuffers();
mIn.
close();
}
@
Override
public void
mark(int
readlimit)
{
if (
mData == null) {
mIn.
mark(
readlimit);
}
}
@
Override
public boolean
markSupported()
{
// Only supports marks past the initial rewindable section...
return (
mData == null) &&
mIn.
markSupported();
}
@
Override
public int
read() throws
IOException
{
if (
mData != null) {
int
c =
mData[
mPtr++] & 0xFF;
if (
mPtr >=
mEnd) {
freeBuffers();
}
return
c;
}
return
mIn.
read();
}
@
Override
public int
read(byte[]
b) throws
IOException
{
return
read(
b, 0,
b.length);
}
@
Override
public int
read(byte[]
b, int
off, int
len) throws
IOException
{
if (
mData != null) {
int
avail =
mEnd -
mPtr;
if (
len >
avail) {
len =
avail;
}
System.
arraycopy(
mData,
mPtr,
b,
off,
len);
mPtr +=
len;
if (
mPtr >=
mEnd) {
freeBuffers();
}
return
len;
}
return
mIn.
read(
b,
off,
len);
}
@
Override
public void
reset() throws
IOException
{
if (
mData == null) {
mIn.
reset();
}
}
@
Override
public long
skip(long
n) throws
IOException
{
long
count = 0L;
if (
mData != null) {
int
amount =
mEnd -
mPtr;
if (
amount >
n) { // all in pushed back segment?
mPtr += (int)
n;
return
n;
}
freeBuffers();
count +=
amount;
n -=
amount;
}
if (
n > 0) {
count +=
mIn.
skip(
n);
}
return
count;
}
/*
/////////////////////////////////////////
// Internal methods
/////////////////////////////////////////
*/
private void
freeBuffers()
{
if (
mData != null) {
byte[]
data =
mData;
mData = null;
if (
mConfig != null) {
mConfig.
freeFullBBuffer(
data);
}
}
}
}