Save This Page
Home » openjdk-7 » java » nio » [javadoc | source]
    1   /*
    2    * Copyright 2000-2007 Sun Microsystems, Inc.  All Rights Reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Sun designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Sun in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22    * CA 95054 USA or visit www.sun.com if you need additional information or
   23    * have any questions.
   24    */
   25   
   26   package java.nio;
   27   
   28   
   29   /**
   30    * A container for data of a specific primitive type.
   31    *
   32    * <p> A buffer is a linear, finite sequence of elements of a specific
   33    * primitive type.  Aside from its content, the essential properties of a
   34    * buffer are its capacity, limit, and position: </p>
   35    *
   36    * <blockquote>
   37    *
   38    *   <p> A buffer's <i>capacity</i> is the number of elements it contains.  The
   39    *   capacity of a buffer is never negative and never changes.  </p>
   40    *
   41    *   <p> A buffer's <i>limit</i> is the index of the first element that should
   42    *   not be read or written.  A buffer's limit is never negative and is never
   43    *   greater than its capacity.  </p>
   44    *
   45    *   <p> A buffer's <i>position</i> is the index of the next element to be
   46    *   read or written.  A buffer's position is never negative and is never
   47    *   greater than its limit.  </p>
   48    *
   49    * </blockquote>
   50    *
   51    * <p> There is one subclass of this class for each non-boolean primitive type.
   52    *
   53    *
   54    * <h4> Transferring data </h4>
   55    *
   56    * <p> Each subclass of this class defines two categories of <i>get</i> and
   57    * <i>put</i> operations: </p>
   58    *
   59    * <blockquote>
   60    *
   61    *   <p> <i>Relative</i> operations read or write one or more elements starting
   62    *   at the current position and then increment the position by the number of
   63    *   elements transferred.  If the requested transfer exceeds the limit then a
   64    *   relative <i>get</i> operation throws a {@link BufferUnderflowException}
   65    *   and a relative <i>put</i> operation throws a {@link
   66    *   BufferOverflowException}; in either case, no data is transferred.  </p>
   67    *
   68    *   <p> <i>Absolute</i> operations take an explicit element index and do not
   69    *   affect the position.  Absolute <i>get</i> and <i>put</i> operations throw
   70    *   an {@link IndexOutOfBoundsException} if the index argument exceeds the
   71    *   limit.  </p>
   72    *
   73    * </blockquote>
   74    *
   75    * <p> Data may also, of course, be transferred in to or out of a buffer by the
   76    * I/O operations of an appropriate channel, which are always relative to the
   77    * current position.
   78    *
   79    *
   80    * <h4> Marking and resetting </h4>
   81    *
   82    * <p> A buffer's <i>mark</i> is the index to which its position will be reset
   83    * when the {@link #reset reset} method is invoked.  The mark is not always
   84    * defined, but when it is defined it is never negative and is never greater
   85    * than the position.  If the mark is defined then it is discarded when the
   86    * position or the limit is adjusted to a value smaller than the mark.  If the
   87    * mark is not defined then invoking the {@link #reset reset} method causes an
   88    * {@link InvalidMarkException} to be thrown.
   89    *
   90    *
   91    * <h4> Invariants </h4>
   92    *
   93    * <p> The following invariant holds for the mark, position, limit, and
   94    * capacity values:
   95    *
   96    * <blockquote>
   97    *     <tt>0</tt> <tt>&lt;=</tt>
   98    *     <i>mark</i> <tt>&lt;=</tt>
   99    *     <i>position</i> <tt>&lt;=</tt>
  100    *     <i>limit</i> <tt>&lt;=</tt>
  101    *     <i>capacity</i>
  102    * </blockquote>
  103    *
  104    * <p> A newly-created buffer always has a position of zero and a mark that is
  105    * undefined.  The initial limit may be zero, or it may be some other value
  106    * that depends upon the type of the buffer and the manner in which it is
  107    * constructed.  Each element of a newly-allocated buffer is initialized
  108    * to zero.
  109    *
  110    *
  111    * <h4> Clearing, flipping, and rewinding </h4>
  112    *
  113    * <p> In addition to methods for accessing the position, limit, and capacity
  114    * values and for marking and resetting, this class also defines the following
  115    * operations upon buffers:
  116    *
  117    * <ul>
  118    *
  119    *   <li><p> {@link #clear} makes a buffer ready for a new sequence of
  120    *   channel-read or relative <i>put</i> operations: It sets the limit to the
  121    *   capacity and the position to zero.  </p></li>
  122    *
  123    *   <li><p> {@link #flip} makes a buffer ready for a new sequence of
  124    *   channel-write or relative <i>get</i> operations: It sets the limit to the
  125    *   current position and then sets the position to zero.  </p></li>
  126    *
  127    *   <li><p> {@link #rewind} makes a buffer ready for re-reading the data that
  128    *   it already contains: It leaves the limit unchanged and sets the position
  129    *   to zero.  </p></li>
  130    *
  131    * </ul>
  132    *
  133    *
  134    * <h4> Read-only buffers </h4>
  135    *
  136    * <p> Every buffer is readable, but not every buffer is writable.  The
  137    * mutation methods of each buffer class are specified as <i>optional
  138    * operations</i> that will throw a {@link ReadOnlyBufferException} when
  139    * invoked upon a read-only buffer.  A read-only buffer does not allow its
  140    * content to be changed, but its mark, position, and limit values are mutable.
  141    * Whether or not a buffer is read-only may be determined by invoking its
  142    * {@link #isReadOnly isReadOnly} method.
  143    *
  144    *
  145    * <h4> Thread safety </h4>
  146    *
  147    * <p> Buffers are not safe for use by multiple concurrent threads.  If a
  148    * buffer is to be used by more than one thread then access to the buffer
  149    * should be controlled by appropriate synchronization.
  150    *
  151    *
  152    * <h4> Invocation chaining </h4>
  153    *
  154    * <p> Methods in this class that do not otherwise have a value to return are
  155    * specified to return the buffer upon which they are invoked.  This allows
  156    * method invocations to be chained; for example, the sequence of statements
  157    *
  158    * <blockquote><pre>
  159    * b.flip();
  160    * b.position(23);
  161    * b.limit(42);</pre></blockquote>
  162    *
  163    * can be replaced by the single, more compact statement
  164    *
  165    * <blockquote><pre>
  166    * b.flip().position(23).limit(42);</pre></blockquote>
  167    *
  168    *
  169    * @author Mark Reinhold
  170    * @author JSR-51 Expert Group
  171    * @since 1.4
  172    */
  173   
  174   public abstract class Buffer {
  175   
  176       // Invariants: mark <= position <= limit <= capacity
  177       private int mark = -1;
  178       private int position = 0;
  179       private int limit;
  180       private int capacity;
  181   
  182       // Used only by direct buffers
  183       // NOTE: hoisted here for speed in JNI GetDirectBufferAddress
  184       long address;
  185   
  186       // Creates a new buffer with the given mark, position, limit, and capacity,
  187       // after checking invariants.
  188       //
  189       Buffer(int mark, int pos, int lim, int cap) {       // package-private
  190           if (cap < 0)
  191               throw new IllegalArgumentException("Negative capacity: " + cap);
  192           this.capacity = cap;
  193           limit(lim);
  194           position(pos);
  195           if (mark >= 0) {
  196               if (mark > pos)
  197                   throw new IllegalArgumentException("mark > position: ("
  198                                                      + mark + " > " + pos + ")");
  199               this.mark = mark;
  200           }
  201       }
  202   
  203       /**
  204        * Returns this buffer's capacity. </p>
  205        *
  206        * @return  The capacity of this buffer
  207        */
  208       public final int capacity() {
  209           return capacity;
  210       }
  211   
  212       /**
  213        * Returns this buffer's position. </p>
  214        *
  215        * @return  The position of this buffer
  216        */
  217       public final int position() {
  218           return position;
  219       }
  220   
  221       /**
  222        * Sets this buffer's position.  If the mark is defined and larger than the
  223        * new position then it is discarded. </p>
  224        *
  225        * @param  newPosition
  226        *         The new position value; must be non-negative
  227        *         and no larger than the current limit
  228        *
  229        * @return  This buffer
  230        *
  231        * @throws  IllegalArgumentException
  232        *          If the preconditions on <tt>newPosition</tt> do not hold
  233        */
  234       public final Buffer position(int newPosition) {
  235           if ((newPosition > limit) || (newPosition < 0))
  236               throw new IllegalArgumentException();
  237           position = newPosition;
  238           if (mark > position) mark = -1;
  239           return this;
  240       }
  241   
  242       /**
  243        * Returns this buffer's limit. </p>
  244        *
  245        * @return  The limit of this buffer
  246        */
  247       public final int limit() {
  248           return limit;
  249       }
  250   
  251       /**
  252        * Sets this buffer's limit.  If the position is larger than the new limit
  253        * then it is set to the new limit.  If the mark is defined and larger than
  254        * the new limit then it is discarded. </p>
  255        *
  256        * @param  newLimit
  257        *         The new limit value; must be non-negative
  258        *         and no larger than this buffer's capacity
  259        *
  260        * @return  This buffer
  261        *
  262        * @throws  IllegalArgumentException
  263        *          If the preconditions on <tt>newLimit</tt> do not hold
  264        */
  265       public final Buffer limit(int newLimit) {
  266           if ((newLimit > capacity) || (newLimit < 0))
  267               throw new IllegalArgumentException();
  268           limit = newLimit;
  269           if (position > limit) position = limit;
  270           if (mark > limit) mark = -1;
  271           return this;
  272       }
  273   
  274       /**
  275        * Sets this buffer's mark at its position. </p>
  276        *
  277        * @return  This buffer
  278        */
  279       public final Buffer mark() {
  280           mark = position;
  281           return this;
  282       }
  283   
  284       /**
  285        * Resets this buffer's position to the previously-marked position.
  286        *
  287        * <p> Invoking this method neither changes nor discards the mark's
  288        * value. </p>
  289        *
  290        * @return  This buffer
  291        *
  292        * @throws  InvalidMarkException
  293        *          If the mark has not been set
  294        */
  295       public final Buffer reset() {
  296           int m = mark;
  297           if (m < 0)
  298               throw new InvalidMarkException();
  299           position = m;
  300           return this;
  301       }
  302   
  303       /**
  304        * Clears this buffer.  The position is set to zero, the limit is set to
  305        * the capacity, and the mark is discarded.
  306        *
  307        * <p> Invoke this method before using a sequence of channel-read or
  308        * <i>put</i> operations to fill this buffer.  For example:
  309        *
  310        * <blockquote><pre>
  311        * buf.clear();     // Prepare buffer for reading
  312        * in.read(buf);    // Read data</pre></blockquote>
  313        *
  314        * <p> This method does not actually erase the data in the buffer, but it
  315        * is named as if it did because it will most often be used in situations
  316        * in which that might as well be the case. </p>
  317        *
  318        * @return  This buffer
  319        */
  320       public final Buffer clear() {
  321           position = 0;
  322           limit = capacity;
  323           mark = -1;
  324           return this;
  325       }
  326   
  327       /**
  328        * Flips this buffer.  The limit is set to the current position and then
  329        * the position is set to zero.  If the mark is defined then it is
  330        * discarded.
  331        *
  332        * <p> After a sequence of channel-read or <i>put</i> operations, invoke
  333        * this method to prepare for a sequence of channel-write or relative
  334        * <i>get</i> operations.  For example:
  335        *
  336        * <blockquote><pre>
  337        * buf.put(magic);    // Prepend header
  338        * in.read(buf);      // Read data into rest of buffer
  339        * buf.flip();        // Flip buffer
  340        * out.write(buf);    // Write header + data to channel</pre></blockquote>
  341        *
  342        * <p> This method is often used in conjunction with the {@link
  343        * java.nio.ByteBuffer#compact compact} method when transferring data from
  344        * one place to another.  </p>
  345        *
  346        * @return  This buffer
  347        */
  348       public final Buffer flip() {
  349           limit = position;
  350           position = 0;
  351           mark = -1;
  352           return this;
  353       }
  354   
  355       /**
  356        * Rewinds this buffer.  The position is set to zero and the mark is
  357        * discarded.
  358        *
  359        * <p> Invoke this method before a sequence of channel-write or <i>get</i>
  360        * operations, assuming that the limit has already been set
  361        * appropriately.  For example:
  362        *
  363        * <blockquote><pre>
  364        * out.write(buf);    // Write remaining data
  365        * buf.rewind();      // Rewind buffer
  366        * buf.get(array);    // Copy data into array</pre></blockquote>
  367        *
  368        * @return  This buffer
  369        */
  370       public final Buffer rewind() {
  371           position = 0;
  372           mark = -1;
  373           return this;
  374       }
  375   
  376       /**
  377        * Returns the number of elements between the current position and the
  378        * limit. </p>
  379        *
  380        * @return  The number of elements remaining in this buffer
  381        */
  382       public final int remaining() {
  383           return limit - position;
  384       }
  385   
  386       /**
  387        * Tells whether there are any elements between the current position and
  388        * the limit. </p>
  389        *
  390        * @return  <tt>true</tt> if, and only if, there is at least one element
  391        *          remaining in this buffer
  392        */
  393       public final boolean hasRemaining() {
  394           return position < limit;
  395       }
  396   
  397       /**
  398        * Tells whether or not this buffer is read-only. </p>
  399        *
  400        * @return  <tt>true</tt> if, and only if, this buffer is read-only
  401        */
  402       public abstract boolean isReadOnly();
  403   
  404       /**
  405        * Tells whether or not this buffer is backed by an accessible
  406        * array.
  407        *
  408        * <p> If this method returns <tt>true</tt> then the {@link #array() array}
  409        * and {@link #arrayOffset() arrayOffset} methods may safely be invoked.
  410        * </p>
  411        *
  412        * @return  <tt>true</tt> if, and only if, this buffer
  413        *          is backed by an array and is not read-only
  414        *
  415        * @since 1.6
  416        */
  417       public abstract boolean hasArray();
  418   
  419       /**
  420        * Returns the array that backs this
  421        * buffer&nbsp;&nbsp;<i>(optional operation)</i>.
  422        *
  423        * <p> This method is intended to allow array-backed buffers to be
  424        * passed to native code more efficiently. Concrete subclasses
  425        * provide more strongly-typed return values for this method.
  426        *
  427        * <p> Modifications to this buffer's content will cause the returned
  428        * array's content to be modified, and vice versa.
  429        *
  430        * <p> Invoke the {@link #hasArray hasArray} method before invoking this
  431        * method in order to ensure that this buffer has an accessible backing
  432        * array.  </p>
  433        *
  434        * @return  The array that backs this buffer
  435        *
  436        * @throws  ReadOnlyBufferException
  437        *          If this buffer is backed by an array but is read-only
  438        *
  439        * @throws  UnsupportedOperationException
  440        *          If this buffer is not backed by an accessible array
  441        *
  442        * @since 1.6
  443        */
  444       public abstract Object array();
  445   
  446       /**
  447        * Returns the offset within this buffer's backing array of the first
  448        * element of the buffer&nbsp;&nbsp;<i>(optional operation)</i>.
  449        *
  450        * <p> If this buffer is backed by an array then buffer position <i>p</i>
  451        * corresponds to array index <i>p</i>&nbsp;+&nbsp;<tt>arrayOffset()</tt>.
  452        *
  453        * <p> Invoke the {@link #hasArray hasArray} method before invoking this
  454        * method in order to ensure that this buffer has an accessible backing
  455        * array.  </p>
  456        *
  457        * @return  The offset within this buffer's array
  458        *          of the first element of the buffer
  459        *
  460        * @throws  ReadOnlyBufferException
  461        *          If this buffer is backed by an array but is read-only
  462        *
  463        * @throws  UnsupportedOperationException
  464        *          If this buffer is not backed by an accessible array
  465        *
  466        * @since 1.6
  467        */
  468       public abstract int arrayOffset();
  469   
  470       /**
  471        * Tells whether or not this buffer is
  472        * <a href="ByteBuffer.html#direct"><i>direct</i></a>. </p>
  473        *
  474        * @return  <tt>true</tt> if, and only if, this buffer is direct
  475        *
  476        * @since 1.6
  477        */
  478       public abstract boolean isDirect();
  479   
  480   
  481       // -- Package-private methods for bounds checking, etc. --
  482   
  483       /**
  484        * Checks the current position against the limit, throwing a {@link
  485        * BufferUnderflowException} if it is not smaller than the limit, and then
  486        * increments the position. </p>
  487        *
  488        * @return  The current position value, before it is incremented
  489        */
  490       final int nextGetIndex() {                          // package-private
  491           if (position >= limit)
  492               throw new BufferUnderflowException();
  493           return position++;
  494       }
  495   
  496       final int nextGetIndex(int nb) {                    // package-private
  497           if (limit - position < nb)
  498               throw new BufferUnderflowException();
  499           int p = position;
  500           position += nb;
  501           return p;
  502       }
  503   
  504       /**
  505        * Checks the current position against the limit, throwing a {@link
  506        * BufferOverflowException} if it is not smaller than the limit, and then
  507        * increments the position. </p>
  508        *
  509        * @return  The current position value, before it is incremented
  510        */
  511       final int nextPutIndex() {                          // package-private
  512           if (position >= limit)
  513               throw new BufferOverflowException();
  514           return position++;
  515       }
  516   
  517       final int nextPutIndex(int nb) {                    // package-private
  518           if (limit - position < nb)
  519               throw new BufferOverflowException();
  520           int p = position;
  521           position += nb;
  522           return p;
  523       }
  524   
  525       /**
  526        * Checks the given index against the limit, throwing an {@link
  527        * IndexOutOfBoundsException} if it is not smaller than the limit
  528        * or is smaller than zero.
  529        */
  530       final int checkIndex(int i) {                       // package-private
  531           if ((i < 0) || (i >= limit))
  532               throw new IndexOutOfBoundsException();
  533           return i;
  534       }
  535   
  536       final int checkIndex(int i, int nb) {               // package-private
  537           if ((i < 0) || (nb > limit - i))
  538               throw new IndexOutOfBoundsException();
  539           return i;
  540       }
  541   
  542       final int markValue() {                             // package-private
  543           return mark;
  544       }
  545   
  546       static void checkBounds(int off, int len, int size) { // package-private
  547           if ((off | len | (off + len) | (size - (off + len))) < 0)
  548               throw new IndexOutOfBoundsException();
  549       }
  550   
  551   }

Save This Page
Home » openjdk-7 » java » nio » [javadoc | source]