summaryrefslogtreecommitdiffstats
path: root/bcprov/src/main/java/org/bouncycastle/util/io/BufferingOutputStream.java
blob: 9d5fe1423b13881adfb8ffe45a0eb7ab2298dea2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package org.bouncycastle.util.io;

import java.io.IOException;
import java.io.OutputStream;

import org.bouncycastle.util.Arrays;

/**
 * An output stream that buffers data to be feed into an encapsulated output stream.
 * <p>
 * The stream zeroes out the internal buffer on each flush.
 * </p>
 */
public class BufferingOutputStream
    extends OutputStream
{
    private final OutputStream other;
    private final byte[] buf;

    private int   bufOff;

    /**
     * Create a buffering stream with the default buffer size (4096).
     *
     * @param other output stream to be wrapped.
     */
    public BufferingOutputStream(OutputStream other)
    {
        this.other = other;
        this.buf = new byte[4096];
    }

    /**
     * Create a buffering stream with a specified buffer size.
     *
     * @param other output stream to be wrapped.
     * @param bufferSize size in bytes for internal buffer.
     */
    public BufferingOutputStream(OutputStream other, int bufferSize)
    {
        this.other = other;
        this.buf = new byte[bufferSize];
    }

    public void write(byte[] bytes, int offset, int len)
        throws IOException
    {
        if (len < buf.length - bufOff)
        {
            System.arraycopy(bytes, offset, buf, bufOff, len);
            bufOff += len;
        }
        else
        {
            int gap = buf.length - bufOff;

            System.arraycopy(bytes, offset, buf, bufOff, gap);
            bufOff += gap;

            flush();

            offset += gap;
            len -= gap;
            while (len >= buf.length)
            {
                other.write(bytes, offset, buf.length);
                offset += buf.length;
                len -= buf.length;
            }

            if (len > 0)
            {
                System.arraycopy(bytes, offset, buf, bufOff, len);
                bufOff += len;
            }
        }
    }

    public void write(int b)
        throws IOException
    {
        buf[bufOff++] = (byte)b;
        if (bufOff == buf.length)
        {
            flush();
        }
    }

    /**
     * Flush the internal buffer to the encapsulated output stream. Zero the buffer contents when done.
     *
     * @throws IOException on error.
     */
    public void flush()
        throws IOException
    {
        other.write(buf, 0, bufOff);
        bufOff = 0;
        Arrays.fill(buf, (byte)0);
    }

    public void close()
        throws IOException
    {
        flush();
        other.close();
    }
}