package net.pms.util; import java.io.IOException; import java.io.OutputStream; import java.nio.ByteBuffer; import java.util.Arrays; public abstract class FlowParserOutputStream extends OutputStream { private ByteBuffer buffer; private OutputStream out; protected int neededByteNumber; protected int streamableByteNumber; protected boolean discard; protected int internalMark; protected int swapOrderBits; protected byte[] swapRemainingByte; public FlowParserOutputStream(OutputStream out, int maxbuffersize) { this.out = out; buffer = ByteBuffer.allocate(maxbuffersize); zerobuffer = new byte[15000]; Arrays.fill(zerobuffer, (byte) 0); } @Override public void write(int b) throws IOException { } public int count; @Override public void write(byte[] b, int off, int len) throws IOException { if (swapOrderBits == 2) { if (swapRemainingByte != null && swapRemainingByte.length == 1) { buffer.put(b[off]); buffer.put(swapRemainingByte[0]); off++; } int modulo = (int) Math.abs(len - off) % swapOrderBits; if (modulo != 0) { swapRemainingByte = new byte[1]; len -= modulo; System.arraycopy(b, len, swapRemainingByte, 0, modulo); } for (int i = off; i < len; i += 2) { byte temp = b[i]; b[i] = b[i + 1]; b[i + 1] = temp; } } buffer.put(b, off, len); int remains = buffer.position() - internalMark; while (remains > streamableByteNumber || remains > neededByteNumber) { if (streamableByteNumber == 0) { // time to analyze if (remains > neededByteNumber) { count++; analyzeBuffer(buffer.array(), internalMark, neededByteNumber); if (streamableByteNumber == 0) { throw new IOException("Packet size cannot be Null !"); } if (!discard) { beforeChunkSend(); } } else { // let's wait for more data buffer.position(internalMark); buffer.compact(); buffer.position(remains); internalMark = 0; return; } } if (streamableByteNumber > 0) { // let's output some bytes if (remains >= streamableByteNumber) { // we can send the whole bunch if (!discard) { out.write(buffer.array(), internalMark, streamableByteNumber); } internalMark += streamableByteNumber; remains = remains - streamableByteNumber; streamableByteNumber = 0; if (!discard) { afterChunkSend(); } if (remains == 0) { //buffer.position(internalMark); //buffer.compact(); buffer.position(0); internalMark = 0; } } else { if (!discard) { out.write(buffer.array(), internalMark, remains); } streamableByteNumber = streamableByteNumber - remains; buffer.position(0); internalMark = 0; remains = 0; } } } } protected void writePayload(byte payload[]) throws IOException { out.write(payload, 0, payload.length); } private byte zerobuffer[]; protected void padWithZeros(int numberOfZeros) throws IOException { if (numberOfZeros > 0) { out.write(zerobuffer, 0, numberOfZeros); } } protected abstract void analyzeBuffer(byte data[], int off, int len); protected abstract void beforeChunkSend() throws IOException; protected abstract void afterChunkSend() throws IOException; @Override public void close() throws IOException { int finalPos = buffer.position(); if (finalPos > 0 && streamableByteNumber > finalPos) { out.write(buffer.array(), 0, finalPos); padWithZeros(streamableByteNumber - finalPos); } out.close(); } }