private int fillFromStream() throws IOException {
        int oldVirtualSize = virtualSize;

        // If the physical buffer isn't full
        if (virtualSize < physicalSize) {
            // If the virtual buffer doesn't wrap
            if (head + virtualSize < physicalSize) {
                // streamIn.read may return -1, so force it to be at least 0.
                virtualSize += Math.max(streamIn.read(buffer, getTail(),
                        physicalSize - getTail()), 0);

                // If we got all the bytes we asked for, then head+virtualSize
                // now equals physicalSize. We'll fill in the space at the
                // beginning of the physical buffer with the following read.
            }

            // If the virtual buffer wraps
            if (head + virtualSize >= physicalSize) {
                // streamIn.read may return -1, so force it to be at least 0.
                virtualSize += Math.max(streamIn.read(buffer, getTail(),
                        physicalSize - virtualSize), 0);
            }
        }
        return virtualSize - oldVirtualSize;
    }