001/*
002 *  Licensed to the Apache Software Foundation (ASF) under one
003 *  or more contributor license agreements.  See the NOTICE file
004 *  distributed with this work for additional information
005 *  regarding copyright ownership.  The ASF licenses this file
006 *  to you under the Apache License, Version 2.0 (the
007 *  "License"); you may not use this file except in compliance
008 *  with the License.  You may obtain a copy of the License at
009 *
010 *    http://www.apache.org/licenses/LICENSE-2.0
011 *
012 *  Unless required by applicable law or agreed to in writing,
013 *  software distributed under the License is distributed on an
014 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 *  KIND, either express or implied.  See the License for the
016 *  specific language governing permissions and limitations
017 *  under the License.
018 *
019 */
020package org.apache.mina.util.byteaccess;
021
022import java.nio.ByteOrder;
023import java.util.Collections;
024
025import org.apache.mina.core.buffer.IoBuffer;
026
027/**
028 * A <code>ByteArray</code> backed by a <code>IoBuffer</code>. This class
029 * is abstract. Subclasses need to override the <code>free()</code> method. An
030 * implementation backed by a heap <code>IoBuffer</code> can be created with
031 * a <code>SimpleByteArrayFactory</code>.
032 *
033 * @author <a href="http://mina.apache.org">Apache MINA Project</a>
034 */
035public abstract class BufferByteArray extends AbstractByteArray {
036
037    /**
038     * The backing <code>IoBuffer</code>.
039     */
040    protected IoBuffer bb;
041
042    /**
043     * 
044     * Creates a new instance of BufferByteArray and uses the supplied
045     * {@link IoBuffer} to back this class
046     *
047     * @param bb
048     *  The backing buffer
049     */
050    public BufferByteArray(IoBuffer bb) {
051        this.bb = bb;
052    }
053
054    /**
055     * {@inheritDoc}
056     */
057    public Iterable<IoBuffer> getIoBuffers() {
058        return Collections.singletonList(bb);
059    }
060
061    /**
062     * {@inheritDoc}
063     */
064    public IoBuffer getSingleIoBuffer() {
065        return bb;
066    }
067
068    /**
069     * {@inheritDoc}
070     * 
071     * Calling <code>free()</code> on the returned slice has no effect.
072     */
073    public ByteArray slice(int index, int length) {
074        int oldLimit = bb.limit();
075        bb.position(index);
076        bb.limit(index + length);
077        IoBuffer slice = bb.slice();
078        bb.limit(oldLimit);
079        return new BufferByteArray(slice) {
080
081            @Override
082            public void free() {
083                // Do nothing.
084            }
085        };
086    }
087
088    /**
089     * {@inheritDoc}
090     */
091    public abstract void free();
092
093    /**
094     * {@inheritDoc}
095     */
096    public Cursor cursor() {
097        return new CursorImpl();
098    }
099
100    /**
101     * {@inheritDoc}
102     */
103    public Cursor cursor(int index) {
104        return new CursorImpl(index);
105    }
106
107    /**
108     * {@inheritDoc}
109     */
110    public int first() {
111        return 0;
112    }
113
114    /**
115     * {@inheritDoc}
116     */
117    public int last() {
118        return bb.limit();
119    }
120
121    /**
122     * {@inheritDoc}
123     */
124    public ByteOrder order() {
125        return bb.order();
126    }
127
128    /**
129     * {@inheritDoc}
130     */
131    public void order(ByteOrder order) {
132        bb.order(order);
133    }
134
135    /**
136     * {@inheritDoc}
137     */
138    public byte get(int index) {
139        return bb.get(index);
140    }
141
142    /**
143     * {@inheritDoc}
144     */
145    public void put(int index, byte b) {
146        bb.put(index, b);
147    }
148
149    /**
150     * {@inheritDoc}
151     */
152    public void get(int index, IoBuffer other) {
153        bb.position(index);
154        other.put(bb);
155    }
156
157    /**
158     * {@inheritDoc}
159     */
160    public void put(int index, IoBuffer other) {
161        bb.position(index);
162        bb.put(other);
163    }
164
165    /**
166     * {@inheritDoc}
167     */
168    public short getShort(int index) {
169        return bb.getShort(index);
170    }
171
172    /**
173     * {@inheritDoc}
174     */
175    public void putShort(int index, short s) {
176        bb.putShort(index, s);
177    }
178
179    /**
180     * {@inheritDoc}
181     */
182    public int getInt(int index) {
183        return bb.getInt(index);
184    }
185
186    /**
187     * {@inheritDoc}
188     */
189    public void putInt(int index, int i) {
190        bb.putInt(index, i);
191    }
192
193    /**
194     * {@inheritDoc}
195     */
196    public long getLong(int index) {
197        return bb.getLong(index);
198    }
199
200    /**
201     * {@inheritDoc}
202     */
203    public void putLong(int index, long l) {
204        bb.putLong(index, l);
205    }
206
207    /**
208     * {@inheritDoc}
209     */
210    public float getFloat(int index) {
211        return bb.getFloat(index);
212    }
213
214    /**
215     * {@inheritDoc}
216     */
217    public void putFloat(int index, float f) {
218        bb.putFloat(index, f);
219    }
220
221    /**
222     * {@inheritDoc}
223     */
224    public double getDouble(int index) {
225        return bb.getDouble(index);
226    }
227
228    /**
229     * {@inheritDoc}
230     */
231    public void putDouble(int index, double d) {
232        bb.putDouble(index, d);
233    }
234
235    /**
236     * {@inheritDoc}
237     */
238    public char getChar(int index) {
239        return bb.getChar(index);
240    }
241
242    /**
243     * {@inheritDoc}
244     */
245    public void putChar(int index, char c) {
246        bb.putChar(index, c);
247    }
248
249    private class CursorImpl implements Cursor {
250
251        private int index;
252
253        public CursorImpl() {
254            // This space intentionally blank.
255        }
256
257        public CursorImpl(int index) {
258            setIndex(index);
259        }
260
261        /**
262         * {@inheritDoc}
263         */
264        public int getRemaining() {
265            return last() - index;
266        }
267
268        /**
269         * {@inheritDoc}
270         */
271        public boolean hasRemaining() {
272            return getRemaining() > 0;
273        }
274
275        /**
276         * {@inheritDoc}
277         */
278        public int getIndex() {
279            return index;
280        }
281
282        /**
283         * {@inheritDoc}
284         */
285        public void setIndex(int index) {
286            if (index < 0 || index > last()) {
287                throw new IndexOutOfBoundsException();
288            }
289            this.index = index;
290        }
291
292        public void skip(int length) {
293            setIndex(index + length);
294        }
295
296        public ByteArray slice(int length) {
297            ByteArray slice = BufferByteArray.this.slice(index, length);
298            index += length;
299            return slice;
300        }
301
302        /**
303         * {@inheritDoc}
304         */
305        public ByteOrder order() {
306            return BufferByteArray.this.order();
307        }
308
309        /**
310         * {@inheritDoc}
311         */
312        public byte get() {
313            byte b = BufferByteArray.this.get(index);
314            index += 1;
315            return b;
316        }
317
318        /**
319         * {@inheritDoc}
320         */
321        public void put(byte b) {
322            BufferByteArray.this.put(index, b);
323            index += 1;
324        }
325
326        /**
327         * {@inheritDoc}
328         */
329        public void get(IoBuffer bb) {
330            int size = Math.min(getRemaining(), bb.remaining());
331            BufferByteArray.this.get(index, bb);
332            index += size;
333        }
334
335        /**
336         * {@inheritDoc}
337         */
338        public void put(IoBuffer bb) {
339            int size = bb.remaining();
340            BufferByteArray.this.put(index, bb);
341            index += size;
342        }
343
344        /**
345         * {@inheritDoc}
346         */
347        public short getShort() {
348            short s = BufferByteArray.this.getShort(index);
349            index += 2;
350            return s;
351        }
352
353        /**
354         * {@inheritDoc}
355         */
356        public void putShort(short s) {
357            BufferByteArray.this.putShort(index, s);
358            index += 2;
359        }
360
361        /**
362         * {@inheritDoc}
363         */
364        public int getInt() {
365            int i = BufferByteArray.this.getInt(index);
366            index += 4;
367            return i;
368        }
369
370        /**
371         * {@inheritDoc}
372         */
373        public void putInt(int i) {
374            BufferByteArray.this.putInt(index, i);
375            index += 4;
376        }
377
378        /**
379         * {@inheritDoc}
380         */
381        public long getLong() {
382            long l = BufferByteArray.this.getLong(index);
383            index += 8;
384            return l;
385        }
386
387        /**
388         * {@inheritDoc}
389         */
390        public void putLong(long l) {
391            BufferByteArray.this.putLong(index, l);
392            index += 8;
393        }
394
395        /**
396         * {@inheritDoc}
397         */
398        public float getFloat() {
399            float f = BufferByteArray.this.getFloat(index);
400            index += 4;
401            return f;
402        }
403
404        /**
405         * {@inheritDoc}
406         */
407        public void putFloat(float f) {
408            BufferByteArray.this.putFloat(index, f);
409            index += 4;
410        }
411
412        /**
413         * {@inheritDoc}
414         */
415        public double getDouble() {
416            double d = BufferByteArray.this.getDouble(index);
417            index += 8;
418            return d;
419        }
420
421        /**
422         * {@inheritDoc}
423         */
424        public void putDouble(double d) {
425            BufferByteArray.this.putDouble(index, d);
426            index += 8;
427        }
428
429        /**
430         * {@inheritDoc}
431         */
432        public char getChar() {
433            char c = BufferByteArray.this.getChar(index);
434            index += 2;
435            return c;
436        }
437
438        /**
439         * {@inheritDoc}
440         */
441        public void putChar(char c) {
442            BufferByteArray.this.putChar(index, c);
443            index += 2;
444        }
445    }
446}