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 }