Source for javax.imageio.stream.ImageInputStreamImpl

   1: /* ImageInputStream.java --
   2:    Copyright (C) 2004  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 javax.imageio.stream;
  40: 
  41: import java.io.DataInputStream;
  42: import java.io.EOFException;
  43: import java.io.IOException;
  44: import java.nio.ByteOrder;
  45: import java.util.Stack;
  46: 
  47: /**
  48:  * @author Michael Koch (konqueror@gmx.de)
  49:  */
  50: public abstract class ImageInputStreamImpl implements ImageInputStream
  51: {
  52:   private boolean closed;
  53:   private Stack markStack = new Stack();
  54:   
  55:   byte[] buffer = new byte[8];
  56:   
  57:   protected int bitOffset;
  58:   protected ByteOrder byteOrder;
  59:   protected long flushedPos;
  60:   protected long streamPos;
  61: 
  62:   public ImageInputStreamImpl()
  63:   {
  64:     // Do nothing here.
  65:   }
  66: 
  67:   protected final void checkClosed()
  68:     throws IOException
  69:   {
  70:     if (closed)
  71:       throw new IOException("stream closed");
  72:   }
  73: 
  74:   public void close()
  75:     throws IOException
  76:   {
  77:     checkClosed();
  78:     closed = true;
  79:   }
  80:   
  81:   protected void finalize()
  82:     throws Throwable
  83:   {
  84:     close();
  85:   }
  86: 
  87:   public void flush()
  88:     throws IOException
  89:   {
  90:     flushBefore(getStreamPosition());
  91:   }
  92: 
  93:   public void flushBefore(long position)
  94:     throws IOException
  95:   {
  96:     if (position < flushedPos)
  97:       throw new IndexOutOfBoundsException();
  98: 
  99:     if (position > streamPos)
 100:       throw new IndexOutOfBoundsException();
 101: 
 102:     flushedPos = position;
 103:   }
 104: 
 105:   public int getBitOffset()
 106:     throws IOException
 107:   {
 108:     checkClosed();
 109:     return bitOffset;
 110:   }
 111: 
 112:   public ByteOrder getByteOrder()
 113:   {
 114:     return byteOrder;
 115:   }
 116: 
 117:   public long getFlushedPosition()
 118:   {
 119:     return flushedPos;
 120:   }
 121: 
 122:   public long getStreamPosition()
 123:     throws IOException
 124:   {
 125:     checkClosed();
 126:     return streamPos;
 127:   }
 128: 
 129:   public boolean isCached()
 130:   {
 131:     return false;
 132:   }
 133: 
 134:   public boolean isCachedFile()
 135:   {
 136:     return false;
 137:   }
 138: 
 139:   public boolean isCachedMemory()
 140:   {
 141:     return false;
 142:   }
 143: 
 144:   public long length()
 145:   {
 146:     return -1L;
 147:   }
 148: 
 149:   public void mark()
 150:   {
 151:     try
 152:       {
 153:     markStack.push(new Long(getStreamPosition()));
 154:       }
 155:     catch (IOException e)
 156:       {
 157:     // Ignored.
 158:       }
 159:   }
 160: 
 161:   public abstract int read()
 162:     throws IOException;
 163: 
 164:   public int read(byte[] data)
 165:     throws IOException
 166:   {
 167:     return read(data, 0, data.length);
 168:   }
 169: 
 170:   public abstract int read(byte[] data, int offset, int len)
 171:     throws IOException;
 172: 
 173:   public int readBit()
 174:     throws IOException
 175:   {
 176:     checkClosed();
 177: 
 178:     // Calc new bit offset here, readByte resets it.
 179:     int newOffset = (bitOffset + 1) & 0x7;
 180: 
 181:     byte data = readByte();
 182:     
 183:     if (bitOffset != 0)
 184:       {
 185:     seek(getStreamPosition() - 1);
 186:     data = (byte) (data >> (8 - newOffset));
 187:       }
 188: 
 189:     bitOffset = newOffset;
 190:     return data & 0x1;
 191:   }
 192: 
 193:   public long readBits(int numBits)
 194:     throws IOException
 195:   {
 196:     checkClosed();
 197: 
 198:     if (numBits < 0 || numBits > 64)
 199:       throw new IllegalArgumentException();
 200: 
 201:     if (numBits == 0)
 202:       return 0L;
 203: 
 204:     long bits = 0L;
 205:     
 206:     for (int i = 0; i < numBits; i++)
 207:       {
 208:     bits <<= 1;
 209:     bits |= readBit();
 210:       }
 211: 
 212:     return bits;
 213:   }
 214: 
 215:   public boolean readBoolean()
 216:     throws IOException
 217:   {
 218:     byte data = readByte();
 219:     return data != 0;
 220:   }
 221: 
 222:   public byte readByte()
 223:     throws IOException
 224:   {
 225:     int data = read();
 226: 
 227:     if (data == -1)
 228:       throw new EOFException();
 229: 
 230:     return (byte) data;
 231:   }
 232: 
 233:   public void readBytes(IIOByteBuffer buffer, int len)
 234:     throws IOException
 235:   {
 236:     int result = read(buffer.getData(), buffer.getOffset(), len);
 237:     
 238:     if (result == -1 || result < len)
 239:       throw new EOFException();
 240: 
 241:     buffer.setLength(len);
 242:   }
 243: 
 244:   public char readChar()
 245:     throws IOException
 246:   {
 247:     return (char) readShort();
 248:   }
 249: 
 250:   public double readDouble()
 251:     throws IOException
 252:   {
 253:     return (double) readLong();
 254:   }
 255: 
 256:   public float readFloat()
 257:     throws IOException
 258:   {
 259:     return (float) readInt();
 260:   }
 261: 
 262:   public void readFully(byte[] data)
 263:     throws IOException
 264:   {
 265:     readFully(data, 0, data.length);
 266:   }
 267: 
 268:   public void readFully(byte[] data, int offset, int len)
 269:     throws IOException
 270:   {
 271:     for (int i = 0; i < len; ++i)
 272:       data[offset + i] = readByte();
 273:   }
 274: 
 275:   public void readFully(char[] data, int offset, int len)
 276:     throws IOException
 277:   {
 278:     for (int i = 0; i < len; ++i)
 279:       data[offset + i] = readChar();
 280:   }
 281: 
 282:   public void readFully(double[] data, int offset, int len)
 283:     throws IOException
 284:   {
 285:     for (int i = 0; i < len; ++i)
 286:       data[offset + i] = readDouble();
 287:   }
 288: 
 289:   public void readFully(float[] data, int offset, int len)
 290:     throws IOException
 291:   {
 292:     for (int i = 0; i < len; ++i)
 293:       data[offset + i] = readFloat();
 294:   }
 295: 
 296:   public void readFully(int[] data, int offset, int len)
 297:     throws IOException
 298:   {
 299:     for (int i = 0; i < len; ++i)
 300:       data[offset + i] = readInt();
 301:   }
 302: 
 303:   public void readFully(long[] data, int offset, int len)
 304:     throws IOException
 305:   {
 306:     for (int i = 0; i < len; ++i)
 307:       data[offset + i] = readLong();
 308:   }
 309: 
 310:   public void readFully(short[] data, int offset, int len)
 311:     throws IOException
 312:   {
 313:     for (int i = 0; i < len; ++i)
 314:       data[offset + i] = readShort();
 315:   }
 316: 
 317:   public int readInt()
 318:     throws IOException
 319:   {
 320:     int result = read(buffer, 0, 4);
 321: 
 322:     if (result == -1)
 323:       throw new EOFException();
 324:     
 325:     if (getByteOrder() == ByteOrder.LITTLE_ENDIAN)
 326:       {
 327:     return ((buffer[0] & 0xff)
 328:         + (buffer[1] << 8)
 329:         + (buffer[2] << 16)
 330:         + (buffer[3] << 24));
 331:       }
 332: 
 333:     return ((buffer[4] << 24)
 334:         + (buffer[3] << 16)
 335:         + (buffer[2] << 8)
 336:         + (buffer[1] & 0xff));
 337:   }
 338: 
 339:   public String readLine()
 340:     throws IOException
 341:   {
 342:     checkClosed();
 343: 
 344:     int c = -1;
 345:     boolean eol = false;
 346:     StringBuffer buffer = new StringBuffer();
 347: 
 348:     while (!eol && (c = read()) != -1)
 349:       {
 350:     switch(c)
 351:       {
 352:       case '\r':
 353:         // Consume following \n'
 354:         long oldPosition = getStreamPosition();
 355:         if (read() != '\n')
 356:            seek(oldPosition);
 357:       case '\n':
 358:         eol = true;
 359:         break;
 360:       default:
 361:         buffer.append((char) c);
 362:         break;
 363:       }
 364:       }
 365: 
 366:     if (c == -1 && buffer.length() == 0)
 367:       return null;
 368: 
 369:     return buffer.toString();
 370:   }
 371: 
 372:   public long readLong()
 373:     throws IOException
 374:   {
 375:     int result = read(buffer, 0, 8);
 376: 
 377:     if (result == -1)
 378:       throw new EOFException();
 379:     
 380:     if (getByteOrder() == ByteOrder.LITTLE_ENDIAN)
 381:       {
 382:         return ((buffer[0] & 0xff)
 383:                 + (((buffer[1] & 0xff)) << 8)
 384:                 + (((buffer[2] & 0xff)) << 16)
 385:                 + (((buffer[3] & 0xffL)) << 24)
 386:                 + (((buffer[4] & 0xffL)) << 32)
 387:                 + (((buffer[5] & 0xffL)) << 40)
 388:                 + (((buffer[6] & 0xffL)) << 48)
 389:                 + (((long) buffer[7]) << 56));
 390:       }
 391: 
 392:     return ((((long) buffer[7]) << 56)
 393:             + ((buffer[6] & 0xffL) << 48)
 394:             + ((buffer[5] & 0xffL) << 40)
 395:             + ((buffer[4] & 0xffL) << 32)
 396:             + ((buffer[3] & 0xffL) << 24)
 397:             + ((buffer[2] & 0xff) << 16)
 398:             + ((buffer[1] & 0xff) << 8)
 399:             + (buffer[0] & 0xff));
 400:   }
 401: 
 402:   public short readShort()
 403:     throws IOException
 404:   {
 405:     int result = read(buffer, 0, 2);
 406: 
 407:     if (result == -1)
 408:       throw new EOFException();
 409:     
 410:     if (getByteOrder() == ByteOrder.LITTLE_ENDIAN)
 411:       {
 412:     return (short) ((buffer[0] & 0xff)
 413:             + (buffer[1] << 8));
 414:       }
 415: 
 416:     return (short) ((buffer[0] << 8)
 417:             + (buffer[1] & 0xff));
 418:   }
 419: 
 420:   public int readUnsignedByte()
 421:     throws IOException
 422:   {
 423:     return readByte() & 0xff;
 424:   }
 425: 
 426:   public long readUnsignedInt()
 427:     throws IOException
 428:   {
 429:     return readInt() & 0xffffffff;
 430:   }
 431: 
 432:   public int readUnsignedShort()
 433:     throws IOException
 434:   {
 435:     return readShort() & 0xffff;
 436:   }
 437: 
 438:   public String readUTF()
 439:     throws IOException
 440:   {
 441:     checkClosed();
 442: 
 443:     String data;
 444:     ByteOrder old = getByteOrder();
 445:     setByteOrder(ByteOrder.BIG_ENDIAN); // Strings are always big endian.
 446: 
 447:     try
 448:       {
 449:     data = DataInputStream.readUTF(this);
 450:       }
 451:     finally
 452:       {
 453:     setByteOrder(old);
 454:       }
 455:     
 456:     return data;
 457:   }
 458: 
 459:   public void reset()
 460:     throws IOException
 461:   {
 462:     checkClosed();
 463:     
 464:     long mark = ((Long) markStack.pop()).longValue();
 465:     seek(mark);
 466:   }
 467: 
 468:   public void seek(long position)
 469:     throws IOException
 470:   {
 471:     checkClosed();
 472: 
 473:     if (position < getFlushedPosition())
 474:       throw new IndexOutOfBoundsException("position < flushed position");
 475: 
 476:     streamPos = position;
 477:     bitOffset = 0;
 478:   }
 479: 
 480:   public void setBitOffset (int bitOffset)
 481:     throws IOException
 482:   {
 483:     checkClosed();
 484:     
 485:     if (bitOffset < 0 || bitOffset > 7)
 486:       throw new IllegalArgumentException();
 487: 
 488:     this.bitOffset = bitOffset;
 489:   }
 490: 
 491:   public void setByteOrder(ByteOrder byteOrder)
 492:   {
 493:     this.byteOrder = byteOrder;
 494:   }
 495: 
 496:   public int skipBytes(int num)
 497:     throws IOException
 498:   {
 499:     checkClosed();
 500:     
 501:     seek(getStreamPosition() + num);
 502:     bitOffset = 0;
 503:     return num;
 504:   }
 505: 
 506:   public long skipBytes(long num)
 507:     throws IOException
 508:   {
 509:     checkClosed();
 510:     
 511:     seek(getStreamPosition() + num);
 512:     bitOffset = 0;
 513:     return num;
 514:   }
 515: }