View Javadoc
1   //******************************************************************************
2   //
3   // File:    ByteBuf.java
4   // Package: edu.rit.mp
5   // Unit:    Class edu.rit.mp.ByteBuf
6   //
7   // This Java source file is copyright (C) 2007 by Alan Kaminsky. All rights
8   // reserved. For further information, contact the author, Alan Kaminsky, at
9   // ark@cs.rit.edu.
10  //
11  // This Java source file is part of the Parallel Java Library ("PJ"). PJ is free
12  // software; you can redistribute it and/or modify it under the terms of the GNU
13  // General Public License as published by the Free Software Foundation; either
14  // version 3 of the License, or (at your option) any later version.
15  //
16  // PJ is distributed in the hope that it will be useful, but WITHOUT ANY
17  // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
18  // A PARTICULAR PURPOSE. See the GNU General Public License for more details.
19  //
20  // Linking this library statically or dynamically with other modules is making a
21  // combined work based on this library. Thus, the terms and conditions of the GNU
22  // General Public License cover the whole combination.
23  //
24  // As a special exception, the copyright holders of this library give you
25  // permission to link this library with independent modules to produce an
26  // executable, regardless of the license terms of these independent modules, and
27  // to copy and distribute the resulting executable under terms of your choice,
28  // provided that you also meet, for each linked independent module, the terms
29  // and conditions of the license of that module. An independent module is a module
30  // which is not derived from or based on this library. If you modify this library,
31  // you may extend this exception to your version of the library, but you are not
32  // obligated to do so. If you do not wish to do so, delete this exception
33  // statement from your version.
34  //
35  // A copy of the GNU General Public License is provided in the file gpl.txt. You
36  // may also obtain a copy of the GNU General Public License on the World Wide
37  // Web at http://www.gnu.org/licenses/gpl.html.
38  //
39  //******************************************************************************
40  package edu.rit.mp;
41  
42  import java.nio.ByteBuffer;
43  
44  import edu.rit.mp.buf.ByteArrayBuf;
45  import edu.rit.mp.buf.ByteArrayBuf_1;
46  import edu.rit.mp.buf.ByteItemBuf;
47  import edu.rit.mp.buf.ByteMatrixBuf;
48  import edu.rit.mp.buf.ByteMatrixBuf_1;
49  import edu.rit.mp.buf.EmptyByteBuf;
50  import edu.rit.mp.buf.SharedByteArrayBuf;
51  import edu.rit.mp.buf.SharedByteArrayBuf_1;
52  import edu.rit.mp.buf.SharedByteBuf;
53  import edu.rit.pj.reduction.SharedByte;
54  import edu.rit.pj.reduction.SharedByteArray;
55  import edu.rit.util.Arrays;
56  import edu.rit.util.Range;
57  
58  /**
59   * Class ByteBuf is the abstract base class for a buffer of byte items sent or
60   * received using the Message Protocol (MP). In a message, a byte item is
61   * represented as one byte.
62   * <P>
63   * A buffer may be used to send one or more messages at the same time in
64   * multiple threads. If a buffer is being used to send a message or messages,
65   * the buffer must not be used to receive a message at the same time.
66   * <P>
67   * A buffer may be used to receive one message at a time. If a buffer is being
68   * used to receive a message, the buffer must not be used to receive another
69   * message in a different thread, and the buffer must not be used to send a
70   * message or messages.
71   * <P>
72   * A buffer is a conduit for retrieving and storing data in some underlying data
73   * structure. If the underlying data structure is multiple thread safe, then one
74   * thread can be retrieving or storing data via the buffer at the same time as
75   * other threads are accessing the data structure. If the underlying data
76   * structure is not multiple thread safe, then other threads must not access the
77   * data structure while one thread is retrieving or storing data via the buffer.
78   * <P>
79   * To create a ByteBuf, call one of the following static factory methods:
80   * <UL>
81   * <LI><code>emptyBuffer()</code>
82   * <LI><code>buffer()</code>
83   * <LI><code>buffer (byte)</code>
84   * <LI><code>buffer (byte[])</code>
85   * <LI><code>sliceBuffer (byte[], Range)</code>
86   * <LI><code>sliceBuffers (byte[], Range[])</code>
87   * <LI><code>buffer (byte[][])</code>
88   * <LI><code>rowSliceBuffer (byte[][], Range)</code>
89   * <LI><code>rowSliceBuffers (byte[][], Range[])</code>
90   * <LI><code>colSliceBuffer (byte[][], Range)</code>
91   * <LI><code>colSliceBuffers (byte[][], Range[])</code>
92   * <LI><code>patchBuffer (byte[][], Range, Range)</code>
93   * <LI><code>patchBuffers (byte[][], Range[], Range[])</code>
94   * <LI><code>buffer (SharedByte)</code>
95   * <LI><code>buffer (SharedByteArray)</code>
96   * <LI><code>sliceBuffer (SharedByteArray, Range)</code>
97   * <LI><code>sliceBuffers (SharedByteArray, Range[])</code>
98   * </UL>
99   *
100  * @author Alan Kaminsky
101  * @version 03-May-2008
102  */
103 public abstract class ByteBuf
104         extends Buf {
105 
106 // Hidden constructors.
107     /**
108      * Construct a new byte buffer.
109      *
110      * @param theLength Number of items.
111      * @exception IllegalArgumentException (unchecked exception) Thrown if
112      * <code>theLength</code> &lt; 0.
113      */
114     protected ByteBuf(int theLength) {
115         super(Constants.TYPE_BOOLEAN, theLength);
116     }
117 
118 // Exported operations.
119     /**
120      * Create an empty buffer. The buffer's length is 0. The buffer's item type
121      * is byte.
122      *
123      * @return Empty buffer.
124      */
125     public static ByteBuf emptyBuffer() {
126         return new EmptyByteBuf();
127     }
128 
129     /**
130      * Create a buffer for a byte item. The item is stored in the <code>item</code>
131      * field of the buffer.
132      *
133      * @return Buffer.
134      */
135     public static ByteItemBuf buffer() {
136         return new ByteItemBuf();
137     }
138 
139     /**
140      * Create a buffer for a byte item with the given initial value. The item is
141      * stored in the <code>item</code> field of the buffer.
142      *
143      * @param item Initial value of the <code>item</code> field.
144      * @return Buffer.
145      */
146     public static ByteItemBuf buffer(byte item) {
147         return new ByteItemBuf(item);
148     }
149 
150     /**
151      * Create a buffer for the entire given byte array. The returned buffer
152      * encompasses all the elements in <code>theArray</code>.
153      *
154      * @param theArray Array.
155      * @return Buffer.
156      * @exception NullPointerException (unchecked exception) Thrown if
157      * <code>theArray</code> is null.
158      */
159     public static ByteBuf buffer(byte[] theArray) {
160         if (theArray == null) {
161             throw new NullPointerException("ByteBuf.buffer(): theArray is null");
162         }
163         int nr = Arrays.length(theArray);
164         return new ByteArrayBuf_1(theArray, new Range(0, nr - 1));
165     }
166 
167     /**
168      * Create a buffer for one slice of the given byte array. The returned
169      * buffer encompasses <code>theRange</code> of elements in <code>theArray</code>.
170      * The range's stride may be 1 or greater than 1.
171      *
172      * @param theArray Array.
173      * @param theRange Range of elements to include.
174      * @return Buffer.
175      * @exception NullPointerException (unchecked exception) Thrown if
176      * <code>theArray</code> is null or
177      * <code>theRange</code> is null.
178      * @exception IndexOutOfBoundsException (unchecked exception) Thrown if
179      * <code>theArray</code> does not include all the indexes in <code>theRange</code>.
180      */
181     public static ByteBuf sliceBuffer(byte[] theArray,
182             Range theRange) {
183         if (theArray == null) {
184             throw new NullPointerException("ByteBuf.sliceBuffer(): theArray is null");
185         }
186         int nr = Arrays.length(theArray);
187         if (0 > theRange.lb() || theRange.ub() >= nr) {
188             throw new IndexOutOfBoundsException("ByteBuf.sliceBuffer(): theArray index range = 0.."
189                     + (nr - 1) + ", theRange = " + theRange);
190         }
191         if (theRange.stride() == 1) {
192             return new ByteArrayBuf_1(theArray, theRange);
193         } else {
194             return new ByteArrayBuf(theArray, theRange);
195         }
196     }
197 
198     /**
199      * Create an array of buffers for multiple slices of the given byte array.
200      * The returned buffer array has the same length as <code>theRanges</code>. Each
201      * element [<I>i</I>] of the returned buffer array encompasses the elements
202      * of <code>theArray</code> specified by <code>theRanges[i]</code>. Each range's
203      * stride may be 1 or greater than 1.
204      *
205      * @param theArray Array.
206      * @param theRanges Array of ranges of elements to include.
207      * @return Array of buffers.
208      * @exception NullPointerException (unchecked exception) Thrown if
209      * <code>theArray</code> is null or
210      * <code>theRanges</code> or any element thereof is null.
211      * @exception IndexOutOfBoundsException (unchecked exception) Thrown if
212      * <code>theArray</code>'s allocation does not include any element of
213      * <code>theRanges</code>.
214      */
215     public static ByteBuf[] sliceBuffers(byte[] theArray,
216             Range[] theRanges) {
217         int n = theRanges.length;
218         ByteBuf[] result = new ByteBuf[n];
219         for (int i = 0; i < n; ++i) {
220             result[i] = sliceBuffer(theArray, theRanges[i]);
221         }
222         return result;
223     }
224 
225     /**
226      * Create a buffer for the entire given byte matrix. The returned buffer
227      * encompasses all the rows and all the columns in <code>theMatrix</code>.
228      *
229      * @param theMatrix Matrix.
230      * @return Buffer.
231      * @exception NullPointerException (unchecked exception) Thrown if
232      * <code>theMatrix</code> is null.
233      */
234     public static ByteBuf buffer(byte[][] theMatrix) {
235         if (theMatrix == null) {
236             throw new NullPointerException("ByteBuf.buffer(): theMatrix is null");
237         }
238         int nr = Arrays.rowLength(theMatrix);
239         int nc = Arrays.colLength(theMatrix, 0);
240         return new ByteMatrixBuf_1(theMatrix, new Range(0, nr - 1), new Range(0, nc - 1));
241     }
242 
243     /**
244      * Create a buffer for one row slice of the given byte matrix. The returned
245      * buffer encompasses <code>theRowRange</code> of rows, and all the columns, in
246      * <code>theMatrix</code>. The range's stride may be 1 or greater than 1.
247      *
248      * @param theMatrix Matrix.
249      * @param theRowRange Range of rows to include.
250      * @return Buffer.
251      * @exception NullPointerException (unchecked exception) Thrown if
252      * <code>theMatrix</code> is null or
253      * <code>theRowRange</code> is null.
254      * @exception IndexOutOfBoundsException (unchecked exception) Thrown if
255      * <code>theMatrix</code>'s allocation does not include <code>theRowRange</code>.
256      */
257     public static ByteBuf rowSliceBuffer(byte[][] theMatrix,
258             Range theRowRange) {
259         if (theMatrix == null) {
260             throw new NullPointerException("ByteBuf.rowSliceBuffer(): theMatrix is null");
261         }
262         int nr = Arrays.rowLength(theMatrix);
263         if (0 > theRowRange.lb() || theRowRange.ub() >= nr) {
264             throw new IndexOutOfBoundsException("ByteBuf.rowSliceBuffer(): theMatrix row index range = 0.."
265                     + (nr - 1) + ", theRowRange = " + theRowRange);
266         }
267         int nc = Arrays.colLength(theMatrix, theRowRange.lb());
268         if (theRowRange.stride() == 1) {
269             return new ByteMatrixBuf_1(theMatrix, theRowRange, new Range(0, nc - 1));
270         } else {
271             return new ByteMatrixBuf(theMatrix, theRowRange, new Range(0, nc - 1));
272         }
273     }
274 
275     /**
276      * Create an array of buffers for multiple row slices of the given byte
277      * matrix. The returned buffer array has the same length as
278      * <code>theRowRanges</code>. Each element [<I>i</I>] of the returned buffer
279      * array encompasses the rows of <code>theMatrix</code> specified by
280      * <code>theRowRanges[i]</code> and all the columns of <code>theMatrix</code>. Each
281      * range's stride may be 1 or greater than 1.
282      *
283      * @param theMatrix Matrix.
284      * @param theRowRanges Array of ranges of rows to include.
285      * @return Array of buffers.
286      * @exception NullPointerException (unchecked exception) Thrown if
287      * <code>theMatrix</code> is null or
288      * <code>theRowRanges</code> or any element thereof is null.
289      * @exception IndexOutOfBoundsException (unchecked exception) Thrown if
290      * <code>theMatrix</code>'s allocation does not include any element of
291      * <code>theRowRanges</code>.
292      */
293     public static ByteBuf[] rowSliceBuffers(byte[][] theMatrix,
294             Range[] theRowRanges) {
295         int n = theRowRanges.length;
296         ByteBuf[] result = new ByteBuf[n];
297         for (int i = 0; i < n; ++i) {
298             result[i] = rowSliceBuffer(theMatrix, theRowRanges[i]);
299         }
300         return result;
301     }
302 
303     /**
304      * Create a buffer for one column slice of the given byte matrix. The
305      * returned buffer encompasses all the rows, and <code>theColRange</code> of
306      * columns, in <code>theMatrix</code>. The range's stride may be 1 or greater
307      * than 1.
308      *
309      * @param theMatrix Matrix.
310      * @param theColRange Range of columns to include.
311      * @return Buffer.
312      * @exception NullPointerException (unchecked exception) Thrown if
313      * <code>theMatrix</code> is null or
314      * <code>theColRange</code> is null.
315      * @exception IndexOutOfBoundsException (unchecked exception) Thrown if
316      * <code>theMatrix</code>'s allocation does not include <code>theColRange</code>.
317      */
318     public static ByteBuf colSliceBuffer(byte[][] theMatrix,
319             Range theColRange) {
320         if (theMatrix == null) {
321             throw new NullPointerException("ByteBuf.colSliceBuffer(): theMatrix is null");
322         }
323         int nr = Arrays.rowLength(theMatrix);
324         int nc = Arrays.colLength(theMatrix, 0);
325         if (0 > theColRange.lb() || theColRange.ub() >= nc) {
326             throw new IndexOutOfBoundsException("ByteBuf.colSliceBuffer(): theMatrix column index range = 0.."
327                     + (nc - 1) + ", theColRange = " + theColRange);
328         }
329         if (theColRange.stride() == 1) {
330             return new ByteMatrixBuf_1(theMatrix, new Range(0, nr - 1), theColRange);
331         } else {
332             return new ByteMatrixBuf(theMatrix, new Range(0, nr - 1), theColRange);
333         }
334     }
335 
336     /**
337      * Create an array of buffers for multiple column slices of the given byte
338      * matrix. The returned buffer array has the same length as
339      * <code>theColRanges</code>. Each element [<I>i</I>] of the returned buffer
340      * array encompasses all the rows of <code>theMatrix</code> and the columns of
341      * <code>theMatrix</code> specified by <code>theColRanges[i]</code>. Each range's
342      * stride may be 1 or greater than 1.
343      *
344      * @param theMatrix Matrix.
345      * @param theColRanges Array of ranges of columns to include.
346      * @return Array of buffers.
347      * @exception NullPointerException (unchecked exception) Thrown if
348      * <code>theMatrix</code> is null or
349      * <code>theColRanges</code> or any element thereof is null.
350      * @exception IndexOutOfBoundsException (unchecked exception) Thrown if
351      * <code>theMatrix</code>'s allocation does not include any element of
352      * <code>theColRanges</code>.
353      */
354     public static ByteBuf[] colSliceBuffers(byte[][] theMatrix,
355             Range[] theColRanges) {
356         int n = theColRanges.length;
357         ByteBuf[] result = new ByteBuf[n];
358         for (int i = 0; i < n; ++i) {
359             result[i] = colSliceBuffer(theMatrix, theColRanges[i]);
360         }
361         return result;
362     }
363 
364     /**
365      * Create a buffer for one patch of the given byte matrix. The returned
366      * buffer encompasses <code>theRowRange</code> of rows, and <code>theColRange</code>
367      * of columns, in <code>theMatrix</code>. Each range's stride may be 1 or
368      * greater than 1.
369      *
370      * @param theMatrix Matrix.
371      * @param theRowRange Range of rows to include.
372      * @param theColRange Range of columns to include.
373      * @return Buffer.
374      * @exception NullPointerException (unchecked exception) Thrown if
375      * <code>theMatrix</code> is null,
376      * <code>theRowRange</code> is null, or <code>theColRange</code> is null.
377      * @exception IndexOutOfBoundsException (unchecked exception) Thrown if
378      * <code>theMatrix</code>'s allocation does not include <code>theRowRange</code> and
379      * <code>theColRange</code>.
380      */
381     public static ByteBuf patchBuffer(byte[][] theMatrix,
382             Range theRowRange,
383             Range theColRange) {
384         if (theMatrix == null) {
385             throw new NullPointerException("ByteBuf.patchBuffer(): theMatrix is null");
386         }
387         int nr = Arrays.rowLength(theMatrix);
388         if (0 > theRowRange.lb() || theRowRange.ub() >= nr) {
389             throw new IndexOutOfBoundsException("ByteBuf.patchBuffer(): theMatrix row index range = 0.."
390                     + (nr - 1) + ", theRowRange = " + theRowRange);
391         }
392         int nc = Arrays.colLength(theMatrix, theRowRange.lb());
393         if (0 > theColRange.lb() || theColRange.ub() >= nc) {
394             throw new IndexOutOfBoundsException("ByteBuf.patchBuffer(): theMatrix column index range = 0.."
395                     + (nc - 1) + ", theColRange = " + theColRange);
396         }
397         if (theRowRange.stride() == 1 && theColRange.stride() == 1) {
398             return new ByteMatrixBuf_1(theMatrix, theRowRange, theColRange);
399         } else {
400             return new ByteMatrixBuf(theMatrix, theRowRange, theColRange);
401         }
402     }
403 
404     /**
405      * Create an array of buffers for multiple patches of the given byte matrix.
406      * The length of the returned buffer array is equal to the length of
407      * <code>theRowRanges</code> times the length of <code>theColRanges</code>. Each
408      * element of the returned buffer array encompasses the rows given in one
409      * element of <code>theRowRanges</code> array, and the columns given in one
410      * element of <code>theColRanges</code> array, in all possible combinations, of
411      * <code>theMatrix</code>. Each range's stride may be 1 or greater than 1.
412      *
413      * @param theMatrix Matrix.
414      * @param theRowRanges Array of ranges of rows to include.
415      * @param theColRanges Array of ranges of columns to include.
416      * @return Array of buffers.
417      * @exception NullPointerException (unchecked exception) Thrown if
418      * <code>theMatrix</code> is null,
419      * <code>theRowRanges</code> or any element thereof is null, or
420      * <code>theColRanges</code> or any element thereof is null.
421      * @exception IndexOutOfBoundsException (unchecked exception) Thrown if
422      * <code>theMatrix</code>'s allocation does not include any element of
423      * <code>theRowRanges</code> or
424      * <code>theColRanges</code>.
425      */
426     public static ByteBuf[] patchBuffers(byte[][] theMatrix,
427             Range[] theRowRanges,
428             Range[] theColRanges) {
429         int m = theRowRanges.length;
430         int n = theColRanges.length;
431         ByteBuf[] result = new ByteBuf[m * n];
432         int k = 0;
433         for (int i = 0; i < m; ++i) {
434             Range rowrange = theRowRanges[i];
435             for (int j = 0; j < n; ++j) {
436                 result[k++]
437                         = patchBuffer(theMatrix, rowrange, theColRanges[j]);
438             }
439         }
440         return result;
441     }
442 
443     /**
444      * Create a buffer for a shared byte item. The item is wrapped in an
445      * instance of class {@linkplain edu.rit.pj.reduction.SharedByte
446      * SharedByte}. Use the methods of the SharedByte object to access the
447      * actual item.
448      *
449      * @param item SharedByte object that wraps the item.
450      * @exception NullPointerException (unchecked exception) Thrown if
451      * <code>item</code> is null.
452      * @return a {@link edu.rit.mp.ByteBuf} object.
453      */
454     public static ByteBuf buffer(SharedByte item) {
455         if (item == null) {
456             throw new NullPointerException("ByteBuf.buffer(): item is null");
457         }
458         return new SharedByteBuf(item);
459     }
460 
461     /**
462      * Create a buffer for the entire given shared byte array. The returned
463      * buffer encompasses all the elements in <code>theArray</code>.
464      *
465      * @param theArray Array.
466      * @return Buffer.
467      * @exception NullPointerException (unchecked exception) Thrown if
468      * <code>theArray</code> is null.
469      */
470     public static ByteBuf buffer(SharedByteArray theArray) {
471         if (theArray == null) {
472             throw new NullPointerException("ByteBuf.buffer(): theArray is null");
473         }
474         int nr = theArray.length();
475         return new SharedByteArrayBuf_1(theArray, new Range(0, nr - 1));
476     }
477 
478     /**
479      * Create a buffer for one slice of the given shared byte array. The
480      * returned buffer encompasses <code>theRange</code> of elements in
481      * <code>theArray</code>. The range's stride may be 1 or greater than 1.
482      *
483      * @param theArray Array.
484      * @param theRange Range of elements to include.
485      * @return Buffer.
486      * @exception NullPointerException (unchecked exception) Thrown if
487      * <code>theArray</code> is null or
488      * <code>theRange</code> is null.
489      * @exception IndexOutOfBoundsException (unchecked exception) Thrown if
490      * <code>theArray</code> does not include all the indexes in <code>theRange</code>.
491      */
492     public static ByteBuf sliceBuffer(SharedByteArray theArray,
493             Range theRange) {
494         if (theArray == null) {
495             throw new NullPointerException("ByteBuf.sliceBuffer(): theArray is null");
496         }
497         int nr = theArray.length();
498         if (0 > theRange.lb() || theRange.ub() >= nr) {
499             throw new IndexOutOfBoundsException("ByteBuf.sliceBuffer(): theArray index range = 0.."
500                     + (nr - 1) + ", theRange = " + theRange);
501         }
502         if (theRange.stride() == 1) {
503             return new SharedByteArrayBuf_1(theArray, theRange);
504         } else {
505             return new SharedByteArrayBuf(theArray, theRange);
506         }
507     }
508 
509     /**
510      * Create an array of buffers for multiple slices of the given shared byte
511      * array. The returned buffer array has the same length as
512      * <code>theRanges</code>. Each element [<I>i</I>] of the returned buffer array
513      * encompasses the elements of <code>theArray</code> specified by
514      * <code>theRanges[i]</code>. Each range's stride may be 1 or greater than 1.
515      *
516      * @param theArray Array.
517      * @param theRanges Array of ranges of elements to include.
518      * @return Array of buffers.
519      * @exception NullPointerException (unchecked exception) Thrown if
520      * <code>theArray</code> is null or
521      * <code>theRanges</code> or any element thereof is null.
522      * @exception IndexOutOfBoundsException (unchecked exception) Thrown if
523      * <code>theArray</code>'s allocation does not include any element of
524      * <code>theRanges</code>.
525      */
526     public static ByteBuf[] sliceBuffers(SharedByteArray theArray,
527             Range[] theRanges) {
528         int n = theRanges.length;
529         ByteBuf[] result = new ByteBuf[n];
530         for (int i = 0; i < n; ++i) {
531             result[i] = sliceBuffer(theArray, theRanges[i]);
532         }
533         return result;
534     }
535 
536     /**
537      * Obtain the given item from this buffer.
538      * <P>
539      * The <code>get()</code> method must not block the calling thread; if it does,
540      * all message I/O in MP will be blocked.
541      *
542      * @param i Item index in the range 0 .. <code>length()</code>-1.
543      * @return Item at index <code>i</code>.
544      */
545     public abstract byte get(int i);
546 
547     /**
548      * Store the given item in this buffer.
549      * <P>
550      * The <code>put()</code> method must not block the calling thread; if it does,
551      * all message I/O in MP will be blocked.
552      *
553      * @param i Item index in the range 0 .. <code>length()</code>-1.
554      * @param item Item to be stored at index <code>i</code>.
555      */
556     public abstract void put(int i,
557             byte item);
558 
559     /**
560      * {@inheritDoc}
561      *
562      * Copy items from the given buffer to this buffer. The number of items
563      * copied is this buffer's length or <code>theSrc</code>'s length, whichever is
564      * smaller. If <code>theSrc</code> is this buffer, the <code>copy()</code> method
565      * does nothing.
566      * <P>
567      * The default implementation of the <code>copy()</code> method calls the
568      * <code>defaultCopy()</code> method. A subclass can override the
569      * <code>copy()</code> method to use a more efficient algorithm.
570      * @exception ClassCastException (unchecked exception) Thrown if
571      * <code>theSrc</code>'s item data type is not the same as this buffer's item
572      * data type.
573      */
574     public void copy(Buf theSrc) {
575         if (theSrc != this) {
576             defaultCopy((ByteBuf) theSrc, this);
577         }
578     }
579 
580     /**
581      * {@inheritDoc}
582      *
583      * Fill this buffer with the given item. The <code>item</code> is assigned to
584      * each element in this buffer.
585      * <P>
586      * The <code>item</code> must be an instance of class Byte. If the <code>item</code>
587      * is null, 0 is assigned to each element in this buffer.
588      * @exception ClassCastException (unchecked exception) Thrown if the
589      * <code>item</code>'s data type is not the same as this buffer's item data
590      * type.
591      */
592     public void fill(Object item) {
593         byte value = item == null ? (byte) 0 : ((Byte) item).byteValue();
594         for (int i = 0; i < myLength; ++i) {
595             put(i, value);
596         }
597     }
598 
599     /**
600      * Create a temporary buffer with the same type of items and the same length
601      * as this buffer. The new buffer items are stored in a newly created array,
602      * separate from the storage for this buffer's items.
603      *
604      * @return a {@link edu.rit.mp.Buf} object.
605      */
606     public Buf getTemporaryBuf() {
607         return buffer(new byte[myLength]);
608     }
609 
610 // Hidden operations.
611     /**
612      * Skip as many items as possible from the given byte buffer.
613      *
614      * @param num Number of items to skip.
615      * @param buffer Buffer.
616      *
617      * @return Number of items actually skipped.
618      */
619     int skipItems(int num,
620             ByteBuffer buffer) {
621         int n = Math.min(num, buffer.remaining());
622         buffer.position(buffer.position() + n);
623         return n;
624     }
625 
626     /**
627      * Copy items from the given source buffer to the given destination buffer.
628      * The number of items copied is <code>theSrc</code>'s length or
629      * <code>theDst</code>'s length, whichever is smaller. Each item is copied
630      * individually using the <code>get()</code> and <code>put()</code> methods. It is
631      * assumed that <code>theSrc</code> is not the same as <code>theDst</code>.
632      *
633      * @param theSrc Source of items to copy.
634      * @param theDst Destination of items to copy.
635      */
636     protected static void defaultCopy(ByteBuf theSrc,
637             ByteBuf theDst) {
638         int n = Math.min(theSrc.myLength, theDst.myLength);
639         for (int i = 0; i < n; ++i) {
640             theDst.put(i, theSrc.get(i));
641         }
642     }
643 
644 }