public int read(byte[] dst, int offset, int len) throws IOException { // guard agains buffer overflows if (len > dst.length - offset) { throw new IndexOutOfBoundsException( "Requested lenght " + len + " exceeds the buffer size " + dst.length + " from offset " + offset); } // the buffer is empty while (oEnd == oPos) { int iPos = 0; long toRead = nextSrcSizeToDecompress(ctx); // Reached end of stream (-1) if there is anything more to read if (toRead == 0) { return -1; } // Start from the beginning if we have reached the end of the oBuff if (oBuffSize - oPos < blockSize) { oPos = 0; oEnd = 0; } // in.read is not guaranteed to return the requested size in one go while (iPos < toRead) { long read = in.read(iBuff, iPos, (int) toRead - iPos); if (read > 0) { iPos += read; } else { throw new IOException("Read error or truncated source"); } } // Decode long decoded = decompressContinue(ctx, oBuff, oPos, oBuffSize - oPos, iBuff, iPos); if (Zstd.isError(decoded)) { throw new IOException("Decode Error: " + Zstd.getErrorName(decoded)); } oEnd += (int) decoded; } // return size is min(requested, available) int size = Math.min(len, oEnd - oPos); oBuff.position(oPos); oBuff.get(dst, offset, size); oPos += size; return size; }
// The main constuctor public ZstdInputStream(InputStream inStream) throws IOException { // FilterInputStream constructor super(inStream); // create decompression context ctx = createDCtx(); /* allocate input buffer memory */ iBuff = ByteBuffer.allocate(iBuffSize).array(); if (iBuff == null) { throw new IOException("Error allocating the input buffer of size " + iBuffSize); } long toRead = nextSrcSizeToDecompress(ctx); // read the header - we need it in order know the size of the output buffer // in.read is not guaranteed to return the requested size in one go int iPos = in.read(iBuff, 0, (int) toRead); // find the size and allocate the output buffer while (oBuffSize < 0) { oBuffSize = findOBuffSize(iBuff, iPos); if (oBuffSize < 0) { iPos += in.read(iBuff, iPos, -oBuffSize - iPos); } } // allocate the output buffer oBuff = ByteBuffer.allocateDirect(oBuffSize); if (oBuff == null) { throw new IOException("Error allocating the output buffers of size " + oBuffSize); } // decode the first frame long decoded = decompressContinue(ctx, oBuff, oPos, oBuffSize - oPos, iBuff, iPos); if (Zstd.isError(decoded)) { throw new IOException("Decode Error: " + Zstd.getErrorName(decoded)); } oEnd += (int) decoded; }