View Javadoc
1   /*
2    * Copyright 2012 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the 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 hides its parent's tail data beyond a certain index.
29   * It is recommended to use {@link ChannelBuffer#slice()} and
30   * {@link ChannelBuffer#slice(int, int)} instead of calling the constructor
31   * explicitly.
32   */
33  public class TruncatedChannelBuffer extends AbstractChannelBuffer implements WrappedChannelBuffer {
34  
35      private final ChannelBuffer buffer;
36      private final int length;
37  
38      public TruncatedChannelBuffer(ChannelBuffer buffer, int length) {
39          if (length > buffer.capacity()) {
40              throw new IndexOutOfBoundsException("Length is too large, got "
41                      + length + " but can't go higher than " + buffer.capacity());
42          }
43  
44          this.buffer = buffer;
45          this.length = length;
46          writerIndex(length);
47      }
48  
49      public ChannelBuffer unwrap() {
50          return buffer;
51      }
52  
53      public ChannelBufferFactory factory() {
54          return buffer.factory();
55      }
56  
57      public ByteOrder order() {
58          return buffer.order();
59      }
60  
61      public boolean isDirect() {
62          return buffer.isDirect();
63      }
64  
65      public int capacity() {
66          return length;
67      }
68  
69      public boolean hasArray() {
70          return buffer.hasArray();
71      }
72  
73      public byte[] array() {
74          return buffer.array();
75      }
76  
77      public int arrayOffset() {
78          return buffer.arrayOffset();
79      }
80  
81      public byte getByte(int index) {
82          checkIndex(index);
83          return buffer.getByte(index);
84      }
85  
86      public short getShort(int index) {
87          checkIndex(index, 2);
88          return buffer.getShort(index);
89      }
90  
91      public int getUnsignedMedium(int index) {
92          checkIndex(index, 3);
93          return buffer.getUnsignedMedium(index);
94      }
95  
96      public int getInt(int index) {
97          checkIndex(index, 4);
98          return buffer.getInt(index);
99      }
100 
101     public long getLong(int index) {
102         checkIndex(index, 8);
103         return buffer.getLong(index);
104     }
105 
106     public ChannelBuffer duplicate() {
107         ChannelBuffer duplicate = new TruncatedChannelBuffer(buffer, length);
108         duplicate.setIndex(readerIndex(), writerIndex());
109         return duplicate;
110     }
111 
112     public ChannelBuffer copy(int index, int length) {
113         checkIndex(index, length);
114         return buffer.copy(index, length);
115     }
116 
117     public ChannelBuffer slice(int index, int length) {
118         checkIndex(index, length);
119         if (length == 0) {
120             return ChannelBuffers.EMPTY_BUFFER;
121         }
122         return buffer.slice(index, length);
123     }
124 
125     public void getBytes(int index, ChannelBuffer dst, int dstIndex, int length) {
126         checkIndex(index, length);
127         buffer.getBytes(index, dst, dstIndex, length);
128     }
129 
130     public void getBytes(int index, byte[] dst, int dstIndex, int length) {
131         checkIndex(index, length);
132         buffer.getBytes(index, dst, dstIndex, length);
133     }
134 
135     public void getBytes(int index, ByteBuffer dst) {
136         checkIndex(index, dst.remaining());
137         buffer.getBytes(index, dst);
138     }
139 
140     public void setByte(int index, int value) {
141         checkIndex(index);
142         buffer.setByte(index, value);
143     }
144 
145     public void setShort(int index, int value) {
146         checkIndex(index, 2);
147         buffer.setShort(index, value);
148     }
149 
150     public void setMedium(int index, int value) {
151         checkIndex(index, 3);
152         buffer.setMedium(index, value);
153     }
154 
155     public void setInt(int index, int value) {
156         checkIndex(index, 4);
157         buffer.setInt(index, value);
158     }
159 
160     public void setLong(int index, long value) {
161         checkIndex(index, 8);
162         buffer.setLong(index, value);
163     }
164 
165     public void setBytes(int index, byte[] src, int srcIndex, int length) {
166         checkIndex(index, length);
167         buffer.setBytes(index, src, srcIndex, length);
168     }
169 
170     public void setBytes(int index, ChannelBuffer src, int srcIndex, int length) {
171         checkIndex(index, length);
172         buffer.setBytes(index, src, srcIndex, length);
173     }
174 
175     public void setBytes(int index, ByteBuffer src) {
176         checkIndex(index, src.remaining());
177         buffer.setBytes(index, src);
178     }
179 
180     public void getBytes(int index, OutputStream out, int length)
181             throws IOException {
182         checkIndex(index, length);
183         buffer.getBytes(index, out, length);
184     }
185 
186     public int getBytes(int index, GatheringByteChannel out, int length)
187             throws IOException {
188         checkIndex(index, length);
189         return buffer.getBytes(index, out, length);
190     }
191 
192     public int setBytes(int index, InputStream in, int length)
193             throws IOException {
194         checkIndex(index, length);
195         return buffer.setBytes(index, in, length);
196     }
197 
198     public int setBytes(int index, ScatteringByteChannel in, int length)
199             throws IOException {
200         checkIndex(index, length);
201         return buffer.setBytes(index, in, length);
202     }
203 
204     public ByteBuffer toByteBuffer(int index, int length) {
205         checkIndex(index, length);
206         return buffer.toByteBuffer(index, length);
207     }
208 
209     private void checkIndex(int index) {
210         if (index < 0 || index >= capacity()) {
211             throw new IndexOutOfBoundsException("Invalid index of " + index
212                     + ", maximum is " + capacity());
213         }
214     }
215 
216     private void checkIndex(int index, int length) {
217         if (length < 0) {
218             throw new IllegalArgumentException(
219                     "length is negative: " + length);
220         }
221         if (index + length > capacity()) {
222             throw new IndexOutOfBoundsException("Invalid index of "
223                     + (index + length) + ", maximum is " + capacity());
224         }
225     }
226 }