1d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru/* 2d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru * Copyright (C) 2012 The Android Open Source Project 3d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru * 4d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru * Licensed under the Apache License, Version 2.0 (the "License"); 5d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru * you may not use this file except in compliance with the License. 6d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru * You may obtain a copy of the License at 7d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru * 8d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru * http://www.apache.org/licenses/LICENSE-2.0 9d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru * 10d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru * Unless required by applicable law or agreed to in writing, software 11d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru * distributed under the License is distributed on an "AS IS" BASIS, 12d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru * See the License for the specific language governing permissions and 14d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru * limitations under the License. 15d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru */ 16d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru 17d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Querupackage com.android.volley.toolbox; 18d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru 19d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queruimport java.io.ByteArrayOutputStream; 20d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queruimport java.io.IOException; 21d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru 22d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru/** 23d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru * A variation of {@link java.io.ByteArrayOutputStream} that uses a pool of byte[] buffers instead 24d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru * of always allocating them fresh, saving on heap churn. 25d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru */ 26d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Querupublic class PoolingByteArrayOutputStream extends ByteArrayOutputStream { 27d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru /** 28d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru * If the {@link #PoolingByteArrayOutputStream(ByteArrayPool)} constructor is called, this is 29d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru * the default size to which the underlying byte array is initialized. 30d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru */ 31d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru private static final int DEFAULT_SIZE = 256; 32d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru 33d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru private final ByteArrayPool mPool; 34d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru 35d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru /** 36d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru * Constructs a new PoolingByteArrayOutputStream with a default size. If more bytes are written 37d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru * to this instance, the underlying byte array will expand. 38d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru */ 39d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru public PoolingByteArrayOutputStream(ByteArrayPool pool) { 40d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru this(pool, DEFAULT_SIZE); 41d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru } 42d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru 43d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru /** 44d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru * Constructs a new {@code ByteArrayOutputStream} with a default size of {@code size} bytes. If 45d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru * more than {@code size} bytes are written to this instance, the underlying byte array will 46d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru * expand. 47d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru * 48d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru * @param size initial size for the underlying byte array. The value will be pinned to a default 49d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru * minimum size. 50d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru */ 51d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru public PoolingByteArrayOutputStream(ByteArrayPool pool, int size) { 52d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru mPool = pool; 53d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru buf = mPool.getBuf(Math.max(size, DEFAULT_SIZE)); 54d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru } 55d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru 56d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru @Override 57d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru public void close() throws IOException { 58d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru mPool.returnBuf(buf); 59d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru buf = null; 60d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru super.close(); 61d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru } 62d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru 63d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru @Override 64d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru public void finalize() { 65d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru mPool.returnBuf(buf); 66d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru } 67d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru 68d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru /** 69d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru * Ensures there is enough space in the buffer for the given number of additional bytes. 70d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru */ 71d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru private void expand(int i) { 72d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru /* Can the buffer handle @i more bytes, if not expand it */ 73d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru if (count + i <= buf.length) { 74d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru return; 75d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru } 76d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru byte[] newbuf = mPool.getBuf((count + i) * 2); 77d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru System.arraycopy(buf, 0, newbuf, 0, count); 78d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru mPool.returnBuf(buf); 79d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru buf = newbuf; 80d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru } 81d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru 82d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru @Override 83d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru public synchronized void write(byte[] buffer, int offset, int len) { 84d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru expand(len); 85d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru super.write(buffer, offset, len); 86d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru } 87d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru 88d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru @Override 89d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru public synchronized void write(int oneByte) { 90d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru expand(1); 91d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru super.write(oneByte); 92d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru } 93d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru} 94