* 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.
/**
* Capacitor
- *
+ *
* Storage mechanism for read data, specifically designed for InputStreams.
- *
- * The Standard BufferedInputStream requires a limit to be set for buffered reading, which is
+ *
+ * The Standard BufferedInputStream requires a limit to be set for buffered reading, which is
* impractical for reading SOAP headers, which can be quite large.
* @author Jonathan
*
private ArrayList<ByteBuffer> bbs = new ArrayList<>();
private ByteBuffer curr = null;
private int idx;
-
+
// Maintain a private RingBuffer for Memory, for efficiency
private static ByteBuffer[] ring = new ByteBuffer[16];
private static int start, end;
-
-
+
+
public void put(byte b) {
- if(curr == null || curr.remaining()==0) { // ensure we have a "curr" buffer ready for data
+ if (curr == null || curr.remaining()==0) { // ensure we have a "curr" buffer ready for data
curr = ringGet();
bbs.add(curr);
}
- curr.put(b);
+ curr.put(b);
}
public int read() {
- if(curr!=null) {
- if(curr.remaining()>0) { // have a buffer, use it!
+ if (curr!=null) {
+ if (curr.remaining()>0) { // have a buffer, use it!
return curr.get();
- } else if(idx<bbs.size()){ // Buffer not enough, get next one from array
+ } else if (idx<bbs.size()){ // Buffer not enough, get next one from array
curr=bbs.get(idx++);
return curr.get();
}
} // if no curr buffer, treat as end of stream
return -1;
}
-
+
/**
* read into an array like Streams
- *
+ *
* @param array
* @param offset
* @param length
* @return
*/
public int read(byte[] array, int offset, int length) {
- if(curr==null)return -1;
+ if (curr==null)return -1;
int len;
int count=0;
- while(length>0) { // loop through while there's data needed
- if((len=curr.remaining())>length) { // if enough data in curr buffer, use this code
+ while (length>0) { // loop through while there's data needed
+ if ((len=curr.remaining())>length) { // if enough data in curr buffer, use this code
curr.get(array,offset,length);
count+=length;
length=0;
count+=len;
offset+=len;
length-=len;
- if(idx<bbs.size()) {
+ if (idx<bbs.size()) {
curr=bbs.get(idx++);
} else {
length=0; // stop, and return the count of how many we were able to load
/**
* Put an array of data into Capacitor
- *
+ *
* @param array
* @param offset
* @param length
*/
public void put(byte[] array, int offset, int length) {
- if(curr == null || curr.remaining()==0) {
+ if (curr == null || curr.remaining()==0) {
curr = ringGet();
bbs.add(curr);
}
-
+
int len;
- while(length>0) {
- if((len=curr.remaining())>length) {
+ while (length>0) {
+ if ((len=curr.remaining())>length) {
curr.put(array,offset,length);
length=0;
} else {
}
}
}
-
+
/**
* Move state from Storage mode into Read mode, changing all internal buffers to read mode, etc
*/
public void setForRead() {
- for(ByteBuffer bb : bbs) {
+ for (ByteBuffer bb : bbs) {
bb.flip();
}
- if(bbs.isEmpty()) {
+ if (bbs.isEmpty()) {
curr = null;
idx = 0;
} else {
idx=1;
}
}
-
+
/**
* reuse all the buffers
*/
public void done() {
- for(ByteBuffer bb : bbs) {
+ for (ByteBuffer bb : bbs) {
ringPut(bb);
}
bbs.clear();
curr = null;
}
-
+
/**
* Declare amount of data available to be read at once.
- *
+ *
* @return
*/
public int available() {
int count = 0;
- for(ByteBuffer bb : bbs) {
+ for (ByteBuffer bb : bbs) {
count+=bb.remaining();
}
return count;
}
-
+
/**
* Returns how many are left that were not skipped
* @param n
public long skip(long n) {
long skipped=0L;
int skip;
- if(curr==null) {
+ if (curr==null) {
return 0;
}
- while(n>0) {
- if(n<(skip=curr.remaining())) {
+ while (n>0) {
+ if (n<(skip=curr.remaining())) {
curr.position(curr.position()+(int)n);
skipped+=skip;
n=0;
} else {
curr.position(curr.limit());
-
+
skipped-=skip;
- if(idx<bbs.size()) {
+ if (idx<bbs.size()) {
curr=bbs.get(idx++);
n-=skip;
} else {
* in a standalone mode.
*/
public void reset() {
- for(ByteBuffer bb : bbs) {
+ for (ByteBuffer bb : bbs) {
bb.position(0);
}
- if(bbs.isEmpty()) {
+ if (bbs.isEmpty()) {
curr = null;
idx = 0;
} else {
}
/*
- * Ring Functions. Reuse allocated memory
+ * Ring Functions. Reuse allocated memory
*/
private ByteBuffer ringGet() {
ByteBuffer bb = null;
synchronized(ring) {
bb=ring[start];
ring[start]=null;
- if(bb!=null && ++start>15)start=0;
+ if (bb!=null && ++start>15)start=0;
}
- if(bb==null) {
+ if (bb==null) {
bb=ByteBuffer.allocate(DEFAULT_CHUNK);
} else {
bb.clear();// refresh reused buffer
}
return bb;
}
-
+
private void ringPut(ByteBuffer bb) {
synchronized(ring) {
ring[end]=bb; // if null or not, BB will just be Garbage collected
- if(++end>15)end=0;
+ if (++end>15)end=0;
}
}