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> < 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 }