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.IOException;
021    import java.io.InputStream;
022    import java.io.OutputStream;
023    import java.nio.ByteBuffer;
024    import java.nio.ByteOrder;
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     */
036    public class SlicedChannelBuffer extends AbstractChannelBuffer implements WrappedChannelBuffer {
037    
038        private final ChannelBuffer buffer;
039        private final int adjustment;
040        private final int length;
041    
042        public SlicedChannelBuffer(ChannelBuffer buffer, int index, int length) {
043            if (index < 0 || index > buffer.capacity()) {
044                throw new IndexOutOfBoundsException();
045            }
046    
047            if (index + length > buffer.capacity()) {
048                throw new IndexOutOfBoundsException();
049            }
050    
051            this.buffer = buffer;
052            adjustment = index;
053            this.length = length;
054            writerIndex(length);
055        }
056    
057        public ChannelBuffer unwrap() {
058            return buffer;
059        }
060    
061        public ByteOrder order() {
062            return buffer.order();
063        }
064    
065        public int capacity() {
066            return length;
067        }
068    
069        public byte getByte(int index) {
070            checkIndex(index);
071            return buffer.getByte(index + adjustment);
072        }
073    
074        public short getShort(int index) {
075            checkIndex(index, 2);
076            return buffer.getShort(index + adjustment);
077        }
078    
079        public int getMedium(int index) {
080            checkIndex(index, 3);
081            return buffer.getMedium(index + adjustment);
082        }
083    
084        public int getInt(int index) {
085            checkIndex(index, 4);
086            return buffer.getInt(index + adjustment);
087        }
088    
089        public long getLong(int index) {
090            checkIndex(index, 8);
091            return buffer.getLong(index + adjustment);
092        }
093    
094        public ChannelBuffer duplicate() {
095            return new SlicedChannelBuffer(buffer, adjustment, length);
096        }
097    
098        public ChannelBuffer copy(int index, int length) {
099            return buffer.copy(index + adjustment, length);
100        }
101    
102        public ChannelBuffer slice(int index, int length) {
103            checkIndex(index, length);
104            return new SlicedChannelBuffer(buffer, index + adjustment, length);
105        }
106    
107        public void getBytes(int index, ChannelBuffer dst, int dstIndex, int length) {
108            checkIndex(index, length);
109            buffer.getBytes(index + adjustment, dst, dstIndex, length);
110        }
111    
112        public void getBytes(int index, byte[] dst, int dstIndex, int length) {
113            checkIndex(index, length);
114            buffer.getBytes(index + adjustment, dst, dstIndex, length);
115        }
116    
117        public void getBytes(int index, ByteBuffer dst) {
118            checkIndex(index, dst.remaining());
119            buffer.getBytes(index + adjustment, dst);
120        }
121    
122        public void setByte(int index, byte value) {
123            checkIndex(index);
124            buffer.setByte(index + adjustment, value);
125        }
126    
127        public void setShort(int index, short value) {
128            checkIndex(index, 2);
129            buffer.setShort(index + adjustment, value);
130        }
131    
132        public void setMedium(int index, int value) {
133            checkIndex(index, 3);
134            buffer.setMedium(index + adjustment, value);
135        }
136    
137        public void setInt(int index, int value) {
138            checkIndex(index, 4);
139            buffer.setInt(index + adjustment, value);
140        }
141    
142        public void setLong(int index, long value) {
143            checkIndex(index, 8);
144            buffer.setLong(index + adjustment, value);
145        }
146    
147        public void setBytes(int index, byte[] src, int srcIndex, int length) {
148            checkIndex(index, length);
149            buffer.setBytes(index + adjustment, src, srcIndex, length);
150        }
151    
152        public void setBytes(int index, ChannelBuffer src, int srcIndex, int length) {
153            checkIndex(index, length);
154            buffer.setBytes(index + adjustment, src, srcIndex, length);
155        }
156    
157        public void setBytes(int index, ByteBuffer src) {
158            checkIndex(index, src.remaining());
159            buffer.setBytes(index + adjustment, src);
160        }
161    
162        public void getBytes(int index, OutputStream out, int length)
163                throws IOException {
164            checkIndex(index, length);
165            buffer.getBytes(index + adjustment, out, length);
166        }
167    
168        public int getBytes(int index, GatheringByteChannel out, int length)
169                throws IOException {
170            checkIndex(index, length);
171            return buffer.getBytes(index + adjustment, out, length);
172        }
173    
174        public void setBytes(int index, InputStream in, int length)
175                throws IOException {
176            checkIndex(index, length);
177            buffer.setBytes(index + adjustment, in, length);
178        }
179    
180        public int setBytes(int index, ScatteringByteChannel in, int length)
181                throws IOException {
182            checkIndex(index, length);
183            return buffer.setBytes(index + adjustment, in, length);
184        }
185    
186        public ByteBuffer toByteBuffer(int index, int length) {
187            checkIndex(index, length);
188            return buffer.toByteBuffer(index + adjustment, length);
189        }
190    
191        private void checkIndex(int index) {
192            if (index < 0 || index >= capacity()) {
193                throw new IndexOutOfBoundsException();
194            }
195        }
196    
197        private void checkIndex(int startIndex, int length) {
198            if (length < 0) {
199                throw new IllegalArgumentException(
200                        "length is negative: " + length);
201            }
202            if (startIndex < 0) {
203                throw new IndexOutOfBoundsException();
204            }
205            if (startIndex + length > capacity()) {
206                throw new IndexOutOfBoundsException();
207            }
208        }
209    }