001    /* ByteBuffer.java -- 
002       Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
003    
004    This file is part of GNU Classpath.
005    
006    GNU Classpath is free software; you can redistribute it and/or modify
007    it under the terms of the GNU General Public License as published by
008    the Free Software Foundation; either version 2, or (at your option)
009    any later version.
010    
011    GNU Classpath is distributed in the hope that it will be useful, but
012    WITHOUT ANY WARRANTY; without even the implied warranty of
013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014    General Public License for more details.
015    
016    You should have received a copy of the GNU General Public License
017    along with GNU Classpath; see the file COPYING.  If not, write to the
018    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019    02110-1301 USA.
020    
021    Linking this library statically or dynamically with other modules is
022    making a combined work based on this library.  Thus, the terms and
023    conditions of the GNU General Public License cover the whole
024    combination.
025    
026    As a special exception, the copyright holders of this library give you
027    permission to link this library with independent modules to produce an
028    executable, regardless of the license terms of these independent
029    modules, and to copy and distribute the resulting executable under
030    terms of your choice, provided that you also meet, for each linked
031    independent module, the terms and conditions of the license of that
032    module.  An independent module is a module which is not derived from
033    or based on this library.  If you modify this library, you may extend
034    this exception to your version of the library, but you are not
035    obligated to do so.  If you do not wish to do so, delete this
036    exception statement from your version. */
037    
038    
039    package java.nio;
040    
041    /**
042     * @since 1.4
043     */
044    public abstract class ByteBuffer extends Buffer
045      implements Comparable<ByteBuffer>
046    {
047      ByteOrder endian = ByteOrder.BIG_ENDIAN;
048    
049      int array_offset;
050      byte[] backing_buffer;
051    
052      ByteBuffer (int capacity, int limit, int position, int mark)
053      {
054        super (capacity, limit, position, mark);
055      }
056    
057      /**
058       * Allocates a new direct byte buffer.
059       */ 
060      public static ByteBuffer allocateDirect (int capacity)
061      {
062        return DirectByteBufferImpl.allocate (capacity);
063      }
064    
065      /**
066       * Allocates a new <code>ByteBuffer</code> object with a given capacity.
067       */
068      public static ByteBuffer allocate (int capacity)
069      {
070        return wrap(new byte[capacity], 0, capacity);
071      }
072    
073      /**
074       * Wraps a <code>byte</code> array into a <code>ByteBuffer</code>
075       * object.
076       *
077       * @exception IndexOutOfBoundsException If the preconditions on the offset
078       * and length parameters do not hold
079       */
080      public static final ByteBuffer wrap (byte[] array, int offset, int length)
081      {
082        // FIXME: In GCJ and other implementations where arrays may not
083        // move we might consider, at least when offset==0:
084        // return new DirectByteBufferImpl(array,
085        //                                 address_of_data(array) + offset,
086        //                                 length, length, 0, false);
087        // This may be more efficient, mainly because we can then use the
088        // same logic for all ByteBuffers.
089    
090        return new ByteBufferImpl (array, 0, array.length, offset + length, offset, -1, false);
091      }
092    
093      /**
094       * Wraps a <code>byte</code> array into a <code>ByteBuffer</code>
095       * object.
096       */
097      public static final ByteBuffer wrap (byte[] array)
098      {
099        return wrap (array, 0, array.length);
100      }
101      
102      /**
103       * This method transfers <code>byte</code>s from this buffer into the given
104       * destination array. Before the transfer, it checks if there are fewer than
105       * length <code>byte</code>s remaining in this buffer.
106       *
107       * @param dst The destination array
108       * @param offset The offset within the array of the first <code>byte</code>
109       * to be written; must be non-negative and no larger than dst.length.
110       * @param length The maximum number of bytes to be written to the given array;
111       * must be non-negative and no larger than dst.length - offset.
112       *
113       * @exception BufferUnderflowException If there are fewer than length
114       * <code>byte</code>s remaining in this buffer.
115       * @exception IndexOutOfBoundsException If the preconditions on the offset
116       * and length parameters do not hold.
117       */
118      public ByteBuffer get (byte[] dst, int offset, int length)
119      {
120        checkArraySize(dst.length, offset, length);
121        checkForUnderflow(length);
122    
123        for (int i = offset; i < offset + length; i++)
124          {
125            dst [i] = get ();
126          }
127    
128        return this;
129      }
130    
131      /**
132       * This method transfers <code>byte</code>s from this buffer into the given
133       * destination array.
134       *
135       * @param dst The byte array to write into.
136       *
137       * @exception BufferUnderflowException If there are fewer than dst.length
138       * <code>byte</code>s remaining in this buffer.
139       */
140      public ByteBuffer get (byte[] dst)
141      {
142        return get (dst, 0, dst.length);
143      }
144    
145      /**
146       * Writes the content of the the <code>ByteBUFFER</code> src
147       * into the buffer. Before the transfer, it checks if there is fewer than
148       * <code>src.remaining()</code> space remaining in this buffer.
149       *
150       * @param src The source data.
151       *
152       * @exception BufferOverflowException If there is insufficient space in this
153       * buffer for the remaining <code>byte</code>s in the source buffer.
154       * @exception IllegalArgumentException If the source buffer is this buffer.
155       * @exception ReadOnlyBufferException If this buffer is read-only.
156       */
157      public ByteBuffer put (ByteBuffer src)
158      {
159        if (src == this)
160          throw new IllegalArgumentException ();
161    
162        checkForOverflow(src.remaining());
163    
164        if (src.remaining () > 0)
165          {
166            byte[] toPut = new byte [src.remaining ()];
167            src.get (toPut);
168            put (toPut);
169          }
170    
171        return this;
172      }
173    
174      /**
175       * Writes the content of the the <code>byte array</code> src
176       * into the buffer. Before the transfer, it checks if there is fewer than
177       * length space remaining in this buffer.
178       *
179       * @param src The array to copy into the buffer.
180       * @param offset The offset within the array of the first byte to be read;
181       * must be non-negative and no larger than src.length.
182       * @param length The number of bytes to be read from the given array;
183       * must be non-negative and no larger than src.length - offset.
184       * 
185       * @exception BufferOverflowException If there is insufficient space in this
186       * buffer for the remaining <code>byte</code>s in the source array.
187       * @exception IndexOutOfBoundsException If the preconditions on the offset
188       * and length parameters do not hold
189       * @exception ReadOnlyBufferException If this buffer is read-only.
190       */
191      public ByteBuffer put (byte[] src, int offset, int length)
192      {
193        checkArraySize(src.length, offset, length);
194        checkForOverflow(length);
195    
196        for (int i = offset; i < offset + length; i++)
197          put (src [i]);
198    
199        return this;
200      }
201    
202      /**
203       * Writes the content of the the <code>byte array</code> src
204       * into the buffer.
205       *
206       * @param src The array to copy into the buffer.
207       * 
208       * @exception BufferOverflowException If there is insufficient space in this
209       * buffer for the remaining <code>byte</code>s in the source array.
210       * @exception ReadOnlyBufferException If this buffer is read-only.
211       */
212      public final ByteBuffer put (byte[] src)
213      {
214        return put (src, 0, src.length);
215      }
216    
217      /**
218       * Tells whether ot not this buffer is backed by an accessible
219       * <code>byte</code> array.
220       */
221      public final boolean hasArray ()
222      {
223        return (backing_buffer != null
224                && !isReadOnly ());
225      }
226    
227      /**
228       * Returns the <code>byte</code> array that backs this buffer.
229       *
230       * @exception ReadOnlyBufferException If this buffer is read-only.
231       * @exception UnsupportedOperationException If this buffer is not backed
232       * by an accessible array.
233       */
234      public final byte[] array ()
235      {
236        if (backing_buffer == null)
237          throw new UnsupportedOperationException ();
238    
239        checkIfReadOnly();
240        
241        return backing_buffer;
242      }
243    
244      /**
245       * Returns the offset within this buffer's backing array of the first element.
246       *
247       * @exception ReadOnlyBufferException If this buffer is read-only.
248       * @exception UnsupportedOperationException If this buffer is not backed
249       * by an accessible array.
250       */
251      public final int arrayOffset ()
252      {
253        if (backing_buffer == null)
254          throw new UnsupportedOperationException ();
255    
256        checkIfReadOnly();
257        
258        return array_offset;
259      }
260    
261      /**
262       * Calculates a hash code for this buffer.
263       *
264       * This is done with <code>int</code> arithmetic,
265       * where ** represents exponentiation, by this formula:<br>
266       * <code>s[position()] + 31 + (s[position()+1] + 30)*31**1 + ... +
267       * (s[limit()-1]+30)*31**(limit()-1)</code>.
268       * Where s is the buffer data. Note that the hashcode is dependent
269       * on buffer content, and therefore is not useful if the buffer
270       * content may change.
271       *
272       * @return the hash code
273       */
274      public int hashCode ()
275      {
276        int hashCode = get(position()) + 31;
277        int multiplier = 1;
278        for (int i = position() + 1; i < limit(); ++i)
279          {
280              multiplier *= 31;
281              hashCode += (get(i) + 30)*multiplier;
282          }
283        return hashCode;
284      }
285    
286      /**
287       * Checks if this buffer is equal to obj.
288       */
289      public boolean equals (Object obj)
290      {
291        if (obj instanceof ByteBuffer)
292          {
293            return compareTo ((ByteBuffer) obj) == 0;
294          }
295    
296        return false;
297      }
298    
299      /**
300       * Compares two <code>ByteBuffer</code> objects.
301       *
302       * @exception ClassCastException If obj is not an object derived from
303       * <code>ByteBuffer</code>.
304       */
305      public int compareTo (ByteBuffer other)
306      {
307        int num = Math.min(remaining(), other.remaining());
308        int pos_this = position();
309        int pos_other = other.position();
310        
311        for (int count = 0; count < num; count++)
312          {
313            byte a = get(pos_this++);
314            byte b = other.get(pos_other++);
315             
316            if (a == b)
317              continue;
318               
319            if (a < b)
320              return -1;
321               
322            return 1;
323          }
324          
325        return remaining() - other.remaining();
326      }
327    
328      /**
329       * Returns the byte order of this buffer.
330       */  
331      public final ByteOrder order ()
332      {
333        return endian;
334      }
335      
336      /**
337       * Modifies this buffer's byte order.
338       */
339      public final ByteBuffer order (ByteOrder endian)
340      {
341        this.endian = endian;
342        return this;
343      }
344      
345      /**
346       * Reads the <code>byte</code> at this buffer's current position,
347       * and then increments the position.
348       *
349       * @exception BufferUnderflowException If there are no remaining
350       * <code>byte</code>s in this buffer.
351       */
352      public abstract byte get ();
353    
354      /**
355       * Writes the <code>byte</code> at this buffer's current position,
356       * and then increments the position.
357       *
358       * @exception BufferOverflowException If there no remaining 
359       * <code>byte</code>s in this buffer.
360       * @exception ReadOnlyBufferException If this buffer is read-only.
361       */
362      public abstract ByteBuffer put (byte b);
363    
364      /**
365       * Absolute get method.
366       *
367       * @exception IndexOutOfBoundsException If index is negative or not smaller
368       * than the buffer's limit.
369       */
370      public abstract byte get (int index);
371      
372      /**
373       * Absolute put method.
374       *
375       * @exception IndexOutOfBoundsException If index is negative or not smaller
376       * than the buffer's limit.
377       * @exception ReadOnlyBufferException If this buffer is read-only.
378       */
379      public abstract ByteBuffer put (int index, byte b);
380    
381      /**
382       * Compacts this buffer.
383       * 
384       * @exception ReadOnlyBufferException If this buffer is read-only.
385       */
386      public abstract ByteBuffer compact ();
387    
388      void shiftDown (int dst_offset, int src_offset, int count)
389      {
390        for (int i = 0; i < count; i++)
391          put(dst_offset + i, get(src_offset + i));
392      }
393    
394      /**
395       * Tells whether or not this buffer is direct.
396       */
397      public abstract boolean isDirect ();
398    
399      /**
400       * Creates a new <code>ByteBuffer</code> whose content is a shared
401       * subsequence of this buffer's content.
402       */
403      public abstract ByteBuffer slice ();
404    
405      /**
406       * Creates a new <code>ByteBuffer</code> that shares this buffer's
407       * content.
408       */
409      public abstract ByteBuffer duplicate ();
410    
411      /**
412       * Creates a new read-only <code>ByteBuffer</code> that shares this
413       * buffer's content.
414       */
415      public abstract ByteBuffer asReadOnlyBuffer ();
416     
417      /**
418       * Creates a view of this byte buffer as a short buffer.
419       */
420      public abstract ShortBuffer asShortBuffer ();
421      
422      /**
423       * Creates a view of this byte buffer as a char buffer.
424       */
425      public abstract CharBuffer asCharBuffer ();
426      
427      /**
428       * Creates a view of this byte buffer as an integer buffer.
429       */
430      public abstract IntBuffer asIntBuffer ();
431      
432      /**
433       * Creates a view of this byte buffer as a long buffer.
434       */
435      public abstract LongBuffer asLongBuffer ();
436      
437      /**
438       * Creates a view of this byte buffer as a float buffer.
439       */
440      public abstract FloatBuffer asFloatBuffer ();
441      
442      /**
443       * Creates a view of this byte buffer as a double buffer.
444       */
445      public abstract DoubleBuffer asDoubleBuffer ();
446    
447      /**
448       * Relative get method for reading a character value.
449       *
450       * @exception BufferUnderflowException  If there are fewer than two bytes
451       * remaining in this buffer.
452       */
453      public abstract char getChar ();
454      
455      /**
456       * Relative put method for writing a character value.
457       *
458       * @exception BufferOverflowException If this buffer's current position is
459       * not smaller than its limit.
460       */
461      public abstract ByteBuffer putChar (char value);
462      
463      /**
464       * Absolute get method for reading a character value.
465       *
466       * @exception IndexOutOfBoundsException If there are fewer than two bytes
467       * remaining in this buffer
468       */
469      public abstract char getChar (int index);
470      
471      /**
472       * Absolute put method for writing a character value.
473       *
474       * @exception IndexOutOfBoundsException If index is negative or not smaller
475       * than the buffer's limit, minus one.
476       */
477      public abstract ByteBuffer putChar (int index, char value);
478      
479      /**
480       * Relative get method for reading a short value.
481       *
482       * @exception BufferUnderflowException If index is negative or not smaller
483       * than the buffer's limit, minus one.
484       */
485      public abstract short getShort ();
486      
487      /**
488       * Relative put method for writing a short value.
489       *
490       * @exception BufferOverflowException If this buffer's current position is
491       * not smaller than its limit.
492       */
493      public abstract ByteBuffer putShort (short value);
494      
495      /**
496       * Absolute get method for reading a short value.
497       *
498       * @exception IndexOutOfBoundsException If there are fewer than two bytes
499       * remaining in this buffer
500       */
501      public abstract short getShort (int index);
502     
503      /**
504       * Absolute put method for writing a short value.
505       *
506       * @exception IndexOutOfBoundsException If index is negative or not smaller
507       * than the buffer's limit, minus one.
508       */
509      public abstract ByteBuffer putShort (int index, short value);
510      
511      /**
512       * Relative get method for reading an integer value.
513       *
514       * @exception BufferUnderflowException If there are fewer than four bytes
515       * remaining in this buffer.
516       */
517      public abstract int getInt ();
518      
519      /**
520       * Relative put method for writing an integer value.
521       *
522       * @exception BufferOverflowException If this buffer's current position is
523       * not smaller than its limit.
524       */
525      public abstract ByteBuffer putInt (int value);
526      
527      /**
528       * Absolute get method for reading an integer value.
529       *
530       * @exception IndexOutOfBoundsException If index is negative or not smaller
531       * than the buffer's limit, minus three.
532       */
533      public abstract int getInt (int index);
534      
535      /**
536       * Absolute put method for writing an integer value.
537       *
538       * @exception IndexOutOfBoundsException If index is negative or not smaller
539       * than the buffer's limit, minus three.
540       */
541      public abstract ByteBuffer putInt (int index, int value);
542      
543      /**
544       * Relative get method for reading a long value.
545       *
546       * @exception BufferUnderflowException If there are fewer than eight bytes
547       * remaining in this buffer.
548       */
549      public abstract long getLong ();
550      
551      /**
552       * Relative put method for writing a long value.
553       *
554       * @exception BufferOverflowException If this buffer's current position is
555       * not smaller than its limit.
556       */
557      public abstract ByteBuffer putLong (long value);
558      
559      /**
560       * Absolute get method for reading a long value.
561       *
562       * @exception IndexOutOfBoundsException If index is negative or not smaller
563       * than the buffer's limit, minus seven.
564       */
565      public abstract long getLong (int index);
566      
567      /**
568       * Absolute put method for writing a float value.
569       *
570       * @exception IndexOutOfBoundsException If index is negative or not smaller
571       * than the buffer's limit, minus seven.
572       */
573      public abstract ByteBuffer putLong (int index, long value);
574      
575      /**
576       * Relative get method for reading a float value.
577       *
578       * @exception BufferUnderflowException If there are fewer than four bytes
579       * remaining in this buffer.
580       */
581      public abstract float getFloat ();
582      
583      /**
584       * Relative put method for writing a float value.
585       *
586       * @exception BufferOverflowException If there are fewer than four bytes
587       * remaining in this buffer.
588       */
589      public abstract ByteBuffer putFloat (float value);
590      
591      /**
592       * Absolute get method for reading a float value.
593       *
594       * @exception IndexOutOfBoundsException If index is negative or not smaller
595       * than the buffer's limit, minus three.
596       */
597      public abstract float getFloat (int index);
598      
599      /**
600       * Relative put method for writing a float value.
601       *
602       * @exception IndexOutOfBoundsException If index is negative or not smaller
603       * than the buffer's limit, minus three.
604       */
605      public abstract ByteBuffer putFloat (int index, float value);
606      
607      /**
608       * Relative get method for reading a double value.
609       *
610       * @exception BufferUnderflowException If there are fewer than eight bytes
611       * remaining in this buffer.
612       */
613      public abstract double getDouble ();
614      
615      /**
616       * Relative put method for writing a double value.
617       *
618       * @exception BufferOverflowException If this buffer's current position is
619       * not smaller than its limit.
620       */
621      public abstract ByteBuffer putDouble (double value);
622      
623      /**
624       * Absolute get method for reading a double value.
625       *
626       * @exception IndexOutOfBoundsException If index is negative or not smaller
627       * than the buffer's limit, minus seven.
628       */
629      public abstract double getDouble (int index);
630      
631      /**
632       * Absolute put method for writing a double value.
633       *
634       * @exception IndexOutOfBoundsException If index is negative or not smaller
635       * than the buffer's limit, minus seven.
636       */
637      public abstract ByteBuffer putDouble (int index, double value);
638    
639      /**
640       * Returns a string summarizing the state of this buffer.
641       */
642      public String toString ()
643      {
644        return getClass ().getName () +
645                "[pos=" + position () +
646                " lim=" + limit () +
647                " cap=" + capacity () + "]";
648      }
649    }