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