/*
* Copyright 2014 Baidu, Inc.
*
* 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. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.baidubce.internal;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.IOException;
import java.util.List;
/**
* Restartable MultiByteArray InputStream extends Restartable InputStream.
*/
public class RestartableMultiByteArrayInputStream extends RestartableInputStream {
private List<byte[]> byteArrayList;
private long pos = 0;
private int blockSize;
private long length;
public RestartableMultiByteArrayInputStream(List<byte[]> byteArrayList, long length) {
checkNotNull(byteArrayList, "byteArrayList should not be null.");
checkArgument(!byteArrayList.isEmpty(), "byteArrayList should not be empty.");
long total = 0;
for (byte[] byteArray : byteArrayList) {
checkNotNull(byteArray, "byteArrayList should not contain null element.");
checkArgument(byteArray.length > 0, "byteArrayList should not contain empty byte array.");
total += byteArray.length;
}
checkArgument(total >= length,
"The specified length(%s) is greater than the total length(%s) of elements in byteArrayList.",
length, total);
this.blockSize = byteArrayList.get(0).length;
for (int i = 1; i < byteArrayList.size() - 1; ++i) {
int len = byteArrayList.get(i).length;
checkArgument(len == this.blockSize,
"All elements in byteArrayList except the last one should have the same length. " +
"The first element's length is %s but the %sth element's length is %s.",
this.blockSize, i, len);
}
this.byteArrayList = byteArrayList;
this.length = length;
}
@Override
public void restart() {
this.pos = 0;
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
checkNotNull(b, "b should not be null.");
if (off < 0 || len < 0 || len > b.length - off) {
throw new IndexOutOfBoundsException();
}
if (this.pos == this.length) {
return -1;
}
int count = 0;
while (len > 0 && this.pos < this.length) {
int index = (int) (this.pos / this.blockSize);
int offset = (int) (this.pos % this.blockSize);
byte[] byteArray = this.byteArrayList.get(index);
int copyLength = byteArray.length - offset;
if (copyLength > len) {
copyLength = len;
}
System.arraycopy(byteArray, offset, b, off, copyLength);
this.pos += copyLength;
off += copyLength;
len -= copyLength;
count += copyLength;
}
return count;
}
@Override
public int read() {
if (this.pos == this.length) {
return -1;
}
int index = (int) (this.pos / this.blockSize);
int offset = (int) (this.pos % this.blockSize);
++this.pos;
return this.byteArrayList.get(index)[offset] & 0xff;
}
}