|
|||||||||||||||||||
Source file | Conditionals | Statements | Methods | TOTAL | |||||||||||||||
ExposedByteArrayOutputStream.java | 40% | 33.3% | 37.5% | 35.6% |
|
1 | /* | |
2 | * JBoss, the OpenSource J2EE webOS | |
3 | * | |
4 | * Distributable under LGPL license. | |
5 | * See terms of license at gnu.org. | |
6 | */ | |
7 | ||
8 | package org.jboss.cache.util; | |
9 | ||
10 | import java.io.ByteArrayOutputStream; | |
11 | ||
12 | /** | |
13 | * Extends ByteArrayOutputStream, but exposes the internal buffer. | |
14 | * Using this, callers don't need to call toByteArray() which copies the | |
15 | * internal buffer. | |
16 | * <p> | |
17 | * Also overrides the superclass' behavior of always doubling the size of the | |
18 | * internal buffer any time more capacity is needed. This class doubles the | |
19 | * size until the internal buffer reaches a configurable max size (default is | |
20 | * 4MB), after which it begins growing the buffer in 25% increments. This is | |
21 | * intended to help prevent an OutOfMemoryError during a resize of a large | |
22 | * buffer. | |
23 | * </p> | |
24 | * <p> | |
25 | * A version of this class was originally created by Bela Ban as part of the | |
26 | * JGroups library. | |
27 | * </p> | |
28 | * | |
29 | * @author <a href="mailto://brian.stansberry@jboss.com">Brian Stansberry</a> | |
30 | * @version $Id$ | |
31 | */ | |
32 | public class ExposedByteArrayOutputStream extends ByteArrayOutputStream | |
33 | { | |
34 | /** | |
35 | * Default buffer size after which if more buffer capacity | |
36 | * is needed the buffer will grow by 25% rather than 100% | |
37 | */ | |
38 | public static final int DEFAULT_DOUBLING_SIZE = 4 * 1024 * 1024; // 4MB | |
39 | ||
40 | private int maxDoublingSize = DEFAULT_DOUBLING_SIZE; | |
41 | ||
42 | 0 | public ExposedByteArrayOutputStream() |
43 | { | |
44 | 0 | super(); |
45 | } | |
46 | ||
47 | 393 | public ExposedByteArrayOutputStream(int size) |
48 | { | |
49 | 393 | super(size); |
50 | } | |
51 | ||
52 | /** | |
53 | * Creates a new byte array output stream, with a buffer capacity of | |
54 | * the specified size, in bytes. | |
55 | * | |
56 | * @param size the initial size. | |
57 | * @param maxDoublingSize the buffer size, after which if more capacity | |
58 | * is needed the buffer will grow by 25% | |
59 | * rather than 100% | |
60 | * | |
61 | * @exception IllegalArgumentException if size is negative. | |
62 | */ | |
63 | 0 | public ExposedByteArrayOutputStream(int size, int maxDoublingSize) |
64 | { | |
65 | 0 | super(size); |
66 | 0 | this.maxDoublingSize = maxDoublingSize; |
67 | } | |
68 | ||
69 | /** | |
70 | * Gets the internal buffer array. Note that the length of this array | |
71 | * will almost certainly be longer than the data written to it; call | |
72 | * <code>size()</code> to get the number of bytes of actual data. | |
73 | */ | |
74 | 391 | public byte[] getRawBuffer() { |
75 | 391 | return buf; |
76 | } | |
77 | ||
78 | 7872 | public synchronized void write(byte[] b, int off, int len) |
79 | { | |
80 | 7872 | if ((off < 0) || (off > b.length) || (len < 0) || |
81 | ((off + len) > b.length) || ((off + len) < 0)) { | |
82 | 0 | throw new IndexOutOfBoundsException(); |
83 | } | |
84 | 7872 | else if (len == 0) { |
85 | 20 | return; |
86 | } | |
87 | ||
88 | 7852 | int newcount = count + len; |
89 | 7852 | if (newcount > buf.length) { |
90 | 0 | byte newbuf[] = new byte[getNewBufferSize(buf.length, newcount)]; |
91 | 0 | System.arraycopy(buf, 0, newbuf, 0, count); |
92 | 0 | buf = newbuf; |
93 | } | |
94 | ||
95 | 7852 | System.arraycopy(b, off, buf, count, len); |
96 | 7852 | count = newcount; |
97 | } | |
98 | ||
99 | 0 | public synchronized void write(int b) |
100 | { | |
101 | 0 | int newcount = count + 1; |
102 | 0 | if (newcount > buf.length) { |
103 | 0 | byte newbuf[] = new byte[getNewBufferSize(buf.length, newcount)]; |
104 | 0 | System.arraycopy(buf, 0, newbuf, 0, count); |
105 | 0 | buf = newbuf; |
106 | } | |
107 | 0 | buf[count] = (byte)b; |
108 | 0 | count = newcount; |
109 | } | |
110 | ||
111 | /** | |
112 | * Gets the highest internal buffer size after which if more capacity | |
113 | * is needed the buffer will grow in 25% increments rather than 100%. | |
114 | */ | |
115 | 0 | public int getMaxDoublingSize() |
116 | { | |
117 | 0 | return maxDoublingSize; |
118 | } | |
119 | ||
120 | /** | |
121 | * Gets the number of bytes to which the internal buffer should be resized. | |
122 | * | |
123 | * @param curSize the current number of bytes | |
124 | * @param minNewSize the minimum number of bytes required | |
125 | * @return the size to which the internal buffer should be resized | |
126 | */ | |
127 | 0 | public int getNewBufferSize(int curSize, int minNewSize) |
128 | { | |
129 | 0 | if (curSize <= maxDoublingSize) |
130 | 0 | return Math.max(curSize << 1, minNewSize); |
131 | else | |
132 | 0 | return Math.max(curSize + (curSize >> 2), minNewSize); |
133 | } | |
134 | ||
135 | } |
|