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