001// Copyright (C) 1999-2001 by Jason Hunter <jhunter_AT_acm_DOT_org>.
002// All rights reserved.  Use of this class is limited.
003// Please see the LICENSE for more information.
004
005package com.oreilly.servlet.multipart;
006
007import java.io.OutputStream;
008import java.io.FilterOutputStream;
009import java.io.IOException;
010
011/**
012 * A <code>MacBinaryDecoderOutput</code> filters MacBinary files to normal 
013 * files on the fly; optimized for speed more than readability.
014 * 
015 * @author Jason Hunter
016 */
017public class MacBinaryDecoderOutputStream extends FilterOutputStream {
018  private int bytesFiltered = 0;
019  private int dataForkLength = 0;
020
021  public MacBinaryDecoderOutputStream(OutputStream out) {
022    super(out);
023  }
024
025  public void write(int b) throws IOException {
026    // Bytes 83 through 86 are a long representing the data fork length
027    // Check <= 86 first to short circuit early in the common case
028    if (bytesFiltered <= 86 && bytesFiltered >= 83) {
029      int leftShift = (86 - bytesFiltered) * 8;
030      dataForkLength = dataForkLength | (b & 0xff) << leftShift;
031    }
032
033    // Bytes 128 up to (128 + dataForkLength - 1) are the data fork
034    else if (bytesFiltered < (128 + dataForkLength) && bytesFiltered >= 128) {
035      out.write(b);
036    }
037
038    bytesFiltered++;
039  }
040
041  public void write(byte b[]) throws IOException {
042    write(b, 0, b.length);
043  }
044
045  public void write(byte b[], int off, int len) throws IOException {
046    // If the write is for content past the end of the data fork, ignore
047    if (bytesFiltered >= (128 + dataForkLength)) {
048      bytesFiltered += len;
049    }
050    // If the write is entirely within the data fork, write it directly
051    else if (bytesFiltered >= 128 && 
052             (bytesFiltered + len) <= (128 + dataForkLength)) {
053      out.write(b, off, len);
054      bytesFiltered += len;
055    }
056    // Otherwise, do the write a byte at a time to get the logic above
057    else {
058      for (int i = 0 ; i < len ; i++) {
059        write(b[off + i]);
060      }
061    }
062  }
063}