Implementation of ZipInputStream emul
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Wed, 30 Jan 2013 14:03:49 +0100
branchemul
changeset 6119839e9a75bcf
parent 610 0127bd22630c
child 612 4bc57543ab71
Implementation of ZipInputStream
emul/mini/src/main/java/java/lang/Cloneable.java
emul/mini/src/main/java/java/lang/String.java
emul/mini/src/main/java/java/util/zip/CRC32.java
emul/mini/src/main/java/java/util/zip/Inflater.java
emul/mini/src/main/java/java/util/zip/ZipEntry.java
emul/mini/src/main/java/java/util/zip/ZipInputStream.java
emul/mini/src/main/resources/org/apidesign/vm4brwsr/emul/zip/js-inflate.min.js
vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/GenerateZip.java
vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/GenerateZipProcessor.java
vmtest/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/CRC32Test.java
vmtest/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/ZipFileTest.java
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/emul/mini/src/main/java/java/lang/Cloneable.java	Wed Jan 30 14:03:49 2013 +0100
     1.3 @@ -0,0 +1,54 @@
     1.4 +/*
     1.5 + * Copyright (c) 1995, 2004, Oracle and/or its affiliates. All rights reserved.
     1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 + *
     1.8 + * This code is free software; you can redistribute it and/or modify it
     1.9 + * under the terms of the GNU General Public License version 2 only, as
    1.10 + * published by the Free Software Foundation.  Oracle designates this
    1.11 + * particular file as subject to the "Classpath" exception as provided
    1.12 + * by Oracle in the LICENSE file that accompanied this code.
    1.13 + *
    1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.17 + * version 2 for more details (a copy is included in the LICENSE file that
    1.18 + * accompanied this code).
    1.19 + *
    1.20 + * You should have received a copy of the GNU General Public License version
    1.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.23 + *
    1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    1.25 + * or visit www.oracle.com if you need additional information or have any
    1.26 + * questions.
    1.27 + */
    1.28 +
    1.29 +package java.lang;
    1.30 +
    1.31 +/**
    1.32 + * A class implements the <code>Cloneable</code> interface to
    1.33 + * indicate to the {@link java.lang.Object#clone()} method that it
    1.34 + * is legal for that method to make a
    1.35 + * field-for-field copy of instances of that class.
    1.36 + * <p>
    1.37 + * Invoking Object's clone method on an instance that does not implement the
    1.38 + * <code>Cloneable</code> interface results in the exception
    1.39 + * <code>CloneNotSupportedException</code> being thrown.
    1.40 + * <p>
    1.41 + * By convention, classes that implement this interface should override
    1.42 + * <tt>Object.clone</tt> (which is protected) with a public method.
    1.43 + * See {@link java.lang.Object#clone()} for details on overriding this
    1.44 + * method.
    1.45 + * <p>
    1.46 + * Note that this interface does <i>not</i> contain the <tt>clone</tt> method.
    1.47 + * Therefore, it is not possible to clone an object merely by virtue of the
    1.48 + * fact that it implements this interface.  Even if the clone method is invoked
    1.49 + * reflectively, there is no guarantee that it will succeed.
    1.50 + *
    1.51 + * @author  unascribed
    1.52 + * @see     java.lang.CloneNotSupportedException
    1.53 + * @see     java.lang.Object#clone()
    1.54 + * @since   JDK1.0
    1.55 + */
    1.56 +public interface Cloneable {
    1.57 +}
     2.1 --- a/emul/mini/src/main/java/java/lang/String.java	Wed Jan 30 14:01:52 2013 +0100
     2.2 +++ b/emul/mini/src/main/java/java/lang/String.java	Wed Jan 30 14:03:49 2013 +0100
     2.3 @@ -201,6 +201,10 @@
     2.4       *          If the {@code offset} and {@code count} arguments index
     2.5       *          characters outside the bounds of the {@code value} array
     2.6       */
     2.7 +    public String(char value[], int offset, int count) {
     2.8 +        initFromCharArray(value, offset, count);
     2.9 +    }
    2.10 +    
    2.11      @JavaScriptBody(args = { "charArr", "off", "cnt" }, body =
    2.12          "var up = off + cnt;\n" +
    2.13          "for (var i = off; i < up; i++) {\n" +
    2.14 @@ -208,8 +212,7 @@
    2.15          "}\n" +
    2.16          "this._r(charArr.slice(off, up).join(\"\"));\n"
    2.17      )
    2.18 -    public String(char value[], int offset, int count) {
    2.19 -    }
    2.20 +    private native void initFromCharArray(char value[], int offset, int count);
    2.21  
    2.22      /**
    2.23       * Allocates a new {@code String} that contains characters from a subarray
    2.24 @@ -555,7 +558,7 @@
    2.25              int ch = nextChar(bytes, at);
    2.26              v[chlen++] = (char)ch;
    2.27          }
    2.28 -        this.r = new String(v, 0, chlen);
    2.29 +        initFromCharArray(v, 0, chlen);
    2.30      }
    2.31  
    2.32      /**
     3.1 --- a/emul/mini/src/main/java/java/util/zip/CRC32.java	Wed Jan 30 14:01:52 2013 +0100
     3.2 +++ b/emul/mini/src/main/java/java/util/zip/CRC32.java	Wed Jan 30 14:03:49 2013 +0100
     3.3 @@ -33,7 +33,7 @@
     3.4   */
     3.5  public
     3.6  class CRC32 implements Checksum {
     3.7 -    private int crc;
     3.8 +    private int crc = 0xFFFFFFFF;
     3.9  
    3.10      /**
    3.11       * Creates a new CRC32 object.
    3.12 @@ -49,7 +49,8 @@
    3.13       * @param b the byte to update the checksum with
    3.14       */
    3.15      public void update(int b) {
    3.16 -        crc = update(crc, b);
    3.17 +        byte[] arr = { (byte)b };
    3.18 +        update(arr);
    3.19      }
    3.20  
    3.21      /**
    3.22 @@ -88,6 +89,25 @@
    3.23          return (long)crc & 0xffffffffL;
    3.24      }
    3.25  
    3.26 -    private native static int update(int crc, int b);
    3.27 -    private native static int updateBytes(int crc, byte[] b, int off, int len);
    3.28 +    // XXX: taken from 
    3.29 +    // http://introcs.cs.princeton.edu/java/51data/CRC32.java.html
    3.30 +    private static int updateBytes(int crc, byte[] arr, int off, int len) {
    3.31 +        int poly = 0xEDB88320;   // reverse polynomial
    3.32 +
    3.33 +        while (len-- > 0) {
    3.34 +            byte b = arr[off++];
    3.35 +            int temp = (crc ^ b) & 0xff;
    3.36 +
    3.37 +            // read 8 bits one at a time
    3.38 +            for (int i = 0; i < 8; i++) {
    3.39 +                if ((temp & 1) == 1) {
    3.40 +                    temp = (temp >>> 1) ^ poly;
    3.41 +                } else {
    3.42 +                    temp = (temp >>> 1);
    3.43 +                }
    3.44 +            }
    3.45 +            crc = (crc >>> 8) ^ temp;
    3.46 +        }
    3.47 +        return crc ^ 0xffffffff;
    3.48 +    }
    3.49  }
     4.1 --- a/emul/mini/src/main/java/java/util/zip/Inflater.java	Wed Jan 30 14:01:52 2013 +0100
     4.2 +++ b/emul/mini/src/main/java/java/util/zip/Inflater.java	Wed Jan 30 14:03:49 2013 +0100
     4.3 @@ -25,6 +25,9 @@
     4.4  
     4.5  package java.util.zip;
     4.6  
     4.7 +import org.apidesign.bck2brwsr.core.ExtraJavaScript;
     4.8 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
     4.9 +
    4.10  /**
    4.11   * This class provides support for general purpose decompression using the
    4.12   * popular ZLIB compression library. The ZLIB compression library was
    4.13 @@ -70,22 +73,19 @@
    4.14   * @author      David Connelly
    4.15   *
    4.16   */
    4.17 +@ExtraJavaScript(
    4.18 +    resource = "/org/apidesign/vm4brwsr/emul/zip/js-inflate.min.js"
    4.19 +)
    4.20  public
    4.21  class Inflater {
    4.22 -
    4.23 -    private final ZStreamRef zsRef;
    4.24 -    private byte[] buf = defaultBuf;
    4.25 -    private int off, len;
    4.26 +    private String data = "";
    4.27 +    private int offset;
    4.28 +    private long counter;
    4.29      private boolean finished;
    4.30      private boolean needDict;
    4.31  
    4.32      private static final byte[] defaultBuf = new byte[0];
    4.33  
    4.34 -    static {
    4.35 -        /* Zip library is loaded from System.initializeSystemClass */
    4.36 -        initIDs();
    4.37 -    }
    4.38 -
    4.39      /**
    4.40       * Creates a new decompressor. If the parameter 'nowrap' is true then
    4.41       * the ZLIB header and checksum fields will not be used. This provides
    4.42 @@ -98,7 +98,6 @@
    4.43       * @param nowrap if true then support GZIP compatible compression
    4.44       */
    4.45      public Inflater(boolean nowrap) {
    4.46 -        zsRef = new ZStreamRef(init(nowrap));
    4.47      }
    4.48  
    4.49      /**
    4.50 @@ -124,11 +123,7 @@
    4.51          if (off < 0 || len < 0 || off > b.length - len) {
    4.52              throw new ArrayIndexOutOfBoundsException();
    4.53          }
    4.54 -        synchronized (zsRef) {
    4.55 -            this.buf = b;
    4.56 -            this.off = off;
    4.57 -            this.len = len;
    4.58 -        }
    4.59 +        data = (String) infl(b, off, len);
    4.60      }
    4.61  
    4.62      /**
    4.63 @@ -160,11 +155,7 @@
    4.64          if (off < 0 || len < 0 || off > b.length - len) {
    4.65              throw new ArrayIndexOutOfBoundsException();
    4.66          }
    4.67 -        synchronized (zsRef) {
    4.68 -            ensureOpen();
    4.69 -            setDictionary(zsRef.address(), b, off, len);
    4.70 -            needDict = false;
    4.71 -        }
    4.72 +        needDict = false;
    4.73      }
    4.74  
    4.75      /**
    4.76 @@ -187,9 +178,7 @@
    4.77       * @return the total number of bytes remaining in the input buffer
    4.78       */
    4.79      public int getRemaining() {
    4.80 -        synchronized (zsRef) {
    4.81 -            return len;
    4.82 -        }
    4.83 +        return data.length() - offset;
    4.84      }
    4.85  
    4.86      /**
    4.87 @@ -199,9 +188,7 @@
    4.88       * @return true if no data remains in the input buffer
    4.89       */
    4.90      public boolean needsInput() {
    4.91 -        synchronized (zsRef) {
    4.92 -            return len <= 0;
    4.93 -        }
    4.94 +        return getRemaining() <= 0;
    4.95      }
    4.96  
    4.97      /**
    4.98 @@ -210,9 +197,7 @@
    4.99       * @see Inflater#setDictionary
   4.100       */
   4.101      public boolean needsDictionary() {
   4.102 -        synchronized (zsRef) {
   4.103 -            return needDict;
   4.104 -        }
   4.105 +        return needDict;
   4.106      }
   4.107  
   4.108      /**
   4.109 @@ -222,9 +207,7 @@
   4.110       * reached
   4.111       */
   4.112      public boolean finished() {
   4.113 -        synchronized (zsRef) {
   4.114 -            return finished;
   4.115 -        }
   4.116 +        return finished;
   4.117      }
   4.118  
   4.119      /**
   4.120 @@ -251,11 +234,21 @@
   4.121          if (off < 0 || len < 0 || off > b.length - len) {
   4.122              throw new ArrayIndexOutOfBoundsException();
   4.123          }
   4.124 -        synchronized (zsRef) {
   4.125 -            ensureOpen();
   4.126 -            return inflateBytes(zsRef.address(), b, off, len);
   4.127 +        int cnt = 0;
   4.128 +        while (offset < data.length()) {
   4.129 +            b[off++] = (byte)data.charAt(offset++);
   4.130 +            cnt++;
   4.131 +            counter++;
   4.132          }
   4.133 +        return cnt;
   4.134      }
   4.135 +    
   4.136 +    @JavaScriptBody(args = { "arr", "offset", "len" }, body = 
   4.137 +          "var r = {};\n"
   4.138 +        + "r.charCodeAt = function(idx) { return arr[offset + idx]; };\n"
   4.139 +        + "return JSInflate.inflate(r);"
   4.140 +    )
   4.141 +    private static native Object infl(byte[] arr, int offset, int len);
   4.142  
   4.143      /**
   4.144       * Uncompresses bytes into specified buffer. Returns actual number
   4.145 @@ -279,10 +272,7 @@
   4.146       * @return the ADLER-32 value of the uncompressed data
   4.147       */
   4.148      public int getAdler() {
   4.149 -        synchronized (zsRef) {
   4.150 -            ensureOpen();
   4.151 -            return getAdler(zsRef.address());
   4.152 -        }
   4.153 +        return 0;
   4.154      }
   4.155  
   4.156      /**
   4.157 @@ -305,10 +295,7 @@
   4.158       * @since 1.5
   4.159       */
   4.160      public long getBytesRead() {
   4.161 -        synchronized (zsRef) {
   4.162 -            ensureOpen();
   4.163 -            return getBytesRead(zsRef.address());
   4.164 -        }
   4.165 +        return counter;
   4.166      }
   4.167  
   4.168      /**
   4.169 @@ -331,24 +318,17 @@
   4.170       * @since 1.5
   4.171       */
   4.172      public long getBytesWritten() {
   4.173 -        synchronized (zsRef) {
   4.174 -            ensureOpen();
   4.175 -            return getBytesWritten(zsRef.address());
   4.176 -        }
   4.177 +        return counter;
   4.178      }
   4.179  
   4.180      /**
   4.181       * Resets inflater so that a new set of input data can be processed.
   4.182       */
   4.183      public void reset() {
   4.184 -        synchronized (zsRef) {
   4.185 -            ensureOpen();
   4.186 -            reset(zsRef.address());
   4.187 -            buf = defaultBuf;
   4.188 -            finished = false;
   4.189 -            needDict = false;
   4.190 -            off = len = 0;
   4.191 -        }
   4.192 +        data = "";
   4.193 +        finished = false;
   4.194 +        needDict = false;
   4.195 +        offset = 0;
   4.196      }
   4.197  
   4.198      /**
   4.199 @@ -359,44 +339,5 @@
   4.200       * object is undefined.
   4.201       */
   4.202      public void end() {
   4.203 -        synchronized (zsRef) {
   4.204 -            long addr = zsRef.address();
   4.205 -            zsRef.clear();
   4.206 -            if (addr != 0) {
   4.207 -                end(addr);
   4.208 -                buf = null;
   4.209 -            }
   4.210 -        }
   4.211      }
   4.212 -
   4.213 -    /**
   4.214 -     * Closes the decompressor when garbage is collected.
   4.215 -     */
   4.216 -    protected void finalize() {
   4.217 -        end();
   4.218 -    }
   4.219 -
   4.220 -    private void ensureOpen () {
   4.221 -        assert Thread.holdsLock(zsRef);
   4.222 -        if (zsRef.address() == 0)
   4.223 -            throw new NullPointerException("Inflater has been closed");
   4.224 -    }
   4.225 -
   4.226 -    boolean ended() {
   4.227 -        synchronized (zsRef) {
   4.228 -            return zsRef.address() == 0;
   4.229 -        }
   4.230 -    }
   4.231 -
   4.232 -    private native static void initIDs();
   4.233 -    private native static long init(boolean nowrap);
   4.234 -    private native static void setDictionary(long addr, byte[] b, int off,
   4.235 -                                             int len);
   4.236 -    private native int inflateBytes(long addr, byte[] b, int off, int len)
   4.237 -            throws DataFormatException;
   4.238 -    private native static int getAdler(long addr);
   4.239 -    private native static long getBytesRead(long addr);
   4.240 -    private native static long getBytesWritten(long addr);
   4.241 -    private native static void reset(long addr);
   4.242 -    private native static void end(long addr);
   4.243  }
     5.1 --- a/emul/mini/src/main/java/java/util/zip/ZipEntry.java	Wed Jan 30 14:01:52 2013 +0100
     5.2 +++ b/emul/mini/src/main/java/java/util/zip/ZipEntry.java	Wed Jan 30 14:03:49 2013 +0100
     5.3 @@ -25,8 +25,6 @@
     5.4  
     5.5  package java.util.zip;
     5.6  
     5.7 -import java.util.Date;
     5.8 -
     5.9  /**
    5.10   * This class is used to represent a ZIP file entry.
    5.11   *
    5.12 @@ -281,6 +279,8 @@
    5.13       * Converts DOS time to Java time (number of milliseconds since epoch).
    5.14       */
    5.15      private static long dosToJavaTime(long dtime) {
    5.16 +        return dtime;
    5.17 +        /* XXX:
    5.18          Date d = new Date((int)(((dtime >> 25) & 0x7f) + 80),
    5.19                            (int)(((dtime >> 21) & 0x0f) - 1),
    5.20                            (int)((dtime >> 16) & 0x1f),
    5.21 @@ -288,12 +288,15 @@
    5.22                            (int)((dtime >> 5) & 0x3f),
    5.23                            (int)((dtime << 1) & 0x3e));
    5.24          return d.getTime();
    5.25 +        */
    5.26      }
    5.27  
    5.28      /*
    5.29       * Converts Java time to DOS time.
    5.30       */
    5.31      private static long javaToDosTime(long time) {
    5.32 +        return time;
    5.33 +        /* XXX:
    5.34          Date d = new Date(time);
    5.35          int year = d.getYear() + 1900;
    5.36          if (year < 1980) {
    5.37 @@ -302,6 +305,7 @@
    5.38          return (year - 1980) << 25 | (d.getMonth() + 1) << 21 |
    5.39                 d.getDate() << 16 | d.getHours() << 11 | d.getMinutes() << 5 |
    5.40                 d.getSeconds() >> 1;
    5.41 +        */
    5.42      }
    5.43  
    5.44      /**
    5.45 @@ -321,7 +325,7 @@
    5.46              return e;
    5.47          } catch (CloneNotSupportedException e) {
    5.48              // This should never happen, since we are Cloneable
    5.49 -            throw new InternalError();
    5.50 +            throw new IllegalStateException();
    5.51          }
    5.52      }
    5.53  }
     6.1 --- a/emul/mini/src/main/java/java/util/zip/ZipInputStream.java	Wed Jan 30 14:01:52 2013 +0100
     6.2 +++ b/emul/mini/src/main/java/java/util/zip/ZipInputStream.java	Wed Jan 30 14:03:49 2013 +0100
     6.3 @@ -29,9 +29,8 @@
     6.4  import java.io.IOException;
     6.5  import java.io.EOFException;
     6.6  import java.io.PushbackInputStream;
     6.7 -import java.nio.charset.Charset;
     6.8 -import java.nio.charset.StandardCharsets;
     6.9  import static java.util.zip.ZipConstants64.*;
    6.10 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
    6.11  
    6.12  /**
    6.13   * This class implements an input stream filter for reading files in the
    6.14 @@ -56,8 +55,6 @@
    6.15      // one entry
    6.16      private boolean entryEOF = false;
    6.17  
    6.18 -    private ZipCoder zc;
    6.19 -
    6.20      /**
    6.21       * Check to make sure that this stream has not been closed
    6.22       */
    6.23 @@ -76,7 +73,12 @@
    6.24       * @param in the actual input stream
    6.25       */
    6.26      public ZipInputStream(InputStream in) {
    6.27 -        this(in, StandardCharsets.UTF_8);
    6.28 +//        this(in, "UTF-8");
    6.29 +        super(new PushbackInputStream(in, 512), new Inflater(true), 512);
    6.30 +        usesDefaultInflater = true;
    6.31 +        if(in == null) {
    6.32 +            throw new NullPointerException("in is null");
    6.33 +        }
    6.34      }
    6.35  
    6.36      /**
    6.37 @@ -92,7 +94,7 @@
    6.38       *        flag is set).
    6.39       *
    6.40       * @since 1.7
    6.41 -     */
    6.42 +     *
    6.43      public ZipInputStream(InputStream in, Charset charset) {
    6.44          super(new PushbackInputStream(in, 512), new Inflater(true), 512);
    6.45          usesDefaultInflater = true;
    6.46 @@ -103,6 +105,7 @@
    6.47              throw new NullPointerException("charset is null");
    6.48          this.zc = ZipCoder.get(charset);
    6.49      }
    6.50 +    */
    6.51  
    6.52      /**
    6.53       * Reads the next ZIP file entry and positions the stream at the
    6.54 @@ -295,8 +298,8 @@
    6.55          readFully(b, 0, len);
    6.56          // Force to use UTF-8 if the EFS bit is ON, even the cs is NOT UTF-8
    6.57          ZipEntry e = createZipEntry(((flag & EFS) != 0)
    6.58 -                                    ? zc.toStringUTF8(b, len)
    6.59 -                                    : zc.toString(b, len));
    6.60 +                                    ? toStringUTF8(b, len)
    6.61 +                                    : toString(b, len));
    6.62          // now get the remaining fields for the entry
    6.63          if ((flag & 1) == 1) {
    6.64              throw new ZipException("encrypted ZIP entry not supported");
    6.65 @@ -453,4 +456,12 @@
    6.66      private static final long get64(byte b[], int off) {
    6.67          return get32(b, off) | (get32(b, off+4) << 32);
    6.68      }
    6.69 +
    6.70 +    private static String toStringUTF8(byte[] arr, int len) {
    6.71 +        return new String(arr, 0, len);
    6.72 +    }
    6.73 +    
    6.74 +    private static String toString(byte[] b, int len) {
    6.75 +        return new String(b, 0, len);
    6.76 +    }
    6.77  }
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/emul/mini/src/main/resources/org/apidesign/vm4brwsr/emul/zip/js-inflate.min.js	Wed Jan 30 14:03:49 2013 +0100
     7.3 @@ -0,0 +1,1 @@
     7.4 +(function(G){var n=32768;var w=0;var I=1;var i=2;var S=9;var h=6;var t=32768;var a=64;var C;var k;var Q=null;var b;var M,D;var s;var r;var U;var N;var T;var y;var m,p;var f,j;var B;var E;var P=new Array(0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535);var c=new Array(3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,0,0);var L=new Array(0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,99,99);var J=new Array(1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577);var z=new Array(0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13);var q=new Array(16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15);function x(){this.next=null;this.list=null}function H(){this.e=0;this.b=0;this.n=0;this.t=null}function l(ax,al,ag,av,au,aq){this.BMAX=16;this.N_MAX=288;this.status=0;this.root=null;this.m=0;var ay;var aw=new Array(this.BMAX+1);var V;var at;var ar;var ap;var ao;var an;var am;var W=new Array(this.BMAX+1);var aj;var X;var ai;var ah=new H();var af=new Array(this.BMAX);var ae=new Array(this.N_MAX);var ad;var ab=new Array(this.BMAX+1);var ac;var aa;var Z;var ak;var Y;Y=this.root=null;for(ao=0;ao<aw.length;ao++){aw[ao]=0}for(ao=0;ao<W.length;ao++){W[ao]=0}for(ao=0;ao<af.length;ao++){af[ao]=null}for(ao=0;ao<ae.length;ao++){ae[ao]=0}for(ao=0;ao<ab.length;ao++){ab[ao]=0}V=al>256?ax[256]:this.BMAX;aj=ax;X=0;ao=al;do{aw[aj[X]]++;X++}while(--ao>0);if(aw[0]==al){this.root=null;this.m=0;this.status=0;return}for(an=1;an<=this.BMAX;an++){if(aw[an]!=0){break}}am=an;if(aq<an){aq=an}for(ao=this.BMAX;ao!=0;ao--){if(aw[ao]!=0){break}}ar=ao;if(aq>ao){aq=ao}for(aa=1<<an;an<ao;an++,aa<<=1){if((aa-=aw[an])<0){this.status=2;this.m=aq;return}}if((aa-=aw[ao])<0){this.status=2;this.m=aq;return}aw[ao]+=aa;ab[1]=an=0;aj=aw;X=1;ac=2;while(--ao>0){ab[ac++]=(an+=aj[X++])}aj=ax;X=0;ao=0;do{if((an=aj[X++])!=0){ae[ab[an]++]=ao}}while(++ao<al);al=ab[ar];ab[0]=ao=0;aj=ae;X=0;ap=-1;ad=W[0]=0;ai=null;Z=0;for(;am<=ar;am++){ay=aw[am];while(ay-->0){while(am>ad+W[1+ap]){ad+=W[1+ap];ap++;Z=(Z=ar-ad)>aq?aq:Z;if((at=1<<(an=am-ad))>ay+1){at-=ay+1;ac=am;while(++an<Z){if((at<<=1)<=aw[++ac]){break}at-=aw[ac]}}if(ad+an>V&&ad<V){an=V-ad}Z=1<<an;W[1+ap]=an;ai=new Array(Z);for(ak=0;ak<Z;ak++){ai[ak]=new H()}if(Y==null){Y=this.root=new x()}else{Y=Y.next=new x()}Y.next=null;Y.list=ai;af[ap]=ai;if(ap>0){ab[ap]=ao;ah.b=W[ap];ah.e=16+an;ah.t=ai;an=(ao&((1<<ad)-1))>>(ad-W[ap]);af[ap-1][an].e=ah.e;af[ap-1][an].b=ah.b;af[ap-1][an].n=ah.n;af[ap-1][an].t=ah.t}}ah.b=am-ad;if(X>=al){ah.e=99}else{if(aj[X]<ag){ah.e=(aj[X]<256?16:15);ah.n=aj[X++]}else{ah.e=au[aj[X]-ag];ah.n=av[aj[X++]-ag]}}at=1<<(am-ad);for(an=ao>>ad;an<Z;an+=at){ai[an].e=ah.e;ai[an].b=ah.b;ai[an].n=ah.n;ai[an].t=ah.t}for(an=1<<(am-1);(ao&an)!=0;an>>=1){ao^=an}ao^=an;while((ao&((1<<ad)-1))!=ab[ap]){ad-=W[ap];ap--}}}this.m=W[1];this.status=((aa!=0&&ar!=1)?1:0)}function e(){if(B.length==E){return -1}return B.charCodeAt(E++)&255}function R(V){while(r<V){s|=e()<<r;r+=8}}function u(V){return s&P[V]}function d(V){s>>=V;r-=V}function g(aa,Y,W){var X;var V;var Z;if(W==0){return 0}Z=0;for(;;){R(f);V=m.list[u(f)];X=V.e;while(X>16){if(X==99){return -1}d(V.b);X-=16;R(X);V=V.t[u(X)];X=V.e}d(V.b);if(X==16){k&=n-1;aa[Y+Z++]=C[k++]=V.n;if(Z==W){return W}continue}if(X==15){break}R(X);T=V.n+u(X);d(X);R(j);V=p.list[u(j)];X=V.e;while(X>16){if(X==99){return -1}d(V.b);X-=16;R(X);V=V.t[u(X)];X=V.e}d(V.b);R(X);y=k-V.n-u(X);d(X);while(T>0&&Z<W){T--;y&=n-1;k&=n-1;aa[Y+Z++]=C[k++]=C[y++]}if(Z==W){return W}}U=-1;return Z}function v(Y,W,V){var X;X=r&7;d(X);R(16);X=u(16);d(16);R(16);if(X!=((~s)&65535)){return -1}d(16);T=X;X=0;while(T>0&&X<V){T--;k&=n-1;R(8);Y[W+X++]=C[k++]=u(8);d(8)}if(T==0){U=-1}return X}function K(aa,Z,X){if(Q==null){var W;var V=new Array(288);var Y;for(W=0;W<144;W++){V[W]=8}for(;W<256;W++){V[W]=9}for(;W<280;W++){V[W]=7}for(;W<288;W++){V[W]=8}M=7;Y=new l(V,288,257,c,L,M);if(Y.status!=0){alert("HufBuild error: "+Y.status);return -1}Q=Y.root;M=Y.m;for(W=0;W<30;W++){V[W]=5}zip_fixed_bd=5;Y=new l(V,30,0,J,z,zip_fixed_bd);if(Y.status>1){Q=null;alert("HufBuild error: "+Y.status);return -1}b=Y.root;zip_fixed_bd=Y.m}m=Q;p=b;f=M;j=zip_fixed_bd;return g(aa,Z,X)}function A(af,X,ah){var ab;var aa;var Y;var W;var ag;var ad;var V;var Z;var ae=new Array(286+30);var ac;for(ab=0;ab<ae.length;ab++){ae[ab]=0}R(5);V=257+u(5);d(5);R(5);Z=1+u(5);d(5);R(4);ad=4+u(4);d(4);if(V>286||Z>30){return -1}for(aa=0;aa<ad;aa++){R(3);ae[q[aa]]=u(3);d(3)}for(;aa<19;aa++){ae[q[aa]]=0}f=7;ac=new l(ae,19,19,null,null,f);if(ac.status!=0){return -1}m=ac.root;f=ac.m;W=V+Z;ab=Y=0;while(ab<W){R(f);ag=m.list[u(f)];aa=ag.b;d(aa);aa=ag.n;if(aa<16){ae[ab++]=Y=aa}else{if(aa==16){R(2);aa=3+u(2);d(2);if(ab+aa>W){return -1}while(aa-->0){ae[ab++]=Y}}else{if(aa==17){R(3);aa=3+u(3);d(3);if(ab+aa>W){return -1}while(aa-->0){ae[ab++]=0}Y=0}else{R(7);aa=11+u(7);d(7);if(ab+aa>W){return -1}while(aa-->0){ae[ab++]=0}Y=0}}}}f=S;ac=new l(ae,V,257,c,L,f);if(f==0){ac.status=1}if(ac.status!=0){if(ac.status==1){}return -1}m=ac.root;f=ac.m;for(ab=0;ab<Z;ab++){ae[ab]=ae[ab+V]}j=h;ac=new l(ae,Z,0,J,z,j);p=ac.root;j=ac.m;if(j==0&&V>257){return -1}if(ac.status==1){}if(ac.status!=0){return -1}return g(af,X,ah)}function O(){var V;if(C==null){C=new Array(2*n)}k=0;s=0;r=0;U=-1;N=false;T=y=0;m=null}function F(Z,X,W){var Y,V;Y=0;while(Y<W){if(N&&U==-1){return Y}if(T>0){if(U!=w){while(T>0&&Y<W){T--;y&=n-1;k&=n-1;Z[X+Y++]=C[k++]=C[y++]}}else{while(T>0&&Y<W){T--;k&=n-1;R(8);Z[X+Y++]=C[k++]=u(8);d(8)}if(T==0){U=-1}}if(Y==W){return Y}}if(U==-1){if(N){break}R(1);if(u(1)!=0){N=true}d(1);R(2);U=u(2);d(2);m=null;T=0}switch(U){case 0:V=v(Z,X+Y,W-Y);break;case 1:if(m!=null){V=g(Z,X+Y,W-Y)}else{V=K(Z,X+Y,W-Y)}break;case 2:if(m!=null){V=g(Z,X+Y,W-Y)}else{V=A(Z,X+Y,W-Y)}break;default:V=-1;break}if(V==-1){if(N){return 0}return -1}Y+=V}return Y}var o={};G.JSInflate=o;o.inflate=function(Y){var W,Z;var X,V;O();B=Y;E=0;Z=new Array(1024);W="";while((X=F(Z,0,Z.length))>0){for(V=0;V<X;V++){W+=String.fromCharCode(Z[V])}}B=null;return W}}(this));
     7.5 \ No newline at end of file
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/GenerateZip.java	Wed Jan 30 14:03:49 2013 +0100
     8.3 @@ -0,0 +1,36 @@
     8.4 +/**
     8.5 + * Back 2 Browser Bytecode Translator
     8.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     8.7 + *
     8.8 + * This program is free software: you can redistribute it and/or modify
     8.9 + * it under the terms of the GNU General Public License as published by
    8.10 + * the Free Software Foundation, version 2 of the License.
    8.11 + *
    8.12 + * This program is distributed in the hope that it will be useful,
    8.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    8.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    8.15 + * GNU General Public License for more details.
    8.16 + *
    8.17 + * You should have received a copy of the GNU General Public License
    8.18 + * along with this program. Look for COPYING file in the top folder.
    8.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
    8.20 + */
    8.21 +package org.apidesign.bck2brwsr.vmtest.impl;
    8.22 +
    8.23 +import java.lang.annotation.Retention;
    8.24 +import java.lang.annotation.RetentionPolicy;
    8.25 +
    8.26 +/** Annotation to generate a ZIP or JAR file during build.
    8.27 + *
    8.28 + * @author Jaroslav Tulach <jtulach@netbeans.org>
    8.29 + */
    8.30 +@Retention(RetentionPolicy.SOURCE)
    8.31 +@interface GenerateZip {
    8.32 +    String name();
    8.33 +    
    8.34 +    /** manifest for the file */
    8.35 +    String manifest() default "";
    8.36 +
    8.37 +    /** Array of names (at odd positions) and their content (on even) */
    8.38 +    String[] contents();
    8.39 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/GenerateZipProcessor.java	Wed Jan 30 14:03:49 2013 +0100
     9.3 @@ -0,0 +1,98 @@
     9.4 +/**
     9.5 + * Back 2 Browser Bytecode Translator
     9.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     9.7 + *
     9.8 + * This program is free software: you can redistribute it and/or modify
     9.9 + * it under the terms of the GNU General Public License as published by
    9.10 + * the Free Software Foundation, version 2 of the License.
    9.11 + *
    9.12 + * This program is distributed in the hope that it will be useful,
    9.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    9.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    9.15 + * GNU General Public License for more details.
    9.16 + *
    9.17 + * You should have received a copy of the GNU General Public License
    9.18 + * along with this program. Look for COPYING file in the top folder.
    9.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
    9.20 + */
    9.21 +package org.apidesign.bck2brwsr.vmtest.impl;
    9.22 +
    9.23 +import java.io.ByteArrayInputStream;
    9.24 +import java.io.IOException;
    9.25 +import java.io.OutputStream;
    9.26 +import java.util.Set;
    9.27 +import java.util.jar.JarEntry;
    9.28 +import java.util.jar.JarOutputStream;
    9.29 +import java.util.jar.Manifest;
    9.30 +import javax.annotation.processing.AbstractProcessor;
    9.31 +import javax.annotation.processing.Processor;
    9.32 +import javax.annotation.processing.RoundEnvironment;
    9.33 +import javax.annotation.processing.SupportedAnnotationTypes;
    9.34 +import javax.lang.model.element.Element;
    9.35 +import javax.lang.model.element.ElementKind;
    9.36 +import javax.lang.model.element.PackageElement;
    9.37 +import javax.lang.model.element.TypeElement;
    9.38 +import javax.tools.Diagnostic;
    9.39 +import javax.tools.FileObject;
    9.40 +import javax.tools.StandardLocation;
    9.41 +import org.openide.util.lookup.ServiceProvider;
    9.42 +
    9.43 +/**
    9.44 + *
    9.45 + * @author Jaroslav Tulach <jtulach@netbeans.org>
    9.46 + */
    9.47 +@ServiceProvider(service = Processor.class)
    9.48 +@SupportedAnnotationTypes("org.apidesign.bck2brwsr.vmtest.impl.GenerateZip")
    9.49 +public class GenerateZipProcessor extends AbstractProcessor {
    9.50 +
    9.51 +    @Override
    9.52 +    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
    9.53 +        for (Element e : roundEnv.getElementsAnnotatedWith(GenerateZip.class)) {
    9.54 +            GenerateZip gz = e.getAnnotation(GenerateZip.class);
    9.55 +            if (gz == null) {
    9.56 +                continue;
    9.57 +            }
    9.58 +            PackageElement pe = findPackage(e);
    9.59 +            try {
    9.60 +                generateJar(pe, gz, e);
    9.61 +            } catch (IOException ex) {
    9.62 +                processingEnv.getMessager().printMessage(
    9.63 +                    Diagnostic.Kind.ERROR, 
    9.64 +                    "Can't generate JAR " + gz.name() + ": " + ex.getMessage()
    9.65 +                );
    9.66 +            }
    9.67 +        }
    9.68 +        return true;
    9.69 +    }
    9.70 +
    9.71 +    private static PackageElement findPackage(Element e) {
    9.72 +        while (e.getKind() != ElementKind.PACKAGE) {
    9.73 +            e = e.getEnclosingElement();
    9.74 +        }
    9.75 +        return (PackageElement)e;
    9.76 +    }
    9.77 +
    9.78 +    private void generateJar(PackageElement pe, GenerateZip gz, Element e) throws IOException {
    9.79 +        FileObject res = processingEnv.getFiler().createResource(
    9.80 +            StandardLocation.CLASS_OUTPUT, 
    9.81 +            pe.getQualifiedName().toString(), 
    9.82 +            gz.name(), e
    9.83 +        );
    9.84 +        OutputStream os = res.openOutputStream();
    9.85 +        JarOutputStream jar;
    9.86 +        if (gz.manifest().isEmpty()) {
    9.87 +            jar = new JarOutputStream(os);
    9.88 +        } else {
    9.89 +            Manifest mf = new Manifest(new ByteArrayInputStream(gz.manifest().getBytes("UTF-8")));
    9.90 +            jar = new JarOutputStream(os, mf);
    9.91 +        }
    9.92 +        String[] arr = gz.contents();
    9.93 +        for (int i = 0; i < arr.length; i += 2) {
    9.94 +            JarEntry je = new JarEntry(arr[i]);
    9.95 +            jar.putNextEntry(je);
    9.96 +            jar.write(arr[i + 1].getBytes("UTF-8"));
    9.97 +            jar.closeEntry();
    9.98 +        }
    9.99 +    }
   9.100 +    
   9.101 +}
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/CRC32Test.java	Wed Jan 30 14:03:49 2013 +0100
    10.3 @@ -0,0 +1,41 @@
    10.4 +/**
    10.5 + * Back 2 Browser Bytecode Translator
    10.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    10.7 + *
    10.8 + * This program is free software: you can redistribute it and/or modify
    10.9 + * it under the terms of the GNU General Public License as published by
   10.10 + * the Free Software Foundation, version 2 of the License.
   10.11 + *
   10.12 + * This program is distributed in the hope that it will be useful,
   10.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   10.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   10.15 + * GNU General Public License for more details.
   10.16 + *
   10.17 + * You should have received a copy of the GNU General Public License
   10.18 + * along with this program. Look for COPYING file in the top folder.
   10.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   10.20 + */
   10.21 +package org.apidesign.bck2brwsr.vmtest.impl;
   10.22 +
   10.23 +import java.io.UnsupportedEncodingException;
   10.24 +import java.util.zip.CRC32;
   10.25 +import org.apidesign.bck2brwsr.vmtest.Compare;
   10.26 +import org.apidesign.bck2brwsr.vmtest.VMTest;
   10.27 +import org.testng.annotations.Factory;
   10.28 +
   10.29 +/**
   10.30 + *
   10.31 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   10.32 + */
   10.33 +public class CRC32Test {
   10.34 +
   10.35 +    @Compare public long crc1() throws UnsupportedEncodingException {
   10.36 +        CRC32 crc = new CRC32();
   10.37 +        crc.update("Hello World!".getBytes("UTF-8"));
   10.38 +        return crc.getValue();
   10.39 +    }
   10.40 +    
   10.41 +    @Factory public static Object[] create() {
   10.42 +        return VMTest.create(CRC32Test.class);
   10.43 +    }
   10.44 +}
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/ZipFileTest.java	Wed Jan 30 14:03:49 2013 +0100
    11.3 @@ -0,0 +1,54 @@
    11.4 +/**
    11.5 + * Back 2 Browser Bytecode Translator
    11.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    11.7 + *
    11.8 + * This program is free software: you can redistribute it and/or modify
    11.9 + * it under the terms of the GNU General Public License as published by
   11.10 + * the Free Software Foundation, version 2 of the License.
   11.11 + *
   11.12 + * This program is distributed in the hope that it will be useful,
   11.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   11.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   11.15 + * GNU General Public License for more details.
   11.16 + *
   11.17 + * You should have received a copy of the GNU General Public License
   11.18 + * along with this program. Look for COPYING file in the top folder.
   11.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   11.20 + */
   11.21 +package org.apidesign.bck2brwsr.vmtest.impl;
   11.22 +
   11.23 +import java.io.IOException;
   11.24 +import java.io.InputStream;
   11.25 +import java.util.zip.ZipEntry;
   11.26 +import java.util.zip.ZipInputStream;
   11.27 +import org.apidesign.bck2brwsr.vmtest.Compare;
   11.28 +import org.apidesign.bck2brwsr.vmtest.VMTest;
   11.29 +import org.testng.annotations.Factory;
   11.30 +
   11.31 +/**
   11.32 + *
   11.33 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   11.34 + */
   11.35 +public class ZipFileTest {
   11.36 +    
   11.37 +    @GenerateZip(name = "readAnEntry.zip", contents = { "my/main/file.txt", "Hello World!" })
   11.38 +    @Compare public String readAnEntry() throws IOException {
   11.39 +        InputStream is = ZipFileTest.class.getResourceAsStream("readAnEntry.zip");
   11.40 +        ZipInputStream zip = new ZipInputStream(is);
   11.41 +        ZipEntry entry = zip.getNextEntry();
   11.42 +        assertEquals(entry.getName(), "my/main/file.txt", "Correct entry");
   11.43 +        
   11.44 +        byte[] arr = new byte[4096];
   11.45 +        int len = zip.read(arr);
   11.46 +        
   11.47 +        return new String(arr, 0, len, "UTF-8");
   11.48 +    }
   11.49 +
   11.50 +    private static void assertEquals(String real, String exp, String msg) {
   11.51 +        assert exp.equals(real) : msg + " exp: " + exp + " real: " + real;
   11.52 +    }
   11.53 +    
   11.54 +    @Factory public static Object[] create() {
   11.55 +        return VMTest.create(ZipFileTest.class);
   11.56 +    }
   11.57 +}