/[classpath]/inetlib/source/gnu/inet/ftp/CompressedOutputStream.java
ViewVC logotype

Diff of /inetlib/source/gnu/inet/ftp/CompressedOutputStream.java

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.5 by dog, Thu Oct 21 15:21:54 2004 UTC revision 1.6 by dog, Thu Nov 25 22:15:05 2004 UTC
# Line 1  Line 1 
1  /*  /*
2   * $Id$   * CompressedOutputStream.java
3   * Copyright (C) 2003 The Free Software Foundation   * Copyright (C) 2003 The Free Software Foundation
4   *   *
5   * This file is part of GNU inetlib, a library.   * This file is part of GNU inetlib, a library.
# Line 46  import java.io.OutputStream; Line 46  import java.io.OutputStream;
46   * A DTP output stream that implements the FTP compressed transfer mode.   * A DTP output stream that implements the FTP compressed transfer mode.
47   *   *
48   * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>   * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
  * @version $Revision$ $Date$  
49   */   */
50  class CompressedOutputStream extends DTPOutputStream  class CompressedOutputStream
51      extends DTPOutputStream
52  {  {
53    
54    static final byte RECORD = -128;      // 0x80    static final byte RECORD = -128;      // 0x80
55    static final byte EOF = 64;   // 0x40    static final byte EOF = 64;   // 0x40
56    
57    CompressedOutputStream (DTP dtp, OutputStream out)    CompressedOutputStream(DTP dtp, OutputStream out)
58      {    {
59        super (dtp, out);      super(dtp, out);
60      }    }
61      
62    /**    /**
63     * Just one byte cannot be compressed.     * Just one byte cannot be compressed.
64     * It takes 5 bytes to transmit - hardly very compressed!     * It takes 5 bytes to transmit - hardly very compressed!
65     */     */
66    public void write (int c) throws IOException    public void write(int c)
67      {      throws IOException
68        if (transferComplete)    {
69          {      if (transferComplete)
70            return;        {
71          }          return;
72        byte[] buf = new byte[]        }
73          {      byte[] buf = new byte[]
74            RECORD,                   /* record descriptor */        {
75            0x00, 0x01,             /* one byte */          RECORD,                   /* record descriptor */
76            0x01,                   /* one uncompressed byte */          0x00, 0x01,             /* one byte */
77            (byte) c                /* the byte */          0x01,                   /* one uncompressed byte */
78          };          (byte) c                /* the byte */
79        out.write (buf, 0, 5);        };
80      }      out.write(buf, 0, 5);
81      }
82    public void write (byte[] b) throws IOException  
83      {    public void write(byte[] b)
84        write (b, 0, b.length);      throws IOException
85      }    {
86        write(b, 0, b.length);
87      }
88    
89    /**    /**
90     * The larger len is, the better.     * The larger len is, the better.
91     */     */
92    public void write (byte[] b, int off, int len) throws IOException    public void write(byte[] b, int off, int len)
93      {      throws IOException
94        if (transferComplete)    {
95          {      if (transferComplete)
96            return;        {
97          }          return;
98        byte[] buf = compress (b, off, len);        }
99        len = buf.length;      byte[] buf = compress(b, off, len);
100        buf[0] = RECORD;            /* record descriptor */      len = buf.length;
101        buf[1] = (byte) ((len & 0x00ff) >> 8);      /* high byte of bytecount */      buf[0] = RECORD;            /* record descriptor */
102        buf[2] = (byte) (len & 0xff00);     /* low byte of bytecount */      buf[1] = (byte) ((len & 0x00ff) >> 8);      /* high byte of bytecount */
103        out.write (buf, 0, len);      buf[2] = (byte) (len & 0xff00);     /* low byte of bytecount */
104      }      out.write(buf, 0, len);
105      }
106    
107    /**    /**
108     * Returns the compressed form of the given byte array.     * Returns the compressed form of the given byte array.
109     * The first 3 bytes are left free for header information.     * The first 3 bytes are left free for header information.
110     */     */
111    byte[] compress (byte[] b, int off, int len)    byte[] compress(byte[] b, int off, int len)
112      {    {
113        byte[] buf = new byte[len];      byte[] buf = new byte[len];
114        byte last = 0;      byte last = 0;
115        int pos = 0, raw_count = 0, rep_count = 1;      int pos = 0, raw_count = 0, rep_count = 1;
116        for (int i = off; i < len; i++)      for (int i = off; i < len; i++)
117          {        {
118            byte c = b[i];          byte c = b[i];
119            if (i > off && c == last) // compress          if (i > off && c == last) // compress
120              {            {
121                if (raw_count > 0)      // flush raw bytes to buf              if (raw_count > 0)      // flush raw bytes to buf
122                  {                {
123                    // need to add raw_count+1 bytes                  // need to add raw_count+1 bytes
124                    if (pos + (raw_count + 1) > buf.length)                  if (pos + (raw_count + 1) > buf.length)
125                      {                    {
126                        buf = realloc (buf, len);                      buf = realloc(buf, len);
127                      }                    }
128                    pos = flush_raw (buf, pos, b, (i - raw_count) - 1,                  pos = flush_raw(buf, pos, b, (i - raw_count) - 1,
129                                     raw_count);                                  raw_count);
130                    raw_count = 0;                  raw_count = 0;
131                  }                }
132                rep_count++;            // keep looking for same byte              rep_count++;            // keep looking for same byte
133              }            }
134            else          else
135              {            {
136                if (rep_count > 1)      // flush compressed bytes to buf              if (rep_count > 1)      // flush compressed bytes to buf
137                  {                {
138                    // need to add 2 bytes                  // need to add 2 bytes
139                    if (pos + 2 > buf.length)                  if (pos + 2 > buf.length)
140                      {                    {
141                        buf = realloc (buf, len);                      buf = realloc(buf, len);
142                      }                    }
143                    pos = flush_compressed (buf, pos, rep_count, last);                  pos = flush_compressed(buf, pos, rep_count, last);
144                    rep_count = 1;                  rep_count = 1;
145                  }                }
146                raw_count++;            // keep looking for raw bytes              raw_count++;            // keep looking for raw bytes
147              }            }
148            if (rep_count == 127)     // flush compressed bytes          if (rep_count == 127)     // flush compressed bytes
149              {            {
150                // need to add 2 bytes              // need to add 2 bytes
151                if (pos + 2 > buf.length)              if (pos + 2 > buf.length)
152                  {                {
153                    buf = realloc (buf, len);                  buf = realloc(buf, len);
154                  }                }
155                pos = flush_compressed (buf, pos, rep_count, last);              pos = flush_compressed(buf, pos, rep_count, last);
156                rep_count = 1;              rep_count = 1;
157              }            }
158            if (raw_count == 127)     // flush raw bytes          if (raw_count == 127)     // flush raw bytes
159              {            {
160                // need to add raw_count+1 bytes              // need to add raw_count+1 bytes
161                if (pos + (raw_count + 1) > buf.length)              if (pos + (raw_count + 1) > buf.length)
162                  {                {
163                    buf = realloc (buf, len);                  buf = realloc(buf, len);
164                  }                }
165                pos = flush_raw (buf, pos, b, (i - raw_count), raw_count);              pos = flush_raw(buf, pos, b, (i - raw_count), raw_count);
166                raw_count = 0;              raw_count = 0;
167              }            }
168            last = c;          last = c;
169          }        }
170        if (rep_count > 1)          // flush compressed bytes      if (rep_count > 1)          // flush compressed bytes
171          {        {
172            // need to add 2 bytes          // need to add 2 bytes
173            if (pos + 2 > buf.length)          if (pos + 2 > buf.length)
174              {            {
175                buf = realloc (buf, len);              buf = realloc(buf, len);
176              }            }
177            pos = flush_compressed (buf, pos, rep_count, last);          pos = flush_compressed(buf, pos, rep_count, last);
178            rep_count = 1;          rep_count = 1;
179          }        }
180        if (raw_count > 0)          // flush raw bytes      if (raw_count > 0)          // flush raw bytes
181          {        {
182            // need to add raw_count+1 bytes          // need to add raw_count+1 bytes
183            if (pos + (raw_count + 1) > buf.length)          if (pos + (raw_count + 1) > buf.length)
184              {            {
185                buf = realloc (buf, len);              buf = realloc(buf, len);
186              }            }
187            pos = flush_raw (buf, pos, b, (len - raw_count), raw_count);          pos = flush_raw(buf, pos, b, (len - raw_count), raw_count);
188            raw_count = 0;          raw_count = 0;
189          }        }
190        byte[] ret = new byte[pos + 3];      byte[] ret = new byte[pos + 3];
191        System.arraycopy (buf, 0, ret, 3, pos);      System.arraycopy(buf, 0, ret, 3, pos);
192        return ret;      return ret;
193      }    }
194      
195    int flush_compressed (byte[] buf, int pos, int count, byte c)    int flush_compressed(byte[] buf, int pos, int count, byte c)
196      {    {
197        buf[pos++] = (byte) (0x80 | count);      buf[pos++] = (byte) (0x80 | count);
198        buf[pos++] = c;      buf[pos++] = c;
199        return pos;      return pos;
200      }    }
201    
202    int flush_raw (byte[] buf, int pos, byte[] src, int off, int len)    int flush_raw(byte[] buf, int pos, byte[] src, int off, int len)
203      {    {
204        buf[pos++] = (byte) len;      buf[pos++] = (byte) len;
205        System.arraycopy (src, off, buf, pos, len);      System.arraycopy(src, off, buf, pos, len);
206        return pos + len;      return pos + len;
207      }    }
208    
209    byte[] realloc (byte[] buf, int len)    byte[] realloc(byte[] buf, int len)
210      {    {
211        byte[] ret = new byte[buf.length + len];      byte[] ret = new byte[buf.length + len];
212        System.arraycopy (buf, 0, ret, 0, buf.length);      System.arraycopy(buf, 0, ret, 0, buf.length);
213        return ret;      return ret;
214      }    }
215    
216    public void close () throws IOException    public void close()
217      {      throws IOException
218        byte[] buf = new byte[]    {
219          {      byte[] buf = new byte[]
220            EOF,                      /* eof descriptor */        {
221            0x00, 0x00              /* no bytes */          EOF,                      /* eof descriptor */
222          };          0x00, 0x00              /* no bytes */
223        out.write (buf, 0, 3);        };
224        out.close ();      out.write(buf, 0, 3);
225      }      out.close();
226      }
227    
228  }  }
229    

Legend:
Removed from v.1.5  
changed lines
  Added in v.1.6

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26