001    /*
002     * Copyright (c) Andrey Kuznetsov. All Rights Reserved.
003     *
004     * http://uio.imagero.com
005     *
006     * Redistribution and use in source and binary forms, with or without
007     * modification, are permitted provided that the following conditions are met:
008     *
009     *  o Redistributions of source code must retain the above copyright notice,
010     *    this list of conditions and the following disclaimer.
011     *
012     *  o Redistributions in binary form must reproduce the above copyright notice,
013     *    this list of conditions and the following disclaimer in the documentation
014     *    and/or other materials provided with the distribution.
015     *
016     *  o Neither the name of Andrey Kuznetsov nor the names of
017     *    its contributors may be used to endorse or promote products derived
018     *    from this software without specific prior written permission.
019     *
020     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
021     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
022     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
023     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
024     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
025     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
026     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
027     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
028     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
029     * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
030     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
031     */
032    
033    package com.imagero.uio.io;
034    
035    import java.io.ByteArrayOutputStream;
036    
037    /**
038     * ByteArrayOutputStream which writes to external buffer.
039     * Length of this external buffer can't be changed.
040     *
041     * @author Andrey Kuznetsov
042     */
043    public class ByteArrayOutputStream2 extends ByteArrayOutputStream {
044        public ByteArrayOutputStream2(byte[] buffer) {
045            super(0);
046            buf = buffer;
047        }
048    
049        /**
050         * write given byte to buffer.
051         *
052         * @param b byte to write
053         * @throws ArrayIndexOutOfBoundsException if new byte count would exceed length of buffer after this operation
054         */
055        public synchronized void write(int b) {
056            int newcount = count + 1;
057            if (newcount > buf.length) {
058                throw new ArrayIndexOutOfBoundsException(newcount);
059            }
060            buf[count] = (byte) b;
061            count = newcount;
062        }
063    
064        /**
065         * combine (OR) current value with given byte using supplied mask.
066         * resulting value is (b & mask) | (currentValue & ~mask)
067         * @param b byte to combine
068         * @param mask 8 bit mask
069         * @throws ArrayIndexOutOfBoundsException
070         */
071        public synchronized void write(int b, int mask) {
072            int newcount = count + 1;
073            if (newcount > buf.length) {
074                throw new ArrayIndexOutOfBoundsException(newcount);
075            }
076            buf[count] = (byte) ((b & mask) | (buf[count] & ~mask));
077            count = newcount;
078        }
079    
080        /**
081         * Writes bytes from the specified byte array to buffer
082         * @param b byte array
083         * @param off start offset
084         * @param len number of bytes to write
085         * @throws ArrayIndexOutOfBoundsException if new byte count would exceed length of buffer after this operation (however the max possible byte count is written first)
086         */
087        public synchronized void write(byte b[], int off, int len) {
088            if (len == 0) {
089                return;
090            }
091            if ((off < 0) || (len < 0) || ((off + len) > b.length)) {
092                throw new IndexOutOfBoundsException();
093            }
094            int newcount = count + len;
095            if (newcount > buf.length) {
096                int max = buf.length - count;
097                System.arraycopy(b, off, buf, count, max);
098                throw new ArrayIndexOutOfBoundsException(newcount);
099            }
100            System.arraycopy(b, off, buf, count, len);
101            count = newcount;
102        }
103    
104        public int getCount() {
105            return count;
106        }
107    
108        /**
109         * Skip some bytes.
110         * Negative skip is possible.
111         * @param n byte count to skip
112         * @return how much bytes were skipped
113         */
114        public int skip(int n) {
115            int p = this.count;
116            seek(p + n);
117            return this.count - p;
118    //        if (count + n > buf.length) {
119    //            n = buf.length - count;
120    //        }
121    //        if (n < 0) {
122    //            return 0;
123    //        }
124    //        count += n;
125    //        return n;
126        }
127    
128        public void seek(int pos) {
129            this.count = Math.min(Math.max(pos, 0), buf.length - 1);
130        }
131    }