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