Source for java.nio.CharBuffer

   1: /* CharBuffer.java --
   2:    Copyright (C) 2002, 2003, 2004, 2005  Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: 
  39: package java.nio;
  40: 
  41: // GCJ LOCAL: Use RawData instead of gnu.classpath.Pointer
  42: import gnu.gcj.RawData;
  43: 
  44: import java.io.IOException;
  45: 
  46: /**
  47:  * @since 1.4
  48:  */
  49: public abstract class CharBuffer extends Buffer
  50:   implements Comparable<CharBuffer>, CharSequence, Readable, Appendable
  51: {
  52:   final int array_offset;
  53:   final char[] backing_buffer;
  54: 
  55:   CharBuffer (int capacity, int limit, int position, int mark,
  56:               RawData address, char[] backing_buffer, int array_offset)
  57:   {
  58:     super (capacity, limit, position, mark, address);
  59:     this.backing_buffer = backing_buffer;
  60:     this.array_offset = array_offset;
  61:   }
  62: 
  63:   /**
  64:    * Allocates a new <code>CharBuffer</code> object with a given capacity.
  65:    */
  66:   public static CharBuffer allocate (int capacity)
  67:   {
  68:     return new CharBufferImpl (capacity);
  69:   }
  70: 
  71:   /**
  72:    * Wraps a <code>char</code> array into a <code>CharBuffer</code>
  73:    * object.
  74:    *
  75:    * @param array the array to wrap
  76:    * @param offset the offset of the region in the array to wrap
  77:    * @param length the length of the region in the array to wrap
  78:    *
  79:    * @return a new <code>CharBuffer</code> object
  80:    *
  81:    * @exception IndexOutOfBoundsException If the preconditions on the offset
  82:    * and length parameters do not hold
  83:    */
  84:   public static final CharBuffer wrap(char[] array, int offset, int length)
  85:   {
  86:     return new CharBufferImpl(array, 0, array.length, offset + length, offset,
  87:                               -1, false);
  88:   }
  89: 
  90:   /**
  91:    * Wraps a character sequence into a <code>CharBuffer</code> object.
  92:    *
  93:    * @param seq the sequence to wrap
  94:    *
  95:    * @return a new <code>CharBuffer</code> object
  96:    */
  97:   public static final CharBuffer wrap(CharSequence seq)
  98:   {
  99:     return wrap(seq, 0, seq.length());
 100:   }
 101: 
 102:   /**
 103:    * Wraps a character sequence into a <code>CharBuffer</code> object.
 104:    *
 105:    * @param seq the sequence to wrap
 106:    * @param start the index of the first character to wrap
 107:    * @param end the index of the first character not to wrap
 108:    *
 109:    * @return a new <code>CharBuffer</code> object
 110:    *
 111:    * @exception IndexOutOfBoundsException If the preconditions on the offset
 112:    * and length parameters do not hold
 113:    */
 114:   public static final CharBuffer wrap(CharSequence seq, int start, int end)
 115:   {
 116:     return new CharSequenceBuffer(seq, start, end);
 117:   }
 118: 
 119:   /**
 120:    * Wraps a <code>char</code> array into a <code>CharBuffer</code>
 121:    * object.
 122:    *
 123:    * @param array the array to wrap
 124:    *
 125:    * @return a new <code>CharBuffer</code> object
 126:    */
 127:   public static final CharBuffer wrap(char[] array)
 128:   {
 129:     return wrap(array, 0, array.length);
 130:   }
 131: 
 132:   /**
 133:    * This method transfers <code>char</code>s from this buffer into the given
 134:    * destination array. Before the transfer, it checks if there are fewer than
 135:    * length <code>char</code>s remaining in this buffer.
 136:    *
 137:    * @param dst The destination array
 138:    * @param offset The offset within the array of the first <code>char</code>
 139:    * to be written; must be non-negative and no larger than dst.length.
 140:    * @param length The maximum number of bytes to be written to the given array;
 141:    * must be non-negative and no larger than dst.length - offset.
 142:    *
 143:    * @exception BufferUnderflowException If there are fewer than length
 144:    * <code>char</code>s remaining in this buffer.
 145:    * @exception IndexOutOfBoundsException If the preconditions on the offset
 146:    * and length parameters do not hold.
 147:    */
 148:   public CharBuffer get (char[] dst, int offset, int length)
 149:   {
 150:     checkArraySize(dst.length, offset, length);
 151:     checkForUnderflow(length);
 152: 
 153:     for (int i = offset; i < offset + length; i++)
 154:       {
 155:         dst [i] = get ();
 156:       }
 157: 
 158:     return this;
 159:   }
 160: 
 161:   /** @since 1.5 */
 162:   public int read(CharBuffer buffer) throws IOException
 163:   {
 164:     // We want to call put(), so we don't manipulate the CharBuffer
 165:     // directly.
 166:     int rem = Math.min(buffer.remaining(), remaining());
 167:     char[] buf = new char[rem];
 168:     get(buf);
 169:     buffer.put(buf);
 170:     return rem;
 171:   }
 172: 
 173:   /**
 174:    * This method transfers <code>char</code>s from this buffer into the given
 175:    * destination array.
 176:    *
 177:    * @param dst The byte array to write into.
 178:    *
 179:    * @exception BufferUnderflowException If there are fewer than dst.length
 180:    * <code>char</code>s remaining in this buffer.
 181:    */
 182:   public CharBuffer get (char[] dst)
 183:   {
 184:     return get (dst, 0, dst.length);
 185:   }
 186: 
 187:   /**
 188:    * Writes the content of the the <code>CharBUFFER</code> src
 189:    * into the buffer. Before the transfer, it checks if there is fewer than
 190:    * <code>src.remaining()</code> space remaining in this buffer.
 191:    *
 192:    * @param src The source data.
 193:    *
 194:    * @exception BufferOverflowException If there is insufficient space in this
 195:    * buffer for the remaining <code>char</code>s in the source buffer.
 196:    * @exception IllegalArgumentException If the source buffer is this buffer.
 197:    * @exception ReadOnlyBufferException If this buffer is read-only.
 198:    */
 199:   public CharBuffer put (CharBuffer src)
 200:   {
 201:     if (src == this)
 202:       throw new IllegalArgumentException ();
 203: 
 204:     checkForOverflow(src.remaining());
 205: 
 206:     if (src.remaining () > 0)
 207:       {
 208:         char[] toPut = new char [src.remaining ()];
 209:         src.get (toPut);
 210:         put (toPut);
 211:       }
 212: 
 213:     return this;
 214:   }
 215: 
 216:   /**
 217:    * Writes the content of the the <code>char array</code> src
 218:    * into the buffer. Before the transfer, it checks if there is fewer than
 219:    * length space remaining in this buffer.
 220:    *
 221:    * @param src The array to copy into the buffer.
 222:    * @param offset The offset within the array of the first byte to be read;
 223:    * must be non-negative and no larger than src.length.
 224:    * @param length The number of bytes to be read from the given array;
 225:    * must be non-negative and no larger than src.length - offset.
 226:    *
 227:    * @exception BufferOverflowException If there is insufficient space in this
 228:    * buffer for the remaining <code>char</code>s in the source array.
 229:    * @exception IndexOutOfBoundsException If the preconditions on the offset
 230:    * and length parameters do not hold
 231:    * @exception ReadOnlyBufferException If this buffer is read-only.
 232:    */
 233:   public CharBuffer put (char[] src, int offset, int length)
 234:   {
 235:     checkArraySize(src.length, offset, length);
 236:     checkForOverflow(length);
 237: 
 238:     for (int i = offset; i < offset + length; i++)
 239:       put (src [i]);
 240: 
 241:     return this;
 242:   }
 243: 
 244:   /**
 245:    * Writes the content of the the <code>char array</code> src
 246:    * into the buffer.
 247:    *
 248:    * @param src The array to copy into the buffer.
 249:    *
 250:    * @exception BufferOverflowException If there is insufficient space in this
 251:    * buffer for the remaining <code>char</code>s in the source array.
 252:    * @exception ReadOnlyBufferException If this buffer is read-only.
 253:    */
 254:   public final CharBuffer put (char[] src)
 255:   {
 256:     return put (src, 0, src.length);
 257:   }
 258: 
 259:   /**
 260:    * Tells whether ot not this buffer is backed by an accessible
 261:    * <code>char</code> array.
 262:    */
 263:   public final boolean hasArray ()
 264:   {
 265:     return (backing_buffer != null
 266:             && !isReadOnly ());
 267:   }
 268: 
 269:   /**
 270:    * Returns the <code>char</code> array that backs this buffer.
 271:    *
 272:    * @exception ReadOnlyBufferException If this buffer is read-only.
 273:    * @exception UnsupportedOperationException If this buffer is not backed
 274:    * by an accessible array.
 275:    */
 276:   public final char[] array ()
 277:   {
 278:     if (backing_buffer == null)
 279:       throw new UnsupportedOperationException ();
 280: 
 281:     checkIfReadOnly();
 282: 
 283:     return backing_buffer;
 284:   }
 285: 
 286:   /**
 287:    * Returns the offset within this buffer's backing array of the first element.
 288:    *
 289:    * @exception ReadOnlyBufferException If this buffer is read-only.
 290:    * @exception UnsupportedOperationException If this buffer is not backed
 291:    * by an accessible array.
 292:    */
 293:   public final int arrayOffset ()
 294:   {
 295:     if (backing_buffer == null)
 296:       throw new UnsupportedOperationException ();
 297: 
 298:     checkIfReadOnly();
 299: 
 300:     return array_offset;
 301:   }
 302: 
 303:   /**
 304:    * Calculates a hash code for this buffer.
 305:    *
 306:    * This is done with int arithmetic,
 307:    * where ** represents exponentiation, by this formula:<br>
 308:    * <code>s[position()] + 31 + (s[position()+1] + 30)*31**1 + ... +
 309:    * (s[limit()-1]+30)*31**(limit()-1)</code>.
 310:    * Where s is the buffer data. Note that the hashcode is dependent
 311:    * on buffer content, and therefore is not useful if the buffer
 312:    * content may change.
 313:    */
 314:   public int hashCode ()
 315:   {
 316:     int hashCode = get(position()) + 31;
 317:     int multiplier = 1;
 318:     for (int i = position() + 1; i < limit(); ++i)
 319:       {
 320:           multiplier *= 31;
 321:           hashCode += (get(i) + 30)*multiplier;
 322:       }
 323:     return hashCode;
 324:   }
 325: 
 326:   /**
 327:    * Checks if this buffer is equal to obj.
 328:    */
 329:   public boolean equals (Object obj)
 330:   {
 331:     if (obj instanceof CharBuffer)
 332:       {
 333:         return compareTo ((CharBuffer) obj) == 0;
 334:       }
 335: 
 336:     return false;
 337:   }
 338: 
 339:   /**
 340:    * Compares two <code>CharBuffer</code> objects.
 341:    *
 342:    * @exception ClassCastException If obj is not an object derived from
 343:    * <code>CharBuffer</code>.
 344:    */
 345:   public int compareTo (CharBuffer other)
 346:   {
 347:     int num = Math.min(remaining(), other.remaining());
 348:     int pos_this = position();
 349:     int pos_other = other.position();
 350: 
 351:     for (int count = 0; count < num; count++)
 352:       {
 353:          char a = get(pos_this++);
 354:          char b = other.get(pos_other++);
 355: 
 356:          if (a == b)
 357:            continue;
 358: 
 359:          if (a < b)
 360:            return -1;
 361: 
 362:          return 1;
 363:       }
 364: 
 365:      return remaining() - other.remaining();
 366:   }
 367: 
 368:   /**
 369:    * Returns the byte order of this buffer.
 370:    */
 371:   public abstract ByteOrder order ();
 372: 
 373:   /**
 374:    * Reads the <code>char</code> at this buffer's current position,
 375:    * and then increments the position.
 376:    *
 377:    * @exception BufferUnderflowException If there are no remaining
 378:    * <code>char</code>s in this buffer.
 379:    */
 380:   public abstract char get ();
 381: 
 382:   /**
 383:    * Writes the <code>char</code> at this buffer's current position,
 384:    * and then increments the position.
 385:    *
 386:    * @exception BufferOverflowException If there no remaining
 387:    * <code>char</code>s in this buffer.
 388:    * @exception ReadOnlyBufferException If this buffer is read-only.
 389:    */
 390:   public abstract CharBuffer put (char b);
 391: 
 392:   /**
 393:    * Absolute get method.
 394:    *
 395:    * @exception IndexOutOfBoundsException If index is negative or not smaller
 396:    * than the buffer's limit.
 397:    */
 398:   public abstract char get (int index);
 399: 
 400:   /**
 401:    * Absolute put method.
 402:    *
 403:    * @exception IndexOutOfBoundsException If index is negative or not smaller
 404:    * than the buffer's limit.
 405:    * @exception ReadOnlyBufferException If this buffer is read-only.
 406:    */
 407:   public abstract CharBuffer put (int index, char b);
 408: 
 409:   /**
 410:    * Compacts this buffer.
 411:    *
 412:    * @exception ReadOnlyBufferException If this buffer is read-only.
 413:    */
 414:   public abstract CharBuffer compact ();
 415: 
 416:   /**
 417:    * Tells wether or not this buffer is direct.
 418:    */
 419:   public abstract boolean isDirect ();
 420: 
 421:   /**
 422:    * Creates a new <code>CharBuffer</code> whose content is a shared
 423:    * subsequence of this buffer's content.
 424:    */
 425:   public abstract CharBuffer slice ();
 426: 
 427:   /**
 428:    * Creates a new <code>CharBuffer</code> that shares this buffer's
 429:    * content.
 430:    */
 431:   public abstract CharBuffer duplicate ();
 432: 
 433:   /**
 434:    * Creates a new read-only <code>CharBuffer</code> that shares this
 435:    * buffer's content.
 436:    */
 437:   public abstract CharBuffer asReadOnlyBuffer ();
 438: 
 439:   /**
 440:    * Returns the remaining content of the buffer as a string.
 441:    */
 442:   public String toString ()
 443:   {
 444:     if (hasArray ())
 445:       return new String (array (), position (), length ());
 446: 
 447:     char[] buf = new char [length ()];
 448:     int pos = position ();
 449:     get (buf, 0, buf.length);
 450:     position (pos);
 451:     return new String (buf);
 452:   }
 453: 
 454:   /**
 455:    * Returns the length of the remaining chars in this buffer.
 456:    */
 457:   public final int length ()
 458:   {
 459:     return remaining ();
 460:   }
 461: 
 462:   /**
 463:    * Creates a new character buffer that represents the specified subsequence
 464:    * of this buffer, relative to the current position.
 465:    *
 466:    * @exception IndexOutOfBoundsException If the preconditions on start and
 467:    * end do not hold.
 468:    */
 469:   public abstract CharSequence subSequence (int start, int length);
 470: 
 471:   /**
 472:    * Relative put method.
 473:    *
 474:    * @exception BufferOverflowException If there is insufficient space in this
 475:    * buffer.
 476:    * @exception IndexOutOfBoundsException If the preconditions on the start
 477:    * and end parameters do not hold.
 478:    * @exception ReadOnlyBufferException If this buffer is read-only.
 479:    */
 480:   public CharBuffer put (String str, int start, int length)
 481:   {
 482:     return put (str.toCharArray (), start, length);
 483:   }
 484: 
 485:   /**
 486:    * Relative put method.
 487:    *
 488:    * @exception BufferOverflowException If there is insufficient space in this
 489:    * buffer.
 490:    * @exception ReadOnlyBufferException If this buffer is read-only.
 491:    */
 492:   public final CharBuffer put (String str)
 493:   {
 494:     return put (str.toCharArray (), 0, str.length ());
 495:   }
 496: 
 497:   /**
 498:    * Returns the character at <code>position() + index</code>.
 499:    *
 500:    * @exception IndexOutOfBoundsException If index is negative not smaller than
 501:    * <code>remaining()</code>.
 502:    */
 503:   public final char charAt (int index)
 504:   {
 505:     if (index < 0
 506:         || index >= remaining ())
 507:       throw new IndexOutOfBoundsException ();
 508: 
 509:     return get (position () + index);
 510:   }
 511: 
 512:   /** @since 1.5 */
 513:   public CharBuffer append(char c)
 514:   {
 515:     put(c);
 516:     return this;
 517:   }
 518: 
 519:   /** @since 1.5 */
 520:   public CharBuffer append(CharSequence cs)
 521:   {
 522:     put(cs == null ? "null" : cs.toString());
 523:     return this;
 524:   }
 525: 
 526:   /** @since 1.5 */
 527:   public CharBuffer append(CharSequence cs, int start, int end)
 528:   {
 529:     put(cs == null ? "null" : cs.subSequence(start, end).toString());
 530:     return this;
 531:   }
 532: }