public void decode(InputStream stream, int length, CharBuffer buffer)
			throws IllegalArgumentException, IOException {
		if (stream == null)
			throw new IllegalArgumentException("stream cannot be null");
		if (length < 0)
			throw new IllegalArgumentException("length [" + length
					+ "] must be >= 0.");
		if (buffer == null)
			throw new IllegalArgumentException(
					"buffer cannot be null and must be a CharBuffer with a large enough capacity to hold at least 'length' ("
							+ length + ") characters.");
		if (length > buffer.capacity())
			throw new IllegalArgumentException(
					"length ["
							+ length
							+ "] is larger than the capacity ["
							+ buffer.capacity()
							+ "] of the given buffer; the CharBuffer must be big enough to contain all the characters decoded from the given InputStream.");

		// short-circuit
		if (length == 0)
			buffer.clear();
		else {
			/*
			 * Reset the ByteBuffer.
			 * 
			 * As we read actual bytes in from the given stream into the wrapped
			 * byte[], we will adjust the ByteBuffers pointers to point at the
			 * new data so the decode operation operates on the correct (new)
			 * bytes.
			 */
			bBuffer.clear();

			/*
			 * Reset the destination CharBuffer.
			 * 
			 * This is the target we are decoding the bytes into. We have
			 * confirmed its capacity is large enough to hold the maximum
			 * possible number of chars we will decode (when 1-byte=1-char, e.g.
			 * ASCII). Decoding will *never* result in more chars than bytes.
			 */
			buffer.clear();

			// Reset the decoder to prepare it for new work.
			decoder.reset();

			int read = 0;

			while (length > 0 && (read = stream.read(rBuffer, 0, length)) != -1) {
				// Keep track of how many bytes remaining we need to read.
				length -= read;

				/*
				 * Re-position the frame (position to limit) of the buffer to
				 * point at the bytes just read in from the stream to the
				 * backing array.
				 */
				bBuffer.position(0);
				bBuffer.limit(read);

				// Decode the read bytes to our output buffer.
				decoder.decode(bBuffer, buffer, (length == 0));
			}

			if (length > 0)
				throw new IOException(
						"End of Stream encountered before all requested bytes ["
								+ (length + read)
								+ "] could be read. Unable to read the last "
								+ length + " remaining bytes.");

			// Flush any remaining state from the decoder to our result.
			decoder.flush(buffer);
		}
	}