michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: package org.mozilla.gecko.background.bagheera; michael@0: michael@0: import java.io.UnsupportedEncodingException; michael@0: import java.util.zip.Deflater; michael@0: michael@0: import ch.boye.httpclientandroidlib.HttpEntity; michael@0: michael@0: public class DeflateHelper { michael@0: /** michael@0: * Conservative upper bound for zlib size, equivalent to the first few lines michael@0: * in zlib's deflateBound function. michael@0: * michael@0: * Includes zlib header. michael@0: * michael@0: * @param sourceLen michael@0: * the number of bytes to compress. michael@0: * @return the number of bytes to allocate for the compressed output. michael@0: */ michael@0: public static int deflateBound(final int sourceLen) { michael@0: return sourceLen + ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5 + 6; michael@0: } michael@0: michael@0: /** michael@0: * Deflate the input into the output array, returning the number of bytes michael@0: * written to output. michael@0: */ michael@0: public static int deflate(byte[] input, byte[] output) { michael@0: final Deflater deflater = new Deflater(); michael@0: deflater.setInput(input); michael@0: deflater.finish(); michael@0: michael@0: final int length = deflater.deflate(output); michael@0: deflater.end(); michael@0: return length; michael@0: } michael@0: michael@0: /** michael@0: * Deflate the input, returning an HttpEntity that offers an accurate window michael@0: * on the output. michael@0: * michael@0: * Note that this method does not trim the output array. (Test code can use michael@0: * TestDeflation#deflateTrimmed(byte[]).) michael@0: * michael@0: * Trimming would be more efficient for long-term space use, but we expect this michael@0: * entity to be transient. michael@0: * michael@0: * Note also that deflate can require more space than the input. michael@0: * {@link #deflateBound(int)} tells us the most it will use. michael@0: * michael@0: * @param bytes the input to deflate. michael@0: * @return the deflated input as an entity. michael@0: */ michael@0: public static HttpEntity deflateBytes(final byte[] bytes) { michael@0: // We would like to use DeflaterInputStream here, but it's minSDK=9, and we michael@0: // still target 8. It would also force us to use chunked Transfer-Encoding, michael@0: // so perhaps it's for the best! michael@0: michael@0: final byte[] out = new byte[deflateBound(bytes.length)]; michael@0: final int outLength = deflate(bytes, out); michael@0: return new BoundedByteArrayEntity(out, 0, outLength); michael@0: } michael@0: michael@0: public static HttpEntity deflateBody(final String payload) { michael@0: final byte[] bytes; michael@0: try { michael@0: bytes = payload.getBytes("UTF-8"); michael@0: } catch (UnsupportedEncodingException ex) { michael@0: // This will never happen. Thanks, Java! michael@0: throw new RuntimeException(ex); michael@0: } michael@0: return deflateBytes(bytes); michael@0: } michael@0: }