001    /*
002     * Copyright (C) 2008  Trustin Heuiseung Lee
003     *
004     * This library is free software; you can redistribute it and/or
005     * modify it under the terms of the GNU Lesser General Public
006     * License as published by the Free Software Foundation; either
007     * version 2.1 of the License, or (at your option) any later version.
008     *
009     * This library is distributed in the hope that it will be useful,
010     * but WITHOUT ANY WARRANTY; without even the implied warranty of
011     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
012     * Lesser General Public License for more details.
013     *
014     * You should have received a copy of the GNU Lesser General Public
015     * License along with this library; if not, write to the Free Software
016     * Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA
017     */
018    package net.gleamynode.netty.buffer;
019    
020    import java.io.EOFException;
021    import java.io.IOException;
022    import java.io.InputStream;
023    import java.io.OutputStream;
024    import java.nio.ByteBuffer;
025    import java.nio.channels.GatheringByteChannel;
026    import java.nio.channels.ScatteringByteChannel;
027    
028    /**
029     *
030     * @author The Netty Project (netty@googlegroups.com)
031     * @author Trustin Lee (trustin@gmail.com)
032     *
033     * @version $Rev$, $Date$
034     */
035    public abstract class HeapChannelBuffer extends AbstractChannelBuffer {
036    
037        protected final byte[] array;
038    
039        public HeapChannelBuffer(int length) {
040            this(new byte[length], 0, 0);
041        }
042    
043        public HeapChannelBuffer(byte[] array) {
044            this(array, 0, array.length);
045        }
046    
047        protected HeapChannelBuffer(byte[] array, int readerIndex, int writerIndex) {
048            if (array == null) {
049                throw new NullPointerException("array");
050            }
051            this.array = array;
052            setIndex(readerIndex, writerIndex);
053        }
054    
055        public int capacity() {
056            return array.length;
057        }
058    
059        public byte getByte(int index) {
060            return array[index];
061        }
062    
063        public void getBytes(int index, ChannelBuffer dst, int dstIndex, int length) {
064            if (dst instanceof HeapChannelBuffer) {
065                getBytes(index, ((HeapChannelBuffer) dst).array, dstIndex, length);
066            } else {
067                dst.setBytes(dstIndex, array, index, length);
068            }
069        }
070    
071        public void getBytes(int index, byte[] dst, int dstIndex, int length) {
072            System.arraycopy(array, index, dst, dstIndex, length);
073        }
074    
075        public void getBytes(int index, ByteBuffer dst) {
076            dst.put(array, index, Math.min(capacity() - index, dst.remaining()));
077        }
078    
079        public void getBytes(int index, OutputStream out, int length)
080                throws IOException {
081            out.write(array, index, length);
082        }
083    
084        public int getBytes(int index, GatheringByteChannel out, int length)
085                throws IOException {
086            return out.write(ByteBuffer.wrap(array, index, length));
087        }
088    
089        public void setByte(int index, byte value) {
090            array[index] = value;
091        }
092    
093        public void setBytes(int index, ChannelBuffer src, int srcIndex, int length) {
094            if (src instanceof HeapChannelBuffer) {
095                setBytes(index, ((HeapChannelBuffer) src).array, srcIndex, length);
096            } else {
097                src.getBytes(srcIndex, array, index, length);
098            }
099        }
100    
101        public void setBytes(int index, byte[] src, int srcIndex, int length) {
102            System.arraycopy(src, srcIndex, array, index, length);
103        }
104    
105        public void setBytes(int index, ByteBuffer src) {
106            src.get(array, index, src.remaining());
107        }
108    
109        public void setBytes(int index, InputStream in, int length) throws IOException {
110            while (length > 0) {
111                int readBytes = in.read(array, index, length);
112                if (readBytes < 0) {
113                    throw new EOFException();
114                }
115                index += readBytes;
116                length -= readBytes;
117            }
118        }
119    
120        public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException {
121            ByteBuffer buf = ByteBuffer.wrap(array, index, length);
122            while (length > 0) {
123                int readBytes = in.read(buf);
124                if (readBytes < 0) {
125                    throw new EOFException();
126                } else if (readBytes == 0) {
127                    break;
128                }
129            }
130    
131            return buf.flip().remaining();
132        }
133    
134        public ChannelBuffer slice(int index, int length) {
135            if (index == 0) {
136                if (length == array.length) {
137                    return duplicate();
138                } else {
139                    return new TruncatedChannelBuffer(this, length);
140                }
141            } else {
142                return new SlicedChannelBuffer(this, index, length);
143            }
144        }
145    
146        public ByteBuffer toByteBuffer(int index, int length) {
147            return ByteBuffer.wrap(array, index, length);
148        }
149    }