View Javadoc

1   /*
2    * Copyright 2009 Red Hat, Inc.
3    *
4    * Red Hat licenses this file to you under the Apache License, version 2.0
5    * (the "License"); you may not use this file except in compliance with the
6    * License.  You may obtain a copy of the License at:
7    *
8    *    http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package org.jboss.netty.buffer;
17  
18  import java.io.IOException;
19  import java.io.InputStream;
20  import java.io.OutputStream;
21  import java.nio.ByteBuffer;
22  import java.nio.ByteOrder;
23  import java.nio.channels.GatheringByteChannel;
24  import java.nio.channels.ScatteringByteChannel;
25  
26  
27  /**
28   * A derived buffer which exposes its parent's sub-region only.  It is
29   * recommended to use {@link ChannelBuffer#slice()} and
30   * {@link ChannelBuffer#slice(int, int)} instead of calling the constructor
31   * explicitly.
32   *
33   * @author <a href="http://www.jboss.org/netty/">The Netty Project</a>
34   * @author <a href="http://gleamynode.net/">Trustin Lee</a>
35   *
36   * @version $Rev: 2206 $, $Date: 2010-03-03 14:35:01 +0900 (Wed, 03 Mar 2010) $
37   *
38   */
39  public class SlicedChannelBuffer extends AbstractChannelBuffer implements WrappedChannelBuffer {
40  
41      private final ChannelBuffer buffer;
42      private final int adjustment;
43      private final int length;
44  
45      public SlicedChannelBuffer(ChannelBuffer buffer, int index, int length) {
46          if (index < 0 || index > buffer.capacity()) {
47              throw new IndexOutOfBoundsException();
48          }
49  
50          if (index + length > buffer.capacity()) {
51              throw new IndexOutOfBoundsException();
52          }
53  
54          this.buffer = buffer;
55          adjustment = index;
56          this.length = length;
57          writerIndex(length);
58      }
59  
60      public ChannelBuffer unwrap() {
61          return buffer;
62      }
63  
64      public ChannelBufferFactory factory() {
65          return buffer.factory();
66      }
67  
68      public ByteOrder order() {
69          return buffer.order();
70      }
71  
72      public boolean isDirect() {
73          return buffer.isDirect();
74      }
75  
76      public int capacity() {
77          return length;
78      }
79  
80      public boolean hasArray() {
81          return buffer.hasArray();
82      }
83  
84      public byte[] array() {
85          return buffer.array();
86      }
87  
88      public int arrayOffset() {
89          return buffer.arrayOffset() + adjustment;
90      }
91  
92      public byte getByte(int index) {
93          checkIndex(index);
94          return buffer.getByte(index + adjustment);
95      }
96  
97      public short getShort(int index) {
98          checkIndex(index, 2);
99          return buffer.getShort(index + adjustment);
100     }
101 
102     public int getUnsignedMedium(int index) {
103         checkIndex(index, 3);
104         return buffer.getUnsignedMedium(index + adjustment);
105     }
106 
107     public int getInt(int index) {
108         checkIndex(index, 4);
109         return buffer.getInt(index + adjustment);
110     }
111 
112     public long getLong(int index) {
113         checkIndex(index, 8);
114         return buffer.getLong(index + adjustment);
115     }
116 
117     public ChannelBuffer duplicate() {
118         ChannelBuffer duplicate = new SlicedChannelBuffer(buffer, adjustment, length);
119         duplicate.setIndex(readerIndex(), writerIndex());
120         return duplicate;
121     }
122 
123     public ChannelBuffer copy(int index, int length) {
124         checkIndex(index, length);
125         return buffer.copy(index + adjustment, length);
126     }
127 
128     public ChannelBuffer slice(int index, int length) {
129         checkIndex(index, length);
130         if (length == 0) {
131             return ChannelBuffers.EMPTY_BUFFER;
132         }
133         return new SlicedChannelBuffer(buffer, index + adjustment, length);
134     }
135 
136     public void getBytes(int index, ChannelBuffer dst, int dstIndex, int length) {
137         checkIndex(index, length);
138         buffer.getBytes(index + adjustment, dst, dstIndex, length);
139     }
140 
141     public void getBytes(int index, byte[] dst, int dstIndex, int length) {
142         checkIndex(index, length);
143         buffer.getBytes(index + adjustment, dst, dstIndex, length);
144     }
145 
146     public void getBytes(int index, ByteBuffer dst) {
147         checkIndex(index, dst.remaining());
148         buffer.getBytes(index + adjustment, dst);
149     }
150 
151     public void setByte(int index, int value) {
152         checkIndex(index);
153         buffer.setByte(index + adjustment, value);
154     }
155 
156     public void setShort(int index, int value) {
157         checkIndex(index, 2);
158         buffer.setShort(index + adjustment, value);
159     }
160 
161     public void setMedium(int index, int value) {
162         checkIndex(index, 3);
163         buffer.setMedium(index + adjustment, value);
164     }
165 
166     public void setInt(int index, int value) {
167         checkIndex(index, 4);
168         buffer.setInt(index + adjustment, value);
169     }
170 
171     public void setLong(int index, long value) {
172         checkIndex(index, 8);
173         buffer.setLong(index + adjustment, value);
174     }
175 
176     public void setBytes(int index, byte[] src, int srcIndex, int length) {
177         checkIndex(index, length);
178         buffer.setBytes(index + adjustment, src, srcIndex, length);
179     }
180 
181     public void setBytes(int index, ChannelBuffer src, int srcIndex, int length) {
182         checkIndex(index, length);
183         buffer.setBytes(index + adjustment, src, srcIndex, length);
184     }
185 
186     public void setBytes(int index, ByteBuffer src) {
187         checkIndex(index, src.remaining());
188         buffer.setBytes(index + adjustment, src);
189     }
190 
191     public void getBytes(int index, OutputStream out, int length)
192             throws IOException {
193         checkIndex(index, length);
194         buffer.getBytes(index + adjustment, out, length);
195     }
196 
197     public int getBytes(int index, GatheringByteChannel out, int length)
198             throws IOException {
199         checkIndex(index, length);
200         return buffer.getBytes(index + adjustment, out, length);
201     }
202 
203     public int setBytes(int index, InputStream in, int length)
204             throws IOException {
205         checkIndex(index, length);
206         return buffer.setBytes(index + adjustment, in, length);
207     }
208 
209     public int setBytes(int index, ScatteringByteChannel in, int length)
210             throws IOException {
211         checkIndex(index, length);
212         return buffer.setBytes(index + adjustment, in, length);
213     }
214 
215     public ByteBuffer toByteBuffer(int index, int length) {
216         checkIndex(index, length);
217         return buffer.toByteBuffer(index + adjustment, length);
218     }
219 
220     private void checkIndex(int index) {
221         if (index < 0 || index >= capacity()) {
222             throw new IndexOutOfBoundsException();
223         }
224     }
225 
226     private void checkIndex(int startIndex, int length) {
227         if (length < 0) {
228             throw new IllegalArgumentException(
229                     "length is negative: " + length);
230         }
231         if (startIndex < 0) {
232             throw new IndexOutOfBoundsException();
233         }
234         if (startIndex + length > capacity()) {
235             throw new IndexOutOfBoundsException();
236         }
237     }
238 }