Rebasing the Inflater support on jzlib which, unlike GNU ClassPath, has correct implementation of Huffman code. Making the implementation more easily testable by turning Inflater and ZipInputStream into pure delegates. Current implementation is going to need proper long support. emul
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Thu, 07 Feb 2013 12:58:12 +0100
branchemul
changeset 6940d277415ed02
parent 692 d088fc482c65
child 695 dbcd1a21f3f8
Rebasing the Inflater support on jzlib which, unlike GNU ClassPath, has correct implementation of Huffman code. Making the implementation more easily testable by turning Inflater and ZipInputStream into pure delegates. Current implementation is going to need proper long support.
emul/compact/src/test/java/org/apidesign/bck2brwsr/compact/tck/ZipArchive.java
emul/compact/src/test/java/org/apidesign/bck2brwsr/compact/tck/ZipCompatibilityTest.java
emul/compact/src/test/java/org/apidesign/bck2brwsr/compact/tck/ZipVsJzLibTest.java
emul/compact/src/test/resources/org/apidesign/bck2brwsr/compact/tck/demo.static.calculator-0.3-SNAPSHOT.jar
emul/mini/src/main/java/java/util/zip/Inflater.java
emul/mini/src/main/java/java/util/zip/ZipConstants64.java
emul/mini/src/main/java/java/util/zip/ZipInputStream.java
emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/lang/System.java
emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/Adler32.java
emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/CRC32.java
emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/Checksum.java
emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/GZIPHeader.java
emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/InfBlocks.java
emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/InfCodes.java
emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/InfTree.java
emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/Inflate.java
emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/Inflater.java
emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/JzLibInflater.java
emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/ZStream.java
emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/ZipConstants64.java
emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/ZipInputStream.java
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/emul/compact/src/test/java/org/apidesign/bck2brwsr/compact/tck/ZipArchive.java	Thu Feb 07 12:58:12 2013 +0100
     1.3 @@ -0,0 +1,154 @@
     1.4 +/**
     1.5 + * Back 2 Browser Bytecode Translator
     1.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     1.7 + *
     1.8 + * This program is free software: you can redistribute it and/or modify
     1.9 + * it under the terms of the GNU General Public License as published by
    1.10 + * the Free Software Foundation, version 2 of the License.
    1.11 + *
    1.12 + * This program is distributed in the hope that it will be useful,
    1.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1.15 + * GNU General Public License for more details.
    1.16 + *
    1.17 + * You should have received a copy of the GNU General Public License
    1.18 + * along with this program. Look for COPYING file in the top folder.
    1.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
    1.20 + */
    1.21 +package org.apidesign.bck2brwsr.compact.tck;
    1.22 +
    1.23 +import java.io.ByteArrayOutputStream;
    1.24 +import java.io.IOException;
    1.25 +import java.io.InputStream;
    1.26 +import java.util.Arrays;
    1.27 +import java.util.LinkedHashMap;
    1.28 +import java.util.Map;
    1.29 +import java.util.Objects;
    1.30 +import java.util.zip.ZipEntry;
    1.31 +import org.apidesign.bck2brwsr.emul.zip.ZipInputStream;
    1.32 +
    1.33 +/**
    1.34 + *
    1.35 + * @author Jaroslav Tulach <jtulach@netbeans.org>
    1.36 + */
    1.37 +final class ZipArchive {
    1.38 +    private final Map<String, byte[]> entries = new LinkedHashMap<>();
    1.39 +
    1.40 +    public static ZipArchive createZip(InputStream is) throws IOException {
    1.41 +        ZipArchive a = new ZipArchive();
    1.42 +        readZip(is, a);
    1.43 +        return a;
    1.44 +    }
    1.45 +
    1.46 +    public static ZipArchive createReal(InputStream is) throws IOException {
    1.47 +        ZipArchive a = new ZipArchive();
    1.48 +        realZip(is, a);
    1.49 +        return a;
    1.50 +    }
    1.51 +
    1.52 +    /**
    1.53 +     * Registers entry name and data
    1.54 +     */
    1.55 +    final void register(String entry, InputStream is) throws IOException {
    1.56 +        ByteArrayOutputStream os = new ByteArrayOutputStream();
    1.57 +        for (;;) {
    1.58 +            int ch = is.read();
    1.59 +            if (ch == -1) {
    1.60 +                break;
    1.61 +            }
    1.62 +            os.write(ch);
    1.63 +        }
    1.64 +        os.close();
    1.65 +        entries.put(entry, os.toByteArray());
    1.66 +    }
    1.67 +
    1.68 +    @Override
    1.69 +    public int hashCode() {
    1.70 +        return entries.hashCode();
    1.71 +    }
    1.72 +
    1.73 +    @Override
    1.74 +    public boolean equals(Object obj) {
    1.75 +        if (obj == null) {
    1.76 +            return false;
    1.77 +        }
    1.78 +        if (getClass() != obj.getClass()) {
    1.79 +            return false;
    1.80 +        }
    1.81 +        final ZipArchive other = (ZipArchive) obj;
    1.82 +        if (!Objects.deepEquals(this.entries, other.entries)) {
    1.83 +            return false;
    1.84 +        }
    1.85 +        return true;
    1.86 +    }
    1.87 +
    1.88 +    @Override
    1.89 +    public String toString() {
    1.90 +        StringBuilder sb = new StringBuilder();
    1.91 +        for (Map.Entry<String, byte[]> en : entries.entrySet()) {
    1.92 +            String string = en.getKey();
    1.93 +            byte[] bs = en.getValue();
    1.94 +            sb.append(string).append(" = ").append(Arrays.toString(bs)).append("\n");
    1.95 +        }
    1.96 +        return sb.toString();
    1.97 +    }
    1.98 +
    1.99 +    public void assertEquals(ZipArchive zip, String msg) {
   1.100 +        boolean ok = true;
   1.101 +        StringBuilder sb = new StringBuilder();
   1.102 +        sb.append(msg);
   1.103 +        for (Map.Entry<String, byte[]> en : entries.entrySet()) {
   1.104 +            String string = en.getKey();
   1.105 +            byte[] bs = en.getValue();
   1.106 +            byte[] other = zip.entries.get(string);
   1.107 +            sb.append("\n");
   1.108 +            if (other == null) {
   1.109 +                sb.append("EXTRA ").append(string).append(" = ").append(Arrays.toString(bs));
   1.110 +                ok = false;
   1.111 +                continue;
   1.112 +            }
   1.113 +            if (Arrays.equals(bs, other)) {
   1.114 +                sb.append("OK    ").append(string);
   1.115 +                continue;
   1.116 +            } else {
   1.117 +                sb.append("DIFF  ").append(string).append(" = ").append(Arrays.toString(bs)).append("\n");
   1.118 +                sb.append("    TO").append(string).append(" = ").append(Arrays.toString(other)).append("\n");
   1.119 +                ok = false;
   1.120 +                continue;
   1.121 +            }
   1.122 +        }
   1.123 +        for (Map.Entry<String, byte[]> entry : zip.entries.entrySet()) {
   1.124 +            String string = entry.getKey();
   1.125 +            if (entries.get(string) == null) {
   1.126 +                sb.append("MISS  ").append(string).append(" = ").append(Arrays.toString(entry.getValue()));
   1.127 +                ok = false;
   1.128 +            }
   1.129 +        }
   1.130 +        if (!ok) {
   1.131 +            assert false : sb.toString();
   1.132 +        }
   1.133 +    }
   1.134 +
   1.135 +    public static void readZip(InputStream is, ZipArchive data) throws IOException {
   1.136 +        ZipInputStream zip = new org.apidesign.bck2brwsr.emul.zip.ZipInputStream(is);
   1.137 +        for (;;) {
   1.138 +            ZipEntry en = zip.getNextEntry();
   1.139 +            if (en == null) {
   1.140 +                return;
   1.141 +            }
   1.142 +            data.register(en.getName(), zip);
   1.143 +        }
   1.144 +    }
   1.145 +
   1.146 +    public static void realZip(InputStream is, ZipArchive data) throws IOException {
   1.147 +        java.util.zip.ZipInputStream zip = new java.util.zip.ZipInputStream(is);
   1.148 +        for (;;) {
   1.149 +            ZipEntry en = zip.getNextEntry();
   1.150 +            if (en == null) {
   1.151 +                return;
   1.152 +            }
   1.153 +            data.register(en.getName(), zip);
   1.154 +        }
   1.155 +    }
   1.156 +    
   1.157 +}
     2.1 --- a/emul/compact/src/test/java/org/apidesign/bck2brwsr/compact/tck/ZipCompatibilityTest.java	Wed Feb 06 18:24:53 2013 +0100
     2.2 +++ b/emul/compact/src/test/java/org/apidesign/bck2brwsr/compact/tck/ZipCompatibilityTest.java	Thu Feb 07 12:58:12 2013 +0100
     2.3 @@ -17,15 +17,8 @@
     2.4   */
     2.5  package org.apidesign.bck2brwsr.compact.tck;
     2.6  
     2.7 -import java.io.ByteArrayOutputStream;
     2.8  import java.io.IOException;
     2.9  import java.io.InputStream;
    2.10 -import java.util.Arrays;
    2.11 -import java.util.LinkedHashMap;
    2.12 -import java.util.Map;
    2.13 -import java.util.Objects;
    2.14 -import java.util.zip.ZipEntry;
    2.15 -import java.util.zip.ZipInputStream;
    2.16  import org.apidesign.bck2brwsr.vmtest.Compare;
    2.17  import org.apidesign.bck2brwsr.vmtest.VMTest;
    2.18  import org.testng.annotations.Factory;
    2.19 @@ -38,7 +31,7 @@
    2.20      @Compare
    2.21      public String testDemoStaticCalculator() throws IOException {
    2.22          InputStream is = getClass().getResourceAsStream("demo.static.calculator-0.3-SNAPSHOT.jar");
    2.23 -        Archive zip = Archive.createZip(is);
    2.24 +        ZipArchive zip = ZipArchive.createZip(is);
    2.25          return zip.toString();
    2.26      }
    2.27      
    2.28 @@ -46,115 +39,4 @@
    2.29      public static Object[] create() {
    2.30          return VMTest.create(ZipCompatibilityTest.class);
    2.31      }
    2.32 -    
    2.33 -    private static final class Archive {
    2.34 -
    2.35 -        private final Map<String, byte[]> entries = new LinkedHashMap<>();
    2.36 -
    2.37 -        public static Archive createZip(InputStream is) throws IOException {
    2.38 -            Archive a = new Archive();
    2.39 -            readZip(is, a);
    2.40 -            return a;
    2.41 -        }
    2.42 -
    2.43 -        /**
    2.44 -         * Registers entry name and data
    2.45 -         */
    2.46 -        final void register(String entry, InputStream is) throws IOException {
    2.47 -            ByteArrayOutputStream os = new ByteArrayOutputStream();
    2.48 -            for (;;) {
    2.49 -                int ch = is.read();
    2.50 -                if (ch == -1) {
    2.51 -                    break;
    2.52 -                }
    2.53 -                os.write(ch);
    2.54 -            }
    2.55 -            os.close();
    2.56 -
    2.57 -            entries.put(entry, os.toByteArray());
    2.58 -        }
    2.59 -
    2.60 -        @Override
    2.61 -        public int hashCode() {
    2.62 -            return entries.hashCode();
    2.63 -        }
    2.64 -
    2.65 -        @Override
    2.66 -        public boolean equals(Object obj) {
    2.67 -            if (obj == null) {
    2.68 -                return false;
    2.69 -            }
    2.70 -            if (getClass() != obj.getClass()) {
    2.71 -                return false;
    2.72 -            }
    2.73 -            final Archive other = (Archive) obj;
    2.74 -            if (!Objects.deepEquals(this.entries, other.entries)) {
    2.75 -                return false;
    2.76 -            }
    2.77 -            return true;
    2.78 -        }
    2.79 -
    2.80 -        @Override
    2.81 -        public String toString() {
    2.82 -            StringBuilder sb = new StringBuilder();
    2.83 -            for (Map.Entry<String, byte[]> en : entries.entrySet()) {
    2.84 -                String string = en.getKey();
    2.85 -                byte[] bs = en.getValue();
    2.86 -
    2.87 -                sb.append(string).append(" = ").append(Arrays.toString(bs)).append("\n");
    2.88 -            }
    2.89 -            return sb.toString();
    2.90 -        }
    2.91 -
    2.92 -        public void assertEquals(Archive zip, String msg) {
    2.93 -            boolean ok = true;
    2.94 -
    2.95 -            StringBuilder sb = new StringBuilder();
    2.96 -            sb.append(msg);
    2.97 -            for (Map.Entry<String, byte[]> en : entries.entrySet()) {
    2.98 -                String string = en.getKey();
    2.99 -                byte[] bs = en.getValue();
   2.100 -
   2.101 -                byte[] other = zip.entries.get(string);
   2.102 -
   2.103 -                sb.append("\n");
   2.104 -
   2.105 -                if (other == null) {
   2.106 -                    sb.append("EXTRA ").append(string).append(" = ").append(Arrays.toString(bs));
   2.107 -                    ok = false;
   2.108 -                    continue;
   2.109 -                }
   2.110 -                if (Arrays.equals(bs, other)) {
   2.111 -                    sb.append("OK    ").append(string);
   2.112 -                    continue;
   2.113 -                } else {
   2.114 -                    sb.append("DIFF  ").append(string).append(" = ").append(Arrays.toString(bs)).append("\n");
   2.115 -                    sb.append("    TO").append(string).append(" = ").append(Arrays.toString(other)).append("\n");
   2.116 -                    ok = false;
   2.117 -                    continue;
   2.118 -                }
   2.119 -            }
   2.120 -            for (Map.Entry<String, byte[]> entry : zip.entries.entrySet()) {
   2.121 -                String string = entry.getKey();
   2.122 -                if (entries.get(string) == null) {
   2.123 -                    sb.append("MISS  ").append(string).append(" = ").append(Arrays.toString(entry.getValue()));
   2.124 -                    ok = false;
   2.125 -                }
   2.126 -            }
   2.127 -            if (!ok) {
   2.128 -                assert false : sb.toString();
   2.129 -            }
   2.130 -        }
   2.131 -        public static void readZip(InputStream is, Archive data) throws IOException {
   2.132 -            ZipInputStream zip = new ZipInputStream(is);
   2.133 -            for (;;) {
   2.134 -                ZipEntry en = zip.getNextEntry();
   2.135 -                if (en == null) {
   2.136 -                    return;
   2.137 -                }
   2.138 -                data.register(en.getName(), zip);
   2.139 -            }
   2.140 -        }
   2.141 -    }
   2.142 -    
   2.143  }
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/emul/compact/src/test/java/org/apidesign/bck2brwsr/compact/tck/ZipVsJzLibTest.java	Thu Feb 07 12:58:12 2013 +0100
     3.3 @@ -0,0 +1,39 @@
     3.4 +/**
     3.5 + * Back 2 Browser Bytecode Translator
     3.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     3.7 + *
     3.8 + * This program is free software: you can redistribute it and/or modify
     3.9 + * it under the terms of the GNU General Public License as published by
    3.10 + * the Free Software Foundation, version 2 of the License.
    3.11 + *
    3.12 + * This program is distributed in the hope that it will be useful,
    3.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    3.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    3.15 + * GNU General Public License for more details.
    3.16 + *
    3.17 + * You should have received a copy of the GNU General Public License
    3.18 + * along with this program. Look for COPYING file in the top folder.
    3.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
    3.20 + */
    3.21 +package org.apidesign.bck2brwsr.compact.tck;
    3.22 +
    3.23 +import java.io.IOException;
    3.24 +import java.io.InputStream;
    3.25 +import org.testng.annotations.Test;
    3.26 +
    3.27 +/**
    3.28 + *
    3.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
    3.30 + */
    3.31 +public class ZipVsJzLibTest {
    3.32 +    @Test public void r() throws IOException {
    3.33 +        InputStream is = getClass().getResourceAsStream("demo.static.calculator-0.3-SNAPSHOT.jar");
    3.34 +        ZipArchive zip = ZipArchive.createZip(is);
    3.35 +        
    3.36 +        is = getClass().getResourceAsStream("demo.static.calculator-0.3-SNAPSHOT.jar");
    3.37 +        ZipArchive real = ZipArchive.createReal(is);
    3.38 +        
    3.39 +        real.assertEquals(zip, "Are they the same?");
    3.40 +    }
    3.41 +    
    3.42 +}
     4.1 Binary file emul/compact/src/test/resources/org/apidesign/bck2brwsr/compact/tck/demo.static.calculator-0.3-SNAPSHOT.jar has changed
     5.1 --- a/emul/mini/src/main/java/java/util/zip/Inflater.java	Wed Feb 06 18:24:53 2013 +0100
     5.2 +++ b/emul/mini/src/main/java/java/util/zip/Inflater.java	Thu Feb 07 12:58:12 2013 +0100
     5.3 @@ -1,44 +1,30 @@
     5.4 -/* Inflater.java - Decompress a data stream
     5.5 -   Copyright (C) 1999, 2000, 2001, 2003  Free Software Foundation, Inc.
     5.6 -
     5.7 -This file is part of GNU Classpath.
     5.8 -
     5.9 -GNU Classpath is free software; you can redistribute it and/or modify
    5.10 -it under the terms of the GNU General Public License as published by
    5.11 -the Free Software Foundation; either version 2, or (at your option)
    5.12 -any later version.
    5.13 - 
    5.14 -GNU Classpath is distributed in the hope that it will be useful, but
    5.15 -WITHOUT ANY WARRANTY; without even the implied warranty of
    5.16 -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    5.17 -General Public License for more details.
    5.18 -
    5.19 -You should have received a copy of the GNU General Public License
    5.20 -along with GNU Classpath; see the file COPYING.  If not, write to the
    5.21 -Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    5.22 -02111-1307 USA.
    5.23 -
    5.24 -Linking this library statically or dynamically with other modules is
    5.25 -making a combined work based on this library.  Thus, the terms and
    5.26 -conditions of the GNU General Public License cover the whole
    5.27 -combination.
    5.28 -
    5.29 -As a special exception, the copyright holders of this library give you
    5.30 -permission to link this library with independent modules to produce an
    5.31 -executable, regardless of the license terms of these independent
    5.32 -modules, and to copy and distribute the resulting executable under
    5.33 -terms of your choice, provided that you also meet, for each linked
    5.34 -independent module, the terms and conditions of the license of that
    5.35 -module.  An independent module is a module which is not derived from
    5.36 -or based on this library.  If you modify this library, you may extend
    5.37 -this exception to your version of the library, but you are not
    5.38 -obligated to do so.  If you do not wish to do so, delete this
    5.39 -exception statement from your version. */
    5.40 +/*
    5.41 + * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
    5.42 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    5.43 + *
    5.44 + * This code is free software; you can redistribute it and/or modify it
    5.45 + * under the terms of the GNU General Public License version 2 only, as
    5.46 + * published by the Free Software Foundation.  Oracle designates this
    5.47 + * particular file as subject to the "Classpath" exception as provided
    5.48 + * by Oracle in the LICENSE file that accompanied this code.
    5.49 + *
    5.50 + * This code is distributed in the hope that it will be useful, but WITHOUT
    5.51 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    5.52 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    5.53 + * version 2 for more details (a copy is included in the LICENSE file that
    5.54 + * accompanied this code).
    5.55 + *
    5.56 + * You should have received a copy of the GNU General Public License version
    5.57 + * 2 along with this work; if not, write to the Free Software Foundation,
    5.58 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    5.59 + *
    5.60 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    5.61 + * or visit www.oracle.com if you need additional information or have any
    5.62 + * questions.
    5.63 + */
    5.64  
    5.65  package java.util.zip;
    5.66  
    5.67 -import org.apidesign.bck2brwsr.emul.lang.System;
    5.68 -
    5.69  /**
    5.70   * This class provides support for general purpose decompression using the
    5.71   * popular ZLIB compression library. The ZLIB compression library was
    5.72 @@ -84,1399 +70,241 @@
    5.73   * @author      David Connelly
    5.74   *
    5.75   */
    5.76 -
    5.77 -/* Written using on-line Java Platform 1.2 API Specification
    5.78 - * and JCL book.
    5.79 - * Believed complete and correct.
    5.80 - */
    5.81 -
    5.82 -/**
    5.83 - * Inflater is used to decompress data that has been compressed according 
    5.84 - * to the "deflate" standard described in rfc1950.
    5.85 - *
    5.86 - * The usage is as following.  First you have to set some input with
    5.87 - * <code>setInput()</code>, then inflate() it.  If inflate doesn't
    5.88 - * inflate any bytes there may be three reasons:
    5.89 - * <ul>
    5.90 - * <li>needsInput() returns true because the input buffer is empty.
    5.91 - * You have to provide more input with <code>setInput()</code>.  
    5.92 - * NOTE: needsInput() also returns true when, the stream is finished.
    5.93 - * </li>
    5.94 - * <li>needsDictionary() returns true, you have to provide a preset 
    5.95 - *     dictionary with <code>setDictionary()</code>.</li>
    5.96 - * <li>finished() returns true, the inflater has finished.</li>
    5.97 - * </ul>
    5.98 - * Once the first output byte is produced, a dictionary will not be
    5.99 - * needed at a later stage.
   5.100 - *
   5.101 - * @author John Leuner, Jochen Hoenicke
   5.102 - * @author Tom Tromey
   5.103 - * @date May 17, 1999
   5.104 - * @since JDK 1.1
   5.105 - */
   5.106 -public class Inflater
   5.107 -{
   5.108 -  /* Copy lengths for literal codes 257..285 */
   5.109 -  private static final int CPLENS[] = 
   5.110 -  { 
   5.111 -    3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
   5.112 -    35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258
   5.113 -  };
   5.114 -  
   5.115 -  /* Extra bits for literal codes 257..285 */  
   5.116 -  private static final int CPLEXT[] = 
   5.117 -  { 
   5.118 -    0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
   5.119 -    3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0
   5.120 -  };
   5.121 -
   5.122 -  /* Copy offsets for distance codes 0..29 */
   5.123 -  private static final int CPDIST[] = {
   5.124 -    1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
   5.125 -    257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
   5.126 -    8193, 12289, 16385, 24577
   5.127 -  };
   5.128 -  
   5.129 -  /* Extra bits for distance codes */
   5.130 -  private static final int CPDEXT[] = {
   5.131 -    0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
   5.132 -    7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 
   5.133 -    12, 12, 13, 13
   5.134 -  };
   5.135 -
   5.136 -  /* This are the state in which the inflater can be.  */
   5.137 -  private static final int DECODE_HEADER           = 0;
   5.138 -  private static final int DECODE_DICT             = 1;
   5.139 -  private static final int DECODE_BLOCKS           = 2;
   5.140 -  private static final int DECODE_STORED_LEN1      = 3;
   5.141 -  private static final int DECODE_STORED_LEN2      = 4;
   5.142 -  private static final int DECODE_STORED           = 5;
   5.143 -  private static final int DECODE_DYN_HEADER       = 6;
   5.144 -  private static final int DECODE_HUFFMAN          = 7;
   5.145 -  private static final int DECODE_HUFFMAN_LENBITS  = 8;
   5.146 -  private static final int DECODE_HUFFMAN_DIST     = 9;
   5.147 -  private static final int DECODE_HUFFMAN_DISTBITS = 10;
   5.148 -  private static final int DECODE_CHKSUM           = 11;
   5.149 -  private static final int FINISHED                = 12;
   5.150 -
   5.151 -  /** This variable contains the current state. */
   5.152 -  private int mode;
   5.153 -
   5.154 -  /**
   5.155 -   * The adler checksum of the dictionary or of the decompressed
   5.156 -   * stream, as it is written in the header resp. footer of the
   5.157 -   * compressed stream.  <br>
   5.158 -   *
   5.159 -   * Only valid if mode is DECODE_DICT or DECODE_CHKSUM.
   5.160 -   */
   5.161 -  private int readAdler;
   5.162 -  /** 
   5.163 -   * The number of bits needed to complete the current state.  This
   5.164 -   * is valid, if mode is DECODE_DICT, DECODE_CHKSUM,
   5.165 -   * DECODE_HUFFMAN_LENBITS or DECODE_HUFFMAN_DISTBITS.  
   5.166 -   */
   5.167 -  private int neededBits;
   5.168 -  private int repLength, repDist;
   5.169 -  private int uncomprLen;
   5.170 -  /**
   5.171 -   * True, if the last block flag was set in the last block of the
   5.172 -   * inflated stream.  This means that the stream ends after the
   5.173 -   * current block.  
   5.174 -   */
   5.175 -  private boolean isLastBlock;
   5.176 -
   5.177 -  /**
   5.178 -   * The total number of inflated bytes.
   5.179 -   */
   5.180 -  private long totalOut;
   5.181 -  /**
   5.182 -   * The total number of bytes set with setInput().  This is not the
   5.183 -   * value returned by getTotalIn(), since this also includes the 
   5.184 -   * unprocessed input.
   5.185 -   */
   5.186 -  private long totalIn;
   5.187 -  /**
   5.188 -   * This variable stores the nowrap flag that was given to the constructor.
   5.189 -   * True means, that the inflated stream doesn't contain a header nor the
   5.190 -   * checksum in the footer.
   5.191 -   */
   5.192 -  private boolean nowrap;
   5.193 -
   5.194 -  private StreamManipulator input;
   5.195 -  private OutputWindow outputWindow;
   5.196 -  private InflaterDynHeader dynHeader;
   5.197 -  private InflaterHuffmanTree litlenTree, distTree;
   5.198 -  private Adler32 adler;
   5.199 -
   5.200 -  /**
   5.201 -   * Creates a new inflater.
   5.202 -   */
   5.203 -  public Inflater ()
   5.204 -  {
   5.205 -    this (false);
   5.206 -  }
   5.207 -
   5.208 -  /**
   5.209 -   * Creates a new inflater.
   5.210 -   * @param nowrap true if no header and checksum field appears in the
   5.211 -   * stream.  This is used for GZIPed input.  For compatibility with
   5.212 -   * Sun JDK you should provide one byte of input more than needed in
   5.213 -   * this case.
   5.214 -   */
   5.215 -  public Inflater (boolean nowrap)
   5.216 -  {
   5.217 -    this.nowrap = nowrap;
   5.218 -    this.adler = new Adler32();
   5.219 -    input = new StreamManipulator();
   5.220 -    outputWindow = new OutputWindow();
   5.221 -    mode = nowrap ? DECODE_BLOCKS : DECODE_HEADER;
   5.222 -  }
   5.223 -
   5.224 -  /**
   5.225 -   * Finalizes this object.
   5.226 -   */
   5.227 -  protected void finalize ()
   5.228 -  {
   5.229 -    /* Exists only for compatibility */
   5.230 -  }
   5.231 -
   5.232 -  /**
   5.233 -   * Frees all objects allocated by the inflater.  There's no reason
   5.234 -   * to call this, since you can just rely on garbage collection (even
   5.235 -   * for the Sun implementation).  Exists only for compatibility
   5.236 -   * with Sun's JDK, where the compressor allocates native memory.
   5.237 -   * If you call any method (even reset) afterwards the behaviour is
   5.238 -   * <i>undefined</i>.  
   5.239 -   * @deprecated Just clear all references to inflater instead.
   5.240 -   */
   5.241 -  public void end ()
   5.242 -  {
   5.243 -    outputWindow = null;
   5.244 -    input = null;
   5.245 -    dynHeader = null;
   5.246 -    litlenTree = null;
   5.247 -    distTree = null;
   5.248 -    adler = null;
   5.249 -  }
   5.250 -
   5.251 -  /**
   5.252 -   * Returns true, if the inflater has finished.  This means, that no
   5.253 -   * input is needed and no output can be produced.
   5.254 -   */
   5.255 -  public boolean finished() 
   5.256 -  {
   5.257 -    return mode == FINISHED && outputWindow.getAvailable() == 0;
   5.258 -  }
   5.259 -
   5.260 -  /**
   5.261 -   * Gets the adler checksum.  This is either the checksum of all
   5.262 -   * uncompressed bytes returned by inflate(), or if needsDictionary()
   5.263 -   * returns true (and thus no output was yet produced) this is the
   5.264 -   * adler checksum of the expected dictionary.
   5.265 -   * @returns the adler checksum.
   5.266 -   */
   5.267 -  public int getAdler()
   5.268 -  {
   5.269 -    return needsDictionary() ? readAdler : (int) adler.getValue();
   5.270 -  }
   5.271 -  
   5.272 -  /**
   5.273 -   * Gets the number of unprocessed input.  Useful, if the end of the
   5.274 -   * stream is reached and you want to further process the bytes after
   5.275 -   * the deflate stream.  
   5.276 -   * @return the number of bytes of the input which were not processed.
   5.277 -   */
   5.278 -  public int getRemaining()
   5.279 -  {
   5.280 -    return input.getAvailableBytes();
   5.281 -  }
   5.282 -  
   5.283 -  /**
   5.284 -   * Gets the total number of processed compressed input bytes.
   5.285 -   * @return the total number of bytes of processed input bytes.
   5.286 -   */
   5.287 -  public int getTotalIn()
   5.288 -  {
   5.289 -    return (int)getBytesRead();
   5.290 -  }
   5.291 -  
   5.292 -  /**
   5.293 -   * Gets the total number of output bytes returned by inflate().
   5.294 -   * @return the total number of output bytes.
   5.295 -   */
   5.296 -  public int getTotalOut()
   5.297 -  {
   5.298 -    return (int)totalOut;
   5.299 -  }
   5.300 -  
   5.301 -  public long getBytesWritten() {
   5.302 -     return totalOut;
   5.303 -  }
   5.304 -
   5.305 -  public long getBytesRead() {
   5.306 -    return totalIn - getRemaining();
   5.307 -  }
   5.308 -  
   5.309 -
   5.310 -  /**
   5.311 -   * Inflates the compressed stream to the output buffer.  If this
   5.312 -   * returns 0, you should check, whether needsDictionary(),
   5.313 -   * needsInput() or finished() returns true, to determine why no 
   5.314 -   * further output is produced.
   5.315 -   * @param buffer the output buffer.
   5.316 -   * @return the number of bytes written to the buffer, 0 if no further
   5.317 -   * output can be produced.  
   5.318 -   * @exception DataFormatException if deflated stream is invalid.
   5.319 -   * @exception IllegalArgumentException if buf has length 0.
   5.320 -   */
   5.321 -  public int inflate (byte[] buf) throws DataFormatException
   5.322 -  {
   5.323 -    return inflate (buf, 0, buf.length);
   5.324 -  }
   5.325 -
   5.326 -  /**
   5.327 -   * Inflates the compressed stream to the output buffer.  If this
   5.328 -   * returns 0, you should check, whether needsDictionary(),
   5.329 -   * needsInput() or finished() returns true, to determine why no 
   5.330 -   * further output is produced.
   5.331 -   * @param buffer the output buffer.
   5.332 -   * @param off the offset into buffer where the output should start.
   5.333 -   * @param len the maximum length of the output.
   5.334 -   * @return the number of bytes written to the buffer, 0 if no further
   5.335 -   * output can be produced.  
   5.336 -   * @exception DataFormatException if deflated stream is invalid.
   5.337 -   * @exception IndexOutOfBoundsException if the off and/or len are wrong.
   5.338 -   */
   5.339 -  public int inflate (byte[] buf, int off, int len) throws DataFormatException
   5.340 -  {
   5.341 -    /* Special case: len may be zero */
   5.342 -    if (len == 0)
   5.343 -      return 0;
   5.344 -    /* Check for correct buff, off, len triple */
   5.345 -    if (0 > off || off > off + len || off + len > buf.length)
   5.346 -      throw new ArrayIndexOutOfBoundsException();
   5.347 -    int count = 0;
   5.348 -    int more;
   5.349 -    do
   5.350 -      {
   5.351 -	if (mode != DECODE_CHKSUM)
   5.352 -	  {
   5.353 -	    /* Don't give away any output, if we are waiting for the
   5.354 -	     * checksum in the input stream.
   5.355 -	     *
   5.356 -	     * With this trick we have always:
   5.357 -	     *   needsInput() and not finished() 
   5.358 -	     *   implies more output can be produced.  
   5.359 -	     */
   5.360 -	    more = outputWindow.copyOutput(buf, off, len);
   5.361 -	    adler.update(buf, off, more);
   5.362 -	    off += more;
   5.363 -	    count += more;
   5.364 -	    totalOut += more;
   5.365 -	    len -= more;
   5.366 -	    if (len == 0)
   5.367 -	      return count;
   5.368 -	  }
   5.369 -      }
   5.370 -    while (decode() || (outputWindow.getAvailable() > 0
   5.371 -			&& mode != DECODE_CHKSUM));
   5.372 -    return count;
   5.373 -  }
   5.374 -
   5.375 -  /**
   5.376 -   * Returns true, if a preset dictionary is needed to inflate the input.
   5.377 -   */
   5.378 -  public boolean needsDictionary ()
   5.379 -  {
   5.380 -    return mode == DECODE_DICT && neededBits == 0;
   5.381 -  }
   5.382 -
   5.383 -  /**
   5.384 -   * Returns true, if the input buffer is empty.
   5.385 -   * You should then call setInput(). <br>
   5.386 -   *
   5.387 -   * <em>NOTE</em>: This method also returns true when the stream is finished.
   5.388 -   */
   5.389 -  public boolean needsInput () 
   5.390 -  {
   5.391 -    return input.needsInput ();
   5.392 -  }
   5.393 -
   5.394 -  /**
   5.395 -   * Resets the inflater so that a new stream can be decompressed.  All
   5.396 -   * pending input and output will be discarded.
   5.397 -   */
   5.398 -  public void reset ()
   5.399 -  {
   5.400 -    mode = nowrap ? DECODE_BLOCKS : DECODE_HEADER;
   5.401 -    totalIn = totalOut = 0;
   5.402 -    input.reset();
   5.403 -    outputWindow.reset();
   5.404 -    dynHeader = null;
   5.405 -    litlenTree = null;
   5.406 -    distTree = null;
   5.407 -    isLastBlock = false;
   5.408 -    adler.reset();
   5.409 -  }
   5.410 -
   5.411 -  /**
   5.412 -   * Sets the preset dictionary.  This should only be called, if
   5.413 -   * needsDictionary() returns true and it should set the same
   5.414 -   * dictionary, that was used for deflating.  The getAdler()
   5.415 -   * function returns the checksum of the dictionary needed.
   5.416 -   * @param buffer the dictionary.
   5.417 -   * @exception IllegalStateException if no dictionary is needed.
   5.418 -   * @exception IllegalArgumentException if the dictionary checksum is
   5.419 -   * wrong.  
   5.420 -   */
   5.421 -  public void setDictionary (byte[] buffer)
   5.422 -  {
   5.423 -    setDictionary(buffer, 0, buffer.length);
   5.424 -  }
   5.425 -
   5.426 -  /**
   5.427 -   * Sets the preset dictionary.  This should only be called, if
   5.428 -   * needsDictionary() returns true and it should set the same
   5.429 -   * dictionary, that was used for deflating.  The getAdler()
   5.430 -   * function returns the checksum of the dictionary needed.
   5.431 -   * @param buffer the dictionary.
   5.432 -   * @param off the offset into buffer where the dictionary starts.
   5.433 -   * @param len the length of the dictionary.
   5.434 -   * @exception IllegalStateException if no dictionary is needed.
   5.435 -   * @exception IllegalArgumentException if the dictionary checksum is
   5.436 -   * wrong.  
   5.437 -   * @exception IndexOutOfBoundsException if the off and/or len are wrong.
   5.438 -   */
   5.439 -  public void setDictionary (byte[] buffer, int off, int len)
   5.440 -  {
   5.441 -    if (!needsDictionary())
   5.442 -      throw new IllegalStateException();
   5.443 -
   5.444 -    adler.update(buffer, off, len);
   5.445 -    if ((int) adler.getValue() != readAdler)
   5.446 -      throw new IllegalArgumentException("Wrong adler checksum");
   5.447 -    adler.reset();
   5.448 -    outputWindow.copyDict(buffer, off, len);
   5.449 -    mode = DECODE_BLOCKS;
   5.450 -  }
   5.451 -
   5.452 -  /**
   5.453 -   * Sets the input.  This should only be called, if needsInput()
   5.454 -   * returns true.
   5.455 -   * @param buffer the input.
   5.456 -   * @exception IllegalStateException if no input is needed.
   5.457 -   */
   5.458 -  public void setInput (byte[] buf) 
   5.459 -  {
   5.460 -    setInput (buf, 0, buf.length);
   5.461 -  }
   5.462 -
   5.463 -  /**
   5.464 -   * Sets the input.  This should only be called, if needsInput()
   5.465 -   * returns true.
   5.466 -   * @param buffer the input.
   5.467 -   * @param off the offset into buffer where the input starts.
   5.468 -   * @param len the length of the input.  
   5.469 -   * @exception IllegalStateException if no input is needed.
   5.470 -   * @exception IndexOutOfBoundsException if the off and/or len are wrong.
   5.471 -   */
   5.472 -  public void setInput (byte[] buf, int off, int len) 
   5.473 -  {
   5.474 -    input.setInput (buf, off, len);
   5.475 -    totalIn += len;
   5.476 -  }
   5.477 -  private static final int DEFLATED = 8;
   5.478 -  /**
   5.479 -   * Decodes the deflate header.
   5.480 -   * @return false if more input is needed. 
   5.481 -   * @exception DataFormatException if header is invalid.
   5.482 -   */
   5.483 -  private boolean decodeHeader () throws DataFormatException
   5.484 -  {
   5.485 -    int header = input.peekBits(16);
   5.486 -    if (header < 0)
   5.487 -      return false;
   5.488 -    input.dropBits(16);
   5.489 +public
   5.490 +class Inflater {
   5.491 +    private final org.apidesign.bck2brwsr.emul.zip.Inflater impl;
   5.492      
   5.493 -    /* The header is written in "wrong" byte order */
   5.494 -    header = ((header << 8) | (header >> 8)) & 0xffff;
   5.495 -    if (header % 31 != 0)
   5.496 -      throw new DataFormatException("Header checksum illegal");
   5.497 -    
   5.498 -    if ((header & 0x0f00) != (DEFLATED << 8))
   5.499 -      throw new DataFormatException("Compression Method unknown");
   5.500 -
   5.501 -    /* Maximum size of the backwards window in bits. 
   5.502 -     * We currently ignore this, but we could use it to make the
   5.503 -     * inflater window more space efficient. On the other hand the
   5.504 -     * full window (15 bits) is needed most times, anyway.
   5.505 -     int max_wbits = ((header & 0x7000) >> 12) + 8;
   5.506 +    /**
   5.507 +     * Creates a new decompressor. If the parameter 'nowrap' is true then
   5.508 +     * the ZLIB header and checksum fields will not be used. This provides
   5.509 +     * compatibility with the compression format used by both GZIP and PKZIP.
   5.510 +     * <p>
   5.511 +     * Note: When using the 'nowrap' option it is also necessary to provide
   5.512 +     * an extra "dummy" byte as input. This is required by the ZLIB native
   5.513 +     * library in order to support certain optimizations.
   5.514 +     *
   5.515 +     * @param nowrap if true then support GZIP compatible compression
   5.516       */
   5.517 -    
   5.518 -    if ((header & 0x0020) == 0) // Dictionary flag?
   5.519 -      {
   5.520 -	mode = DECODE_BLOCKS;
   5.521 -      }
   5.522 -    else
   5.523 -      {
   5.524 -	mode = DECODE_DICT;
   5.525 -	neededBits = 32;      
   5.526 -      }
   5.527 -    return true;
   5.528 -  }
   5.529 -   
   5.530 -  /**
   5.531 -   * Decodes the dictionary checksum after the deflate header.
   5.532 -   * @return false if more input is needed. 
   5.533 -   */
   5.534 -  private boolean decodeDict ()
   5.535 -  {
   5.536 -    while (neededBits > 0)
   5.537 -      {
   5.538 -	int dictByte = input.peekBits(8);
   5.539 -	if (dictByte < 0)
   5.540 -	  return false;
   5.541 -	input.dropBits(8);
   5.542 -	readAdler = (readAdler << 8) | dictByte;
   5.543 -	neededBits -= 8;
   5.544 -      }
   5.545 -    return false;
   5.546 -  }
   5.547 -
   5.548 -  /**
   5.549 -   * Decodes the huffman encoded symbols in the input stream.
   5.550 -   * @return false if more input is needed, true if output window is
   5.551 -   * full or the current block ends.
   5.552 -   * @exception DataFormatException if deflated stream is invalid.  
   5.553 -   */
   5.554 -  private boolean decodeHuffman () throws DataFormatException
   5.555 -  {
   5.556 -    int free = outputWindow.getFreeSpace();
   5.557 -    while (free >= 258)
   5.558 -      {
   5.559 -	int symbol;
   5.560 -	switch (mode)
   5.561 -	  {
   5.562 -	  case DECODE_HUFFMAN:
   5.563 -	    /* This is the inner loop so it is optimized a bit */
   5.564 -	    while (((symbol = litlenTree.getSymbol(input)) & ~0xff) == 0)
   5.565 -	      {
   5.566 -		outputWindow.write(symbol);
   5.567 -		if (--free < 258)
   5.568 -		  return true;
   5.569 -	      } 
   5.570 -	    if (symbol < 257)
   5.571 -	      {
   5.572 -		if (symbol < 0)
   5.573 -		  return false;
   5.574 -		else
   5.575 -		  {
   5.576 -		    /* symbol == 256: end of block */
   5.577 -		    distTree = null;
   5.578 -		    litlenTree = null;
   5.579 -		    mode = DECODE_BLOCKS;
   5.580 -		    return true;
   5.581 -		  }
   5.582 -	      }
   5.583 -		
   5.584 -	    try
   5.585 -	      {
   5.586 -		repLength = CPLENS[symbol - 257];
   5.587 -		neededBits = CPLEXT[symbol - 257];
   5.588 -	      }
   5.589 -	    catch (ArrayIndexOutOfBoundsException ex)
   5.590 -	      {
   5.591 -		throw new DataFormatException("Illegal rep length code");
   5.592 -	      }
   5.593 -	    /* fall through */
   5.594 -	  case DECODE_HUFFMAN_LENBITS:
   5.595 -	    if (neededBits > 0)
   5.596 -	      {
   5.597 -		mode = DECODE_HUFFMAN_LENBITS;
   5.598 -		int i = input.peekBits(neededBits);
   5.599 -		if (i < 0)
   5.600 -		  return false;
   5.601 -		input.dropBits(neededBits);
   5.602 -		repLength += i;
   5.603 -	      }
   5.604 -	    mode = DECODE_HUFFMAN_DIST;
   5.605 -	    /* fall through */
   5.606 -	  case DECODE_HUFFMAN_DIST:
   5.607 -	    symbol = distTree.getSymbol(input);
   5.608 -	    if (symbol < 0)
   5.609 -	      return false;
   5.610 -	    try 
   5.611 -	      {
   5.612 -		repDist = CPDIST[symbol];
   5.613 -		neededBits = CPDEXT[symbol];
   5.614 -	      }
   5.615 -	    catch (ArrayIndexOutOfBoundsException ex)
   5.616 -	      {
   5.617 -		throw new DataFormatException("Illegal rep dist code");
   5.618 -	      }
   5.619 -	    /* fall through */
   5.620 -	  case DECODE_HUFFMAN_DISTBITS:
   5.621 -	    if (neededBits > 0)
   5.622 -	      {
   5.623 -		mode = DECODE_HUFFMAN_DISTBITS;
   5.624 -		int i = input.peekBits(neededBits);
   5.625 -		if (i < 0)
   5.626 -		  return false;
   5.627 -		input.dropBits(neededBits);
   5.628 -		repDist += i;
   5.629 -	      }
   5.630 -	    outputWindow.repeat(repLength, repDist);
   5.631 -	    free -= repLength;
   5.632 -	    mode = DECODE_HUFFMAN;
   5.633 -	    break;
   5.634 -	  default:
   5.635 -	    throw new IllegalStateException();
   5.636 -	  }
   5.637 -      }
   5.638 -    return true;
   5.639 -  }
   5.640 -
   5.641 -  /**
   5.642 -   * Decodes the adler checksum after the deflate stream.
   5.643 -   * @return false if more input is needed. 
   5.644 -   * @exception DataFormatException if checksum doesn't match.
   5.645 -   */
   5.646 -  private boolean decodeChksum () throws DataFormatException
   5.647 -  {
   5.648 -    while (neededBits > 0)
   5.649 -      {
   5.650 -	int chkByte = input.peekBits(8);
   5.651 -	if (chkByte < 0)
   5.652 -	  return false;
   5.653 -	input.dropBits(8);
   5.654 -	readAdler = (readAdler << 8) | chkByte;
   5.655 -	neededBits -= 8;
   5.656 -      }
   5.657 -    if ((int) adler.getValue() != readAdler)
   5.658 -      throw new DataFormatException("Adler chksum doesn't match: "
   5.659 -				    +Integer.toHexString((int)adler.getValue())
   5.660 -				    +" vs. "+Integer.toHexString(readAdler));
   5.661 -    mode = FINISHED;
   5.662 -    return false;
   5.663 -  }
   5.664 -
   5.665 -  /**
   5.666 -   * Decodes the deflated stream.
   5.667 -   * @return false if more input is needed, or if finished. 
   5.668 -   * @exception DataFormatException if deflated stream is invalid.
   5.669 -   */
   5.670 -  private boolean decode () throws DataFormatException
   5.671 -  {
   5.672 -    switch (mode) 
   5.673 -      {
   5.674 -      case DECODE_HEADER:
   5.675 -	return decodeHeader();
   5.676 -      case DECODE_DICT:
   5.677 -	return decodeDict();
   5.678 -      case DECODE_CHKSUM:
   5.679 -	return decodeChksum();
   5.680 -
   5.681 -      case DECODE_BLOCKS:
   5.682 -	if (isLastBlock)
   5.683 -	  {
   5.684 -	    if (nowrap)
   5.685 -	      {
   5.686 -		mode = FINISHED;
   5.687 -		return false;
   5.688 -	      }
   5.689 -	    else
   5.690 -	      {
   5.691 -		input.skipToByteBoundary();
   5.692 -		neededBits = 32;
   5.693 -		mode = DECODE_CHKSUM;
   5.694 -		return true;
   5.695 -	      }
   5.696 -	  }
   5.697 -
   5.698 -	int type = input.peekBits(3);
   5.699 -	if (type < 0)
   5.700 -	  return false;
   5.701 -	input.dropBits(3);
   5.702 -
   5.703 -	if ((type & 1) != 0)
   5.704 -	  isLastBlock = true;
   5.705 -	switch (type >> 1)
   5.706 -	  {
   5.707 -	  case DeflaterConstants.STORED_BLOCK:
   5.708 -	    input.skipToByteBoundary();
   5.709 -	    mode = DECODE_STORED_LEN1;
   5.710 -	    break;
   5.711 -	  case DeflaterConstants.STATIC_TREES:
   5.712 -	    litlenTree = InflaterHuffmanTree.defLitLenTree;
   5.713 -	    distTree = InflaterHuffmanTree.defDistTree;
   5.714 -	    mode = DECODE_HUFFMAN;
   5.715 -	    break;
   5.716 -	  case DeflaterConstants.DYN_TREES:
   5.717 -	    dynHeader = new InflaterDynHeader();
   5.718 -	    mode = DECODE_DYN_HEADER;
   5.719 -	    break;
   5.720 -	  default:
   5.721 -	    throw new DataFormatException("Unknown block type "+type);
   5.722 -	  }
   5.723 -	return true;
   5.724 -
   5.725 -      case DECODE_STORED_LEN1:
   5.726 -	{
   5.727 -	  if ((uncomprLen = input.peekBits(16)) < 0)
   5.728 -	    return false;
   5.729 -	  input.dropBits(16);
   5.730 -	  mode = DECODE_STORED_LEN2;
   5.731 -	}
   5.732 -	/* fall through */
   5.733 -      case DECODE_STORED_LEN2:
   5.734 -	{
   5.735 -	  int nlen = input.peekBits(16);
   5.736 -	  if (nlen < 0)
   5.737 -	    return false;
   5.738 -	  input.dropBits(16);
   5.739 -	  if (nlen != (uncomprLen ^ 0xffff))
   5.740 -	    throw new DataFormatException("broken uncompressed block");
   5.741 -	  mode = DECODE_STORED;
   5.742 -	}
   5.743 -	/* fall through */
   5.744 -      case DECODE_STORED:
   5.745 -	{
   5.746 -	  int more = outputWindow.copyStored(input, uncomprLen);
   5.747 -	  uncomprLen -= more;
   5.748 -	  if (uncomprLen == 0)
   5.749 -	    {
   5.750 -	      mode = DECODE_BLOCKS;
   5.751 -	      return true;
   5.752 -	    }
   5.753 -	  return !input.needsInput();
   5.754 -	}
   5.755 -
   5.756 -      case DECODE_DYN_HEADER:
   5.757 -	if (!dynHeader.decode(input))
   5.758 -	  return false;
   5.759 -	litlenTree = dynHeader.buildLitLenTree();
   5.760 -	distTree = dynHeader.buildDistTree();
   5.761 -	mode = DECODE_HUFFMAN;
   5.762 -	/* fall through */
   5.763 -      case DECODE_HUFFMAN:
   5.764 -      case DECODE_HUFFMAN_LENBITS:
   5.765 -      case DECODE_HUFFMAN_DIST:
   5.766 -      case DECODE_HUFFMAN_DISTBITS:
   5.767 -	return decodeHuffman();
   5.768 -      case FINISHED:
   5.769 -	return false;
   5.770 -      default:
   5.771 -	throw new IllegalStateException();
   5.772 -      }	
   5.773 -  }
   5.774 -
   5.775 -
   5.776 -    interface DeflaterConstants {
   5.777 -      final static boolean DEBUGGING = false;
   5.778 -
   5.779 -      final static int STORED_BLOCK = 0;
   5.780 -      final static int STATIC_TREES = 1;
   5.781 -      final static int DYN_TREES    = 2;
   5.782 -      final static int PRESET_DICT  = 0x20;
   5.783 -
   5.784 -      final static int DEFAULT_MEM_LEVEL = 8;
   5.785 -
   5.786 -      final static int MAX_MATCH = 258;
   5.787 -      final static int MIN_MATCH = 3;
   5.788 -
   5.789 -      final static int MAX_WBITS = 15;
   5.790 -      final static int WSIZE = 1 << MAX_WBITS;
   5.791 -      final static int WMASK = WSIZE - 1;
   5.792 -
   5.793 -      final static int HASH_BITS = DEFAULT_MEM_LEVEL + 7;
   5.794 -      final static int HASH_SIZE = 1 << HASH_BITS;
   5.795 -      final static int HASH_MASK = HASH_SIZE - 1;
   5.796 -      final static int HASH_SHIFT = (HASH_BITS + MIN_MATCH - 1) / MIN_MATCH;
   5.797 -
   5.798 -      final static int MIN_LOOKAHEAD = MAX_MATCH + MIN_MATCH + 1;
   5.799 -      final static int MAX_DIST = WSIZE - MIN_LOOKAHEAD;
   5.800 -
   5.801 -      final static int PENDING_BUF_SIZE = 1 << (DEFAULT_MEM_LEVEL + 8);
   5.802 -      final static int MAX_BLOCK_SIZE = Math.min(65535, PENDING_BUF_SIZE-5);
   5.803 -
   5.804 -      final static int DEFLATE_STORED = 0;
   5.805 -      final static int DEFLATE_FAST   = 1;
   5.806 -      final static int DEFLATE_SLOW   = 2;
   5.807 -
   5.808 -      final static int GOOD_LENGTH[] = { 0,4, 4, 4, 4, 8,  8,  8,  32,  32 };
   5.809 -      final static int MAX_LAZY[]    = { 0,4, 5, 6, 4,16, 16, 32, 128, 258 };
   5.810 -      final static int NICE_LENGTH[] = { 0,8,16,32,16,32,128,128, 258, 258 };
   5.811 -      final static int MAX_CHAIN[]   = { 0,4, 8,32,16,32,128,256,1024,4096 };
   5.812 -      final static int COMPR_FUNC[]  = { 0,1, 1, 1, 1, 2,  2,  2,   2,   2 };
   5.813 -    }
   5.814 -    private static class InflaterHuffmanTree {
   5.815 -      private final static int MAX_BITLEN = 15;
   5.816 -      private short[] tree;
   5.817 -
   5.818 -      public static InflaterHuffmanTree defLitLenTree, defDistTree;
   5.819 -
   5.820 -      static
   5.821 -      {
   5.822 -        try 
   5.823 -          {
   5.824 -        byte[] codeLengths = new byte[288];
   5.825 -        int i = 0;
   5.826 -        while (i < 144)
   5.827 -          codeLengths[i++] = 8;
   5.828 -        while (i < 256)
   5.829 -          codeLengths[i++] = 9;
   5.830 -        while (i < 280)
   5.831 -          codeLengths[i++] = 7;
   5.832 -        while (i < 288)
   5.833 -          codeLengths[i++] = 8;
   5.834 -        defLitLenTree = new InflaterHuffmanTree(codeLengths);
   5.835 -
   5.836 -        codeLengths = new byte[32];
   5.837 -        i = 0;
   5.838 -        while (i < 32)
   5.839 -          codeLengths[i++] = 5;
   5.840 -        defDistTree = new InflaterHuffmanTree(codeLengths);
   5.841 -          } 
   5.842 -        catch (DataFormatException ex)
   5.843 -          {
   5.844 -        throw new IllegalStateException
   5.845 -          ("InflaterHuffmanTree: static tree length illegal");
   5.846 -          }
   5.847 -      }
   5.848 -
   5.849 -      /**
   5.850 -       * Constructs a Huffman tree from the array of code lengths.
   5.851 -       *
   5.852 -       * @param codeLengths the array of code lengths
   5.853 -       */
   5.854 -      public InflaterHuffmanTree(byte[] codeLengths) throws DataFormatException
   5.855 -      {
   5.856 -        buildTree(codeLengths);
   5.857 -      }
   5.858 -
   5.859 -      private void buildTree(byte[] codeLengths) throws DataFormatException
   5.860 -      {
   5.861 -        int[] blCount = new int[MAX_BITLEN+1];
   5.862 -        int[] nextCode = new int[MAX_BITLEN+1];
   5.863 -        for (int i = 0; i < codeLengths.length; i++)
   5.864 -          {
   5.865 -        int bits = codeLengths[i];
   5.866 -        if (bits > 0)
   5.867 -          blCount[bits]++;
   5.868 -          }
   5.869 -
   5.870 -        int code = 0;
   5.871 -        int treeSize = 512;
   5.872 -        for (int bits = 1; bits <= MAX_BITLEN; bits++)
   5.873 -          {
   5.874 -        nextCode[bits] = code;
   5.875 -        code += blCount[bits] << (16 - bits);
   5.876 -        if (bits >= 10)
   5.877 -          {
   5.878 -            /* We need an extra table for bit lengths >= 10. */
   5.879 -            int start = nextCode[bits] & 0x1ff80;
   5.880 -            int end   = code & 0x1ff80;
   5.881 -            treeSize += (end - start) >> (16 - bits);
   5.882 -          }
   5.883 -          }
   5.884 -        if (code != 65536)
   5.885 -          throw new DataFormatException("Code lengths don't add up properly.");
   5.886 -
   5.887 -        fillTable1(treeSize, code, blCount);
   5.888 -
   5.889 -        for (int i = 0; i < codeLengths.length; i++)
   5.890 -          {
   5.891 -        int bits = codeLengths[i];
   5.892 -        if (bits == 0)
   5.893 -          continue;
   5.894 -        code = nextCode[bits];
   5.895 -        int revcode = bitReverse(code);
   5.896 -        if (bits <= 9)
   5.897 -          {
   5.898 -            do
   5.899 -              {
   5.900 -            tree[revcode] = (short) ((i << 4) | bits);
   5.901 -            revcode += 1 << bits;
   5.902 -              }
   5.903 -            while (revcode < 512);
   5.904 -          }
   5.905 -        else
   5.906 -          {
   5.907 -            int subTree = tree[revcode & 511];
   5.908 -            int treeLen = 1 << (subTree & 15);
   5.909 -            subTree = -(subTree >> 4);
   5.910 -            do
   5.911 -              { 
   5.912 -            tree[subTree | (revcode >> 9)] = (short) ((i << 4) | bits);
   5.913 -            revcode += 1 << bits;
   5.914 -              }
   5.915 -            while (revcode < treeLen);
   5.916 -          }
   5.917 -        nextCode[bits] = code + (1 << (16 - bits));
   5.918 -          }
   5.919 -      }
   5.920 -      private final static String bit4Reverse =
   5.921 -        "\000\010\004\014\002\012\006\016\001\011\005\015\003\013\007\017";
   5.922 -      static short bitReverse(int value) {
   5.923 -            return (short) (bit4Reverse.charAt(value & 0xf) << 12
   5.924 -                    | bit4Reverse.charAt((value >> 4) & 0xf) << 8
   5.925 -                    | bit4Reverse.charAt((value >> 8) & 0xf) << 4
   5.926 -                    | bit4Reverse.charAt(value >> 12));
   5.927 -      }
   5.928 -      
   5.929 -      /**
   5.930 -       * Reads the next symbol from input.  The symbol is encoded using the
   5.931 -       * huffman tree.
   5.932 -       * @param input the input source.
   5.933 -       * @return the next symbol, or -1 if not enough input is available.
   5.934 -       */
   5.935 -      public int getSymbol(StreamManipulator input) throws DataFormatException
   5.936 -      {
   5.937 -        int lookahead, symbol;
   5.938 -        if ((lookahead = input.peekBits(9)) >= 0)
   5.939 -          {
   5.940 -        if ((symbol = tree[lookahead]) >= 0)
   5.941 -          {
   5.942 -            input.dropBits(symbol & 15);
   5.943 -            return symbol >> 4;
   5.944 -          }
   5.945 -        int subtree = -(symbol >> 4);
   5.946 -        int bitlen = symbol & 15;
   5.947 -        if ((lookahead = input.peekBits(bitlen)) >= 0)
   5.948 -          {
   5.949 -            symbol = tree[subtree | (lookahead >> 9)];
   5.950 -            input.dropBits(symbol & 15);
   5.951 -            return symbol >> 4;
   5.952 -          }
   5.953 -        else
   5.954 -          {
   5.955 -            int bits = input.getAvailableBits();
   5.956 -            lookahead = input.peekBits(bits);
   5.957 -            symbol = tree[subtree | (lookahead >> 9)];
   5.958 -            if ((symbol & 15) <= bits)
   5.959 -              {
   5.960 -            input.dropBits(symbol & 15);
   5.961 -            return symbol >> 4;
   5.962 -              }
   5.963 -            else
   5.964 -              return -1;
   5.965 -          }
   5.966 -          }
   5.967 -        else
   5.968 -          {
   5.969 -        int bits = input.getAvailableBits();
   5.970 -        lookahead = input.peekBits(bits);
   5.971 -        symbol = tree[lookahead];
   5.972 -        if (symbol >= 0 && (symbol & 15) <= bits)
   5.973 -          {
   5.974 -            input.dropBits(symbol & 15);
   5.975 -            return symbol >> 4;
   5.976 -          }
   5.977 -        else
   5.978 -          return -1;
   5.979 -          }
   5.980 -      }
   5.981 -
   5.982 -        private void fillTable1(int treeSize, int code, int[] blCount) {
   5.983 -            /* Now create and fill the extra tables from longest to shortest
   5.984 -             * bit len.  This way the sub trees will be aligned.
   5.985 -             */
   5.986 -            tree = new short[treeSize];
   5.987 -            int treePtr = 512;
   5.988 -            for (int bits = MAX_BITLEN; bits >= 10; bits--) {
   5.989 -                int end = code & 0x1ff80;
   5.990 -                code -= blCount[bits] << (16 - bits);
   5.991 -                int start = code & 0x1ff80;
   5.992 -                final int inc = 1 << 7;
   5.993 -                fillTable2(start, end, inc, treePtr, bits);
   5.994 -            }
   5.995 -        }
   5.996 -
   5.997 -        private void fillTable2(int start, int end, final int inc, int treePtr, int bits) {
   5.998 -            for (int i = start; i < end; i += inc) {
   5.999 -                final short br = bitReverse(i);
  5.1000 -                tree[br] = (short) ((-treePtr << 4) | bits);
  5.1001 -                treePtr += 1 << (bits - 9);
  5.1002 -            }
  5.1003 +    public Inflater(boolean nowrap) {
  5.1004 +        if (getClass() == org.apidesign.bck2brwsr.emul.zip.Inflater.class) {
  5.1005 +            impl = null;
  5.1006 +        } else {
  5.1007 +            impl = new org.apidesign.bck2brwsr.emul.zip.Inflater(nowrap);
  5.1008          }
  5.1009      }
  5.1010 -    private static class InflaterDynHeader
  5.1011 +
  5.1012 +    /**
  5.1013 +     * Creates a new decompressor.
  5.1014 +     */
  5.1015 +    public Inflater() {
  5.1016 +        this(false);
  5.1017 +    }
  5.1018 +
  5.1019 +    /**
  5.1020 +     * Sets input data for decompression. Should be called whenever
  5.1021 +     * needsInput() returns true indicating that more input data is
  5.1022 +     * required.
  5.1023 +     * @param b the input data bytes
  5.1024 +     * @param off the start offset of the input data
  5.1025 +     * @param len the length of the input data
  5.1026 +     * @see Inflater#needsInput
  5.1027 +     */
  5.1028 +    public void setInput(byte[] b, int off, int len) {
  5.1029 +        impl.setInput(b, off, len);
  5.1030 +    }
  5.1031 +
  5.1032 +    /**
  5.1033 +     * Sets input data for decompression. Should be called whenever
  5.1034 +     * needsInput() returns true indicating that more input data is
  5.1035 +     * required.
  5.1036 +     * @param b the input data bytes
  5.1037 +     * @see Inflater#needsInput
  5.1038 +     */
  5.1039 +    public void setInput(byte[] b) {
  5.1040 +        impl.setInput(b);
  5.1041 +    }
  5.1042 +
  5.1043 +    /**
  5.1044 +     * Sets the preset dictionary to the given array of bytes. Should be
  5.1045 +     * called when inflate() returns 0 and needsDictionary() returns true
  5.1046 +     * indicating that a preset dictionary is required. The method getAdler()
  5.1047 +     * can be used to get the Adler-32 value of the dictionary needed.
  5.1048 +     * @param b the dictionary data bytes
  5.1049 +     * @param off the start offset of the data
  5.1050 +     * @param len the length of the data
  5.1051 +     * @see Inflater#needsDictionary
  5.1052 +     * @see Inflater#getAdler
  5.1053 +     */
  5.1054 +    public void setDictionary(byte[] b, int off, int len) {
  5.1055 +        impl.setDictionary(b, off, len);
  5.1056 +    }
  5.1057 +
  5.1058 +    /**
  5.1059 +     * Sets the preset dictionary to the given array of bytes. Should be
  5.1060 +     * called when inflate() returns 0 and needsDictionary() returns true
  5.1061 +     * indicating that a preset dictionary is required. The method getAdler()
  5.1062 +     * can be used to get the Adler-32 value of the dictionary needed.
  5.1063 +     * @param b the dictionary data bytes
  5.1064 +     * @see Inflater#needsDictionary
  5.1065 +     * @see Inflater#getAdler
  5.1066 +     */
  5.1067 +    public void setDictionary(byte[] b) {
  5.1068 +        impl.setDictionary(b);
  5.1069 +    }
  5.1070 +
  5.1071 +    /**
  5.1072 +     * Returns the total number of bytes remaining in the input buffer.
  5.1073 +     * This can be used to find out what bytes still remain in the input
  5.1074 +     * buffer after decompression has finished.
  5.1075 +     * @return the total number of bytes remaining in the input buffer
  5.1076 +     */
  5.1077 +    public int getRemaining() {
  5.1078 +        return impl.getRemaining();
  5.1079 +    }
  5.1080 +
  5.1081 +    /**
  5.1082 +     * Returns true if no data remains in the input buffer. This can
  5.1083 +     * be used to determine if #setInput should be called in order
  5.1084 +     * to provide more input.
  5.1085 +     * @return true if no data remains in the input buffer
  5.1086 +     */
  5.1087 +    public boolean needsInput() {
  5.1088 +        return impl.needsInput();
  5.1089 +    }
  5.1090 +
  5.1091 +    /**
  5.1092 +     * Returns true if a preset dictionary is needed for decompression.
  5.1093 +     * @return true if a preset dictionary is needed for decompression
  5.1094 +     * @see Inflater#setDictionary
  5.1095 +     */
  5.1096 +    public boolean needsDictionary() {
  5.1097 +        return impl.needsDictionary();
  5.1098 +    }
  5.1099 +
  5.1100 +    /**
  5.1101 +     * Returns true if the end of the compressed data stream has been
  5.1102 +     * reached.
  5.1103 +     * @return true if the end of the compressed data stream has been
  5.1104 +     * reached
  5.1105 +     */
  5.1106 +    public boolean finished() {
  5.1107 +        return impl.finished();
  5.1108 +    }
  5.1109 +
  5.1110 +    /**
  5.1111 +     * Uncompresses bytes into specified buffer. Returns actual number
  5.1112 +     * of bytes uncompressed. A return value of 0 indicates that
  5.1113 +     * needsInput() or needsDictionary() should be called in order to
  5.1114 +     * determine if more input data or a preset dictionary is required.
  5.1115 +     * In the latter case, getAdler() can be used to get the Adler-32
  5.1116 +     * value of the dictionary required.
  5.1117 +     * @param b the buffer for the uncompressed data
  5.1118 +     * @param off the start offset of the data
  5.1119 +     * @param len the maximum number of uncompressed bytes
  5.1120 +     * @return the actual number of uncompressed bytes
  5.1121 +     * @exception DataFormatException if the compressed data format is invalid
  5.1122 +     * @see Inflater#needsInput
  5.1123 +     * @see Inflater#needsDictionary
  5.1124 +     */
  5.1125 +    public int inflate(byte[] b, int off, int len)
  5.1126 +        throws DataFormatException
  5.1127      {
  5.1128 -      private static final int LNUM   = 0;
  5.1129 -      private static final int DNUM   = 1;
  5.1130 -      private static final int BLNUM  = 2;
  5.1131 -      private static final int BLLENS = 3;
  5.1132 -      private static final int LENS   = 4;
  5.1133 -      private static final int REPS   = 5;
  5.1134 +        return impl.inflate(b, off, len);
  5.1135 +    }
  5.1136  
  5.1137 -      private static final int repMin[]  = { 3, 3, 11 };
  5.1138 -      private static final int repBits[] = { 2, 3,  7 };
  5.1139 +    /**
  5.1140 +     * Uncompresses bytes into specified buffer. Returns actual number
  5.1141 +     * of bytes uncompressed. A return value of 0 indicates that
  5.1142 +     * needsInput() or needsDictionary() should be called in order to
  5.1143 +     * determine if more input data or a preset dictionary is required.
  5.1144 +     * In the latter case, getAdler() can be used to get the Adler-32
  5.1145 +     * value of the dictionary required.
  5.1146 +     * @param b the buffer for the uncompressed data
  5.1147 +     * @return the actual number of uncompressed bytes
  5.1148 +     * @exception DataFormatException if the compressed data format is invalid
  5.1149 +     * @see Inflater#needsInput
  5.1150 +     * @see Inflater#needsDictionary
  5.1151 +     */
  5.1152 +    public int inflate(byte[] b) throws DataFormatException {
  5.1153 +        return impl.inflate(b);
  5.1154 +    }
  5.1155  
  5.1156 +    /**
  5.1157 +     * Returns the ADLER-32 value of the uncompressed data.
  5.1158 +     * @return the ADLER-32 value of the uncompressed data
  5.1159 +     */
  5.1160 +    public int getAdler() {
  5.1161 +        return impl.getAdler();
  5.1162 +    }
  5.1163  
  5.1164 -      private byte[] blLens;
  5.1165 -      private byte[] litdistLens;
  5.1166 +    /**
  5.1167 +     * Returns the total number of compressed bytes input so far.
  5.1168 +     *
  5.1169 +     * <p>Since the number of bytes may be greater than
  5.1170 +     * Integer.MAX_VALUE, the {@link #getBytesRead()} method is now
  5.1171 +     * the preferred means of obtaining this information.</p>
  5.1172 +     *
  5.1173 +     * @return the total number of compressed bytes input so far
  5.1174 +     */
  5.1175 +    public int getTotalIn() {
  5.1176 +        return impl.getTotalIn();
  5.1177 +    }
  5.1178  
  5.1179 -      private InflaterHuffmanTree blTree;
  5.1180 +    /**
  5.1181 +     * Returns the total number of compressed bytes input so far.</p>
  5.1182 +     *
  5.1183 +     * @return the total (non-negative) number of compressed bytes input so far
  5.1184 +     * @since 1.5
  5.1185 +     */
  5.1186 +    public long getBytesRead() {
  5.1187 +        return impl.getBytesRead();
  5.1188 +    }
  5.1189  
  5.1190 -      private int mode;
  5.1191 -      private int lnum, dnum, blnum, num;
  5.1192 -      private int repSymbol;
  5.1193 -      private byte lastLen;
  5.1194 -      private int ptr;
  5.1195 +    /**
  5.1196 +     * Returns the total number of uncompressed bytes output so far.
  5.1197 +     *
  5.1198 +     * <p>Since the number of bytes may be greater than
  5.1199 +     * Integer.MAX_VALUE, the {@link #getBytesWritten()} method is now
  5.1200 +     * the preferred means of obtaining this information.</p>
  5.1201 +     *
  5.1202 +     * @return the total number of uncompressed bytes output so far
  5.1203 +     */
  5.1204 +    public int getTotalOut() {
  5.1205 +        return impl.getTotalOut();
  5.1206 +    }
  5.1207  
  5.1208 -      private static final int[] BL_ORDER =
  5.1209 -      { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
  5.1210 +    /**
  5.1211 +     * Returns the total number of uncompressed bytes output so far.</p>
  5.1212 +     *
  5.1213 +     * @return the total (non-negative) number of uncompressed bytes output so far
  5.1214 +     * @since 1.5
  5.1215 +     */
  5.1216 +    public long getBytesWritten() {
  5.1217 +        return impl.getBytesWritten();
  5.1218 +    }
  5.1219  
  5.1220 -      public InflaterDynHeader()
  5.1221 -      {
  5.1222 -      }
  5.1223 +    /**
  5.1224 +     * Resets inflater so that a new set of input data can be processed.
  5.1225 +     */
  5.1226 +    public void reset() {
  5.1227 +        impl.reset();
  5.1228 +    }
  5.1229  
  5.1230 -      public boolean decode(StreamManipulator input) throws DataFormatException
  5.1231 -      {
  5.1232 -      decode_loop:
  5.1233 -        for (;;)
  5.1234 -          {
  5.1235 -        switch (mode)
  5.1236 -          {
  5.1237 -          case LNUM:
  5.1238 -            lnum = input.peekBits(5);
  5.1239 -            if (lnum < 0)
  5.1240 -              return false;
  5.1241 -            lnum += 257;
  5.1242 -            input.dropBits(5);
  5.1243 -    //  	    System.err.println("LNUM: "+lnum);
  5.1244 -            mode = DNUM;
  5.1245 -            /* fall through */
  5.1246 -          case DNUM:
  5.1247 -            dnum = input.peekBits(5);
  5.1248 -            if (dnum < 0)
  5.1249 -              return false;
  5.1250 -            dnum++;
  5.1251 -            input.dropBits(5);
  5.1252 -    //  	    System.err.println("DNUM: "+dnum);
  5.1253 -            num = lnum+dnum;
  5.1254 -            litdistLens = new byte[num];
  5.1255 -            mode = BLNUM;
  5.1256 -            /* fall through */
  5.1257 -          case BLNUM:
  5.1258 -            blnum = input.peekBits(4);
  5.1259 -            if (blnum < 0)
  5.1260 -              return false;
  5.1261 -            blnum += 4;
  5.1262 -            input.dropBits(4);
  5.1263 -            blLens = new byte[19];
  5.1264 -            ptr = 0;
  5.1265 -    //  	    System.err.println("BLNUM: "+blnum);
  5.1266 -            mode = BLLENS;
  5.1267 -            /* fall through */
  5.1268 -          case BLLENS:
  5.1269 -            while (ptr < blnum)
  5.1270 -              {
  5.1271 -            int len = input.peekBits(3);
  5.1272 -            if (len < 0)
  5.1273 -              return false;
  5.1274 -            input.dropBits(3);
  5.1275 -    //  		System.err.println("blLens["+BL_ORDER[ptr]+"]: "+len);
  5.1276 -            blLens[BL_ORDER[ptr]] = (byte) len;
  5.1277 -            ptr++;
  5.1278 -              }
  5.1279 -            blTree = new InflaterHuffmanTree(blLens);
  5.1280 -            blLens = null;
  5.1281 -            ptr = 0;
  5.1282 -            mode = LENS;
  5.1283 -            /* fall through */
  5.1284 -          case LENS:
  5.1285 -            {
  5.1286 -              int symbol;
  5.1287 -              while (((symbol = blTree.getSymbol(input)) & ~15) == 0)
  5.1288 -            {
  5.1289 -              /* Normal case: symbol in [0..15] */
  5.1290 +    /**
  5.1291 +     * Closes the decompressor and discards any unprocessed input.
  5.1292 +     * This method should be called when the decompressor is no longer
  5.1293 +     * being used, but will also be called automatically by the finalize()
  5.1294 +     * method. Once this method is called, the behavior of the Inflater
  5.1295 +     * object is undefined.
  5.1296 +     */
  5.1297 +    public void end() {
  5.1298 +        impl.end();
  5.1299 +    }
  5.1300  
  5.1301 -    //  		  System.err.println("litdistLens["+ptr+"]: "+symbol);
  5.1302 -              litdistLens[ptr++] = lastLen = (byte) symbol;
  5.1303 -
  5.1304 -              if (ptr == num)
  5.1305 -                {
  5.1306 -                  /* Finished */
  5.1307 -                  return true;
  5.1308 -                }
  5.1309 -            }
  5.1310 -
  5.1311 -              /* need more input ? */
  5.1312 -              if (symbol < 0)
  5.1313 -            return false;
  5.1314 -
  5.1315 -              /* otherwise repeat code */
  5.1316 -              if (symbol >= 17)
  5.1317 -            {
  5.1318 -              /* repeat zero */
  5.1319 -    //  		  System.err.println("repeating zero");
  5.1320 -              lastLen = 0;
  5.1321 -            }
  5.1322 -              else
  5.1323 -            {
  5.1324 -              if (ptr == 0)
  5.1325 -                throw new DataFormatException();
  5.1326 -            }
  5.1327 -              repSymbol = symbol-16;
  5.1328 -              mode = REPS;
  5.1329 -            }
  5.1330 -            /* fall through */
  5.1331 -
  5.1332 -          case REPS:
  5.1333 -            {
  5.1334 -              int bits = repBits[repSymbol];
  5.1335 -              int count = input.peekBits(bits);
  5.1336 -              if (count < 0)
  5.1337 -            return false;
  5.1338 -              input.dropBits(bits);
  5.1339 -              count += repMin[repSymbol];
  5.1340 -    //  	      System.err.println("litdistLens repeated: "+count);
  5.1341 -
  5.1342 -              if (ptr + count > num)
  5.1343 -            throw new DataFormatException();
  5.1344 -              while (count-- > 0)
  5.1345 -            litdistLens[ptr++] = lastLen;
  5.1346 -
  5.1347 -              if (ptr == num)
  5.1348 -            {
  5.1349 -              /* Finished */
  5.1350 -              return true;
  5.1351 -            }
  5.1352 -            }
  5.1353 -            mode = LENS;
  5.1354 -            continue decode_loop;
  5.1355 -          }
  5.1356 -          }
  5.1357 -      }
  5.1358 -
  5.1359 -      public InflaterHuffmanTree buildLitLenTree() throws DataFormatException
  5.1360 -      {
  5.1361 -        byte[] litlenLens = new byte[lnum];
  5.1362 -        System.arraycopy(litdistLens, 0, litlenLens, 0, lnum);
  5.1363 -        return new InflaterHuffmanTree(litlenLens);
  5.1364 -      }
  5.1365 -
  5.1366 -      public InflaterHuffmanTree buildDistTree() throws DataFormatException
  5.1367 -      {
  5.1368 -        byte[] distLens = new byte[dnum];
  5.1369 -        System.arraycopy(litdistLens, lnum, distLens, 0, dnum);
  5.1370 -        return new InflaterHuffmanTree(distLens);
  5.1371 -      }
  5.1372 +    /**
  5.1373 +     * Closes the decompressor when garbage is collected.
  5.1374 +     */
  5.1375 +    protected void finalize() {
  5.1376 +        end();
  5.1377      }
  5.1378 -    /**
  5.1379 -     * This class allows us to retrieve a specified amount of bits from
  5.1380 -     * the input buffer, as well as copy big byte blocks.
  5.1381 -     *
  5.1382 -     * It uses an int buffer to store up to 31 bits for direct
  5.1383 -     * manipulation.  This guarantees that we can get at least 16 bits,
  5.1384 -     * but we only need at most 15, so this is all safe.
  5.1385 -     *
  5.1386 -     * There are some optimizations in this class, for example, you must
  5.1387 -     * never peek more then 8 bits more than needed, and you must first 
  5.1388 -     * peek bits before you may drop them.  This is not a general purpose
  5.1389 -     * class but optimized for the behaviour of the Inflater.
  5.1390 -     *
  5.1391 -     * @author John Leuner, Jochen Hoenicke
  5.1392 -     */
  5.1393 -
  5.1394 -    private static class StreamManipulator
  5.1395 -    {
  5.1396 -      private byte[] window;
  5.1397 -      private int window_start = 0;
  5.1398 -      private int window_end = 0;
  5.1399 -
  5.1400 -      private int buffer = 0;
  5.1401 -      private int bits_in_buffer = 0;
  5.1402 -
  5.1403 -      /**
  5.1404 -       * Get the next n bits but don't increase input pointer.  n must be
  5.1405 -       * less or equal 16 and if you if this call succeeds, you must drop
  5.1406 -       * at least n-8 bits in the next call.
  5.1407 -       * 
  5.1408 -       * @return the value of the bits, or -1 if not enough bits available.  */
  5.1409 -      public final int peekBits(int n)
  5.1410 -      {
  5.1411 -        if (bits_in_buffer < n)
  5.1412 -          {
  5.1413 -        if (window_start == window_end)
  5.1414 -          return -1;
  5.1415 -        buffer |= (window[window_start++] & 0xff
  5.1416 -               | (window[window_start++] & 0xff) << 8) << bits_in_buffer;
  5.1417 -        bits_in_buffer += 16;
  5.1418 -          }
  5.1419 -        return buffer & ((1 << n) - 1);
  5.1420 -      }
  5.1421 -
  5.1422 -      /* Drops the next n bits from the input.  You should have called peekBits
  5.1423 -       * with a bigger or equal n before, to make sure that enough bits are in
  5.1424 -       * the bit buffer.
  5.1425 -       */
  5.1426 -      public final void dropBits(int n)
  5.1427 -      {
  5.1428 -        buffer >>>= n;
  5.1429 -        bits_in_buffer -= n;
  5.1430 -      }
  5.1431 -
  5.1432 -      /**
  5.1433 -       * Gets the next n bits and increases input pointer.  This is equivalent
  5.1434 -       * to peekBits followed by dropBits, except for correct error handling.
  5.1435 -       * @return the value of the bits, or -1 if not enough bits available. 
  5.1436 -       */
  5.1437 -      public final int getBits(int n)
  5.1438 -      {
  5.1439 -        int bits = peekBits(n);
  5.1440 -        if (bits >= 0)
  5.1441 -          dropBits(n);
  5.1442 -        return bits;
  5.1443 -      }
  5.1444 -      /**
  5.1445 -       * Gets the number of bits available in the bit buffer.  This must be
  5.1446 -       * only called when a previous peekBits() returned -1.
  5.1447 -       * @return the number of bits available.
  5.1448 -       */
  5.1449 -      public final int getAvailableBits()
  5.1450 -      {
  5.1451 -        return bits_in_buffer;
  5.1452 -      }
  5.1453 -
  5.1454 -      /**
  5.1455 -       * Gets the number of bytes available.  
  5.1456 -       * @return the number of bytes available.
  5.1457 -       */
  5.1458 -      public final int getAvailableBytes()
  5.1459 -      {
  5.1460 -        return window_end - window_start + (bits_in_buffer >> 3);
  5.1461 -      }
  5.1462 -
  5.1463 -      /**
  5.1464 -       * Skips to the next byte boundary.
  5.1465 -       */
  5.1466 -      public void skipToByteBoundary()
  5.1467 -      {
  5.1468 -        buffer >>= (bits_in_buffer & 7);
  5.1469 -        bits_in_buffer &= ~7;
  5.1470 -      }
  5.1471 -
  5.1472 -      public final boolean needsInput() {
  5.1473 -        return window_start == window_end;
  5.1474 -      }
  5.1475 -
  5.1476 -
  5.1477 -      /* Copies length bytes from input buffer to output buffer starting
  5.1478 -       * at output[offset].  You have to make sure, that the buffer is
  5.1479 -       * byte aligned.  If not enough bytes are available, copies fewer
  5.1480 -       * bytes.
  5.1481 -       * @param length the length to copy, 0 is allowed.
  5.1482 -       * @return the number of bytes copied, 0 if no byte is available.  
  5.1483 -       */
  5.1484 -      public int copyBytes(byte[] output, int offset, int length)
  5.1485 -      {
  5.1486 -        if (length < 0)
  5.1487 -          throw new IllegalArgumentException("length negative");
  5.1488 -        if ((bits_in_buffer & 7) != 0)  
  5.1489 -          /* bits_in_buffer may only be 0 or 8 */
  5.1490 -          throw new IllegalStateException("Bit buffer is not aligned!");
  5.1491 -
  5.1492 -        int count = 0;
  5.1493 -        while (bits_in_buffer > 0 && length > 0)
  5.1494 -          {
  5.1495 -        output[offset++] = (byte) buffer;
  5.1496 -        buffer >>>= 8;
  5.1497 -        bits_in_buffer -= 8;
  5.1498 -        length--;
  5.1499 -        count++;
  5.1500 -          }
  5.1501 -        if (length == 0)
  5.1502 -          return count;
  5.1503 -
  5.1504 -        int avail = window_end - window_start;
  5.1505 -        if (length > avail)
  5.1506 -          length = avail;
  5.1507 -        System.arraycopy(window, window_start, output, offset, length);
  5.1508 -        window_start += length;
  5.1509 -
  5.1510 -        if (((window_start - window_end) & 1) != 0)
  5.1511 -          {
  5.1512 -        /* We always want an even number of bytes in input, see peekBits */
  5.1513 -        buffer = (window[window_start++] & 0xff);
  5.1514 -        bits_in_buffer = 8;
  5.1515 -          }
  5.1516 -        return count + length;
  5.1517 -      }
  5.1518 -
  5.1519 -      public StreamManipulator()
  5.1520 -      {
  5.1521 -      }
  5.1522 -
  5.1523 -      public void reset()
  5.1524 -      {
  5.1525 -        window_start = window_end = buffer = bits_in_buffer = 0;
  5.1526 -      }
  5.1527 -
  5.1528 -      public void setInput(byte[] buf, int off, int len)
  5.1529 -      {
  5.1530 -        if (window_start < window_end)
  5.1531 -          throw new IllegalStateException
  5.1532 -        ("Old input was not completely processed");
  5.1533 -
  5.1534 -        int end = off + len;
  5.1535 -
  5.1536 -        /* We want to throw an ArrayIndexOutOfBoundsException early.  The
  5.1537 -         * check is very tricky: it also handles integer wrap around.  
  5.1538 -         */
  5.1539 -        if (0 > off || off > end || end > buf.length)
  5.1540 -          throw new ArrayIndexOutOfBoundsException();
  5.1541 -
  5.1542 -        if ((len & 1) != 0)
  5.1543 -          {
  5.1544 -        /* We always want an even number of bytes in input, see peekBits */
  5.1545 -        buffer |= (buf[off++] & 0xff) << bits_in_buffer;
  5.1546 -        bits_in_buffer += 8;
  5.1547 -          }
  5.1548 -
  5.1549 -        window = buf;
  5.1550 -        window_start = off;
  5.1551 -        window_end = end;
  5.1552 -      }
  5.1553 -    }
  5.1554 -    /*
  5.1555 -     * Contains the output from the Inflation process.
  5.1556 -     *
  5.1557 -     * We need to have a window so that we can refer backwards into the output stream
  5.1558 -     * to repeat stuff.
  5.1559 -     *
  5.1560 -     * @author John Leuner
  5.1561 -     * @since JDK 1.1
  5.1562 -     */
  5.1563 -
  5.1564 -    private static class OutputWindow
  5.1565 -    {
  5.1566 -      private final int WINDOW_SIZE = 1 << 15;
  5.1567 -      private final int WINDOW_MASK = WINDOW_SIZE - 1;
  5.1568 -
  5.1569 -      private byte[] window = new byte[WINDOW_SIZE]; //The window is 2^15 bytes
  5.1570 -      private int window_end  = 0;
  5.1571 -      private int window_filled = 0;
  5.1572 -
  5.1573 -      public void write(int abyte)
  5.1574 -      {
  5.1575 -        if (window_filled++ == WINDOW_SIZE)
  5.1576 -          throw new IllegalStateException("Window full");
  5.1577 -        window[window_end++] = (byte) abyte;
  5.1578 -        window_end &= WINDOW_MASK;
  5.1579 -      }
  5.1580 -
  5.1581 -
  5.1582 -      private final void slowRepeat(int rep_start, int len, int dist)
  5.1583 -      {
  5.1584 -        while (len-- > 0)
  5.1585 -          {
  5.1586 -        window[window_end++] = window[rep_start++];
  5.1587 -        window_end &= WINDOW_MASK;
  5.1588 -        rep_start &= WINDOW_MASK;
  5.1589 -          }
  5.1590 -      }
  5.1591 -
  5.1592 -      public void repeat(int len, int dist)
  5.1593 -      {
  5.1594 -        if ((window_filled += len) > WINDOW_SIZE)
  5.1595 -          throw new IllegalStateException("Window full");
  5.1596 -
  5.1597 -        int rep_start = (window_end - dist) & WINDOW_MASK;
  5.1598 -        int border = WINDOW_SIZE - len;
  5.1599 -        if (rep_start <= border && window_end < border)
  5.1600 -          {
  5.1601 -        if (len <= dist)
  5.1602 -          {
  5.1603 -            System.arraycopy(window, rep_start, window, window_end, len);
  5.1604 -            window_end += len;
  5.1605 -          }
  5.1606 -        else
  5.1607 -          {
  5.1608 -            /* We have to copy manually, since the repeat pattern overlaps.
  5.1609 -             */
  5.1610 -            while (len-- > 0)
  5.1611 -              window[window_end++] = window[rep_start++];
  5.1612 -          }
  5.1613 -          }
  5.1614 -        else
  5.1615 -          slowRepeat(rep_start, len, dist);
  5.1616 -      }
  5.1617 -
  5.1618 -      public int copyStored(StreamManipulator input, int len)
  5.1619 -      {
  5.1620 -        len = Math.min(Math.min(len, WINDOW_SIZE - window_filled), 
  5.1621 -               input.getAvailableBytes());
  5.1622 -        int copied;
  5.1623 -
  5.1624 -        int tailLen = WINDOW_SIZE - window_end;
  5.1625 -        if (len > tailLen)
  5.1626 -          {
  5.1627 -        copied = input.copyBytes(window, window_end, tailLen);
  5.1628 -        if (copied == tailLen)
  5.1629 -          copied += input.copyBytes(window, 0, len - tailLen);
  5.1630 -          }
  5.1631 -        else
  5.1632 -          copied = input.copyBytes(window, window_end, len);
  5.1633 -
  5.1634 -        window_end = (window_end + copied) & WINDOW_MASK;
  5.1635 -        window_filled += copied;
  5.1636 -        return copied;
  5.1637 -      }
  5.1638 -
  5.1639 -      public void copyDict(byte[] dict, int offset, int len)
  5.1640 -      {
  5.1641 -        if (window_filled > 0)
  5.1642 -          throw new IllegalStateException();
  5.1643 -
  5.1644 -        if (len > WINDOW_SIZE)
  5.1645 -          {
  5.1646 -        offset += len - WINDOW_SIZE;
  5.1647 -        len = WINDOW_SIZE;
  5.1648 -          }
  5.1649 -        System.arraycopy(dict, offset, window, 0, len);
  5.1650 -        window_end = len & WINDOW_MASK;
  5.1651 -      }
  5.1652 -
  5.1653 -      public int getFreeSpace()
  5.1654 -      {
  5.1655 -        return WINDOW_SIZE - window_filled;
  5.1656 -      }
  5.1657 -
  5.1658 -      public int getAvailable()
  5.1659 -      {
  5.1660 -        return window_filled;
  5.1661 -      }
  5.1662 -
  5.1663 -      public int copyOutput(byte[] output, int offset, int len)
  5.1664 -      {
  5.1665 -        int copy_end = window_end;
  5.1666 -        if (len > window_filled)
  5.1667 -          len = window_filled;
  5.1668 -        else
  5.1669 -          copy_end = (window_end - window_filled + len) & WINDOW_MASK;
  5.1670 -
  5.1671 -        int copied = len;
  5.1672 -        int tailLen = len - copy_end;
  5.1673 -
  5.1674 -        if (tailLen > 0)
  5.1675 -          {
  5.1676 -        System.arraycopy(window, WINDOW_SIZE - tailLen,
  5.1677 -                 output, offset, tailLen);
  5.1678 -        offset += tailLen;
  5.1679 -        len = copy_end;
  5.1680 -          }
  5.1681 -        System.arraycopy(window, copy_end - len, output, offset, len);
  5.1682 -        window_filled -= copied;
  5.1683 -        if (window_filled < 0)
  5.1684 -          throw new IllegalStateException();
  5.1685 -        return copied;
  5.1686 -      }
  5.1687 -
  5.1688 -      public void reset() {
  5.1689 -        window_filled = window_end = 0;
  5.1690 -      }
  5.1691 -    }
  5.1692 -  
  5.1693  }
     6.1 --- a/emul/mini/src/main/java/java/util/zip/ZipConstants64.java	Wed Feb 06 18:24:53 2013 +0100
     6.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.3 @@ -1,84 +0,0 @@
     6.4 -/*
     6.5 - * Copyright (c) 1995, 1996, Oracle and/or its affiliates. All rights reserved.
     6.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     6.7 - *
     6.8 - * This code is free software; you can redistribute it and/or modify it
     6.9 - * under the terms of the GNU General Public License version 2 only, as
    6.10 - * published by the Free Software Foundation.  Oracle designates this
    6.11 - * particular file as subject to the "Classpath" exception as provided
    6.12 - * by Oracle in the LICENSE file that accompanied this code.
    6.13 - *
    6.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
    6.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    6.16 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    6.17 - * version 2 for more details (a copy is included in the LICENSE file that
    6.18 - * accompanied this code).
    6.19 - *
    6.20 - * You should have received a copy of the GNU General Public License version
    6.21 - * 2 along with this work; if not, write to the Free Software Foundation,
    6.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    6.23 - *
    6.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    6.25 - * or visit www.oracle.com if you need additional information or have any
    6.26 - * questions.
    6.27 - */
    6.28 -
    6.29 -package java.util.zip;
    6.30 -
    6.31 -/*
    6.32 - * This class defines the constants that are used by the classes
    6.33 - * which manipulate Zip64 files.
    6.34 - */
    6.35 -
    6.36 -class ZipConstants64 {
    6.37 -
    6.38 -    /*
    6.39 -     * ZIP64 constants
    6.40 -     */
    6.41 -    static final long ZIP64_ENDSIG = 0x06064b50L;  // "PK\006\006"
    6.42 -    static final long ZIP64_LOCSIG = 0x07064b50L;  // "PK\006\007"
    6.43 -    static final int  ZIP64_ENDHDR = 56;           // ZIP64 end header size
    6.44 -    static final int  ZIP64_LOCHDR = 20;           // ZIP64 end loc header size
    6.45 -    static final int  ZIP64_EXTHDR = 24;           // EXT header size
    6.46 -    static final int  ZIP64_EXTID  = 0x0001;       // Extra field Zip64 header ID
    6.47 -
    6.48 -    static final int  ZIP64_MAGICCOUNT = 0xFFFF;
    6.49 -    static final long ZIP64_MAGICVAL = 0xFFFFFFFFL;
    6.50 -
    6.51 -    /*
    6.52 -     * Zip64 End of central directory (END) header field offsets
    6.53 -     */
    6.54 -    static final int  ZIP64_ENDLEN = 4;       // size of zip64 end of central dir
    6.55 -    static final int  ZIP64_ENDVEM = 12;      // version made by
    6.56 -    static final int  ZIP64_ENDVER = 14;      // version needed to extract
    6.57 -    static final int  ZIP64_ENDNMD = 16;      // number of this disk
    6.58 -    static final int  ZIP64_ENDDSK = 20;      // disk number of start
    6.59 -    static final int  ZIP64_ENDTOD = 24;      // total number of entries on this disk
    6.60 -    static final int  ZIP64_ENDTOT = 32;      // total number of entries
    6.61 -    static final int  ZIP64_ENDSIZ = 40;      // central directory size in bytes
    6.62 -    static final int  ZIP64_ENDOFF = 48;      // offset of first CEN header
    6.63 -    static final int  ZIP64_ENDEXT = 56;      // zip64 extensible data sector
    6.64 -
    6.65 -    /*
    6.66 -     * Zip64 End of central directory locator field offsets
    6.67 -     */
    6.68 -    static final int  ZIP64_LOCDSK = 4;       // disk number start
    6.69 -    static final int  ZIP64_LOCOFF = 8;       // offset of zip64 end
    6.70 -    static final int  ZIP64_LOCTOT = 16;      // total number of disks
    6.71 -
    6.72 -    /*
    6.73 -     * Zip64 Extra local (EXT) header field offsets
    6.74 -     */
    6.75 -    static final int  ZIP64_EXTCRC = 4;       // uncompressed file crc-32 value
    6.76 -    static final int  ZIP64_EXTSIZ = 8;       // compressed size, 8-byte
    6.77 -    static final int  ZIP64_EXTLEN = 16;      // uncompressed size, 8-byte
    6.78 -
    6.79 -    /*
    6.80 -     * Language encoding flag EFS
    6.81 -     */
    6.82 -    static final int EFS = 0x800;       // If this bit is set the filename and
    6.83 -                                        // comment fields for this file must be
    6.84 -                                        // encoded using UTF-8.
    6.85 -
    6.86 -    private ZipConstants64() {}
    6.87 -}
     7.1 --- a/emul/mini/src/main/java/java/util/zip/ZipInputStream.java	Wed Feb 06 18:24:53 2013 +0100
     7.2 +++ b/emul/mini/src/main/java/java/util/zip/ZipInputStream.java	Thu Feb 07 12:58:12 2013 +0100
     7.3 @@ -27,10 +27,6 @@
     7.4  
     7.5  import java.io.InputStream;
     7.6  import java.io.IOException;
     7.7 -import java.io.EOFException;
     7.8 -import java.io.PushbackInputStream;
     7.9 -import static java.util.zip.ZipConstants64.*;
    7.10 -import org.apidesign.bck2brwsr.core.JavaScriptBody;
    7.11  
    7.12  /**
    7.13   * This class implements an input stream filter for reading files in the
    7.14 @@ -41,28 +37,7 @@
    7.15   */
    7.16  public
    7.17  class ZipInputStream extends InflaterInputStream implements ZipConstants {
    7.18 -    private ZipEntry entry;
    7.19 -    private int flag;
    7.20 -    private CRC32 crc = new CRC32();
    7.21 -    private long remaining;
    7.22 -    private byte[] tmpbuf = new byte[512];
    7.23 -
    7.24 -    private static final int STORED = ZipEntry.STORED;
    7.25 -    private static final int DEFLATED = ZipEntry.DEFLATED;
    7.26 -
    7.27 -    private boolean closed = false;
    7.28 -    // this flag is set to true after EOF has reached for
    7.29 -    // one entry
    7.30 -    private boolean entryEOF = false;
    7.31 -
    7.32 -    /**
    7.33 -     * Check to make sure that this stream has not been closed
    7.34 -     */
    7.35 -    private void ensureOpen() throws IOException {
    7.36 -        if (closed) {
    7.37 -            throw new IOException("Stream closed");
    7.38 -        }
    7.39 -    }
    7.40 +    private final org.apidesign.bck2brwsr.emul.zip.ZipInputStream impl;
    7.41  
    7.42      /**
    7.43       * Creates a new ZIP input stream.
    7.44 @@ -73,12 +48,8 @@
    7.45       * @param in the actual input stream
    7.46       */
    7.47      public ZipInputStream(InputStream in) {
    7.48 -//        this(in, "UTF-8");
    7.49 -        super(new PushbackInputStream(in, 512), new Inflater(true), 512);
    7.50 -        usesDefaultInflater = true;
    7.51 -        if(in == null) {
    7.52 -            throw new NullPointerException("in is null");
    7.53 -        }
    7.54 +        super(null);
    7.55 +        impl = new org.apidesign.bck2brwsr.emul.zip.ZipInputStream(in);
    7.56      }
    7.57  
    7.58      /**
    7.59 @@ -115,20 +86,7 @@
    7.60       * @exception IOException if an I/O error has occurred
    7.61       */
    7.62      public ZipEntry getNextEntry() throws IOException {
    7.63 -        ensureOpen();
    7.64 -        if (entry != null) {
    7.65 -            closeEntry();
    7.66 -        }
    7.67 -        crc.reset();
    7.68 -        inf.reset();
    7.69 -        if ((entry = readLOC()) == null) {
    7.70 -            return null;
    7.71 -        }
    7.72 -        if (entry.method == STORED) {
    7.73 -            remaining = entry.size;
    7.74 -        }
    7.75 -        entryEOF = false;
    7.76 -        return entry;
    7.77 +        return impl.getNextEntry();
    7.78      }
    7.79  
    7.80      /**
    7.81 @@ -138,9 +96,7 @@
    7.82       * @exception IOException if an I/O error has occurred
    7.83       */
    7.84      public void closeEntry() throws IOException {
    7.85 -        ensureOpen();
    7.86 -        while (read(tmpbuf, 0, tmpbuf.length) != -1) ;
    7.87 -        entryEOF = true;
    7.88 +        impl.closeEntry();
    7.89      }
    7.90  
    7.91      /**
    7.92 @@ -155,12 +111,7 @@
    7.93       *
    7.94       */
    7.95      public int available() throws IOException {
    7.96 -        ensureOpen();
    7.97 -        if (entryEOF) {
    7.98 -            return 0;
    7.99 -        } else {
   7.100 -            return 1;
   7.101 -        }
   7.102 +        return impl.available();
   7.103      }
   7.104  
   7.105      /**
   7.106 @@ -181,51 +132,7 @@
   7.107       * @exception IOException if an I/O error has occurred
   7.108       */
   7.109      public int read(byte[] b, int off, int len) throws IOException {
   7.110 -        ensureOpen();
   7.111 -        if (off < 0 || len < 0 || off > b.length - len) {
   7.112 -            throw new IndexOutOfBoundsException();
   7.113 -        } else if (len == 0) {
   7.114 -            return 0;
   7.115 -        }
   7.116 -
   7.117 -        if (entry == null) {
   7.118 -            return -1;
   7.119 -        }
   7.120 -        switch (entry.method) {
   7.121 -        case DEFLATED:
   7.122 -            len = super.read(b, off, len);
   7.123 -            if (len == -1) {
   7.124 -                readEnd(entry);
   7.125 -                entryEOF = true;
   7.126 -                entry = null;
   7.127 -            } else {
   7.128 -                crc.update(b, off, len);
   7.129 -            }
   7.130 -            return len;
   7.131 -        case STORED:
   7.132 -            if (remaining <= 0) {
   7.133 -                entryEOF = true;
   7.134 -                entry = null;
   7.135 -                return -1;
   7.136 -            }
   7.137 -            if (len > remaining) {
   7.138 -                len = (int)remaining;
   7.139 -            }
   7.140 -            len = in.read(b, off, len);
   7.141 -            if (len == -1) {
   7.142 -                throw new ZipException("unexpected EOF");
   7.143 -            }
   7.144 -            crc.update(b, off, len);
   7.145 -            remaining -= len;
   7.146 -            if (remaining == 0 && entry.crc != crc.getValue()) {
   7.147 -                throw new ZipException(
   7.148 -                    "invalid entry CRC (expected 0x" + Long.toHexString(entry.crc) +
   7.149 -                    " but got 0x" + Long.toHexString(crc.getValue()) + ")");
   7.150 -            }
   7.151 -            return len;
   7.152 -        default:
   7.153 -            throw new ZipException("invalid compression method");
   7.154 -        }
   7.155 +        return impl.read(b, off, len);
   7.156      }
   7.157  
   7.158      /**
   7.159 @@ -237,25 +144,7 @@
   7.160       * @exception IllegalArgumentException if n < 0
   7.161       */
   7.162      public long skip(long n) throws IOException {
   7.163 -        if (n < 0) {
   7.164 -            throw new IllegalArgumentException("negative skip length");
   7.165 -        }
   7.166 -        ensureOpen();
   7.167 -        int max = (int)Math.min(n, Integer.MAX_VALUE);
   7.168 -        int total = 0;
   7.169 -        while (total < max) {
   7.170 -            int len = max - total;
   7.171 -            if (len > tmpbuf.length) {
   7.172 -                len = tmpbuf.length;
   7.173 -            }
   7.174 -            len = read(tmpbuf, 0, len);
   7.175 -            if (len == -1) {
   7.176 -                entryEOF = true;
   7.177 -                break;
   7.178 -            }
   7.179 -            total += len;
   7.180 -        }
   7.181 -        return total;
   7.182 +        return impl.skip(n);
   7.183      }
   7.184  
   7.185      /**
   7.186 @@ -264,89 +153,7 @@
   7.187       * @exception IOException if an I/O error has occurred
   7.188       */
   7.189      public void close() throws IOException {
   7.190 -        if (!closed) {
   7.191 -            super.close();
   7.192 -            closed = true;
   7.193 -        }
   7.194 -    }
   7.195 -
   7.196 -    private byte[] b = new byte[256];
   7.197 -
   7.198 -    /*
   7.199 -     * Reads local file (LOC) header for next entry.
   7.200 -     */
   7.201 -    private ZipEntry readLOC() throws IOException {
   7.202 -        try {
   7.203 -            readFully(tmpbuf, 0, LOCHDR);
   7.204 -        } catch (EOFException e) {
   7.205 -            return null;
   7.206 -        }
   7.207 -        if (get32(tmpbuf, 0) != LOCSIG) {
   7.208 -            return null;
   7.209 -        }
   7.210 -        // get flag first, we need check EFS.
   7.211 -        flag = get16(tmpbuf, LOCFLG);
   7.212 -        // get the entry name and create the ZipEntry first
   7.213 -        int len = get16(tmpbuf, LOCNAM);
   7.214 -        int blen = b.length;
   7.215 -        if (len > blen) {
   7.216 -            do
   7.217 -                blen = blen * 2;
   7.218 -            while (len > blen);
   7.219 -            b = new byte[blen];
   7.220 -        }
   7.221 -        readFully(b, 0, len);
   7.222 -        // Force to use UTF-8 if the EFS bit is ON, even the cs is NOT UTF-8
   7.223 -        ZipEntry e = createZipEntry(((flag & EFS) != 0)
   7.224 -                                    ? toStringUTF8(b, len)
   7.225 -                                    : toString(b, len));
   7.226 -        // now get the remaining fields for the entry
   7.227 -        if ((flag & 1) == 1) {
   7.228 -            throw new ZipException("encrypted ZIP entry not supported");
   7.229 -        }
   7.230 -        e.method = get16(tmpbuf, LOCHOW);
   7.231 -        e.time = get32(tmpbuf, LOCTIM);
   7.232 -        if ((flag & 8) == 8) {
   7.233 -            /* "Data Descriptor" present */
   7.234 -            if (e.method != DEFLATED) {
   7.235 -                throw new ZipException(
   7.236 -                        "only DEFLATED entries can have EXT descriptor");
   7.237 -            }
   7.238 -        } else {
   7.239 -            e.crc = get32(tmpbuf, LOCCRC);
   7.240 -            e.csize = get32(tmpbuf, LOCSIZ);
   7.241 -            e.size = get32(tmpbuf, LOCLEN);
   7.242 -        }
   7.243 -        len = get16(tmpbuf, LOCEXT);
   7.244 -        if (len > 0) {
   7.245 -            byte[] bb = new byte[len];
   7.246 -            readFully(bb, 0, len);
   7.247 -            e.setExtra(bb);
   7.248 -            // extra fields are in "HeaderID(2)DataSize(2)Data... format
   7.249 -            if (e.csize == ZIP64_MAGICVAL || e.size == ZIP64_MAGICVAL) {
   7.250 -                int off = 0;
   7.251 -                while (off + 4 < len) {
   7.252 -                    int sz = get16(bb, off + 2);
   7.253 -                    if (get16(bb, off) == ZIP64_EXTID) {
   7.254 -                        off += 4;
   7.255 -                        // LOC extra zip64 entry MUST include BOTH original and
   7.256 -                        // compressed file size fields
   7.257 -                        if (sz < 16 || (off + sz) > len ) {
   7.258 -                            // Invalid zip64 extra fields, simply skip. Even it's
   7.259 -                            // rare, it's possible the entry size happens to be
   7.260 -                            // the magic value and it "accidnetly" has some bytes
   7.261 -                            // in extra match the id.
   7.262 -                            return e;
   7.263 -                        }
   7.264 -                        e.size = get64(bb, off);
   7.265 -                        e.csize = get64(bb, off + 8);
   7.266 -                        break;
   7.267 -                    }
   7.268 -                    off += (sz + 4);
   7.269 -                }
   7.270 -            }
   7.271 -        }
   7.272 -        return e;
   7.273 +        impl.close();
   7.274      }
   7.275  
   7.276      /**
   7.277 @@ -360,108 +167,28 @@
   7.278          return new ZipEntry(name);
   7.279      }
   7.280  
   7.281 -    /*
   7.282 -     * Reads end of deflated entry as well as EXT descriptor if present.
   7.283 -     */
   7.284 -    private void readEnd(ZipEntry e) throws IOException {
   7.285 -        int n = inf.getRemaining();
   7.286 -        if (n > 0) {
   7.287 -            ((PushbackInputStream)in).unread(buf, len - n, n);
   7.288 -        }
   7.289 -        if ((flag & 8) == 8) {
   7.290 -            /* "Data Descriptor" present */
   7.291 -            if (inf.getBytesWritten() > ZIP64_MAGICVAL ||
   7.292 -                inf.getBytesRead() > ZIP64_MAGICVAL) {
   7.293 -                // ZIP64 format
   7.294 -                readFully(tmpbuf, 0, ZIP64_EXTHDR);
   7.295 -                long sig = get32(tmpbuf, 0);
   7.296 -                if (sig != EXTSIG) { // no EXTSIG present
   7.297 -                    e.crc = sig;
   7.298 -                    e.csize = get64(tmpbuf, ZIP64_EXTSIZ - ZIP64_EXTCRC);
   7.299 -                    e.size = get64(tmpbuf, ZIP64_EXTLEN - ZIP64_EXTCRC);
   7.300 -                    ((PushbackInputStream)in).unread(
   7.301 -                        tmpbuf, ZIP64_EXTHDR - ZIP64_EXTCRC - 1, ZIP64_EXTCRC);
   7.302 -                } else {
   7.303 -                    e.crc = get32(tmpbuf, ZIP64_EXTCRC);
   7.304 -                    e.csize = get64(tmpbuf, ZIP64_EXTSIZ);
   7.305 -                    e.size = get64(tmpbuf, ZIP64_EXTLEN);
   7.306 -                }
   7.307 -            } else {
   7.308 -                readFully(tmpbuf, 0, EXTHDR);
   7.309 -                long sig = get32(tmpbuf, 0);
   7.310 -                if (sig != EXTSIG) { // no EXTSIG present
   7.311 -                    e.crc = sig;
   7.312 -                    e.csize = get32(tmpbuf, EXTSIZ - EXTCRC);
   7.313 -                    e.size = get32(tmpbuf, EXTLEN - EXTCRC);
   7.314 -                    ((PushbackInputStream)in).unread(
   7.315 -                                               tmpbuf, EXTHDR - EXTCRC - 1, EXTCRC);
   7.316 -                } else {
   7.317 -                    e.crc = get32(tmpbuf, EXTCRC);
   7.318 -                    e.csize = get32(tmpbuf, EXTSIZ);
   7.319 -                    e.size = get32(tmpbuf, EXTLEN);
   7.320 -                }
   7.321 -            }
   7.322 -        }
   7.323 -        if (e.size != inf.getBytesWritten()) {
   7.324 -            throw new ZipException(
   7.325 -                "invalid entry size (expected " + e.size +
   7.326 -                " but got " + inf.getBytesWritten() + " bytes)");
   7.327 -        }
   7.328 -        if (e.csize != inf.getBytesRead()) {
   7.329 -            throw new ZipException(
   7.330 -                "invalid entry compressed size (expected " + e.csize +
   7.331 -                " but got " + inf.getBytesRead() + " bytes)");
   7.332 -        }
   7.333 -        if (e.crc != crc.getValue()) {
   7.334 -            throw new ZipException(
   7.335 -                "invalid entry CRC (expected 0x" + Long.toHexString(e.crc) +
   7.336 -                " but got 0x" + Long.toHexString(crc.getValue()) + ")");
   7.337 -        }
   7.338 +    @Override
   7.339 +    public int read() throws IOException {
   7.340 +        return impl.read();
   7.341      }
   7.342  
   7.343 -    /*
   7.344 -     * Reads bytes, blocking until all bytes are read.
   7.345 -     */
   7.346 -    private void readFully(byte[] b, int off, int len) throws IOException {
   7.347 -        while (len > 0) {
   7.348 -            int n = in.read(b, off, len);
   7.349 -            if (n == -1) {
   7.350 -                throw new EOFException();
   7.351 -            }
   7.352 -            off += n;
   7.353 -            len -= n;
   7.354 -        }
   7.355 +    @Override
   7.356 +    public boolean markSupported() {
   7.357 +        return impl.markSupported();
   7.358      }
   7.359  
   7.360 -    /*
   7.361 -     * Fetches unsigned 16-bit value from byte array at specified offset.
   7.362 -     * The bytes are assumed to be in Intel (little-endian) byte order.
   7.363 -     */
   7.364 -    private static final int get16(byte b[], int off) {
   7.365 -        return (b[off] & 0xff) | ((b[off+1] & 0xff) << 8);
   7.366 +    @Override
   7.367 +    public void mark(int readlimit) {
   7.368 +        impl.mark(readlimit);
   7.369      }
   7.370  
   7.371 -    /*
   7.372 -     * Fetches unsigned 32-bit value from byte array at specified offset.
   7.373 -     * The bytes are assumed to be in Intel (little-endian) byte order.
   7.374 -     */
   7.375 -    private static final long get32(byte b[], int off) {
   7.376 -        return (get16(b, off) | ((long)get16(b, off+2) << 16)) & 0xffffffffL;
   7.377 +    @Override
   7.378 +    public void reset() throws IOException {
   7.379 +        impl.reset();
   7.380      }
   7.381  
   7.382 -    /*
   7.383 -     * Fetches signed 64-bit value from byte array at specified offset.
   7.384 -     * The bytes are assumed to be in Intel (little-endian) byte order.
   7.385 -     */
   7.386 -    private static final long get64(byte b[], int off) {
   7.387 -        return get32(b, off) | (get32(b, off+4) << 32);
   7.388 -    }
   7.389 -
   7.390 -    private static String toStringUTF8(byte[] arr, int len) {
   7.391 -        return new String(arr, 0, len);
   7.392 -    }
   7.393 -    
   7.394 -    private static String toString(byte[] b, int len) {
   7.395 -        return new String(b, 0, len);
   7.396 +    @Override
   7.397 +    public int read(byte[] b) throws IOException {
   7.398 +        return impl.read(b);
   7.399      }
   7.400  }
     8.1 --- a/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/lang/System.java	Wed Feb 06 18:24:53 2013 +0100
     8.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/lang/System.java	Thu Feb 07 12:58:12 2013 +0100
     8.3 @@ -17,6 +17,7 @@
     8.4   */
     8.5  package org.apidesign.bck2brwsr.emul.lang;
     8.6  
     8.7 +import java.lang.reflect.Method;
     8.8  import org.apidesign.bck2brwsr.core.JavaScriptBody;
     8.9  
    8.10  /**
    8.11 @@ -38,7 +39,15 @@
    8.12          "    }\n" +
    8.13          "}"
    8.14      )
    8.15 -    public static native void arraycopy(Object value, int srcBegin, Object dst, int dstBegin, int count);
    8.16 +    public static void arraycopy(Object src, int srcBegin, Object dst, int dstBegin, int count) {
    8.17 +        try {
    8.18 +            Class<?> system = Class.forName("java.lang.System");
    8.19 +            Method m = system.getMethod("arraycopy", Object.class, int.class, Object.class, int.class, int.class);
    8.20 +            m.invoke(null, src, srcBegin, dst, dstBegin, count);
    8.21 +        } catch (Exception ex) {
    8.22 +            throw new IllegalStateException(ex);
    8.23 +        }
    8.24 +    }
    8.25  
    8.26      @JavaScriptBody(args = { "arr", "expectedSize" }, body = 
    8.27          "while (expectedSize-- > arr.length) { arr.push(0); }; return arr;"
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/Adler32.java	Thu Feb 07 12:58:12 2013 +0100
     9.3 @@ -0,0 +1,139 @@
     9.4 +/* -*-mode:java; c-basic-offset:2; -*- */
     9.5 +/*
     9.6 +Copyright (c) 2000-2011 ymnk, JCraft,Inc. All rights reserved.
     9.7 +
     9.8 +Redistribution and use in source and binary forms, with or without
     9.9 +modification, are permitted provided that the following conditions are met:
    9.10 +
    9.11 +  1. Redistributions of source code must retain the above copyright notice,
    9.12 +     this list of conditions and the following disclaimer.
    9.13 +
    9.14 +  2. Redistributions in binary form must reproduce the above copyright 
    9.15 +     notice, this list of conditions and the following disclaimer in 
    9.16 +     the documentation and/or other materials provided with the distribution.
    9.17 +
    9.18 +  3. The names of the authors may not be used to endorse or promote products
    9.19 +     derived from this software without specific prior written permission.
    9.20 +
    9.21 +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
    9.22 +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
    9.23 +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
    9.24 +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
    9.25 +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    9.26 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
    9.27 +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
    9.28 +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
    9.29 +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
    9.30 +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    9.31 + */
    9.32 +/*
    9.33 + * This program is based on zlib-1.1.3, so all credit should go authors
    9.34 + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
    9.35 + * and contributors of zlib.
    9.36 + */
    9.37 +
    9.38 +package org.apidesign.bck2brwsr.emul.zip;
    9.39 +
    9.40 +final class Adler32 implements Checksum {
    9.41 +
    9.42 +  // largest prime smaller than 65536
    9.43 +  static final private int BASE=65521; 
    9.44 +  // NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1
    9.45 +  static final private int NMAX=5552;
    9.46 +
    9.47 +  private long s1=1L;
    9.48 +  private long s2=0L;
    9.49 +
    9.50 +  public void reset(long init){
    9.51 +    s1=init&0xffff;
    9.52 +    s2=(init>>16)&0xffff;
    9.53 +  }
    9.54 +
    9.55 +  public void reset(){
    9.56 +    s1=1L;
    9.57 +    s2=0L;
    9.58 +  }
    9.59 +
    9.60 +  public long getValue(){
    9.61 +    return ((s2<<16)|s1);
    9.62 +  }
    9.63 +
    9.64 +  public void update(byte[] buf, int index, int len){
    9.65 +
    9.66 +    if(len==1){
    9.67 +      s1+=buf[index++]&0xff; s2+=s1;
    9.68 +      s1%=BASE;
    9.69 +      s2%=BASE;
    9.70 +      return;
    9.71 +    }
    9.72 +
    9.73 +    int len1 = len/NMAX;
    9.74 +    int len2 = len%NMAX;
    9.75 +    while(len1-->0) {
    9.76 +      int k=NMAX;
    9.77 +      len-=k;
    9.78 +      while(k-->0){
    9.79 +	s1+=buf[index++]&0xff; s2+=s1;
    9.80 +      }
    9.81 +      s1%=BASE;
    9.82 +      s2%=BASE;
    9.83 +    }
    9.84 +
    9.85 +    int k=len2;
    9.86 +    len-=k;
    9.87 +    while(k-->0){
    9.88 +      s1+=buf[index++]&0xff; s2+=s1;
    9.89 +    }
    9.90 +    s1%=BASE;
    9.91 +    s2%=BASE;
    9.92 +  }
    9.93 +
    9.94 +  public Adler32 copy(){
    9.95 +    Adler32 foo = new Adler32();
    9.96 +    foo.s1 = this.s1;
    9.97 +    foo.s2 = this.s2;
    9.98 +    return foo;
    9.99 +  }
   9.100 +
   9.101 +  // The following logic has come from zlib.1.2.
   9.102 +  static long combine(long adler1, long adler2, long len2){
   9.103 +    long BASEL = (long)BASE;
   9.104 +    long sum1;
   9.105 +    long sum2;
   9.106 +    long rem;  // unsigned int
   9.107 +
   9.108 +    rem = len2 % BASEL;
   9.109 +    sum1 = adler1 & 0xffffL;
   9.110 +    sum2 = rem * sum1;
   9.111 +    sum2 %= BASEL; // MOD(sum2);
   9.112 +    sum1 += (adler2 & 0xffffL) + BASEL - 1;
   9.113 +    sum2 += ((adler1 >> 16) & 0xffffL) + ((adler2 >> 16) & 0xffffL) + BASEL - rem;
   9.114 +    if (sum1 >= BASEL) sum1 -= BASEL;
   9.115 +    if (sum1 >= BASEL) sum1 -= BASEL;
   9.116 +    if (sum2 >= (BASEL << 1)) sum2 -= (BASEL << 1);
   9.117 +    if (sum2 >= BASEL) sum2 -= BASEL;
   9.118 +    return sum1 | (sum2 << 16);
   9.119 +  }
   9.120 +
   9.121 +/*
   9.122 +  private java.util.zip.Adler32 adler=new java.util.zip.Adler32();
   9.123 +  public void update(byte[] buf, int index, int len){
   9.124 +    if(buf==null) {adler.reset();}
   9.125 +    else{adler.update(buf, index, len);}
   9.126 +  }
   9.127 +  public void reset(){
   9.128 +    adler.reset();
   9.129 +  }
   9.130 +  public void reset(long init){
   9.131 +    if(init==1L){
   9.132 +      adler.reset();
   9.133 +    }
   9.134 +    else{
   9.135 +      System.err.println("unsupported operation");
   9.136 +    }
   9.137 +  }
   9.138 +  public long getValue(){
   9.139 +    return adler.getValue();
   9.140 +  }
   9.141 +*/
   9.142 +}
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/CRC32.java	Thu Feb 07 12:58:12 2013 +0100
    10.3 @@ -0,0 +1,181 @@
    10.4 +/* -*-mode:java; c-basic-offset:2; -*- */
    10.5 +/*
    10.6 +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved.
    10.7 +
    10.8 +Redistribution and use in source and binary forms, with or without
    10.9 +modification, are permitted provided that the following conditions are met:
   10.10 +
   10.11 +  1. Redistributions of source code must retain the above copyright notice,
   10.12 +     this list of conditions and the following disclaimer.
   10.13 +
   10.14 +  2. Redistributions in binary form must reproduce the above copyright 
   10.15 +     notice, this list of conditions and the following disclaimer in 
   10.16 +     the documentation and/or other materials provided with the distribution.
   10.17 +
   10.18 +  3. The names of the authors may not be used to endorse or promote products
   10.19 +     derived from this software without specific prior written permission.
   10.20 +
   10.21 +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   10.22 +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   10.23 +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
   10.24 +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
   10.25 +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   10.26 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
   10.27 +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   10.28 +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   10.29 +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
   10.30 +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   10.31 + */
   10.32 +/*
   10.33 + * This program is based on zlib-1.1.3, so all credit should go authors
   10.34 + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
   10.35 + * and contributors of zlib.
   10.36 + */
   10.37 +
   10.38 +package org.apidesign.bck2brwsr.emul.zip;
   10.39 +
   10.40 +import org.apidesign.bck2brwsr.emul.lang.System;
   10.41 +
   10.42 +final class CRC32 implements Checksum {
   10.43 +
   10.44 +  /*
   10.45 +   *  The following logic has come from RFC1952.
   10.46 +   */
   10.47 +  private int v = 0;
   10.48 +  private static int[] crc_table = null;
   10.49 +  static {
   10.50 +    crc_table = new int[256];
   10.51 +    for (int n = 0; n < 256; n++) {
   10.52 +      int c = n;
   10.53 +      for (int k = 8;  --k >= 0; ) {
   10.54 +        if ((c & 1) != 0)
   10.55 +	  c = 0xedb88320 ^ (c >>> 1);
   10.56 +        else
   10.57 +          c = c >>> 1;
   10.58 +      }
   10.59 +      crc_table[n] = c;
   10.60 +    }
   10.61 +  }
   10.62 +
   10.63 +  public void update (byte[] buf, int index, int len) {
   10.64 +    int c = ~v;
   10.65 +    while (--len >= 0)
   10.66 +      c = crc_table[(c^buf[index++])&0xff]^(c >>> 8);
   10.67 +    v = ~c;
   10.68 +  }
   10.69 +
   10.70 +  public void reset(){
   10.71 +    v = 0;
   10.72 +  }
   10.73 +
   10.74 +  public void reset(long vv){
   10.75 +    v = (int)(vv&0xffffffffL);
   10.76 +  }
   10.77 +
   10.78 +  public long getValue(){
   10.79 +    return (long)(v&0xffffffffL);
   10.80 +  }
   10.81 +
   10.82 +  // The following logic has come from zlib.1.2.
   10.83 +  private static final int GF2_DIM = 32;
   10.84 +  static long combine(long crc1, long crc2, long len2){
   10.85 +    long row;
   10.86 +    long[] even = new long[GF2_DIM];
   10.87 +    long[] odd = new long[GF2_DIM];
   10.88 +
   10.89 +    // degenerate case (also disallow negative lengths)
   10.90 +    if (len2 <= 0)
   10.91 +      return crc1;
   10.92 +
   10.93 +    // put operator for one zero bit in odd
   10.94 +    odd[0] = 0xedb88320L;          // CRC-32 polynomial
   10.95 +    row = 1;
   10.96 +    for (int n = 1; n < GF2_DIM; n++) {
   10.97 +        odd[n] = row;
   10.98 +        row <<= 1;
   10.99 +    }
  10.100 +
  10.101 +    // put operator for two zero bits in even
  10.102 +    gf2_matrix_square(even, odd);
  10.103 +
  10.104 +    // put operator for four zero bits in odd
  10.105 +    gf2_matrix_square(odd, even);
  10.106 +
  10.107 +    // apply len2 zeros to crc1 (first square will put the operator for one
  10.108 +    // zero byte, eight zero bits, in even)
  10.109 +    do {
  10.110 +      // apply zeros operator for this bit of len2
  10.111 +      gf2_matrix_square(even, odd);
  10.112 +      if ((len2 & 1)!=0)
  10.113 +        crc1 = gf2_matrix_times(even, crc1);
  10.114 +      len2 >>= 1;
  10.115 +
  10.116 +      // if no more bits set, then done
  10.117 +      if (len2 == 0)
  10.118 +        break;
  10.119 +
  10.120 +      // another iteration of the loop with odd and even swapped
  10.121 +      gf2_matrix_square(odd, even);
  10.122 +      if ((len2 & 1)!=0)
  10.123 +        crc1 = gf2_matrix_times(odd, crc1);
  10.124 +      len2 >>= 1;
  10.125 +
  10.126 +      // if no more bits set, then done
  10.127 +    } while (len2 != 0);
  10.128 +
  10.129 +    /* return combined crc */
  10.130 +    crc1 ^= crc2;
  10.131 +    return crc1;
  10.132 +  }
  10.133 +
  10.134 +  private static long gf2_matrix_times(long[] mat, long vec){
  10.135 +    long sum = 0;
  10.136 +    int index = 0;
  10.137 +    while (vec!=0) {
  10.138 +      if ((vec & 1)!=0)
  10.139 +        sum ^= mat[index];
  10.140 +      vec >>= 1;
  10.141 +      index++;
  10.142 +    }
  10.143 +    return sum;
  10.144 +  }
  10.145 +
  10.146 +  static final void gf2_matrix_square(long[] square, long[] mat) {
  10.147 +    for (int n = 0; n < GF2_DIM; n++)
  10.148 +      square[n] = gf2_matrix_times(mat, mat[n]);
  10.149 +  }
  10.150 +
  10.151 +  /*
  10.152 +  private java.util.zip.CRC32 crc32 = new java.util.zip.CRC32();
  10.153 +
  10.154 +  public void update(byte[] buf, int index, int len){
  10.155 +    if(buf==null) {crc32.reset();}
  10.156 +    else{crc32.update(buf, index, len);}
  10.157 +  }
  10.158 +  public void reset(){
  10.159 +    crc32.reset();
  10.160 +  }
  10.161 +  public void reset(long init){
  10.162 +    if(init==0L){
  10.163 +      crc32.reset();
  10.164 +    }
  10.165 +    else{
  10.166 +      System.err.println("unsupported operation");
  10.167 +    }
  10.168 +  }
  10.169 +  public long getValue(){
  10.170 +    return crc32.getValue();
  10.171 +  }
  10.172 +*/
  10.173 +  public CRC32 copy(){
  10.174 +    CRC32 foo = new CRC32();
  10.175 +    foo.v = this.v;
  10.176 +    return foo;
  10.177 +  }
  10.178 +
  10.179 +  public static int[] getCRC32Table(){
  10.180 +    int[] tmp = new int[crc_table.length];
  10.181 +    System.arraycopy(crc_table, 0, tmp, 0, tmp.length);
  10.182 +    return tmp;
  10.183 +  }
  10.184 +}
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/Checksum.java	Thu Feb 07 12:58:12 2013 +0100
    11.3 @@ -0,0 +1,43 @@
    11.4 +/* -*-mode:java; c-basic-offset:2; -*- */
    11.5 +/*
    11.6 +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved.
    11.7 +
    11.8 +Redistribution and use in source and binary forms, with or without
    11.9 +modification, are permitted provided that the following conditions are met:
   11.10 +
   11.11 +  1. Redistributions of source code must retain the above copyright notice,
   11.12 +     this list of conditions and the following disclaimer.
   11.13 +
   11.14 +  2. Redistributions in binary form must reproduce the above copyright 
   11.15 +     notice, this list of conditions and the following disclaimer in 
   11.16 +     the documentation and/or other materials provided with the distribution.
   11.17 +
   11.18 +  3. The names of the authors may not be used to endorse or promote products
   11.19 +     derived from this software without specific prior written permission.
   11.20 +
   11.21 +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   11.22 +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   11.23 +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
   11.24 +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
   11.25 +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   11.26 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
   11.27 +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   11.28 +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   11.29 +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
   11.30 +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   11.31 + */
   11.32 +/*
   11.33 + * This program is based on zlib-1.1.3, so all credit should go authors
   11.34 + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
   11.35 + * and contributors of zlib.
   11.36 + */
   11.37 +
   11.38 +package org.apidesign.bck2brwsr.emul.zip;
   11.39 +
   11.40 +interface Checksum {
   11.41 +  void update(byte[] buf, int index, int len);
   11.42 +  void reset();
   11.43 +  void reset(long init);
   11.44 +  long getValue();
   11.45 +  Checksum copy();
   11.46 +}
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/GZIPHeader.java	Thu Feb 07 12:58:12 2013 +0100
    12.3 @@ -0,0 +1,215 @@
    12.4 +/* -*-mode:java; c-basic-offset:2; -*- */
    12.5 +/*
    12.6 +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved.
    12.7 +
    12.8 +Redistribution and use in source and binary forms, with or without
    12.9 +modification, are permitted provided that the following conditions are met:
   12.10 +
   12.11 +  1. Redistributions of source code must retain the above copyright notice,
   12.12 +     this list of conditions and the following disclaimer.
   12.13 +
   12.14 +  2. Redistributions in binary form must reproduce the above copyright 
   12.15 +     notice, this list of conditions and the following disclaimer in 
   12.16 +     the documentation and/or other materials provided with the distribution.
   12.17 +
   12.18 +  3. The names of the authors may not be used to endorse or promote products
   12.19 +     derived from this software without specific prior written permission.
   12.20 +
   12.21 +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   12.22 +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   12.23 +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
   12.24 +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
   12.25 +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   12.26 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
   12.27 +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   12.28 +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   12.29 +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
   12.30 +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   12.31 + */
   12.32 +/*
   12.33 + * This program is based on zlib-1.1.3, so all credit should go authors
   12.34 + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
   12.35 + * and contributors of zlib.
   12.36 + */
   12.37 +
   12.38 +package org.apidesign.bck2brwsr.emul.zip;
   12.39 +
   12.40 +import org.apidesign.bck2brwsr.emul.lang.System;
   12.41 +import java.io.UnsupportedEncodingException;
   12.42 +
   12.43 +/**
   12.44 + * @see "http://www.ietf.org/rfc/rfc1952.txt"
   12.45 + */
   12.46 +final class GZIPHeader implements Cloneable {
   12.47 +
   12.48 +  public static final byte OS_MSDOS = (byte) 0x00;
   12.49 +  public static final byte OS_AMIGA = (byte) 0x01;
   12.50 +  public static final byte OS_VMS = (byte) 0x02;
   12.51 +  public static final byte OS_UNIX = (byte) 0x03;
   12.52 +  public static final byte OS_ATARI = (byte) 0x05;
   12.53 +  public static final byte OS_OS2 = (byte) 0x06;
   12.54 +  public static final byte OS_MACOS = (byte) 0x07;
   12.55 +  public static final byte OS_TOPS20 = (byte) 0x0a;
   12.56 +  public static final byte OS_WIN32 = (byte) 0x0b;
   12.57 +  public static final byte OS_VMCMS = (byte) 0x04;
   12.58 +  public static final byte OS_ZSYSTEM = (byte) 0x08;
   12.59 +  public static final byte OS_CPM = (byte) 0x09;
   12.60 +  public static final byte OS_QDOS = (byte) 0x0c;
   12.61 +  public static final byte OS_RISCOS = (byte) 0x0d;
   12.62 +  public static final byte OS_UNKNOWN = (byte) 0xff;
   12.63 +
   12.64 +  boolean text = false;
   12.65 +  private boolean fhcrc = false;
   12.66 +  long time;
   12.67 +  int xflags;
   12.68 +  int os = 255;
   12.69 +  byte[] extra;
   12.70 +  byte[] name;
   12.71 +  byte[] comment;
   12.72 +  int hcrc;
   12.73 +  long crc;
   12.74 +  boolean done = false;
   12.75 +  long mtime = 0;
   12.76 +
   12.77 +  public void setModifiedTime(long mtime) {
   12.78 +    this.mtime = mtime;
   12.79 +  }
   12.80 +
   12.81 +  public long getModifiedTime() {
   12.82 +    return mtime;
   12.83 +  }
   12.84 +
   12.85 +  public void setOS(int os) {
   12.86 +    if((0<=os && os <=13) || os==255)
   12.87 +      this.os=os;
   12.88 +    else
   12.89 +      throw new IllegalArgumentException("os: "+os);
   12.90 +  }
   12.91 +
   12.92 +  public int getOS(){
   12.93 +    return os;
   12.94 +  }
   12.95 +
   12.96 +  public void setName(String name) {
   12.97 +    try{
   12.98 +      this.name=name.getBytes("ISO-8859-1");
   12.99 +    }
  12.100 +    catch(UnsupportedEncodingException e){
  12.101 +      throw new IllegalArgumentException("name must be in ISO-8859-1 "+name);
  12.102 +    }
  12.103 +  }
  12.104 +
  12.105 +  public String getName(){
  12.106 +    if(name==null) return "";
  12.107 +    try {
  12.108 +      return new String(name, "ISO-8859-1");
  12.109 +    }
  12.110 +    catch (UnsupportedEncodingException e) {
  12.111 +      throw new IllegalArgumentException(e.toString());
  12.112 +    }
  12.113 +  }
  12.114 +
  12.115 +  public void setComment(String comment) {
  12.116 +    try{
  12.117 +      this.comment=comment.getBytes("ISO-8859-1");
  12.118 +    }
  12.119 +    catch(UnsupportedEncodingException e){
  12.120 +      throw new IllegalArgumentException("comment must be in ISO-8859-1 "+name);
  12.121 +    }
  12.122 +  }
  12.123 +
  12.124 +  public String getComment(){
  12.125 +    if(comment==null) return "";
  12.126 +    try {
  12.127 +      return new String(comment, "ISO-8859-1");
  12.128 +    }
  12.129 +    catch (UnsupportedEncodingException e) {
  12.130 +      throw new IllegalArgumentException(e.toString());
  12.131 +    }
  12.132 +  }
  12.133 +
  12.134 +  public void setCRC(long crc){
  12.135 +    this.crc = crc;
  12.136 +  }
  12.137 +
  12.138 +  public long getCRC(){
  12.139 +    return crc;
  12.140 +  }
  12.141 +/*
  12.142 +  void put(Deflate d){
  12.143 +    int flag = 0;
  12.144 +    if(text){
  12.145 +      flag |= 1;     // FTEXT
  12.146 +    }
  12.147 +    if(fhcrc){
  12.148 +      flag |= 2;     // FHCRC
  12.149 +    }
  12.150 +    if(extra!=null){
  12.151 +      flag |= 4;     // FEXTRA
  12.152 +    }
  12.153 +    if(name!=null){
  12.154 +      flag |= 8;    // FNAME
  12.155 +    }
  12.156 +    if(comment!=null){
  12.157 +      flag |= 16;   // FCOMMENT
  12.158 +    }
  12.159 +    int xfl = 0;
  12.160 +    if(d.level == JZlib.Z_BEST_SPEED){
  12.161 +      xfl |= 4;
  12.162 +    }
  12.163 +    else if (d.level == JZlib.Z_BEST_COMPRESSION){
  12.164 +      xfl |= 2;
  12.165 +    }
  12.166 +
  12.167 +    d.put_short((short)0x8b1f);  // ID1 ID2
  12.168 +    d.put_byte((byte)8);         // CM(Compression Method)
  12.169 +    d.put_byte((byte)flag);
  12.170 +    d.put_byte((byte)mtime);
  12.171 +    d.put_byte((byte)(mtime>>8));
  12.172 +    d.put_byte((byte)(mtime>>16));
  12.173 +    d.put_byte((byte)(mtime>>24));
  12.174 +    d.put_byte((byte)xfl);
  12.175 +    d.put_byte((byte)os);
  12.176 +
  12.177 +    if(extra!=null){
  12.178 +      d.put_byte((byte)extra.length);
  12.179 +      d.put_byte((byte)(extra.length>>8));
  12.180 +      d.put_byte(extra, 0, extra.length);
  12.181 +    }
  12.182 +
  12.183 +    if(name!=null){
  12.184 +      d.put_byte(name, 0, name.length);
  12.185 +      d.put_byte((byte)0);
  12.186 +    }
  12.187 +
  12.188 +    if(comment!=null){
  12.189 +      d.put_byte(comment, 0, comment.length);
  12.190 +      d.put_byte((byte)0);
  12.191 +    }
  12.192 +  }
  12.193 +*/
  12.194 +  @Override
  12.195 +  public Object clone() throws CloneNotSupportedException {
  12.196 +    GZIPHeader gheader = (GZIPHeader)super.clone();
  12.197 +    byte[] tmp;
  12.198 +    if(gheader.extra!=null){
  12.199 +      tmp=new byte[gheader.extra.length];
  12.200 +      System.arraycopy(gheader.extra, 0, tmp, 0, tmp.length);
  12.201 +      gheader.extra = tmp;
  12.202 +    }
  12.203 +
  12.204 +    if(gheader.name!=null){
  12.205 +      tmp=new byte[gheader.name.length];
  12.206 +      System.arraycopy(gheader.name, 0, tmp, 0, tmp.length);
  12.207 +      gheader.name = tmp;
  12.208 +    }
  12.209 +
  12.210 +    if(gheader.comment!=null){
  12.211 +      tmp=new byte[gheader.comment.length];
  12.212 +      System.arraycopy(gheader.comment, 0, tmp, 0, tmp.length);
  12.213 +      gheader.comment = tmp;
  12.214 +    }
  12.215 +
  12.216 +    return gheader;
  12.217 +  }
  12.218 +}
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/InfBlocks.java	Thu Feb 07 12:58:12 2013 +0100
    13.3 @@ -0,0 +1,616 @@
    13.4 +/* -*-mode:java; c-basic-offset:2; -*- */
    13.5 +/*
    13.6 +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved.
    13.7 +
    13.8 +Redistribution and use in source and binary forms, with or without
    13.9 +modification, are permitted provided that the following conditions are met:
   13.10 +
   13.11 +  1. Redistributions of source code must retain the above copyright notice,
   13.12 +     this list of conditions and the following disclaimer.
   13.13 +
   13.14 +  2. Redistributions in binary form must reproduce the above copyright 
   13.15 +     notice, this list of conditions and the following disclaimer in 
   13.16 +     the documentation and/or other materials provided with the distribution.
   13.17 +
   13.18 +  3. The names of the authors may not be used to endorse or promote products
   13.19 +     derived from this software without specific prior written permission.
   13.20 +
   13.21 +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   13.22 +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   13.23 +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
   13.24 +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
   13.25 +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   13.26 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
   13.27 +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   13.28 +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   13.29 +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
   13.30 +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   13.31 + */
   13.32 +/*
   13.33 + * This program is based on zlib-1.1.3, so all credit should go authors
   13.34 + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
   13.35 + * and contributors of zlib.
   13.36 + */
   13.37 +
   13.38 +package org.apidesign.bck2brwsr.emul.zip;
   13.39 +
   13.40 +import org.apidesign.bck2brwsr.emul.lang.System;
   13.41 +
   13.42 +final class InfBlocks{
   13.43 +  static final private int MANY=1440;
   13.44 +
   13.45 +  // And'ing with mask[n] masks the lower n bits
   13.46 +  static final private int[] inflate_mask = {
   13.47 +    0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
   13.48 +    0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff,
   13.49 +    0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff,
   13.50 +    0x00007fff, 0x0000ffff
   13.51 +  };
   13.52 +
   13.53 +  // Table for deflate from PKZIP's appnote.txt.
   13.54 +  static final int[] border = { // Order of the bit length code lengths
   13.55 +    16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
   13.56 +  };
   13.57 +
   13.58 +  static final private int Z_OK=0;
   13.59 +  static final private int Z_STREAM_END=1;
   13.60 +  static final private int Z_NEED_DICT=2;
   13.61 +  static final private int Z_ERRNO=-1;
   13.62 +  static final private int Z_STREAM_ERROR=-2;
   13.63 +  static final private int Z_DATA_ERROR=-3;
   13.64 +  static final private int Z_MEM_ERROR=-4;
   13.65 +  static final private int Z_BUF_ERROR=-5;
   13.66 +  static final private int Z_VERSION_ERROR=-6;
   13.67 +
   13.68 +  static final private int TYPE=0;  // get type bits (3, including end bit)
   13.69 +  static final private int LENS=1;  // get lengths for stored
   13.70 +  static final private int STORED=2;// processing stored block
   13.71 +  static final private int TABLE=3; // get table lengths
   13.72 +  static final private int BTREE=4; // get bit lengths tree for a dynamic block
   13.73 +  static final private int DTREE=5; // get length, distance trees for a dynamic block
   13.74 +  static final private int CODES=6; // processing fixed or dynamic block
   13.75 +  static final private int DRY=7;   // output remaining window bytes
   13.76 +  static final private int DONE=8;  // finished last block, done
   13.77 +  static final private int BAD=9;   // ot a data error--stuck here
   13.78 +
   13.79 +  int mode;            // current inflate_block mode 
   13.80 +
   13.81 +  int left;            // if STORED, bytes left to copy 
   13.82 +
   13.83 +  int table;           // table lengths (14 bits) 
   13.84 +  int index;           // index into blens (or border) 
   13.85 +  int[] blens;         // bit lengths of codes 
   13.86 +  int[] bb=new int[1]; // bit length tree depth 
   13.87 +  int[] tb=new int[1]; // bit length decoding tree 
   13.88 +
   13.89 +  int[] bl=new int[1];
   13.90 +  int[] bd=new int[1];
   13.91 +
   13.92 +  int[][] tl=new int[1][];
   13.93 +  int[][] td=new int[1][];
   13.94 +  int[] tli=new int[1]; // tl_index
   13.95 +  int[] tdi=new int[1]; // td_index
   13.96 +
   13.97 +  private final InfCodes codes;      // if CODES, current state 
   13.98 +
   13.99 +  int last;            // true if this block is the last block 
  13.100 +
  13.101 +  // mode independent information 
  13.102 +  int bitk;            // bits in bit buffer 
  13.103 +  int bitb;            // bit buffer 
  13.104 +  int[] hufts;         // single malloc for tree space 
  13.105 +  byte[] window;       // sliding window 
  13.106 +  int end;             // one byte after sliding window 
  13.107 +  int read;            // window read pointer 
  13.108 +  int write;           // window write pointer 
  13.109 +  private boolean check;
  13.110 +
  13.111 +  private final InfTree inftree=new InfTree();
  13.112 +
  13.113 +  private final ZStream z; 
  13.114 +
  13.115 +  InfBlocks(ZStream z, int w){
  13.116 +    this.z=z;
  13.117 +    this.codes=new InfCodes(this.z, this);
  13.118 +    hufts=new int[MANY*3];
  13.119 +    window=new byte[w];
  13.120 +    end=w;
  13.121 +    this.check = (z.istate.wrap==0) ? false : true;
  13.122 +    mode = TYPE;
  13.123 +    reset();
  13.124 +  }
  13.125 +
  13.126 +  void reset(){
  13.127 +    if(mode==BTREE || mode==DTREE){
  13.128 +    }
  13.129 +    if(mode==CODES){
  13.130 +      codes.free(z);
  13.131 +    }
  13.132 +    mode=TYPE;
  13.133 +    bitk=0;
  13.134 +    bitb=0;
  13.135 +    read=write=0;
  13.136 +    if(check){
  13.137 +      z.adler.reset();
  13.138 +    }
  13.139 +  }
  13.140 +
  13.141 +  int proc(int r){
  13.142 +    int t;              // temporary storage
  13.143 +    int b;              // bit buffer
  13.144 +    int k;              // bits in bit buffer
  13.145 +    int p;              // input data pointer
  13.146 +    int n;              // bytes available there
  13.147 +    int q;              // output window write pointer
  13.148 +    int m;              // bytes to end of window or read pointer
  13.149 +
  13.150 +    // copy input/output information to locals (UPDATE macro restores)
  13.151 +    {p=z.next_in_index;n=z.avail_in;b=bitb;k=bitk;}
  13.152 +    {q=write;m=(int)(q<read?read-q-1:end-q);}
  13.153 +
  13.154 +    // process input based on current state
  13.155 +    while(true){
  13.156 +      switch (mode){
  13.157 +      case TYPE:
  13.158 +
  13.159 +	while(k<(3)){
  13.160 +	  if(n!=0){
  13.161 +	    r=Z_OK;
  13.162 +	  }
  13.163 +	  else{
  13.164 +	    bitb=b; bitk=k; 
  13.165 +	    z.avail_in=n;
  13.166 +	    z.total_in+=p-z.next_in_index;z.next_in_index=p;
  13.167 +	    write=q;
  13.168 +	    return inflate_flush(r);
  13.169 +	  };
  13.170 +	  n--;
  13.171 +	  b|=(z.next_in[p++]&0xff)<<k;
  13.172 +	  k+=8;
  13.173 +	}
  13.174 +	t = (int)(b & 7);
  13.175 +	last = t & 1;
  13.176 +
  13.177 +	switch (t >>> 1){
  13.178 +        case 0:                         // stored 
  13.179 +          {b>>>=(3);k-=(3);}
  13.180 +          t = k & 7;                    // go to byte boundary
  13.181 +
  13.182 +          {b>>>=(t);k-=(t);}
  13.183 +          mode = LENS;                  // get length of stored block
  13.184 +          break;
  13.185 +        case 1:                         // fixed
  13.186 +          InfTree.inflate_trees_fixed(bl, bd, tl, td, z);
  13.187 +          codes.init(bl[0], bd[0], tl[0], 0, td[0], 0);
  13.188 +
  13.189 +          {b>>>=(3);k-=(3);}
  13.190 +
  13.191 +          mode = CODES;
  13.192 +          break;
  13.193 +        case 2:                         // dynamic
  13.194 +
  13.195 +          {b>>>=(3);k-=(3);}
  13.196 +
  13.197 +          mode = TABLE;
  13.198 +          break;
  13.199 +        case 3:                         // illegal
  13.200 +
  13.201 +          {b>>>=(3);k-=(3);}
  13.202 +          mode = BAD;
  13.203 +          z.msg = "invalid block type";
  13.204 +          r = Z_DATA_ERROR;
  13.205 +
  13.206 +	  bitb=b; bitk=k; 
  13.207 +	  z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  13.208 +	  write=q;
  13.209 +	  return inflate_flush(r);
  13.210 +	}
  13.211 +	break;
  13.212 +      case LENS:
  13.213 +
  13.214 +	while(k<(32)){
  13.215 +	  if(n!=0){
  13.216 +	    r=Z_OK;
  13.217 +	  }
  13.218 +	  else{
  13.219 +	    bitb=b; bitk=k; 
  13.220 +	    z.avail_in=n;
  13.221 +	    z.total_in+=p-z.next_in_index;z.next_in_index=p;
  13.222 +	    write=q;
  13.223 +	    return inflate_flush(r);
  13.224 +	  };
  13.225 +	  n--;
  13.226 +	  b|=(z.next_in[p++]&0xff)<<k;
  13.227 +	  k+=8;
  13.228 +	}
  13.229 +
  13.230 +	if ((((~b) >>> 16) & 0xffff) != (b & 0xffff)){
  13.231 +	  mode = BAD;
  13.232 +	  z.msg = "invalid stored block lengths";
  13.233 +	  r = Z_DATA_ERROR;
  13.234 +
  13.235 +	  bitb=b; bitk=k; 
  13.236 +	  z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  13.237 +	  write=q;
  13.238 +	  return inflate_flush(r);
  13.239 +	}
  13.240 +	left = (b & 0xffff);
  13.241 +	b = k = 0;                       // dump bits
  13.242 +	mode = left!=0 ? STORED : (last!=0 ? DRY : TYPE);
  13.243 +	break;
  13.244 +      case STORED:
  13.245 +	if (n == 0){
  13.246 +	  bitb=b; bitk=k; 
  13.247 +	  z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  13.248 +	  write=q;
  13.249 +	  return inflate_flush(r);
  13.250 +	}
  13.251 +
  13.252 +	if(m==0){
  13.253 +	  if(q==end&&read!=0){
  13.254 +	    q=0; m=(int)(q<read?read-q-1:end-q);
  13.255 +	  }
  13.256 +	  if(m==0){
  13.257 +	    write=q; 
  13.258 +	    r=inflate_flush(r);
  13.259 +	    q=write;m=(int)(q<read?read-q-1:end-q);
  13.260 +	    if(q==end&&read!=0){
  13.261 +	      q=0; m=(int)(q<read?read-q-1:end-q);
  13.262 +	    }
  13.263 +	    if(m==0){
  13.264 +	      bitb=b; bitk=k; 
  13.265 +	      z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  13.266 +	      write=q;
  13.267 +	      return inflate_flush(r);
  13.268 +	    }
  13.269 +	  }
  13.270 +	}
  13.271 +	r=Z_OK;
  13.272 +
  13.273 +	t = left;
  13.274 +	if(t>n) t = n;
  13.275 +	if(t>m) t = m;
  13.276 +	System.arraycopy(z.next_in, p, window, q, t);
  13.277 +	p += t;  n -= t;
  13.278 +	q += t;  m -= t;
  13.279 +	if ((left -= t) != 0)
  13.280 +	  break;
  13.281 +	mode = last!=0 ? DRY : TYPE;
  13.282 +	break;
  13.283 +      case TABLE:
  13.284 +
  13.285 +	while(k<(14)){
  13.286 +	  if(n!=0){
  13.287 +	    r=Z_OK;
  13.288 +	  }
  13.289 +	  else{
  13.290 +	    bitb=b; bitk=k; 
  13.291 +	    z.avail_in=n;
  13.292 +	    z.total_in+=p-z.next_in_index;z.next_in_index=p;
  13.293 +	    write=q;
  13.294 +	    return inflate_flush(r);
  13.295 +	  };
  13.296 +	  n--;
  13.297 +	  b|=(z.next_in[p++]&0xff)<<k;
  13.298 +	  k+=8;
  13.299 +	}
  13.300 +
  13.301 +	table = t = (b & 0x3fff);
  13.302 +	if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
  13.303 +	  {
  13.304 +	    mode = BAD;
  13.305 +	    z.msg = "too many length or distance symbols";
  13.306 +	    r = Z_DATA_ERROR;
  13.307 +
  13.308 +	    bitb=b; bitk=k; 
  13.309 +	    z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  13.310 +	    write=q;
  13.311 +	    return inflate_flush(r);
  13.312 +	  }
  13.313 +	t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
  13.314 +	if(blens==null || blens.length<t){
  13.315 +	  blens=new int[t];
  13.316 +	}
  13.317 +	else{
  13.318 +	  for(int i=0; i<t; i++){blens[i]=0;}
  13.319 +	}
  13.320 +
  13.321 +	{b>>>=(14);k-=(14);}
  13.322 +
  13.323 +	index = 0;
  13.324 +	mode = BTREE;
  13.325 +      case BTREE:
  13.326 +	while (index < 4 + (table >>> 10)){
  13.327 +	  while(k<(3)){
  13.328 +	    if(n!=0){
  13.329 +	      r=Z_OK;
  13.330 +	    }
  13.331 +	    else{
  13.332 +	      bitb=b; bitk=k; 
  13.333 +	      z.avail_in=n;
  13.334 +	      z.total_in+=p-z.next_in_index;z.next_in_index=p;
  13.335 +	      write=q;
  13.336 +	      return inflate_flush(r);
  13.337 +	    };
  13.338 +	    n--;
  13.339 +	    b|=(z.next_in[p++]&0xff)<<k;
  13.340 +	    k+=8;
  13.341 +	  }
  13.342 +
  13.343 +	  blens[border[index++]] = b&7;
  13.344 +
  13.345 +	  {b>>>=(3);k-=(3);}
  13.346 +	}
  13.347 +
  13.348 +	while(index < 19){
  13.349 +	  blens[border[index++]] = 0;
  13.350 +	}
  13.351 +
  13.352 +	bb[0] = 7;
  13.353 +	t = inftree.inflate_trees_bits(blens, bb, tb, hufts, z);
  13.354 +	if (t != Z_OK){
  13.355 +	  r = t;
  13.356 +	  if (r == Z_DATA_ERROR){
  13.357 +	    blens=null;
  13.358 +	    mode = BAD;
  13.359 +	  }
  13.360 +
  13.361 +	  bitb=b; bitk=k; 
  13.362 +	  z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  13.363 +	  write=q;
  13.364 +	  return inflate_flush(r);
  13.365 +	}
  13.366 +
  13.367 +	index = 0;
  13.368 +	mode = DTREE;
  13.369 +      case DTREE:
  13.370 +	while (true){
  13.371 +	  t = table;
  13.372 +	  if(!(index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))){
  13.373 +	    break;
  13.374 +	  }
  13.375 +
  13.376 +	  int[] h;
  13.377 +	  int i, j, c;
  13.378 +
  13.379 +	  t = bb[0];
  13.380 +
  13.381 +	  while(k<(t)){
  13.382 +	    if(n!=0){
  13.383 +	      r=Z_OK;
  13.384 +	    }
  13.385 +	    else{
  13.386 +	      bitb=b; bitk=k; 
  13.387 +	      z.avail_in=n;
  13.388 +	      z.total_in+=p-z.next_in_index;z.next_in_index=p;
  13.389 +	      write=q;
  13.390 +	      return inflate_flush(r);
  13.391 +	    };
  13.392 +	    n--;
  13.393 +	    b|=(z.next_in[p++]&0xff)<<k;
  13.394 +	    k+=8;
  13.395 +	  }
  13.396 +
  13.397 +	  if(tb[0]==-1){
  13.398 +            //System.err.println("null...");
  13.399 +	  }
  13.400 +
  13.401 +	  t=hufts[(tb[0]+(b&inflate_mask[t]))*3+1];
  13.402 +	  c=hufts[(tb[0]+(b&inflate_mask[t]))*3+2];
  13.403 +
  13.404 +	  if (c < 16){
  13.405 +	    b>>>=(t);k-=(t);
  13.406 +	    blens[index++] = c;
  13.407 +	  }
  13.408 +	  else { // c == 16..18
  13.409 +	    i = c == 18 ? 7 : c - 14;
  13.410 +	    j = c == 18 ? 11 : 3;
  13.411 +
  13.412 +	    while(k<(t+i)){
  13.413 +	      if(n!=0){
  13.414 +		r=Z_OK;
  13.415 +	      }
  13.416 +	      else{
  13.417 +		bitb=b; bitk=k; 
  13.418 +		z.avail_in=n;
  13.419 +		z.total_in+=p-z.next_in_index;z.next_in_index=p;
  13.420 +		write=q;
  13.421 +		return inflate_flush(r);
  13.422 +	      };
  13.423 +	      n--;
  13.424 +	      b|=(z.next_in[p++]&0xff)<<k;
  13.425 +	      k+=8;
  13.426 +	    }
  13.427 +
  13.428 +	    b>>>=(t);k-=(t);
  13.429 +
  13.430 +	    j += (b & inflate_mask[i]);
  13.431 +
  13.432 +	    b>>>=(i);k-=(i);
  13.433 +
  13.434 +	    i = index;
  13.435 +	    t = table;
  13.436 +	    if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
  13.437 +		(c == 16 && i < 1)){
  13.438 +	      blens=null;
  13.439 +	      mode = BAD;
  13.440 +	      z.msg = "invalid bit length repeat";
  13.441 +	      r = Z_DATA_ERROR;
  13.442 +
  13.443 +	      bitb=b; bitk=k; 
  13.444 +	      z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  13.445 +	      write=q;
  13.446 +	      return inflate_flush(r);
  13.447 +	    }
  13.448 +
  13.449 +	    c = c == 16 ? blens[i-1] : 0;
  13.450 +	    do{
  13.451 +	      blens[i++] = c;
  13.452 +	    }
  13.453 +	    while (--j!=0);
  13.454 +	    index = i;
  13.455 +	  }
  13.456 +	}
  13.457 +
  13.458 +	tb[0]=-1;
  13.459 +	{
  13.460 +	  bl[0] = 9;         // must be <= 9 for lookahead assumptions
  13.461 +	  bd[0] = 6;         // must be <= 9 for lookahead assumptions
  13.462 +	  t = table;
  13.463 +	  t = inftree.inflate_trees_dynamic(257 + (t & 0x1f), 
  13.464 +					    1 + ((t >> 5) & 0x1f),
  13.465 +					    blens, bl, bd, tli, tdi, hufts, z);
  13.466 +
  13.467 +	  if (t != Z_OK){
  13.468 +	    if (t == Z_DATA_ERROR){
  13.469 +	      blens=null;
  13.470 +	      mode = BAD;
  13.471 +	    }
  13.472 +	    r = t;
  13.473 +
  13.474 +	    bitb=b; bitk=k; 
  13.475 +	    z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  13.476 +	    write=q;
  13.477 +	    return inflate_flush(r);
  13.478 +	  }
  13.479 +	  codes.init(bl[0], bd[0], hufts, tli[0], hufts, tdi[0]);
  13.480 +	}
  13.481 +	mode = CODES;
  13.482 +      case CODES:
  13.483 +	bitb=b; bitk=k;
  13.484 +	z.avail_in=n; z.total_in+=p-z.next_in_index;z.next_in_index=p;
  13.485 +	write=q;
  13.486 +
  13.487 +	if ((r = codes.proc(r)) != Z_STREAM_END){
  13.488 +	  return inflate_flush(r);
  13.489 +	}
  13.490 +	r = Z_OK;
  13.491 +	codes.free(z);
  13.492 +
  13.493 +	p=z.next_in_index; n=z.avail_in;b=bitb;k=bitk;
  13.494 +	q=write;m=(int)(q<read?read-q-1:end-q);
  13.495 +
  13.496 +	if (last==0){
  13.497 +	  mode = TYPE;
  13.498 +	  break;
  13.499 +	}
  13.500 +	mode = DRY;
  13.501 +      case DRY:
  13.502 +	write=q; 
  13.503 +	r=inflate_flush(r); 
  13.504 +	q=write; m=(int)(q<read?read-q-1:end-q);
  13.505 +	if (read != write){
  13.506 +	  bitb=b; bitk=k; 
  13.507 +	  z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  13.508 +	  write=q;
  13.509 +	  return inflate_flush(r);
  13.510 +	}
  13.511 +	mode = DONE;
  13.512 +      case DONE:
  13.513 +	r = Z_STREAM_END;
  13.514 +
  13.515 +	bitb=b; bitk=k; 
  13.516 +	z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  13.517 +	write=q;
  13.518 +	return inflate_flush(r);
  13.519 +      case BAD:
  13.520 +	r = Z_DATA_ERROR;
  13.521 +
  13.522 +	bitb=b; bitk=k; 
  13.523 +	z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  13.524 +	write=q;
  13.525 +	return inflate_flush(r);
  13.526 +
  13.527 +      default:
  13.528 +	r = Z_STREAM_ERROR;
  13.529 +
  13.530 +	bitb=b; bitk=k; 
  13.531 +	z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  13.532 +	write=q;
  13.533 +	return inflate_flush(r);
  13.534 +      }
  13.535 +    }
  13.536 +  }
  13.537 +
  13.538 +  void free(){
  13.539 +    reset();
  13.540 +    window=null;
  13.541 +    hufts=null;
  13.542 +    //ZFREE(z, s);
  13.543 +  }
  13.544 +
  13.545 +  void set_dictionary(byte[] d, int start, int n){
  13.546 +    System.arraycopy(d, start, window, 0, n);
  13.547 +    read = write = n;
  13.548 +  }
  13.549 +
  13.550 +  // Returns true if inflate is currently at the end of a block generated
  13.551 +  // by Z_SYNC_FLUSH or Z_FULL_FLUSH. 
  13.552 +  int sync_point(){
  13.553 +    return mode == LENS ? 1 : 0;
  13.554 +  }
  13.555 +
  13.556 +  // copy as much as possible from the sliding window to the output area
  13.557 +  int inflate_flush(int r){
  13.558 +    int n;
  13.559 +    int p;
  13.560 +    int q;
  13.561 +
  13.562 +    // local copies of source and destination pointers
  13.563 +    p = z.next_out_index;
  13.564 +    q = read;
  13.565 +
  13.566 +    // compute number of bytes to copy as far as end of window
  13.567 +    n = (int)((q <= write ? write : end) - q);
  13.568 +    if(n > z.avail_out) n = z.avail_out;
  13.569 +    if(n!=0 && r == Z_BUF_ERROR) r = Z_OK;
  13.570 +
  13.571 +    // update counters
  13.572 +    z.avail_out -= n;
  13.573 +    z.total_out += n;
  13.574 +
  13.575 +    // update check information
  13.576 +    if(check && n>0){
  13.577 +      z.adler.update(window, q, n);
  13.578 +    }
  13.579 +
  13.580 +    // copy as far as end of window
  13.581 +    System.arraycopy(window, q, z.next_out, p, n);
  13.582 +    p += n;
  13.583 +    q += n;
  13.584 +
  13.585 +    // see if more to copy at beginning of window
  13.586 +    if (q == end){
  13.587 +      // wrap pointers
  13.588 +      q = 0;
  13.589 +      if (write == end)
  13.590 +        write = 0;
  13.591 +
  13.592 +      // compute bytes to copy
  13.593 +      n = write - q;
  13.594 +      if (n > z.avail_out) n = z.avail_out;
  13.595 +      if (n!=0 && r == Z_BUF_ERROR) r = Z_OK;
  13.596 +
  13.597 +      // update counters
  13.598 +      z.avail_out -= n;
  13.599 +      z.total_out += n;
  13.600 +
  13.601 +      // update check information
  13.602 +      if(check && n>0){
  13.603 +	z.adler.update(window, q, n);
  13.604 +      }
  13.605 +
  13.606 +      // copy
  13.607 +      System.arraycopy(window, q, z.next_out, p, n);
  13.608 +      p += n;
  13.609 +      q += n;
  13.610 +    }
  13.611 +
  13.612 +    // update pointers
  13.613 +    z.next_out_index = p;
  13.614 +    read = q;
  13.615 +
  13.616 +    // done
  13.617 +    return r;
  13.618 +  }
  13.619 +}
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/InfCodes.java	Thu Feb 07 12:58:12 2013 +0100
    14.3 @@ -0,0 +1,612 @@
    14.4 +/* -*-mode:java; c-basic-offset:2; -*- */
    14.5 +/*
    14.6 +Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
    14.7 +
    14.8 +Redistribution and use in source and binary forms, with or without
    14.9 +modification, are permitted provided that the following conditions are met:
   14.10 +
   14.11 +  1. Redistributions of source code must retain the above copyright notice,
   14.12 +     this list of conditions and the following disclaimer.
   14.13 +
   14.14 +  2. Redistributions in binary form must reproduce the above copyright 
   14.15 +     notice, this list of conditions and the following disclaimer in 
   14.16 +     the documentation and/or other materials provided with the distribution.
   14.17 +
   14.18 +  3. The names of the authors may not be used to endorse or promote products
   14.19 +     derived from this software without specific prior written permission.
   14.20 +
   14.21 +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   14.22 +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   14.23 +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
   14.24 +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
   14.25 +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   14.26 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
   14.27 +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   14.28 +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   14.29 +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
   14.30 +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   14.31 + */
   14.32 +/*
   14.33 + * This program is based on zlib-1.1.3, so all credit should go authors
   14.34 + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
   14.35 + * and contributors of zlib.
   14.36 + */
   14.37 +
   14.38 +package org.apidesign.bck2brwsr.emul.zip;
   14.39 +
   14.40 +import org.apidesign.bck2brwsr.emul.lang.System;
   14.41 +
   14.42 +final class InfCodes{
   14.43 +
   14.44 +  static final private int[] inflate_mask = {
   14.45 +    0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
   14.46 +    0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff,
   14.47 +    0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff,
   14.48 +    0x00007fff, 0x0000ffff
   14.49 +  };
   14.50 +
   14.51 +  static final private int Z_OK=0;
   14.52 +  static final private int Z_STREAM_END=1;
   14.53 +  static final private int Z_NEED_DICT=2;
   14.54 +  static final private int Z_ERRNO=-1;
   14.55 +  static final private int Z_STREAM_ERROR=-2;
   14.56 +  static final private int Z_DATA_ERROR=-3;
   14.57 +  static final private int Z_MEM_ERROR=-4;
   14.58 +  static final private int Z_BUF_ERROR=-5;
   14.59 +  static final private int Z_VERSION_ERROR=-6;
   14.60 +
   14.61 +  // waiting for "i:"=input,
   14.62 +  //             "o:"=output,
   14.63 +  //             "x:"=nothing
   14.64 +  static final private int START=0;  // x: set up for LEN
   14.65 +  static final private int LEN=1;    // i: get length/literal/eob next
   14.66 +  static final private int LENEXT=2; // i: getting length extra (have base)
   14.67 +  static final private int DIST=3;   // i: get distance next
   14.68 +  static final private int DISTEXT=4;// i: getting distance extra
   14.69 +  static final private int COPY=5;   // o: copying bytes in window, waiting for space
   14.70 +  static final private int LIT=6;    // o: got literal, waiting for output space
   14.71 +  static final private int WASH=7;   // o: got eob, possibly still output waiting
   14.72 +  static final private int END=8;    // x: got eob and all data flushed
   14.73 +  static final private int BADCODE=9;// x: got error
   14.74 +
   14.75 +  int mode;      // current inflate_codes mode
   14.76 +
   14.77 +  // mode dependent information
   14.78 +  int len;
   14.79 +
   14.80 +  int[] tree; // pointer into tree
   14.81 +  int tree_index=0;
   14.82 +  int need;   // bits needed
   14.83 +
   14.84 +  int lit;
   14.85 +
   14.86 +  // if EXT or COPY, where and how much
   14.87 +  int get;              // bits to get for extra
   14.88 +  int dist;             // distance back to copy from
   14.89 +
   14.90 +  byte lbits;           // ltree bits decoded per branch
   14.91 +  byte dbits;           // dtree bits decoder per branch
   14.92 +  int[] ltree;          // literal/length/eob tree
   14.93 +  int ltree_index;      // literal/length/eob tree
   14.94 +  int[] dtree;          // distance tree
   14.95 +  int dtree_index;      // distance tree
   14.96 +
   14.97 +  private final ZStream z;
   14.98 +  private final InfBlocks s;
   14.99 +  InfCodes(ZStream z, InfBlocks s){
  14.100 +    this.z=z; 
  14.101 +    this.s=s; 
  14.102 +  }
  14.103 +
  14.104 +  void init(int bl, int bd,
  14.105 +	   int[] tl, int tl_index,
  14.106 +	   int[] td, int td_index){
  14.107 +    mode=START;
  14.108 +    lbits=(byte)bl;
  14.109 +    dbits=(byte)bd;
  14.110 +    ltree=tl;
  14.111 +    ltree_index=tl_index;
  14.112 +    dtree = td;
  14.113 +    dtree_index=td_index;
  14.114 +    tree=null;
  14.115 +  }
  14.116 +
  14.117 +  int proc(int r){ 
  14.118 +    int j;              // temporary storage
  14.119 +    int[] t;            // temporary pointer
  14.120 +    int tindex;         // temporary pointer
  14.121 +    int e;              // extra bits or operation
  14.122 +    int b=0;            // bit buffer
  14.123 +    int k=0;            // bits in bit buffer
  14.124 +    int p=0;            // input data pointer
  14.125 +    int n;              // bytes available there
  14.126 +    int q;              // output window write pointer
  14.127 +    int m;              // bytes to end of window or read pointer
  14.128 +    int f;              // pointer to copy strings from
  14.129 +
  14.130 +    // copy input/output information to locals (UPDATE macro restores)
  14.131 +    p=z.next_in_index;n=z.avail_in;b=s.bitb;k=s.bitk;
  14.132 +    q=s.write;m=q<s.read?s.read-q-1:s.end-q;
  14.133 +
  14.134 +    // process input and output based on current state
  14.135 +    while (true){
  14.136 +      switch (mode){
  14.137 +	// waiting for "i:"=input, "o:"=output, "x:"=nothing
  14.138 +      case START:         // x: set up for LEN
  14.139 +	if (m >= 258 && n >= 10){
  14.140 +
  14.141 +	  s.bitb=b;s.bitk=k;
  14.142 +	  z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  14.143 +	  s.write=q;
  14.144 +	  r = inflate_fast(lbits, dbits, 
  14.145 +			   ltree, ltree_index, 
  14.146 +			   dtree, dtree_index,
  14.147 +			   s, z);
  14.148 +
  14.149 +	  p=z.next_in_index;n=z.avail_in;b=s.bitb;k=s.bitk;
  14.150 +	  q=s.write;m=q<s.read?s.read-q-1:s.end-q;
  14.151 +
  14.152 +	  if (r != Z_OK){
  14.153 +	    mode = r == Z_STREAM_END ? WASH : BADCODE;
  14.154 +	    break;
  14.155 +	  }
  14.156 +	}
  14.157 +	need = lbits;
  14.158 +	tree = ltree;
  14.159 +	tree_index=ltree_index;
  14.160 +
  14.161 +	mode = LEN;
  14.162 +      case LEN:           // i: get length/literal/eob next
  14.163 +	j = need;
  14.164 +
  14.165 +	while(k<(j)){
  14.166 +	  if(n!=0)r=Z_OK;
  14.167 +	  else{
  14.168 +
  14.169 +	    s.bitb=b;s.bitk=k;
  14.170 +	    z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  14.171 +	    s.write=q;
  14.172 +	    return s.inflate_flush(r);
  14.173 +	  }
  14.174 +	  n--;
  14.175 +	  b|=(z.next_in[p++]&0xff)<<k;
  14.176 +	  k+=8;
  14.177 +	}
  14.178 +
  14.179 +	tindex=(tree_index+(b&inflate_mask[j]))*3;
  14.180 +
  14.181 +	b>>>=(tree[tindex+1]);
  14.182 +	k-=(tree[tindex+1]);
  14.183 +
  14.184 +	e=tree[tindex];
  14.185 +
  14.186 +	if(e == 0){               // literal
  14.187 +	  lit = tree[tindex+2];
  14.188 +	  mode = LIT;
  14.189 +	  break;
  14.190 +	}
  14.191 +	if((e & 16)!=0 ){          // length
  14.192 +	  get = e & 15;
  14.193 +	  len = tree[tindex+2];
  14.194 +	  mode = LENEXT;
  14.195 +	  break;
  14.196 +	}
  14.197 +	if ((e & 64) == 0){        // next table
  14.198 +	  need = e;
  14.199 +	  tree_index = tindex/3+tree[tindex+2];
  14.200 +	  break;
  14.201 +	}
  14.202 +	if ((e & 32)!=0){               // end of block
  14.203 +	  mode = WASH;
  14.204 +	  break;
  14.205 +	}
  14.206 +	mode = BADCODE;        // invalid code
  14.207 +	z.msg = "invalid literal/length code";
  14.208 +	r = Z_DATA_ERROR;
  14.209 +
  14.210 +	s.bitb=b;s.bitk=k;
  14.211 +	z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  14.212 +	s.write=q;
  14.213 +	return s.inflate_flush(r);
  14.214 +
  14.215 +      case LENEXT:        // i: getting length extra (have base)
  14.216 +	j = get;
  14.217 +
  14.218 +	while(k<(j)){
  14.219 +	  if(n!=0)r=Z_OK;
  14.220 +	  else{
  14.221 +
  14.222 +	    s.bitb=b;s.bitk=k;
  14.223 +	    z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  14.224 +	    s.write=q;
  14.225 +	    return s.inflate_flush(r);
  14.226 +	  }
  14.227 +	  n--; b|=(z.next_in[p++]&0xff)<<k;
  14.228 +	  k+=8;
  14.229 +	}
  14.230 +
  14.231 +	len += (b & inflate_mask[j]);
  14.232 +
  14.233 +	b>>=j;
  14.234 +	k-=j;
  14.235 +
  14.236 +	need = dbits;
  14.237 +	tree = dtree;
  14.238 +	tree_index=dtree_index;
  14.239 +	mode = DIST;
  14.240 +      case DIST:          // i: get distance next
  14.241 +	j = need;
  14.242 +
  14.243 +	while(k<(j)){
  14.244 +	  if(n!=0)r=Z_OK;
  14.245 +	  else{
  14.246 +
  14.247 +	    s.bitb=b;s.bitk=k;
  14.248 +	    z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  14.249 +	    s.write=q;
  14.250 +	    return s.inflate_flush(r);
  14.251 +	  }
  14.252 +	  n--; b|=(z.next_in[p++]&0xff)<<k;
  14.253 +	  k+=8;
  14.254 +	}
  14.255 +
  14.256 +	tindex=(tree_index+(b & inflate_mask[j]))*3;
  14.257 +
  14.258 +	b>>=tree[tindex+1];
  14.259 +	k-=tree[tindex+1];
  14.260 +
  14.261 +	e = (tree[tindex]);
  14.262 +	if((e & 16)!=0){               // distance
  14.263 +	  get = e & 15;
  14.264 +	  dist = tree[tindex+2];
  14.265 +	  mode = DISTEXT;
  14.266 +	  break;
  14.267 +	}
  14.268 +	if ((e & 64) == 0){        // next table
  14.269 +	  need = e;
  14.270 +	  tree_index = tindex/3 + tree[tindex+2];
  14.271 +	  break;
  14.272 +	}
  14.273 +	mode = BADCODE;        // invalid code
  14.274 +	z.msg = "invalid distance code";
  14.275 +	r = Z_DATA_ERROR;
  14.276 +
  14.277 +	s.bitb=b;s.bitk=k;
  14.278 +	z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  14.279 +	s.write=q;
  14.280 +	return s.inflate_flush(r);
  14.281 +
  14.282 +      case DISTEXT:       // i: getting distance extra
  14.283 +	j = get;
  14.284 +
  14.285 +	while(k<(j)){
  14.286 +	  if(n!=0)r=Z_OK;
  14.287 +	  else{
  14.288 +
  14.289 +	    s.bitb=b;s.bitk=k;
  14.290 +	    z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  14.291 +	    s.write=q;
  14.292 +	    return s.inflate_flush(r);
  14.293 +	  }
  14.294 +	  n--; b|=(z.next_in[p++]&0xff)<<k;
  14.295 +	  k+=8;
  14.296 +	}
  14.297 +
  14.298 +	dist += (b & inflate_mask[j]);
  14.299 +
  14.300 +	b>>=j;
  14.301 +	k-=j;
  14.302 +
  14.303 +	mode = COPY;
  14.304 +      case COPY:          // o: copying bytes in window, waiting for space
  14.305 +        f = q - dist;
  14.306 +        while(f < 0){     // modulo window size-"while" instead
  14.307 +          f += s.end;     // of "if" handles invalid distances
  14.308 +	}
  14.309 +	while (len!=0){
  14.310 +
  14.311 +	  if(m==0){
  14.312 +	    if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;}
  14.313 +	    if(m==0){
  14.314 +	      s.write=q; r=s.inflate_flush(r);
  14.315 +	      q=s.write;m=q<s.read?s.read-q-1:s.end-q;
  14.316 +
  14.317 +	      if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;}
  14.318 +
  14.319 +	      if(m==0){
  14.320 +		s.bitb=b;s.bitk=k;
  14.321 +		z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  14.322 +		s.write=q;
  14.323 +		return s.inflate_flush(r);
  14.324 +	      }  
  14.325 +	    }
  14.326 +	  }
  14.327 +
  14.328 +	  s.window[q++]=s.window[f++]; m--;
  14.329 +
  14.330 +	  if (f == s.end)
  14.331 +            f = 0;
  14.332 +	  len--;
  14.333 +	}
  14.334 +	mode = START;
  14.335 +	break;
  14.336 +      case LIT:           // o: got literal, waiting for output space
  14.337 +	if(m==0){
  14.338 +	  if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;}
  14.339 +	  if(m==0){
  14.340 +	    s.write=q; r=s.inflate_flush(r);
  14.341 +	    q=s.write;m=q<s.read?s.read-q-1:s.end-q;
  14.342 +
  14.343 +	    if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;}
  14.344 +	    if(m==0){
  14.345 +	      s.bitb=b;s.bitk=k;
  14.346 +	      z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  14.347 +	      s.write=q;
  14.348 +	      return s.inflate_flush(r);
  14.349 +	    }
  14.350 +	  }
  14.351 +	}
  14.352 +	r=Z_OK;
  14.353 +
  14.354 +	s.window[q++]=(byte)lit; m--;
  14.355 +
  14.356 +	mode = START;
  14.357 +	break;
  14.358 +      case WASH:           // o: got eob, possibly more output
  14.359 +	if (k > 7){        // return unused byte, if any
  14.360 +	  k -= 8;
  14.361 +	  n++;
  14.362 +	  p--;             // can always return one
  14.363 +	}
  14.364 +
  14.365 +	s.write=q; r=s.inflate_flush(r);
  14.366 +	q=s.write;m=q<s.read?s.read-q-1:s.end-q;
  14.367 +
  14.368 +	if (s.read != s.write){
  14.369 +	  s.bitb=b;s.bitk=k;
  14.370 +	  z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  14.371 +	  s.write=q;
  14.372 +	  return s.inflate_flush(r);
  14.373 +	}
  14.374 +	mode = END;
  14.375 +      case END:
  14.376 +	r = Z_STREAM_END;
  14.377 +	s.bitb=b;s.bitk=k;
  14.378 +	z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  14.379 +	s.write=q;
  14.380 +	return s.inflate_flush(r);
  14.381 +
  14.382 +      case BADCODE:       // x: got error
  14.383 +
  14.384 +	r = Z_DATA_ERROR;
  14.385 +
  14.386 +	s.bitb=b;s.bitk=k;
  14.387 +	z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  14.388 +	s.write=q;
  14.389 +	return s.inflate_flush(r);
  14.390 +
  14.391 +      default:
  14.392 +	r = Z_STREAM_ERROR;
  14.393 +
  14.394 +	s.bitb=b;s.bitk=k;
  14.395 +	z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  14.396 +	s.write=q;
  14.397 +	return s.inflate_flush(r);
  14.398 +      }
  14.399 +    }
  14.400 +  }
  14.401 +
  14.402 +  void free(ZStream z){
  14.403 +    //  ZFREE(z, c);
  14.404 +  }
  14.405 +
  14.406 +  // Called with number of bytes left to write in window at least 258
  14.407 +  // (the maximum string length) and number of input bytes available
  14.408 +  // at least ten.  The ten bytes are six bytes for the longest length/
  14.409 +  // distance pair plus four bytes for overloading the bit buffer.
  14.410 +
  14.411 +  int inflate_fast(int bl, int bd, 
  14.412 +		   int[] tl, int tl_index,
  14.413 +		   int[] td, int td_index,
  14.414 +		   InfBlocks s, ZStream z){
  14.415 +    int t;                // temporary pointer
  14.416 +    int[] tp;             // temporary pointer
  14.417 +    int tp_index;         // temporary pointer
  14.418 +    int e;                // extra bits or operation
  14.419 +    int b;                // bit buffer
  14.420 +    int k;                // bits in bit buffer
  14.421 +    int p;                // input data pointer
  14.422 +    int n;                // bytes available there
  14.423 +    int q;                // output window write pointer
  14.424 +    int m;                // bytes to end of window or read pointer
  14.425 +    int ml;               // mask for literal/length tree
  14.426 +    int md;               // mask for distance tree
  14.427 +    int c;                // bytes to copy
  14.428 +    int d;                // distance back to copy from
  14.429 +    int r;                // copy source pointer
  14.430 +
  14.431 +    int tp_index_t_3;     // (tp_index+t)*3
  14.432 +
  14.433 +    // load input, output, bit values
  14.434 +    p=z.next_in_index;n=z.avail_in;b=s.bitb;k=s.bitk;
  14.435 +    q=s.write;m=q<s.read?s.read-q-1:s.end-q;
  14.436 +
  14.437 +    // initialize masks
  14.438 +    ml = inflate_mask[bl];
  14.439 +    md = inflate_mask[bd];
  14.440 +
  14.441 +    // do until not enough input or output space for fast loop
  14.442 +    do {                          // assume called with m >= 258 && n >= 10
  14.443 +      // get literal/length code
  14.444 +      while(k<(20)){              // max bits for literal/length code
  14.445 +	n--;
  14.446 +	b|=(z.next_in[p++]&0xff)<<k;k+=8;
  14.447 +      }
  14.448 +
  14.449 +      t= b&ml;
  14.450 +      tp=tl; 
  14.451 +      tp_index=tl_index;
  14.452 +      tp_index_t_3=(tp_index+t)*3;
  14.453 +      if ((e = tp[tp_index_t_3]) == 0){
  14.454 +	b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]);
  14.455 +
  14.456 +	s.window[q++] = (byte)tp[tp_index_t_3+2];
  14.457 +	m--;
  14.458 +	continue;
  14.459 +      }
  14.460 +      do {
  14.461 +
  14.462 +	b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]);
  14.463 +
  14.464 +	if((e&16)!=0){
  14.465 +	  e &= 15;
  14.466 +	  c = tp[tp_index_t_3+2] + ((int)b & inflate_mask[e]);
  14.467 +
  14.468 +	  b>>=e; k-=e;
  14.469 +
  14.470 +	  // decode distance base of block to copy
  14.471 +	  while(k<(15)){           // max bits for distance code
  14.472 +	    n--;
  14.473 +	    b|=(z.next_in[p++]&0xff)<<k;k+=8;
  14.474 +	  }
  14.475 +
  14.476 +	  t= b&md;
  14.477 +	  tp=td;
  14.478 +	  tp_index=td_index;
  14.479 +          tp_index_t_3=(tp_index+t)*3;
  14.480 +	  e = tp[tp_index_t_3];
  14.481 +
  14.482 +	  do {
  14.483 +
  14.484 +	    b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]);
  14.485 +
  14.486 +	    if((e&16)!=0){
  14.487 +	      // get extra bits to add to distance base
  14.488 +	      e &= 15;
  14.489 +	      while(k<(e)){         // get extra bits (up to 13)
  14.490 +		n--;
  14.491 +		b|=(z.next_in[p++]&0xff)<<k;k+=8;
  14.492 +	      }
  14.493 +
  14.494 +	      d = tp[tp_index_t_3+2] + (b&inflate_mask[e]);
  14.495 +
  14.496 +	      b>>=(e); k-=(e);
  14.497 +
  14.498 +	      // do the copy
  14.499 +	      m -= c;
  14.500 +	      if (q >= d){                // offset before dest
  14.501 +		//  just copy
  14.502 +		r=q-d;
  14.503 +		if(q-r>0 && 2>(q-r)){           
  14.504 +		  s.window[q++]=s.window[r++]; // minimum count is three,
  14.505 +		  s.window[q++]=s.window[r++]; // so unroll loop a little
  14.506 +		  c-=2;
  14.507 +		}
  14.508 +		else{
  14.509 +		  System.arraycopy(s.window, r, s.window, q, 2);
  14.510 +		  q+=2; r+=2; c-=2;
  14.511 +		}
  14.512 +	      }
  14.513 +	      else{                  // else offset after destination
  14.514 +                r=q-d;
  14.515 +                do{
  14.516 +                  r+=s.end;          // force pointer in window
  14.517 +                }while(r<0);         // covers invalid distances
  14.518 +		e=s.end-r;
  14.519 +		if(c>e){             // if source crosses,
  14.520 +		  c-=e;              // wrapped copy
  14.521 +		  if(q-r>0 && e>(q-r)){           
  14.522 +		    do{s.window[q++] = s.window[r++];}
  14.523 +		    while(--e!=0);
  14.524 +		  }
  14.525 +		  else{
  14.526 +		    System.arraycopy(s.window, r, s.window, q, e);
  14.527 +		    q+=e; r+=e; e=0;
  14.528 +		  }
  14.529 +		  r = 0;                  // copy rest from start of window
  14.530 +		}
  14.531 +
  14.532 +	      }
  14.533 +
  14.534 +	      // copy all or what's left
  14.535 +	      if(q-r>0 && c>(q-r)){           
  14.536 +		do{s.window[q++] = s.window[r++];}
  14.537 +		while(--c!=0);
  14.538 +	      }
  14.539 +	      else{
  14.540 +		System.arraycopy(s.window, r, s.window, q, c);
  14.541 +		q+=c; r+=c; c=0;
  14.542 +	      }
  14.543 +	      break;
  14.544 +	    }
  14.545 +	    else if((e&64)==0){
  14.546 +	      t+=tp[tp_index_t_3+2];
  14.547 +	      t+=(b&inflate_mask[e]);
  14.548 +	      tp_index_t_3=(tp_index+t)*3;
  14.549 +	      e=tp[tp_index_t_3];
  14.550 +	    }
  14.551 +	    else{
  14.552 +	      z.msg = "invalid distance code";
  14.553 +
  14.554 +	      c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;
  14.555 +
  14.556 +	      s.bitb=b;s.bitk=k;
  14.557 +	      z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  14.558 +	      s.write=q;
  14.559 +
  14.560 +	      return Z_DATA_ERROR;
  14.561 +	    }
  14.562 +	  }
  14.563 +	  while(true);
  14.564 +	  break;
  14.565 +	}
  14.566 +
  14.567 +	if((e&64)==0){
  14.568 +	  t+=tp[tp_index_t_3+2];
  14.569 +	  t+=(b&inflate_mask[e]);
  14.570 +	  tp_index_t_3=(tp_index+t)*3;
  14.571 +	  if((e=tp[tp_index_t_3])==0){
  14.572 +
  14.573 +	    b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]);
  14.574 +
  14.575 +	    s.window[q++]=(byte)tp[tp_index_t_3+2];
  14.576 +	    m--;
  14.577 +	    break;
  14.578 +	  }
  14.579 +	}
  14.580 +	else if((e&32)!=0){
  14.581 +
  14.582 +	  c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;
  14.583 + 
  14.584 +	  s.bitb=b;s.bitk=k;
  14.585 +	  z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  14.586 +	  s.write=q;
  14.587 +
  14.588 +	  return Z_STREAM_END;
  14.589 +	}
  14.590 +	else{
  14.591 +	  z.msg="invalid literal/length code";
  14.592 +
  14.593 +	  c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;
  14.594 +
  14.595 +	  s.bitb=b;s.bitk=k;
  14.596 +	  z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  14.597 +	  s.write=q;
  14.598 +
  14.599 +	  return Z_DATA_ERROR;
  14.600 +	}
  14.601 +      } 
  14.602 +      while(true);
  14.603 +    } 
  14.604 +    while(m>=258 && n>= 10);
  14.605 +
  14.606 +    // not enough input or output--restore pointers and return
  14.607 +    c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;
  14.608 +
  14.609 +    s.bitb=b;s.bitk=k;
  14.610 +    z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
  14.611 +    s.write=q;
  14.612 +
  14.613 +    return Z_OK;
  14.614 +  }
  14.615 +}
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/InfTree.java	Thu Feb 07 12:58:12 2013 +0100
    15.3 @@ -0,0 +1,520 @@
    15.4 +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
    15.5 +/*
    15.6 +Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
    15.7 +
    15.8 +Redistribution and use in source and binary forms, with or without
    15.9 +modification, are permitted provided that the following conditions are met:
   15.10 +
   15.11 +  1. Redistributions of source code must retain the above copyright notice,
   15.12 +     this list of conditions and the following disclaimer.
   15.13 +
   15.14 +  2. Redistributions in binary form must reproduce the above copyright 
   15.15 +     notice, this list of conditions and the following disclaimer in 
   15.16 +     the documentation and/or other materials provided with the distribution.
   15.17 +
   15.18 +  3. The names of the authors may not be used to endorse or promote products
   15.19 +     derived from this software without specific prior written permission.
   15.20 +
   15.21 +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   15.22 +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   15.23 +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
   15.24 +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
   15.25 +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   15.26 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
   15.27 +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   15.28 +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   15.29 +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
   15.30 +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   15.31 + */
   15.32 +/*
   15.33 + * This program is based on zlib-1.1.3, so all credit should go authors
   15.34 + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
   15.35 + * and contributors of zlib.
   15.36 + */
   15.37 +
   15.38 +package org.apidesign.bck2brwsr.emul.zip;
   15.39 +
   15.40 +import org.apidesign.bck2brwsr.emul.lang.System;
   15.41 +
   15.42 +final class InfTree{
   15.43 +
   15.44 +  static final private int MANY=1440;
   15.45 +
   15.46 +  static final private int Z_OK=0;
   15.47 +  static final private int Z_STREAM_END=1;
   15.48 +  static final private int Z_NEED_DICT=2;
   15.49 +  static final private int Z_ERRNO=-1;
   15.50 +  static final private int Z_STREAM_ERROR=-2;
   15.51 +  static final private int Z_DATA_ERROR=-3;
   15.52 +  static final private int Z_MEM_ERROR=-4;
   15.53 +  static final private int Z_BUF_ERROR=-5;
   15.54 +  static final private int Z_VERSION_ERROR=-6;
   15.55 +
   15.56 +  static final int fixed_bl = 9;
   15.57 +  static final int fixed_bd = 5;
   15.58 +
   15.59 +  static final int[] fixed_tl = {
   15.60 +    96,7,256, 0,8,80, 0,8,16, 84,8,115,
   15.61 +    82,7,31, 0,8,112, 0,8,48, 0,9,192,
   15.62 +    80,7,10, 0,8,96, 0,8,32, 0,9,160,
   15.63 +    0,8,0, 0,8,128, 0,8,64, 0,9,224,
   15.64 +    80,7,6, 0,8,88, 0,8,24, 0,9,144,
   15.65 +    83,7,59, 0,8,120, 0,8,56, 0,9,208,
   15.66 +    81,7,17, 0,8,104, 0,8,40, 0,9,176,
   15.67 +    0,8,8, 0,8,136, 0,8,72, 0,9,240,
   15.68 +    80,7,4, 0,8,84, 0,8,20, 85,8,227,
   15.69 +    83,7,43, 0,8,116, 0,8,52, 0,9,200,
   15.70 +    81,7,13, 0,8,100, 0,8,36, 0,9,168,
   15.71 +    0,8,4, 0,8,132, 0,8,68, 0,9,232,
   15.72 +    80,7,8, 0,8,92, 0,8,28, 0,9,152,
   15.73 +    84,7,83, 0,8,124, 0,8,60, 0,9,216,
   15.74 +    82,7,23, 0,8,108, 0,8,44, 0,9,184,
   15.75 +    0,8,12, 0,8,140, 0,8,76, 0,9,248,
   15.76 +    80,7,3, 0,8,82, 0,8,18, 85,8,163,
   15.77 +    83,7,35, 0,8,114, 0,8,50, 0,9,196,
   15.78 +    81,7,11, 0,8,98, 0,8,34, 0,9,164,
   15.79 +    0,8,2, 0,8,130, 0,8,66, 0,9,228,
   15.80 +    80,7,7, 0,8,90, 0,8,26, 0,9,148,
   15.81 +    84,7,67, 0,8,122, 0,8,58, 0,9,212,
   15.82 +    82,7,19, 0,8,106, 0,8,42, 0,9,180,
   15.83 +    0,8,10, 0,8,138, 0,8,74, 0,9,244,
   15.84 +    80,7,5, 0,8,86, 0,8,22, 192,8,0,
   15.85 +    83,7,51, 0,8,118, 0,8,54, 0,9,204,
   15.86 +    81,7,15, 0,8,102, 0,8,38, 0,9,172,
   15.87 +    0,8,6, 0,8,134, 0,8,70, 0,9,236,
   15.88 +    80,7,9, 0,8,94, 0,8,30, 0,9,156,
   15.89 +    84,7,99, 0,8,126, 0,8,62, 0,9,220,
   15.90 +    82,7,27, 0,8,110, 0,8,46, 0,9,188,
   15.91 +    0,8,14, 0,8,142, 0,8,78, 0,9,252,
   15.92 +    96,7,256, 0,8,81, 0,8,17, 85,8,131,
   15.93 +    82,7,31, 0,8,113, 0,8,49, 0,9,194,
   15.94 +    80,7,10, 0,8,97, 0,8,33, 0,9,162,
   15.95 +    0,8,1, 0,8,129, 0,8,65, 0,9,226,
   15.96 +    80,7,6, 0,8,89, 0,8,25, 0,9,146,
   15.97 +    83,7,59, 0,8,121, 0,8,57, 0,9,210,
   15.98 +    81,7,17, 0,8,105, 0,8,41, 0,9,178,
   15.99 +    0,8,9, 0,8,137, 0,8,73, 0,9,242,
  15.100 +    80,7,4, 0,8,85, 0,8,21, 80,8,258,
  15.101 +    83,7,43, 0,8,117, 0,8,53, 0,9,202,
  15.102 +    81,7,13, 0,8,101, 0,8,37, 0,9,170,
  15.103 +    0,8,5, 0,8,133, 0,8,69, 0,9,234,
  15.104 +    80,7,8, 0,8,93, 0,8,29, 0,9,154,
  15.105 +    84,7,83, 0,8,125, 0,8,61, 0,9,218,
  15.106 +    82,7,23, 0,8,109, 0,8,45, 0,9,186,
  15.107 +    0,8,13, 0,8,141, 0,8,77, 0,9,250,
  15.108 +    80,7,3, 0,8,83, 0,8,19, 85,8,195,
  15.109 +    83,7,35, 0,8,115, 0,8,51, 0,9,198,
  15.110 +    81,7,11, 0,8,99, 0,8,35, 0,9,166,
  15.111 +    0,8,3, 0,8,131, 0,8,67, 0,9,230,
  15.112 +    80,7,7, 0,8,91, 0,8,27, 0,9,150,
  15.113 +    84,7,67, 0,8,123, 0,8,59, 0,9,214,
  15.114 +    82,7,19, 0,8,107, 0,8,43, 0,9,182,
  15.115 +    0,8,11, 0,8,139, 0,8,75, 0,9,246,
  15.116 +    80,7,5, 0,8,87, 0,8,23, 192,8,0,
  15.117 +    83,7,51, 0,8,119, 0,8,55, 0,9,206,
  15.118 +    81,7,15, 0,8,103, 0,8,39, 0,9,174,
  15.119 +    0,8,7, 0,8,135, 0,8,71, 0,9,238,
  15.120 +    80,7,9, 0,8,95, 0,8,31, 0,9,158,
  15.121 +    84,7,99, 0,8,127, 0,8,63, 0,9,222,
  15.122 +    82,7,27, 0,8,111, 0,8,47, 0,9,190,
  15.123 +    0,8,15, 0,8,143, 0,8,79, 0,9,254,
  15.124 +    96,7,256, 0,8,80, 0,8,16, 84,8,115,
  15.125 +    82,7,31, 0,8,112, 0,8,48, 0,9,193,
  15.126 +
  15.127 +    80,7,10, 0,8,96, 0,8,32, 0,9,161,
  15.128 +    0,8,0, 0,8,128, 0,8,64, 0,9,225,
  15.129 +    80,7,6, 0,8,88, 0,8,24, 0,9,145,
  15.130 +    83,7,59, 0,8,120, 0,8,56, 0,9,209,
  15.131 +    81,7,17, 0,8,104, 0,8,40, 0,9,177,
  15.132 +    0,8,8, 0,8,136, 0,8,72, 0,9,241,
  15.133 +    80,7,4, 0,8,84, 0,8,20, 85,8,227,
  15.134 +    83,7,43, 0,8,116, 0,8,52, 0,9,201,
  15.135 +    81,7,13, 0,8,100, 0,8,36, 0,9,169,
  15.136 +    0,8,4, 0,8,132, 0,8,68, 0,9,233,
  15.137 +    80,7,8, 0,8,92, 0,8,28, 0,9,153,
  15.138 +    84,7,83, 0,8,124, 0,8,60, 0,9,217,
  15.139 +    82,7,23, 0,8,108, 0,8,44, 0,9,185,
  15.140 +    0,8,12, 0,8,140, 0,8,76, 0,9,249,
  15.141 +    80,7,3, 0,8,82, 0,8,18, 85,8,163,
  15.142 +    83,7,35, 0,8,114, 0,8,50, 0,9,197,
  15.143 +    81,7,11, 0,8,98, 0,8,34, 0,9,165,
  15.144 +    0,8,2, 0,8,130, 0,8,66, 0,9,229,
  15.145 +    80,7,7, 0,8,90, 0,8,26, 0,9,149,
  15.146 +    84,7,67, 0,8,122, 0,8,58, 0,9,213,
  15.147 +    82,7,19, 0,8,106, 0,8,42, 0,9,181,
  15.148 +    0,8,10, 0,8,138, 0,8,74, 0,9,245,
  15.149 +    80,7,5, 0,8,86, 0,8,22, 192,8,0,
  15.150 +    83,7,51, 0,8,118, 0,8,54, 0,9,205,
  15.151 +    81,7,15, 0,8,102, 0,8,38, 0,9,173,
  15.152 +    0,8,6, 0,8,134, 0,8,70, 0,9,237,
  15.153 +    80,7,9, 0,8,94, 0,8,30, 0,9,157,
  15.154 +    84,7,99, 0,8,126, 0,8,62, 0,9,221,
  15.155 +    82,7,27, 0,8,110, 0,8,46, 0,9,189,
  15.156 +    0,8,14, 0,8,142, 0,8,78, 0,9,253,
  15.157 +    96,7,256, 0,8,81, 0,8,17, 85,8,131,
  15.158 +    82,7,31, 0,8,113, 0,8,49, 0,9,195,
  15.159 +    80,7,10, 0,8,97, 0,8,33, 0,9,163,
  15.160 +    0,8,1, 0,8,129, 0,8,65, 0,9,227,
  15.161 +    80,7,6, 0,8,89, 0,8,25, 0,9,147,
  15.162 +    83,7,59, 0,8,121, 0,8,57, 0,9,211,
  15.163 +    81,7,17, 0,8,105, 0,8,41, 0,9,179,
  15.164 +    0,8,9, 0,8,137, 0,8,73, 0,9,243,
  15.165 +    80,7,4, 0,8,85, 0,8,21, 80,8,258,
  15.166 +    83,7,43, 0,8,117, 0,8,53, 0,9,203,
  15.167 +    81,7,13, 0,8,101, 0,8,37, 0,9,171,
  15.168 +    0,8,5, 0,8,133, 0,8,69, 0,9,235,
  15.169 +    80,7,8, 0,8,93, 0,8,29, 0,9,155,
  15.170 +    84,7,83, 0,8,125, 0,8,61, 0,9,219,
  15.171 +    82,7,23, 0,8,109, 0,8,45, 0,9,187,
  15.172 +    0,8,13, 0,8,141, 0,8,77, 0,9,251,
  15.173 +    80,7,3, 0,8,83, 0,8,19, 85,8,195,
  15.174 +    83,7,35, 0,8,115, 0,8,51, 0,9,199,
  15.175 +    81,7,11, 0,8,99, 0,8,35, 0,9,167,
  15.176 +    0,8,3, 0,8,131, 0,8,67, 0,9,231,
  15.177 +    80,7,7, 0,8,91, 0,8,27, 0,9,151,
  15.178 +    84,7,67, 0,8,123, 0,8,59, 0,9,215,
  15.179 +    82,7,19, 0,8,107, 0,8,43, 0,9,183,
  15.180 +    0,8,11, 0,8,139, 0,8,75, 0,9,247,
  15.181 +    80,7,5, 0,8,87, 0,8,23, 192,8,0,
  15.182 +    83,7,51, 0,8,119, 0,8,55, 0,9,207,
  15.183 +    81,7,15, 0,8,103, 0,8,39, 0,9,175,
  15.184 +    0,8,7, 0,8,135, 0,8,71, 0,9,239,
  15.185 +    80,7,9, 0,8,95, 0,8,31, 0,9,159,
  15.186 +    84,7,99, 0,8,127, 0,8,63, 0,9,223,
  15.187 +    82,7,27, 0,8,111, 0,8,47, 0,9,191,
  15.188 +    0,8,15, 0,8,143, 0,8,79, 0,9,255
  15.189 +  };
  15.190 +  static final int[] fixed_td = {
  15.191 +    80,5,1, 87,5,257, 83,5,17, 91,5,4097,
  15.192 +    81,5,5, 89,5,1025, 85,5,65, 93,5,16385,
  15.193 +    80,5,3, 88,5,513, 84,5,33, 92,5,8193,
  15.194 +    82,5,9, 90,5,2049, 86,5,129, 192,5,24577,
  15.195 +    80,5,2, 87,5,385, 83,5,25, 91,5,6145,
  15.196 +    81,5,7, 89,5,1537, 85,5,97, 93,5,24577,
  15.197 +    80,5,4, 88,5,769, 84,5,49, 92,5,12289,
  15.198 +    82,5,13, 90,5,3073, 86,5,193, 192,5,24577
  15.199 +  };
  15.200 +
  15.201 +  // Tables for deflate from PKZIP's appnote.txt.
  15.202 +  static final int[] cplens = { // Copy lengths for literal codes 257..285
  15.203 +        3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
  15.204 +        35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
  15.205 +  };
  15.206 +
  15.207 +  // see note #13 above about 258
  15.208 +  static final int[] cplext = { // Extra bits for literal codes 257..285
  15.209 +        0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
  15.210 +        3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112  // 112==invalid
  15.211 +  };
  15.212 +
  15.213 +  static final int[] cpdist = { // Copy offsets for distance codes 0..29
  15.214 +        1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
  15.215 +        257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
  15.216 +        8193, 12289, 16385, 24577
  15.217 +  };
  15.218 +
  15.219 +  static final int[] cpdext = { // Extra bits for distance codes
  15.220 +        0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
  15.221 +        7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
  15.222 +        12, 12, 13, 13};
  15.223 +
  15.224 +  // If BMAX needs to be larger than 16, then h and x[] should be uLong.
  15.225 +  static final int BMAX=15;         // maximum bit length of any code
  15.226 +
  15.227 +  int[] hn = null;  // hufts used in space
  15.228 +  int[] v = null;   // work area for huft_build 
  15.229 +  int[] c = null;   // bit length count table
  15.230 +  int[] r = null;   // table entry for structure assignment
  15.231 +  int[] u = null;   // table stack
  15.232 +  int[] x = null;   // bit offsets, then code stack
  15.233 +
  15.234 +  private int huft_build(int[] b, // code lengths in bits (all assumed <= BMAX)
  15.235 +                         int bindex, 
  15.236 +                         int n,   // number of codes (assumed <= 288)
  15.237 +                         int s,   // number of simple-valued codes (0..s-1)
  15.238 +                         int[] d, // list of base values for non-simple codes
  15.239 +                         int[] e, // list of extra bits for non-simple codes
  15.240 +                         int[] t, // result: starting table
  15.241 +                         int[] m, // maximum lookup bits, returns actual
  15.242 +                         int[] hp,// space for trees
  15.243 +                         int[] hn,// hufts used in space
  15.244 +                         int[] v  // working area: values in order of bit length
  15.245 +                         ){
  15.246 +    // Given a list of code lengths and a maximum table size, make a set of
  15.247 +    // tables to decode that set of codes.  Return Z_OK on success, Z_BUF_ERROR
  15.248 +    // if the given code set is incomplete (the tables are still built in this
  15.249 +    // case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of
  15.250 +    // lengths), or Z_MEM_ERROR if not enough memory.
  15.251 +
  15.252 +    int a;                       // counter for codes of length k
  15.253 +    int f;                       // i repeats in table every f entries
  15.254 +    int g;                       // maximum code length
  15.255 +    int h;                       // table level
  15.256 +    int i;                       // counter, current code
  15.257 +    int j;                       // counter
  15.258 +    int k;                       // number of bits in current code
  15.259 +    int l;                       // bits per table (returned in m)
  15.260 +    int mask;                    // (1 << w) - 1, to avoid cc -O bug on HP
  15.261 +    int p;                       // pointer into c[], b[], or v[]
  15.262 +    int q;                       // points to current table
  15.263 +    int w;                       // bits before this table == (l * h)
  15.264 +    int xp;                      // pointer into x
  15.265 +    int y;                       // number of dummy codes added
  15.266 +    int z;                       // number of entries in current table
  15.267 +
  15.268 +    // Generate counts for each bit length
  15.269 +
  15.270 +    p = 0; i = n;
  15.271 +    do {
  15.272 +      c[b[bindex+p]]++; p++; i--;   // assume all entries <= BMAX
  15.273 +    }while(i!=0);
  15.274 +
  15.275 +    if(c[0] == n){                // null input--all zero length codes
  15.276 +      t[0] = -1;
  15.277 +      m[0] = 0;
  15.278 +      return Z_OK;
  15.279 +    }
  15.280 +
  15.281 +    // Find minimum and maximum length, bound *m by those
  15.282 +    l = m[0];
  15.283 +    for (j = 1; j <= BMAX; j++)
  15.284 +      if(c[j]!=0) break;
  15.285 +    k = j;                        // minimum code length
  15.286 +    if(l < j){
  15.287 +      l = j;
  15.288 +    }
  15.289 +    for (i = BMAX; i!=0; i--){
  15.290 +      if(c[i]!=0) break;
  15.291 +    }
  15.292 +    g = i;                        // maximum code length
  15.293 +    if(l > i){
  15.294 +      l = i;
  15.295 +    }
  15.296 +    m[0] = l;
  15.297 +
  15.298 +    // Adjust last length count to fill out codes, if needed
  15.299 +    for (y = 1 << j; j < i; j++, y <<= 1){
  15.300 +      if ((y -= c[j]) < 0){
  15.301 +        return Z_DATA_ERROR;
  15.302 +      }
  15.303 +    }
  15.304 +    if ((y -= c[i]) < 0){
  15.305 +      return Z_DATA_ERROR;
  15.306 +    }
  15.307 +    c[i] += y;
  15.308 +
  15.309 +    // Generate starting offsets into the value table for each length
  15.310 +    x[1] = j = 0;
  15.311 +    p = 1;  xp = 2;
  15.312 +    while (--i!=0) {                 // note that i == g from above
  15.313 +      x[xp] = (j += c[p]);
  15.314 +      xp++;
  15.315 +      p++;
  15.316 +    }
  15.317 +
  15.318 +    // Make a table of values in order of bit lengths
  15.319 +    i = 0; p = 0;
  15.320 +    do {
  15.321 +      if ((j = b[bindex+p]) != 0){
  15.322 +        v[x[j]++] = i;
  15.323 +      }
  15.324 +      p++;
  15.325 +    }
  15.326 +    while (++i < n);
  15.327 +    n = x[g];                     // set n to length of v
  15.328 +
  15.329 +    // Generate the Huffman codes and for each, make the table entries
  15.330 +    x[0] = i = 0;                 // first Huffman code is zero
  15.331 +    p = 0;                        // grab values in bit order
  15.332 +    h = -1;                       // no tables yet--level -1
  15.333 +    w = -l;                       // bits decoded == (l * h)
  15.334 +    u[0] = 0;                     // just to keep compilers happy
  15.335 +    q = 0;                        // ditto
  15.336 +    z = 0;                        // ditto
  15.337 +
  15.338 +    // go through the bit lengths (k already is bits in shortest code)
  15.339 +    for (; k <= g; k++){
  15.340 +      a = c[k];
  15.341 +      while (a--!=0){
  15.342 +	// here i is the Huffman code of length k bits for value *p
  15.343 +	// make tables up to required level
  15.344 +        while (k > w + l){
  15.345 +          h++;
  15.346 +          w += l;                 // previous table always l bits
  15.347 +	  // compute minimum size table less than or equal to l bits
  15.348 +          z = g - w;
  15.349 +          z = (z > l) ? l : z;        // table size upper limit
  15.350 +          if((f=1<<(j=k-w))>a+1){     // try a k-w bit table
  15.351 +                                      // too few codes for k-w bit table
  15.352 +            f -= a + 1;               // deduct codes from patterns left
  15.353 +            xp = k;
  15.354 +            if(j < z){
  15.355 +              while (++j < z){        // try smaller tables up to z bits
  15.356 +                if((f <<= 1) <= c[++xp])
  15.357 +                  break;              // enough codes to use up j bits
  15.358 +                f -= c[xp];           // else deduct codes from patterns
  15.359 +              }
  15.360 +	    }
  15.361 +          }
  15.362 +          z = 1 << j;                 // table entries for j-bit table
  15.363 +
  15.364 +	  // allocate new table
  15.365 +          if (hn[0] + z > MANY){       // (note: doesn't matter for fixed)
  15.366 +            return Z_DATA_ERROR;       // overflow of MANY
  15.367 +          }
  15.368 +          u[h] = q = /*hp+*/ hn[0];   // DEBUG
  15.369 +          hn[0] += z;
  15.370 + 
  15.371 +	  // connect to last table, if there is one
  15.372 +	  if(h!=0){
  15.373 +            x[h]=i;           // save pattern for backing up
  15.374 +            r[0]=(byte)j;     // bits in this table
  15.375 +            r[1]=(byte)l;     // bits to dump before this table
  15.376 +            j=i>>>(w - l);
  15.377 +            r[2] = (int)(q - u[h-1] - j);               // offset to this table
  15.378 +            System.arraycopy(r, 0, hp, (u[h-1]+j)*3, 3); // connect to last table
  15.379 +          }
  15.380 +          else{
  15.381 +            t[0] = q;               // first table is returned result
  15.382 +	  }
  15.383 +        }
  15.384 +
  15.385 +	// set up table entry in r
  15.386 +        r[1] = (byte)(k - w);
  15.387 +        if (p >= n){
  15.388 +          r[0] = 128 + 64;      // out of values--invalid code
  15.389 +	}
  15.390 +        else if (v[p] < s){
  15.391 +          r[0] = (byte)(v[p] < 256 ? 0 : 32 + 64);  // 256 is end-of-block
  15.392 +          r[2] = v[p++];          // simple code is just the value
  15.393 +        }
  15.394 +        else{
  15.395 +          r[0]=(byte)(e[v[p]-s]+16+64); // non-simple--look up in lists
  15.396 +          r[2]=d[v[p++] - s];
  15.397 +        }
  15.398 +
  15.399 +        // fill code-like entries with r
  15.400 +        f=1<<(k-w);
  15.401 +        for (j=i>>>w;j<z;j+=f){
  15.402 +          System.arraycopy(r, 0, hp, (q+j)*3, 3);
  15.403 +	}
  15.404 +
  15.405 +	// backwards increment the k-bit code i
  15.406 +        for (j = 1 << (k - 1); (i & j)!=0; j >>>= 1){
  15.407 +          i ^= j;
  15.408 +	}
  15.409 +        i ^= j;
  15.410 +
  15.411 +	// backup over finished tables
  15.412 +        mask = (1 << w) - 1;      // needed on HP, cc -O bug
  15.413 +        while ((i & mask) != x[h]){
  15.414 +          h--;                    // don't need to update q
  15.415 +          w -= l;
  15.416 +          mask = (1 << w) - 1;
  15.417 +        }
  15.418 +      }
  15.419 +    }
  15.420 +    // Return Z_BUF_ERROR if we were given an incomplete table
  15.421 +    return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK;
  15.422 +  }
  15.423 +
  15.424 +  int inflate_trees_bits(int[] c,  // 19 code lengths
  15.425 +                         int[] bb, // bits tree desired/actual depth
  15.426 +                         int[] tb, // bits tree result
  15.427 +                         int[] hp, // space for trees
  15.428 +                         ZStream z // for messages
  15.429 +                         ){
  15.430 +    int result;
  15.431 +    initWorkArea(19);
  15.432 +    hn[0]=0;
  15.433 +    result = huft_build(c, 0, 19, 19, null, null, tb, bb, hp, hn, v);
  15.434 +
  15.435 +    if(result == Z_DATA_ERROR){
  15.436 +      z.msg = "oversubscribed dynamic bit lengths tree";
  15.437 +    }
  15.438 +    else if(result == Z_BUF_ERROR || bb[0] == 0){
  15.439 +      z.msg = "incomplete dynamic bit lengths tree";
  15.440 +      result = Z_DATA_ERROR;
  15.441 +    }
  15.442 +    return result;
  15.443 +  }
  15.444 +
  15.445 +  int inflate_trees_dynamic(int nl,   // number of literal/length codes
  15.446 +                            int nd,   // number of distance codes
  15.447 +                            int[] c,  // that many (total) code lengths
  15.448 +                            int[] bl, // literal desired/actual bit depth
  15.449 +                            int[] bd, // distance desired/actual bit depth 
  15.450 +                            int[] tl, // literal/length tree result
  15.451 +                            int[] td, // distance tree result
  15.452 +                            int[] hp, // space for trees
  15.453 +                            ZStream z // for messages
  15.454 +                            ){
  15.455 +    int result;
  15.456 +
  15.457 +    // build literal/length tree
  15.458 +    initWorkArea(288);
  15.459 +    hn[0]=0;
  15.460 +    result = huft_build(c, 0, nl, 257, cplens, cplext, tl, bl, hp, hn, v);
  15.461 +    if (result != Z_OK || bl[0] == 0){
  15.462 +      if(result == Z_DATA_ERROR){
  15.463 +        z.msg = "oversubscribed literal/length tree";
  15.464 +      }
  15.465 +      else if (result != Z_MEM_ERROR){
  15.466 +        z.msg = "incomplete literal/length tree";
  15.467 +        result = Z_DATA_ERROR;
  15.468 +      }
  15.469 +      return result;
  15.470 +    }
  15.471 +
  15.472 +    // build distance tree
  15.473 +    initWorkArea(288);
  15.474 +    result = huft_build(c, nl, nd, 0, cpdist, cpdext, td, bd, hp, hn, v);
  15.475 +
  15.476 +    if (result != Z_OK || (bd[0] == 0 && nl > 257)){
  15.477 +      if (result == Z_DATA_ERROR){
  15.478 +        z.msg = "oversubscribed distance tree";
  15.479 +      }
  15.480 +      else if (result == Z_BUF_ERROR) {
  15.481 +        z.msg = "incomplete distance tree";
  15.482 +        result = Z_DATA_ERROR;
  15.483 +      }
  15.484 +      else if (result != Z_MEM_ERROR){
  15.485 +        z.msg = "empty distance tree with lengths";
  15.486 +        result = Z_DATA_ERROR;
  15.487 +      }
  15.488 +      return result;
  15.489 +    }
  15.490 +
  15.491 +    return Z_OK;
  15.492 +  }
  15.493 +
  15.494 +  static int inflate_trees_fixed(int[] bl,  //literal desired/actual bit depth
  15.495 +                                 int[] bd,  //distance desired/actual bit depth
  15.496 +                                 int[][] tl,//literal/length tree result
  15.497 +                                 int[][] td,//distance tree result 
  15.498 +                                 ZStream z  //for memory allocation
  15.499 +				 ){
  15.500 +    bl[0]=fixed_bl;
  15.501 +    bd[0]=fixed_bd;
  15.502 +    tl[0]=fixed_tl;
  15.503 +    td[0]=fixed_td;
  15.504 +    return Z_OK;
  15.505 +  }
  15.506 +
  15.507 +  private void initWorkArea(int vsize){
  15.508 +    if(hn==null){
  15.509 +      hn=new int[1];
  15.510 +      v=new int[vsize];
  15.511 +      c=new int[BMAX+1];
  15.512 +      r=new int[3];
  15.513 +      u=new int[BMAX];
  15.514 +      x=new int[BMAX+1];
  15.515 +    }
  15.516 +    if(v.length<vsize){ v=new int[vsize]; }
  15.517 +    for(int i=0; i<vsize; i++){v[i]=0;}
  15.518 +    for(int i=0; i<BMAX+1; i++){c[i]=0;}
  15.519 +    for(int i=0; i<3; i++){r[i]=0;}
  15.520 +    System.arraycopy(c, 0, u, 0, BMAX);
  15.521 +    System.arraycopy(c, 0, x, 0, BMAX+1);
  15.522 +  }
  15.523 +}
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/Inflate.java	Thu Feb 07 12:58:12 2013 +0100
    16.3 @@ -0,0 +1,727 @@
    16.4 +/* -*-mode:java; c-basic-offset:2; -*- */
    16.5 +/*
    16.6 +Copyright (c) 2000-2011 ymnk, JCraft,Inc. All rights reserved.
    16.7 +
    16.8 +Redistribution and use in source and binary forms, with or without
    16.9 +modification, are permitted provided that the following conditions are met:
   16.10 +
   16.11 +  1. Redistributions of source code must retain the above copyright notice,
   16.12 +     this list of conditions and the following disclaimer.
   16.13 +
   16.14 +  2. Redistributions in binary form must reproduce the above copyright 
   16.15 +     notice, this list of conditions and the following disclaimer in 
   16.16 +     the documentation and/or other materials provided with the distribution.
   16.17 +
   16.18 +  3. The names of the authors may not be used to endorse or promote products
   16.19 +     derived from this software without specific prior written permission.
   16.20 +
   16.21 +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   16.22 +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   16.23 +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
   16.24 +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
   16.25 +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   16.26 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
   16.27 +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   16.28 +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   16.29 +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
   16.30 +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   16.31 + */
   16.32 +/*
   16.33 + * This program is based on zlib-1.1.3, so all credit should go authors
   16.34 + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
   16.35 + * and contributors of zlib.
   16.36 + */
   16.37 +
   16.38 +package org.apidesign.bck2brwsr.emul.zip;
   16.39 +
   16.40 +import org.apidesign.bck2brwsr.emul.lang.System;
   16.41 +
   16.42 +final class Inflate{
   16.43 +  
   16.44 +  static final private int MAX_WBITS=15; // 32K LZ77 window
   16.45 +
   16.46 +  // preset dictionary flag in zlib header
   16.47 +  static final private int PRESET_DICT=0x20;
   16.48 +
   16.49 +  static final int Z_NO_FLUSH=0;
   16.50 +  static final int Z_PARTIAL_FLUSH=1;
   16.51 +  static final int Z_SYNC_FLUSH=2;
   16.52 +  static final int Z_FULL_FLUSH=3;
   16.53 +  static final int Z_FINISH=4;
   16.54 +
   16.55 +  static final private int Z_DEFLATED=8;
   16.56 +
   16.57 +  static final private int Z_OK=0;
   16.58 +  static final private int Z_STREAM_END=1;
   16.59 +  static final private int Z_NEED_DICT=2;
   16.60 +  static final private int Z_ERRNO=-1;
   16.61 +  static final private int Z_STREAM_ERROR=-2;
   16.62 +  static final private int Z_DATA_ERROR=-3;
   16.63 +  static final private int Z_MEM_ERROR=-4;
   16.64 +  static final private int Z_BUF_ERROR=-5;
   16.65 +  static final private int Z_VERSION_ERROR=-6;
   16.66 +
   16.67 +  static final private int METHOD=0;   // waiting for method byte
   16.68 +  static final private int FLAG=1;     // waiting for flag byte
   16.69 +  static final private int DICT4=2;    // four dictionary check bytes to go
   16.70 +  static final private int DICT3=3;    // three dictionary check bytes to go
   16.71 +  static final private int DICT2=4;    // two dictionary check bytes to go
   16.72 +  static final private int DICT1=5;    // one dictionary check byte to go
   16.73 +  static final int DICT0=6;    // waiting for inflateSetDictionary
   16.74 +  static final private int BLOCKS=7;   // decompressing blocks
   16.75 +  static final private int CHECK4=8;   // four check bytes to go
   16.76 +  static final private int CHECK3=9;   // three check bytes to go
   16.77 +  static final private int CHECK2=10;  // two check bytes to go
   16.78 +  static final private int CHECK1=11;  // one check byte to go
   16.79 +  static final private int DONE=12;    // finished check, done
   16.80 +  static final private int BAD=13;     // got an error--stay here
   16.81 +
   16.82 +  static final private int HEAD=14;
   16.83 +  static final private int LENGTH=15;
   16.84 +  static final private int TIME=16;
   16.85 +  static final private int OS=17;
   16.86 +  static final private int EXLEN=18;
   16.87 +  static final private int EXTRA=19;
   16.88 +  static final private int NAME=20;
   16.89 +  static final private int COMMENT=21;
   16.90 +  static final private int HCRC=22;
   16.91 +  static final private int FLAGS=23;
   16.92 +
   16.93 +  int mode;                            // current inflate mode
   16.94 +
   16.95 +  // mode dependent information
   16.96 +  int method;        // if FLAGS, method byte
   16.97 +
   16.98 +  // if CHECK, check values to compare
   16.99 +  long was = -1;           // computed check value
  16.100 +  long need;               // stream check value
  16.101 +
  16.102 +  // if BAD, inflateSync's marker bytes count
  16.103 +  int marker;
  16.104 +
  16.105 +  // mode independent information
  16.106 +  int  wrap;          // flag for no wrapper
  16.107 +  int wbits;            // log2(window size)  (8..15, defaults to 15)
  16.108 +
  16.109 +  InfBlocks blocks;     // current inflate_blocks state
  16.110 +
  16.111 +  private final ZStream z;
  16.112 +
  16.113 +  private int flags; 
  16.114 +
  16.115 +  private int need_bytes = -1;
  16.116 +  private byte[] crcbuf=new byte[4];
  16.117 +
  16.118 +  GZIPHeader gheader = null;
  16.119 +
  16.120 +  int inflateReset(){
  16.121 +    if(z == null) return Z_STREAM_ERROR;
  16.122 +    
  16.123 +    z.total_in = z.total_out = 0;
  16.124 +    z.msg = null;
  16.125 +    this.mode = HEAD;
  16.126 +    this.need_bytes = -1;
  16.127 +    this.blocks.reset();
  16.128 +    return Z_OK;
  16.129 +  }
  16.130 +
  16.131 +  int inflateEnd(){
  16.132 +    if(blocks != null){
  16.133 +      blocks.free();
  16.134 +    }
  16.135 +    return Z_OK;
  16.136 +  }
  16.137 +
  16.138 +  Inflate(ZStream z){
  16.139 +    this.z=z;
  16.140 +  }
  16.141 +
  16.142 +  int inflateInit(int w){
  16.143 +    z.msg = null;
  16.144 +    blocks = null;
  16.145 +
  16.146 +    // handle undocumented wrap option (no zlib header or check)
  16.147 +    wrap = 0;
  16.148 +    if(w < 0){
  16.149 +      w = - w;
  16.150 +    }
  16.151 +    else {
  16.152 +      wrap = (w >> 4) + 1;
  16.153 +      if(w < 48)
  16.154 +        w &= 15;
  16.155 +    }
  16.156 +
  16.157 +    if(w<8 ||w>15){
  16.158 +      inflateEnd();
  16.159 +      return Z_STREAM_ERROR;
  16.160 +    }
  16.161 +    if(blocks != null && wbits != w){
  16.162 +      blocks.free();
  16.163 +      blocks=null;
  16.164 +    }
  16.165 +
  16.166 +    // set window size
  16.167 +    wbits=w;
  16.168 +
  16.169 +    this.blocks=new InfBlocks(z, 1<<w);
  16.170 +
  16.171 +    // reset state
  16.172 +    inflateReset();
  16.173 +
  16.174 +    return Z_OK;
  16.175 +  }
  16.176 +
  16.177 +  int inflate(int f){
  16.178 +    int hold = 0;
  16.179 +
  16.180 +    int r;
  16.181 +    int b;
  16.182 +
  16.183 +    if(z == null || z.next_in == null){
  16.184 +      if(f == Z_FINISH && this.mode==HEAD)
  16.185 +        return Z_OK; 
  16.186 +      return Z_STREAM_ERROR;
  16.187 +    }
  16.188 +
  16.189 +    f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK;
  16.190 +    r = Z_BUF_ERROR;
  16.191 +    while (true){
  16.192 +
  16.193 +      switch (this.mode){
  16.194 +      case HEAD:
  16.195 +        if(wrap==0){
  16.196 +	  this.mode = BLOCKS;
  16.197 +          break;
  16.198 +        } 
  16.199 +
  16.200 +        try { r=readBytes(2, r, f); }
  16.201 +        catch(Return e){ return e.r; }
  16.202 +
  16.203 +        if((wrap&2)!=0 && this.need == 0x8b1fL) {   // gzip header
  16.204 +	  z.adler=new CRC32();
  16.205 +          checksum(2, this.need);
  16.206 +
  16.207 +          if(gheader==null) 
  16.208 +            gheader=new GZIPHeader();
  16.209 +
  16.210 +          this.mode = FLAGS;
  16.211 +          break;
  16.212 +        }
  16.213 +
  16.214 +        flags = 0;
  16.215 +
  16.216 +        this.method = ((int)this.need)&0xff;
  16.217 +        b=((int)(this.need>>8))&0xff;
  16.218 +
  16.219 +        if((wrap&1)==0 ||  // check if zlib header allowed
  16.220 +           (((this.method << 8)+b) % 31)!=0){
  16.221 +          this.mode = BAD;
  16.222 +          z.msg = "incorrect header check";
  16.223 +          // since zlib 1.2, it is allowted to inflateSync for this case.
  16.224 +          /*
  16.225 +          this.marker = 5;       // can't try inflateSync
  16.226 +          */
  16.227 +          break;
  16.228 +        }
  16.229 +
  16.230 +        if((this.method&0xf)!=Z_DEFLATED){
  16.231 +          this.mode = BAD;
  16.232 +          z.msg="unknown compression method";
  16.233 +          // since zlib 1.2, it is allowted to inflateSync for this case.
  16.234 +	  /*
  16.235 +          this.marker = 5;       // can't try inflateSync
  16.236 +	  */
  16.237 +          break;
  16.238 +        }
  16.239 +
  16.240 +        if((this.method>>4)+8>this.wbits){
  16.241 +          this.mode = BAD;
  16.242 +          z.msg="invalid window size";
  16.243 +          // since zlib 1.2, it is allowted to inflateSync for this case.
  16.244 +	  /*
  16.245 +          this.marker = 5;       // can't try inflateSync
  16.246 +	  */
  16.247 +          break;
  16.248 +        }
  16.249 +
  16.250 +        z.adler=new Adler32();
  16.251 +
  16.252 +        if((b&PRESET_DICT)==0){
  16.253 +          this.mode = BLOCKS;
  16.254 +          break;
  16.255 +        }
  16.256 +        this.mode = DICT4;
  16.257 +      case DICT4:
  16.258 +
  16.259 +        if(z.avail_in==0)return r;r=f;
  16.260 +
  16.261 +        z.avail_in--; z.total_in++;
  16.262 +        this.need=((z.next_in[z.next_in_index++]&0xff)<<24)&0xff000000L;
  16.263 +        this.mode=DICT3;
  16.264 +      case DICT3:
  16.265 +
  16.266 +        if(z.avail_in==0)return r;r=f;
  16.267 +
  16.268 +        z.avail_in--; z.total_in++;
  16.269 +        this.need+=((z.next_in[z.next_in_index++]&0xff)<<16)&0xff0000L;
  16.270 +        this.mode=DICT2;
  16.271 +      case DICT2:
  16.272 +
  16.273 +        if(z.avail_in==0)return r;r=f;
  16.274 +
  16.275 +        z.avail_in--; z.total_in++;
  16.276 +        this.need+=((z.next_in[z.next_in_index++]&0xff)<<8)&0xff00L;
  16.277 +        this.mode=DICT1;
  16.278 +      case DICT1:
  16.279 +
  16.280 +        if(z.avail_in==0)return r;r=f;
  16.281 +
  16.282 +        z.avail_in--; z.total_in++;
  16.283 +        this.need += (z.next_in[z.next_in_index++]&0xffL);
  16.284 +        z.adler.reset(this.need);
  16.285 +        this.mode = DICT0;
  16.286 +        return Z_NEED_DICT;
  16.287 +      case DICT0:
  16.288 +        this.mode = BAD;
  16.289 +        z.msg = "need dictionary";
  16.290 +        this.marker = 0;       // can try inflateSync
  16.291 +        return Z_STREAM_ERROR;
  16.292 +      case BLOCKS:
  16.293 +        r = this.blocks.proc(r);
  16.294 +        if(r == Z_DATA_ERROR){
  16.295 +          this.mode = BAD;
  16.296 +          this.marker = 0;     // can try inflateSync
  16.297 +          break;
  16.298 +        }
  16.299 +        if(r == Z_OK){
  16.300 +          r = f;
  16.301 +        }
  16.302 +        if(r != Z_STREAM_END){
  16.303 +          return r;
  16.304 +        }
  16.305 +        r = f;
  16.306 +        this.was=z.adler.getValue();
  16.307 +        this.blocks.reset();
  16.308 +        if(this.wrap==0){
  16.309 +          this.mode=DONE;
  16.310 +          break;
  16.311 +        }
  16.312 +        this.mode=CHECK4;
  16.313 +      case CHECK4:
  16.314 +
  16.315 +        if(z.avail_in==0)return r;r=f;
  16.316 +
  16.317 +        z.avail_in--; z.total_in++;
  16.318 +        this.need=((z.next_in[z.next_in_index++]&0xff)<<24)&0xff000000L;
  16.319 +        this.mode=CHECK3;
  16.320 +      case CHECK3:
  16.321 +
  16.322 +        if(z.avail_in==0)return r;r=f;
  16.323 +
  16.324 +        z.avail_in--; z.total_in++;
  16.325 +        this.need+=((z.next_in[z.next_in_index++]&0xff)<<16)&0xff0000L;
  16.326 +        this.mode = CHECK2;
  16.327 +      case CHECK2:
  16.328 +
  16.329 +        if(z.avail_in==0)return r;r=f;
  16.330 +
  16.331 +        z.avail_in--; z.total_in++;
  16.332 +        this.need+=((z.next_in[z.next_in_index++]&0xff)<<8)&0xff00L;
  16.333 +        this.mode = CHECK1;
  16.334 +      case CHECK1:
  16.335 +
  16.336 +        if(z.avail_in==0)return r;r=f;
  16.337 +
  16.338 +        z.avail_in--; z.total_in++;
  16.339 +        this.need+=(z.next_in[z.next_in_index++]&0xffL);
  16.340 +
  16.341 +        if(flags!=0){  // gzip
  16.342 +          this.need = ((this.need&0xff000000)>>24 | 
  16.343 +                          (this.need&0x00ff0000)>>8 | 
  16.344 +                          (this.need&0x0000ff00)<<8 | 
  16.345 +                          (this.need&0x0000ffff)<<24)&0xffffffffL;
  16.346 +        }
  16.347 +
  16.348 +        if(((int)(this.was)) != ((int)(this.need))){
  16.349 +          z.msg = "incorrect data check";
  16.350 +          // chack is delayed
  16.351 +          /*
  16.352 +          this.mode = BAD;
  16.353 +          this.marker = 5;       // can't try inflateSync
  16.354 +          break;
  16.355 +	  */
  16.356 +        }
  16.357 +        else if(flags!=0 && gheader!=null){
  16.358 +          gheader.crc = this.need; 
  16.359 +        }
  16.360 +
  16.361 +        this.mode = LENGTH;
  16.362 +      case LENGTH:
  16.363 +        if (wrap!=0 && flags!=0) {
  16.364 +
  16.365 +          try { r=readBytes(4, r, f); }
  16.366 +          catch(Return e){ return e.r; }
  16.367 +
  16.368 +          if(z.msg!=null && z.msg.equals("incorrect data check")){
  16.369 +            this.mode = BAD;
  16.370 +            this.marker = 5;       // can't try inflateSync
  16.371 +            break;
  16.372 +          }
  16.373 +
  16.374 +          if (this.need != (z.total_out & 0xffffffffL)) {
  16.375 +            z.msg = "incorrect length check";
  16.376 +            this.mode = BAD;
  16.377 +            break;
  16.378 +          }
  16.379 +          z.msg = null;
  16.380 +        }
  16.381 +        else {
  16.382 +          if(z.msg!=null && z.msg.equals("incorrect data check")){
  16.383 +            this.mode = BAD;
  16.384 +            this.marker = 5;       // can't try inflateSync
  16.385 +            break;
  16.386 +          }
  16.387 +        }
  16.388 +
  16.389 +        this.mode = DONE;
  16.390 +      case DONE:
  16.391 +        return Z_STREAM_END;
  16.392 +      case BAD:
  16.393 +        return Z_DATA_ERROR;
  16.394 +
  16.395 +      case FLAGS:
  16.396 +
  16.397 +        try { r=readBytes(2, r, f); }
  16.398 +        catch(Return e){ return e.r; }
  16.399 +
  16.400 +        flags = ((int)this.need)&0xffff;
  16.401 +
  16.402 +        if ((flags & 0xff) != Z_DEFLATED) {
  16.403 +          z.msg = "unknown compression method";
  16.404 +          this.mode = BAD; 
  16.405 +          break;
  16.406 +        }
  16.407 +        if ((flags & 0xe000)!=0) {
  16.408 +          z.msg = "unknown header flags set";
  16.409 +          this.mode = BAD; 
  16.410 +          break;
  16.411 +        }
  16.412 +
  16.413 +        if ((flags & 0x0200)!=0){
  16.414 +          checksum(2, this.need);
  16.415 +        } 
  16.416 +
  16.417 +        this.mode = TIME;
  16.418 +
  16.419 +      case TIME:
  16.420 +        try { r=readBytes(4, r, f); }
  16.421 +        catch(Return e){ return e.r; }
  16.422 +        if(gheader!=null)
  16.423 +          gheader.time = this.need;
  16.424 +        if ((flags & 0x0200)!=0){
  16.425 +          checksum(4, this.need);
  16.426 +        }
  16.427 +        this.mode = OS;
  16.428 +      case OS:
  16.429 +        try { r=readBytes(2, r, f); }
  16.430 +        catch(Return e){ return e.r; }
  16.431 +        if(gheader!=null){
  16.432 +          gheader.xflags = ((int)this.need)&0xff;
  16.433 +          gheader.os = (((int)this.need)>>8)&0xff;
  16.434 +        }
  16.435 +        if ((flags & 0x0200)!=0){
  16.436 +          checksum(2, this.need);
  16.437 +        }
  16.438 +        this.mode = EXLEN;
  16.439 +      case EXLEN:
  16.440 +        if ((flags & 0x0400)!=0) {
  16.441 +          try { r=readBytes(2, r, f); }
  16.442 +          catch(Return e){ return e.r; }
  16.443 +          if(gheader!=null){
  16.444 +            gheader.extra = new byte[((int)this.need)&0xffff];
  16.445 +          }
  16.446 +          if ((flags & 0x0200)!=0){
  16.447 +            checksum(2, this.need);
  16.448 +          }
  16.449 +        }
  16.450 +        else if(gheader!=null){
  16.451 +          gheader.extra=null;
  16.452 +        }
  16.453 +        this.mode = EXTRA;
  16.454 +
  16.455 +      case EXTRA:
  16.456 +        if ((flags & 0x0400)!=0) {
  16.457 +          try { 
  16.458 +            r=readBytes(r, f);
  16.459 +            if(gheader!=null){
  16.460 +              byte[] foo = tmp_array;
  16.461 +              tmp_array=null;
  16.462 +              if(foo.length == gheader.extra.length){
  16.463 +                System.arraycopy(foo, 0, gheader.extra, 0, foo.length);
  16.464 +	      }
  16.465 +              else{
  16.466 +                z.msg = "bad extra field length";
  16.467 +                this.mode = BAD; 
  16.468 +                break;
  16.469 +	      }
  16.470 +            }
  16.471 +          }
  16.472 +          catch(Return e){ return e.r; }
  16.473 +        }
  16.474 +        else if(gheader!=null){
  16.475 +          gheader.extra=null;
  16.476 +	}
  16.477 +	this.mode = NAME;
  16.478 +      case NAME:
  16.479 +	if ((flags & 0x0800)!=0) {
  16.480 +          try { 
  16.481 +            r=readString(r, f);
  16.482 +            if(gheader!=null){
  16.483 +              gheader.name=tmp_array;
  16.484 +            }
  16.485 +            tmp_array=null;
  16.486 +          }
  16.487 +          catch(Return e){ return e.r; }
  16.488 +        }
  16.489 +        else if(gheader!=null){
  16.490 +          gheader.name=null;
  16.491 +	}
  16.492 +        this.mode = COMMENT;
  16.493 +      case COMMENT:
  16.494 +        if ((flags & 0x1000)!=0) {
  16.495 +          try { 
  16.496 +            r=readString(r, f);
  16.497 +            if(gheader!=null){
  16.498 +              gheader.comment=tmp_array;
  16.499 +            }
  16.500 +            tmp_array=null;
  16.501 +          }
  16.502 +          catch(Return e){ return e.r; }
  16.503 +        }
  16.504 +        else if(gheader!=null){
  16.505 +          gheader.comment=null;
  16.506 +	}
  16.507 +        this.mode = HCRC;
  16.508 +      case HCRC:
  16.509 +	if ((flags & 0x0200)!=0) {
  16.510 +          try { r=readBytes(2, r, f); }
  16.511 +          catch(Return e){ return e.r; }
  16.512 +          if(gheader!=null){
  16.513 +            gheader.hcrc=(int)(this.need&0xffff);
  16.514 +          }
  16.515 +          if(this.need != (z.adler.getValue()&0xffffL)){
  16.516 +            this.mode = BAD;
  16.517 +            z.msg = "header crc mismatch";
  16.518 +            this.marker = 5;       // can't try inflateSync
  16.519 +            break;
  16.520 +          }
  16.521 +        }
  16.522 +        z.adler = new CRC32();
  16.523 +
  16.524 +        this.mode = BLOCKS;
  16.525 +        break;
  16.526 +      default:
  16.527 +        return Z_STREAM_ERROR;
  16.528 +      }
  16.529 +    }
  16.530 +  }
  16.531 +
  16.532 +  int inflateSetDictionary(byte[] dictionary, int dictLength){
  16.533 +    if(z==null || (this.mode != DICT0 && this.wrap != 0)){
  16.534 +      return Z_STREAM_ERROR;
  16.535 +    }
  16.536 +
  16.537 +    int index=0;
  16.538 +    int length = dictLength;
  16.539 +
  16.540 +    if(this.mode==DICT0){
  16.541 +      long adler_need=z.adler.getValue();
  16.542 +      z.adler.reset();
  16.543 +      z.adler.update(dictionary, 0, dictLength);
  16.544 +      if(z.adler.getValue()!=adler_need){
  16.545 +        return Z_DATA_ERROR;
  16.546 +      }
  16.547 +    }
  16.548 +
  16.549 +    z.adler.reset();
  16.550 +
  16.551 +    if(length >= (1<<this.wbits)){
  16.552 +      length = (1<<this.wbits)-1;
  16.553 +      index=dictLength - length;
  16.554 +    }
  16.555 +    this.blocks.set_dictionary(dictionary, index, length);
  16.556 +    this.mode = BLOCKS;
  16.557 +    return Z_OK;
  16.558 +  }
  16.559 +
  16.560 +  static private byte[] mark = {(byte)0, (byte)0, (byte)0xff, (byte)0xff};
  16.561 +
  16.562 +  int inflateSync(){
  16.563 +    int n;       // number of bytes to look at
  16.564 +    int p;       // pointer to bytes
  16.565 +    int m;       // number of marker bytes found in a row
  16.566 +    long r, w;   // temporaries to save total_in and total_out
  16.567 +
  16.568 +    // set up
  16.569 +    if(z == null)
  16.570 +      return Z_STREAM_ERROR;
  16.571 +    if(this.mode != BAD){
  16.572 +      this.mode = BAD;
  16.573 +      this.marker = 0;
  16.574 +    }
  16.575 +    if((n=z.avail_in)==0)
  16.576 +      return Z_BUF_ERROR;
  16.577 +
  16.578 +    p=z.next_in_index;
  16.579 +    m=this.marker;
  16.580 +    // search
  16.581 +    while (n!=0 && m < 4){
  16.582 +      if(z.next_in[p] == mark[m]){
  16.583 +        m++;
  16.584 +      }
  16.585 +      else if(z.next_in[p]!=0){
  16.586 +        m = 0;
  16.587 +      }
  16.588 +      else{
  16.589 +        m = 4 - m;
  16.590 +      }
  16.591 +      p++; n--;
  16.592 +    }
  16.593 +
  16.594 +    // restore
  16.595 +    z.total_in += p-z.next_in_index;
  16.596 +    z.next_in_index = p;
  16.597 +    z.avail_in = n;
  16.598 +    this.marker = m;
  16.599 +
  16.600 +    // return no joy or set up to restart on a new block
  16.601 +    if(m != 4){
  16.602 +      return Z_DATA_ERROR;
  16.603 +    }
  16.604 +    r=z.total_in;  w=z.total_out;
  16.605 +    inflateReset();
  16.606 +    z.total_in=r;  z.total_out = w;
  16.607 +    this.mode = BLOCKS;
  16.608 +
  16.609 +    return Z_OK;
  16.610 +  }
  16.611 +
  16.612 +  // Returns true if inflate is currently at the end of a block generated
  16.613 +  // by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
  16.614 +  // implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH
  16.615 +  // but removes the length bytes of the resulting empty stored block. When
  16.616 +  // decompressing, PPP checks that at the end of input packet, inflate is
  16.617 +  // waiting for these length bytes.
  16.618 +  int inflateSyncPoint(){
  16.619 +    if(z == null || this.blocks == null)
  16.620 +      return Z_STREAM_ERROR;
  16.621 +    return this.blocks.sync_point();
  16.622 +  }
  16.623 +
  16.624 +  private int readBytes(int n, int r, int f) throws Return{
  16.625 +    if(need_bytes == -1){
  16.626 +      need_bytes=n;
  16.627 +      this.need=0;
  16.628 +    }
  16.629 +    while(need_bytes>0){
  16.630 +      if(z.avail_in==0){ throw new Return(r); }; r=f;
  16.631 +      z.avail_in--; z.total_in++;
  16.632 +      this.need = this.need | 
  16.633 +	((z.next_in[z.next_in_index++]&0xff)<<((n-need_bytes)*8));
  16.634 +      need_bytes--;
  16.635 +    }
  16.636 +    if(n==2){
  16.637 +      this.need&=0xffffL;
  16.638 +    }
  16.639 +    else if(n==4) {
  16.640 +      this.need&=0xffffffffL;
  16.641 +    }
  16.642 +    need_bytes=-1;
  16.643 +    return r;
  16.644 +  }
  16.645 +  class Return extends Exception{
  16.646 +    int r;
  16.647 +    Return(int r){this.r=r; }
  16.648 +  }
  16.649 +
  16.650 +  private byte[] tmp_array;
  16.651 +  private int readString(int r, int f) throws Return{
  16.652 +    int b=0; 
  16.653 +    byte[] arr = new byte[4092];
  16.654 +    int at = 0;
  16.655 +    do {
  16.656 +      if(z.avail_in==0){ throw new Return(r); }; r=f;
  16.657 +      z.avail_in--; z.total_in++;
  16.658 +      b = z.next_in[z.next_in_index];
  16.659 +      if(b!=0) arr = append(arr, z.next_in[z.next_in_index], at++);
  16.660 +      z.adler.update(z.next_in, z.next_in_index, 1);
  16.661 +      z.next_in_index++;
  16.662 +    }while(b!=0);
  16.663 +    
  16.664 +    tmp_array = copy(arr, at);
  16.665 +    
  16.666 +    return r;
  16.667 +  }
  16.668 +
  16.669 +  private int readBytes(int r, int f) throws Return{
  16.670 +    int b=0; 
  16.671 +    byte[] arr = new byte[4092];
  16.672 +    int at = 0;
  16.673 +    while(this.need>0){
  16.674 +      if(z.avail_in==0){ throw new Return(r); }; r=f;
  16.675 +      z.avail_in--; z.total_in++;
  16.676 +      b = z.next_in[z.next_in_index];
  16.677 +      arr = append(arr, z.next_in[z.next_in_index], at++);
  16.678 +      z.adler.update(z.next_in, z.next_in_index, 1);
  16.679 +      z.next_in_index++;
  16.680 +      this.need--;
  16.681 +    }
  16.682 +    
  16.683 +    tmp_array = copy(arr, at);
  16.684 +    
  16.685 +    return r;
  16.686 +  }
  16.687 +  
  16.688 +  private static byte[] copy(byte[] arr, int len) {
  16.689 +      byte[] ret = new byte[len];
  16.690 +      org.apidesign.bck2brwsr.emul.lang.System.arraycopy(arr, 0, ret, 0, len);
  16.691 +      return ret;
  16.692 +  }
  16.693 +  private static byte[] append(byte[] arr, byte b, int index) {
  16.694 +      arr[index] = b;
  16.695 +      return arr;
  16.696 +  }
  16.697 +
  16.698 +  private void checksum(int n, long v){
  16.699 +    for(int i=0; i<n; i++){
  16.700 +      crcbuf[i]=(byte)(v&0xff);
  16.701 +      v>>=8;
  16.702 +    }
  16.703 +    z.adler.update(crcbuf, 0, n);
  16.704 +  }
  16.705 +
  16.706 +  public GZIPHeader getGZIPHeader(){
  16.707 +    return gheader;
  16.708 +  }
  16.709 +
  16.710 +  boolean inParsingHeader(){
  16.711 +    switch(mode){
  16.712 +      case HEAD:
  16.713 +      case DICT4:
  16.714 +      case DICT3:
  16.715 +      case DICT2:
  16.716 +      case DICT1:
  16.717 +      case FLAGS:
  16.718 +      case TIME:
  16.719 +      case OS:
  16.720 +      case EXLEN:
  16.721 +      case EXTRA:
  16.722 +      case NAME:
  16.723 +      case COMMENT:
  16.724 +      case HCRC:
  16.725 +	return true;
  16.726 +      default:
  16.727 +	return false;
  16.728 +    }
  16.729 +  }
  16.730 +}
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/Inflater.java	Thu Feb 07 12:58:12 2013 +0100
    17.3 @@ -0,0 +1,338 @@
    17.4 +/*
    17.5 + * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
    17.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    17.7 + *
    17.8 + * This code is free software; you can redistribute it and/or modify it
    17.9 + * under the terms of the GNU General Public License version 2 only, as
   17.10 + * published by the Free Software Foundation.  Oracle designates this
   17.11 + * particular file as subject to the "Classpath" exception as provided
   17.12 + * by Oracle in the LICENSE file that accompanied this code.
   17.13 + *
   17.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   17.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   17.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   17.17 + * version 2 for more details (a copy is included in the LICENSE file that
   17.18 + * accompanied this code).
   17.19 + *
   17.20 + * You should have received a copy of the GNU General Public License version
   17.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   17.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   17.23 + *
   17.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   17.25 + * or visit www.oracle.com if you need additional information or have any
   17.26 + * questions.
   17.27 + */
   17.28 +
   17.29 +package org.apidesign.bck2brwsr.emul.zip;
   17.30 +
   17.31 +import java.util.zip.*;
   17.32 +import java.io.IOException;
   17.33 +
   17.34 +/**
   17.35 + * This class provides support for general purpose decompression using the
   17.36 + * popular ZLIB compression library. The ZLIB compression library was
   17.37 + * initially developed as part of the PNG graphics standard and is not
   17.38 + * protected by patents. It is fully described in the specifications at
   17.39 + * the <a href="package-summary.html#package_description">java.util.zip
   17.40 + * package description</a>.
   17.41 + *
   17.42 + * <p>The following code fragment demonstrates a trivial compression
   17.43 + * and decompression of a string using <tt>Deflater</tt> and
   17.44 + * <tt>Inflater</tt>.
   17.45 + *
   17.46 + * <blockquote><pre>
   17.47 + * try {
   17.48 + *     // Encode a String into bytes
   17.49 + *     String inputString = "blahblahblah\u20AC\u20AC";
   17.50 + *     byte[] input = inputString.getBytes("UTF-8");
   17.51 + *
   17.52 + *     // Compress the bytes
   17.53 + *     byte[] output = new byte[100];
   17.54 + *     Deflater compresser = new Deflater();
   17.55 + *     compresser.setInput(input);
   17.56 + *     compresser.finish();
   17.57 + *     int compressedDataLength = compresser.deflate(output);
   17.58 + *
   17.59 + *     // Decompress the bytes
   17.60 + *     Inflater decompresser = new Inflater();
   17.61 + *     decompresser.setInput(output, 0, compressedDataLength);
   17.62 + *     byte[] result = new byte[100];
   17.63 + *     int resultLength = decompresser.inflate(result);
   17.64 + *     decompresser.end();
   17.65 + *
   17.66 + *     // Decode the bytes into a String
   17.67 + *     String outputString = new String(result, 0, resultLength, "UTF-8");
   17.68 + * } catch(java.io.UnsupportedEncodingException ex) {
   17.69 + *     // handle
   17.70 + * } catch (java.util.zip.DataFormatException ex) {
   17.71 + *     // handle
   17.72 + * }
   17.73 + * </pre></blockquote>
   17.74 + *
   17.75 + * @see         Deflater
   17.76 + * @author      David Connelly
   17.77 + *
   17.78 + */
   17.79 +public
   17.80 +class Inflater extends java.util.zip.Inflater {
   17.81 +    private final boolean nowrap;
   17.82 +    private JzLibInflater impl;
   17.83 +    
   17.84 +    /**
   17.85 +     * Creates a new decompressor. If the parameter 'nowrap' is true then
   17.86 +     * the ZLIB header and checksum fields will not be used. This provides
   17.87 +     * compatibility with the compression format used by both GZIP and PKZIP.
   17.88 +     * <p>
   17.89 +     * Note: When using the 'nowrap' option it is also necessary to provide
   17.90 +     * an extra "dummy" byte as input. This is required by the ZLIB native
   17.91 +     * library in order to support certain optimizations.
   17.92 +     *
   17.93 +     * @param nowrap if true then support GZIP compatible compression
   17.94 +     */
   17.95 +    public Inflater(boolean nowrap) {
   17.96 +        this.nowrap = nowrap;
   17.97 +        reset();
   17.98 +    }
   17.99 +
  17.100 +    /**
  17.101 +     * Creates a new decompressor.
  17.102 +     */
  17.103 +    public Inflater() {
  17.104 +        this(false);
  17.105 +    }
  17.106 +
  17.107 +    /**
  17.108 +     * Sets input data for decompression. Should be called whenever
  17.109 +     * needsInput() returns true indicating that more input data is
  17.110 +     * required.
  17.111 +     * @param b the input data bytes
  17.112 +     * @param off the start offset of the input data
  17.113 +     * @param len the length of the input data
  17.114 +     * @see Inflater#needsInput
  17.115 +     */
  17.116 +    public void setInput(byte[] b, int off, int len) {
  17.117 +        if (b == null) {
  17.118 +            throw new NullPointerException();
  17.119 +        }
  17.120 +        if (off < 0 || len < 0 || off > b.length - len) {
  17.121 +            throw new ArrayIndexOutOfBoundsException();
  17.122 +        }
  17.123 +        impl.setInput(b, off, len, false);
  17.124 +    }
  17.125 +
  17.126 +    /**
  17.127 +     * Sets input data for decompression. Should be called whenever
  17.128 +     * needsInput() returns true indicating that more input data is
  17.129 +     * required.
  17.130 +     * @param b the input data bytes
  17.131 +     * @see Inflater#needsInput
  17.132 +     */
  17.133 +    public void setInput(byte[] b) {
  17.134 +        setInput(b, 0, b.length);
  17.135 +    }
  17.136 +
  17.137 +    /**
  17.138 +     * Sets the preset dictionary to the given array of bytes. Should be
  17.139 +     * called when inflate() returns 0 and needsDictionary() returns true
  17.140 +     * indicating that a preset dictionary is required. The method getAdler()
  17.141 +     * can be used to get the Adler-32 value of the dictionary needed.
  17.142 +     * @param b the dictionary data bytes
  17.143 +     * @param off the start offset of the data
  17.144 +     * @param len the length of the data
  17.145 +     * @see Inflater#needsDictionary
  17.146 +     * @see Inflater#getAdler
  17.147 +     */
  17.148 +    public void setDictionary(byte[] b, int off, int len) {
  17.149 +        if (b == null) {
  17.150 +            throw new NullPointerException();
  17.151 +        }
  17.152 +        if (off < 0 || len < 0 || off > b.length - len) {
  17.153 +            throw new ArrayIndexOutOfBoundsException();
  17.154 +        }
  17.155 +        byte[] arr;
  17.156 +        if (off == 0) {
  17.157 +            arr = b;
  17.158 +        } else {
  17.159 +            arr = new byte[len];
  17.160 +            org.apidesign.bck2brwsr.emul.lang.System.arraycopy(b, off, arr, 0, len);
  17.161 +        }
  17.162 +        impl.setDictionary(arr, len);
  17.163 +    }
  17.164 +
  17.165 +    /**
  17.166 +     * Sets the preset dictionary to the given array of bytes. Should be
  17.167 +     * called when inflate() returns 0 and needsDictionary() returns true
  17.168 +     * indicating that a preset dictionary is required. The method getAdler()
  17.169 +     * can be used to get the Adler-32 value of the dictionary needed.
  17.170 +     * @param b the dictionary data bytes
  17.171 +     * @see Inflater#needsDictionary
  17.172 +     * @see Inflater#getAdler
  17.173 +     */
  17.174 +    public void setDictionary(byte[] b) {
  17.175 +        impl.setDictionary(b, b.length);
  17.176 +    }
  17.177 +
  17.178 +    /**
  17.179 +     * Returns the total number of bytes remaining in the input buffer.
  17.180 +     * This can be used to find out what bytes still remain in the input
  17.181 +     * buffer after decompression has finished.
  17.182 +     * @return the total number of bytes remaining in the input buffer
  17.183 +     */
  17.184 +    public int getRemaining() {
  17.185 +        return impl.getAvailIn();
  17.186 +    }
  17.187 +
  17.188 +    /**
  17.189 +     * Returns true if no data remains in the input buffer. This can
  17.190 +     * be used to determine if #setInput should be called in order
  17.191 +     * to provide more input.
  17.192 +     * @return true if no data remains in the input buffer
  17.193 +     */
  17.194 +    public boolean needsInput() {
  17.195 +        return getRemaining() <= 0;
  17.196 +    }
  17.197 +
  17.198 +    /**
  17.199 +     * Returns true if a preset dictionary is needed for decompression.
  17.200 +     * @return true if a preset dictionary is needed for decompression
  17.201 +     * @see Inflater#setDictionary
  17.202 +     */
  17.203 +    public boolean needsDictionary() {
  17.204 +        return impl.needDict();
  17.205 +    }
  17.206 +
  17.207 +    /**
  17.208 +     * Returns true if the end of the compressed data stream has been
  17.209 +     * reached.
  17.210 +     * @return true if the end of the compressed data stream has been
  17.211 +     * reached
  17.212 +     */
  17.213 +    public boolean finished() {
  17.214 +        return impl.finished();
  17.215 +    }
  17.216 +
  17.217 +    /**
  17.218 +     * Uncompresses bytes into specified buffer. Returns actual number
  17.219 +     * of bytes uncompressed. A return value of 0 indicates that
  17.220 +     * needsInput() or needsDictionary() should be called in order to
  17.221 +     * determine if more input data or a preset dictionary is required.
  17.222 +     * In the latter case, getAdler() can be used to get the Adler-32
  17.223 +     * value of the dictionary required.
  17.224 +     * @param b the buffer for the uncompressed data
  17.225 +     * @param off the start offset of the data
  17.226 +     * @param len the maximum number of uncompressed bytes
  17.227 +     * @return the actual number of uncompressed bytes
  17.228 +     * @exception DataFormatException if the compressed data format is invalid
  17.229 +     * @see Inflater#needsInput
  17.230 +     * @see Inflater#needsDictionary
  17.231 +     */
  17.232 +    public int inflate(byte[] b, int off, int len)
  17.233 +        throws DataFormatException
  17.234 +    {
  17.235 +        if (b == null) {
  17.236 +            throw new NullPointerException();
  17.237 +        }
  17.238 +        if (off < 0 || len < 0 || off > b.length - len) {
  17.239 +            throw new ArrayIndexOutOfBoundsException();
  17.240 +        }
  17.241 +        impl.setOutput(b, off, len);
  17.242 +        int err = impl.inflate(JzLibInflater.Z_NO_FLUSH);
  17.243 +        return impl.next_out_index - off;
  17.244 +    }
  17.245 +
  17.246 +    /**
  17.247 +     * Uncompresses bytes into specified buffer. Returns actual number
  17.248 +     * of bytes uncompressed. A return value of 0 indicates that
  17.249 +     * needsInput() or needsDictionary() should be called in order to
  17.250 +     * determine if more input data or a preset dictionary is required.
  17.251 +     * In the latter case, getAdler() can be used to get the Adler-32
  17.252 +     * value of the dictionary required.
  17.253 +     * @param b the buffer for the uncompressed data
  17.254 +     * @return the actual number of uncompressed bytes
  17.255 +     * @exception DataFormatException if the compressed data format is invalid
  17.256 +     * @see Inflater#needsInput
  17.257 +     * @see Inflater#needsDictionary
  17.258 +     */
  17.259 +    public int inflate(byte[] b) throws DataFormatException {
  17.260 +        return inflate(b, 0, b.length);
  17.261 +    }
  17.262 +
  17.263 +    /**
  17.264 +     * Returns the ADLER-32 value of the uncompressed data.
  17.265 +     * @return the ADLER-32 value of the uncompressed data
  17.266 +     */
  17.267 +    public int getAdler() {
  17.268 +        return (int) impl.getAdler();
  17.269 +    }
  17.270 +
  17.271 +    /**
  17.272 +     * Returns the total number of compressed bytes input so far.
  17.273 +     *
  17.274 +     * <p>Since the number of bytes may be greater than
  17.275 +     * Integer.MAX_VALUE, the {@link #getBytesRead()} method is now
  17.276 +     * the preferred means of obtaining this information.</p>
  17.277 +     *
  17.278 +     * @return the total number of compressed bytes input so far
  17.279 +     */
  17.280 +    public int getTotalIn() {
  17.281 +        return (int) getBytesRead();
  17.282 +    }
  17.283 +
  17.284 +    /**
  17.285 +     * Returns the total number of compressed bytes input so far.</p>
  17.286 +     *
  17.287 +     * @return the total (non-negative) number of compressed bytes input so far
  17.288 +     * @since 1.5
  17.289 +     */
  17.290 +    public long getBytesRead() {
  17.291 +        return impl.total_in;
  17.292 +    }
  17.293 +
  17.294 +    /**
  17.295 +     * Returns the total number of uncompressed bytes output so far.
  17.296 +     *
  17.297 +     * <p>Since the number of bytes may be greater than
  17.298 +     * Integer.MAX_VALUE, the {@link #getBytesWritten()} method is now
  17.299 +     * the preferred means of obtaining this information.</p>
  17.300 +     *
  17.301 +     * @return the total number of uncompressed bytes output so far
  17.302 +     */
  17.303 +    public int getTotalOut() {
  17.304 +        return (int) getBytesWritten();
  17.305 +    }
  17.306 +
  17.307 +    /**
  17.308 +     * Returns the total number of uncompressed bytes output so far.</p>
  17.309 +     *
  17.310 +     * @return the total (non-negative) number of uncompressed bytes output so far
  17.311 +     * @since 1.5
  17.312 +     */
  17.313 +    public long getBytesWritten() {
  17.314 +        return impl.total_out;
  17.315 +    }
  17.316 +
  17.317 +    /**
  17.318 +     * Resets inflater so that a new set of input data can be processed.
  17.319 +     */
  17.320 +    public void reset() {
  17.321 +        impl = new JzLibInflater(15, nowrap);
  17.322 +    }
  17.323 +
  17.324 +    /**
  17.325 +     * Closes the decompressor and discards any unprocessed input.
  17.326 +     * This method should be called when the decompressor is no longer
  17.327 +     * being used, but will also be called automatically by the finalize()
  17.328 +     * method. Once this method is called, the behavior of the Inflater
  17.329 +     * object is undefined.
  17.330 +     */
  17.331 +    public void end() {
  17.332 +        impl.end();
  17.333 +    }
  17.334 +
  17.335 +    /**
  17.336 +     * Closes the decompressor when garbage is collected.
  17.337 +     */
  17.338 +    protected void finalize() {
  17.339 +        end();
  17.340 +    }
  17.341 +}
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/JzLibInflater.java	Thu Feb 07 12:58:12 2013 +0100
    18.3 @@ -0,0 +1,137 @@
    18.4 +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
    18.5 +/*
    18.6 +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved.
    18.7 +
    18.8 +Redistribution and use in source and binary forms, with or without
    18.9 +modification, are permitted provided that the following conditions are met:
   18.10 +
   18.11 +  1. Redistributions of source code must retain the above copyright notice,
   18.12 +     this list of conditions and the following disclaimer.
   18.13 +
   18.14 +  2. Redistributions in binary form must reproduce the above copyright 
   18.15 +     notice, this list of conditions and the following disclaimer in 
   18.16 +     the documentation and/or other materials provided with the distribution.
   18.17 +
   18.18 +  3. The names of the authors may not be used to endorse or promote products
   18.19 +     derived from this software without specific prior written permission.
   18.20 +
   18.21 +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   18.22 +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   18.23 +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
   18.24 +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
   18.25 +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   18.26 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
   18.27 +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   18.28 +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   18.29 +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
   18.30 +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   18.31 + */
   18.32 +/*
   18.33 + * This program is based on zlib-1.1.3, so all credit should go authors
   18.34 + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
   18.35 + * and contributors of zlib.
   18.36 + */
   18.37 +
   18.38 +package org.apidesign.bck2brwsr.emul.zip;
   18.39 +
   18.40 +final class JzLibInflater extends ZStream{
   18.41 +
   18.42 +  static final private int MAX_WBITS=15;        // 32K LZ77 window
   18.43 +  static final private int DEF_WBITS=MAX_WBITS;
   18.44 +
   18.45 +  public static final int Z_NO_FLUSH=0;
   18.46 +  static final private int Z_PARTIAL_FLUSH=1;
   18.47 +  static final private int Z_SYNC_FLUSH=2;
   18.48 +  static final private int Z_FULL_FLUSH=3;
   18.49 +  static final private int Z_FINISH=4;
   18.50 +
   18.51 +  static final private int MAX_MEM_LEVEL=9;
   18.52 +
   18.53 +  static final private int Z_OK=0;
   18.54 +  static final private int Z_STREAM_END=1;
   18.55 +  static final private int Z_NEED_DICT=2;
   18.56 +  static final private int Z_ERRNO=-1;
   18.57 +  static final private int Z_STREAM_ERROR=-2;
   18.58 +  static final private int Z_DATA_ERROR=-3;
   18.59 +  static final private int Z_MEM_ERROR=-4;
   18.60 +  static final private int Z_BUF_ERROR=-5;
   18.61 +  static final private int Z_VERSION_ERROR=-6;
   18.62 +
   18.63 +  public JzLibInflater() {
   18.64 +    super();
   18.65 +    init();
   18.66 +  }
   18.67 +
   18.68 +  public JzLibInflater(int w)  {
   18.69 +    this(w, false);
   18.70 +  }
   18.71 +
   18.72 +  public JzLibInflater(int w, boolean nowrap)  {
   18.73 +    super();
   18.74 +    int ret = init(w, nowrap);
   18.75 +    if(ret!=Z_OK)
   18.76 +      throw new IllegalStateException(ret+": "+msg);
   18.77 +  }
   18.78 +
   18.79 +  private boolean finished = false;
   18.80 +
   18.81 +  public int init(){
   18.82 +    return init(DEF_WBITS);
   18.83 +  }
   18.84 +
   18.85 +  public int init(boolean nowrap){
   18.86 +    return init(DEF_WBITS, nowrap);
   18.87 +  }
   18.88 +
   18.89 +  public int init(int w){
   18.90 +    return init(w, false);
   18.91 +  }
   18.92 +
   18.93 +  public int init(int w, boolean nowrap){
   18.94 +    finished = false;
   18.95 +    istate=new Inflate(this);
   18.96 +    return istate.inflateInit(nowrap?-w:w);
   18.97 +  }
   18.98 +
   18.99 +  public int inflate(int f){
  18.100 +    if(istate==null) return Z_STREAM_ERROR;
  18.101 +    int ret = istate.inflate(f);
  18.102 +    if(ret == Z_STREAM_END) 
  18.103 +      finished = true;
  18.104 +    return ret;
  18.105 +  }
  18.106 +
  18.107 +  public int end(){
  18.108 +    finished = true;
  18.109 +    if(istate==null) return Z_STREAM_ERROR;
  18.110 +    int ret=istate.inflateEnd();
  18.111 +//    istate = null;
  18.112 +    return ret;
  18.113 +  }
  18.114 +
  18.115 +  public int sync(){
  18.116 +    if(istate == null)
  18.117 +      return Z_STREAM_ERROR;
  18.118 +    return istate.inflateSync();
  18.119 +  }
  18.120 +
  18.121 +  public int syncPoint(){
  18.122 +    if(istate == null)
  18.123 +      return Z_STREAM_ERROR;
  18.124 +    return istate.inflateSyncPoint();
  18.125 +  }
  18.126 +
  18.127 +  public int setDictionary(byte[] dictionary, int dictLength){
  18.128 +    if(istate == null)
  18.129 +      return Z_STREAM_ERROR;
  18.130 +    return istate.inflateSetDictionary(dictionary, dictLength);
  18.131 +  }
  18.132 +
  18.133 +  public boolean finished(){
  18.134 +    return istate.mode==12 /*DONE*/;
  18.135 +  }
  18.136 +
  18.137 +  public boolean needDict() {
  18.138 +    return istate == null ? false : istate.mode == Inflate.DICT0;
  18.139 +  }
  18.140 +}
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/ZStream.java	Thu Feb 07 12:58:12 2013 +0100
    19.3 @@ -0,0 +1,253 @@
    19.4 +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
    19.5 +/*
    19.6 +Copyright (c) 2000-2011 ymnk, JCraft,Inc. All rights reserved.
    19.7 +
    19.8 +Redistribution and use in source and binary forms, with or without
    19.9 +modification, are permitted provided that the following conditions are met:
   19.10 +
   19.11 +  1. Redistributions of source code must retain the above copyright notice,
   19.12 +     this list of conditions and the following disclaimer.
   19.13 +
   19.14 +  2. Redistributions in binary form must reproduce the above copyright 
   19.15 +     notice, this list of conditions and the following disclaimer in 
   19.16 +     the documentation and/or other materials provided with the distribution.
   19.17 +
   19.18 +  3. The names of the authors may not be used to endorse or promote products
   19.19 +     derived from this software without specific prior written permission.
   19.20 +
   19.21 +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   19.22 +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   19.23 +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
   19.24 +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
   19.25 +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   19.26 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
   19.27 +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   19.28 +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   19.29 +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
   19.30 +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   19.31 + */
   19.32 +/*
   19.33 + * This program is based on zlib-1.1.3, so all credit should go authors
   19.34 + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
   19.35 + * and contributors of zlib.
   19.36 + */
   19.37 +
   19.38 +package org.apidesign.bck2brwsr.emul.zip;
   19.39 +
   19.40 +import org.apidesign.bck2brwsr.emul.lang.System;
   19.41 +
   19.42 +/**
   19.43 + * ZStream
   19.44 + *
   19.45 + * @deprecated  Not for public use in the future.
   19.46 + */
   19.47 +@Deprecated
   19.48 +class ZStream{
   19.49 +
   19.50 +  static final private int MAX_WBITS=15;        // 32K LZ77 window
   19.51 +  static final private int DEF_WBITS=MAX_WBITS;
   19.52 +
   19.53 +  static final private int Z_NO_FLUSH=0;
   19.54 +  static final private int Z_PARTIAL_FLUSH=1;
   19.55 +  static final private int Z_SYNC_FLUSH=2;
   19.56 +  static final private int Z_FULL_FLUSH=3;
   19.57 +  static final private int Z_FINISH=4;
   19.58 +
   19.59 +  static final private int MAX_MEM_LEVEL=9;
   19.60 +
   19.61 +  static final private int Z_OK=0;
   19.62 +  static final private int Z_STREAM_END=1;
   19.63 +  static final private int Z_NEED_DICT=2;
   19.64 +  static final private int Z_ERRNO=-1;
   19.65 +  static final private int Z_STREAM_ERROR=-2;
   19.66 +  static final private int Z_DATA_ERROR=-3;
   19.67 +  static final private int Z_MEM_ERROR=-4;
   19.68 +  static final private int Z_BUF_ERROR=-5;
   19.69 +  static final private int Z_VERSION_ERROR=-6;
   19.70 +
   19.71 +  public byte[] next_in;     // next input byte
   19.72 +  public int next_in_index;
   19.73 +  public int avail_in;       // number of bytes available at next_in
   19.74 +  public long total_in;      // total nb of input bytes read so far
   19.75 +
   19.76 +  public byte[] next_out;    // next output byte should be put there
   19.77 +  public int next_out_index;
   19.78 +  public int avail_out;      // remaining free space at next_out
   19.79 +  public long total_out;     // total nb of bytes output so far
   19.80 +
   19.81 +  public String msg;
   19.82 +
   19.83 +  Inflate istate; 
   19.84 +
   19.85 +  int data_type; // best guess about the data type: ascii or binary
   19.86 +
   19.87 +  Checksum adler;
   19.88 +
   19.89 +  public ZStream(){
   19.90 +    this(new Adler32());
   19.91 +  }
   19.92 +
   19.93 +  public ZStream(Checksum adler){
   19.94 +    this.adler=adler;
   19.95 +  }
   19.96 +
   19.97 +  public int inflateInit(){
   19.98 +    return inflateInit(DEF_WBITS);
   19.99 +  }
  19.100 +  public int inflateInit(boolean nowrap){
  19.101 +    return inflateInit(DEF_WBITS, nowrap);
  19.102 +  }
  19.103 +  public int inflateInit(int w){
  19.104 +    return inflateInit(w, false);
  19.105 +  }
  19.106 +
  19.107 +  public int inflateInit(int w, boolean nowrap){
  19.108 +    istate=new Inflate(this);
  19.109 +    return istate.inflateInit(nowrap?-w:w);
  19.110 +  }
  19.111 +
  19.112 +  public int inflate(int f){
  19.113 +    if(istate==null) return Z_STREAM_ERROR;
  19.114 +    return istate.inflate(f);
  19.115 +  }
  19.116 +  public int inflateEnd(){
  19.117 +    if(istate==null) return Z_STREAM_ERROR;
  19.118 +    int ret=istate.inflateEnd();
  19.119 +//    istate = null;
  19.120 +    return ret;
  19.121 +  }
  19.122 +  
  19.123 +  public int inflateSync(){
  19.124 +    if(istate == null)
  19.125 +      return Z_STREAM_ERROR;
  19.126 +    return istate.inflateSync();
  19.127 +  }
  19.128 +  public int inflateSyncPoint(){
  19.129 +    if(istate == null)
  19.130 +      return Z_STREAM_ERROR;
  19.131 +    return istate.inflateSyncPoint();
  19.132 +  }
  19.133 +  public int inflateSetDictionary(byte[] dictionary, int dictLength){
  19.134 +    if(istate == null)
  19.135 +      return Z_STREAM_ERROR;
  19.136 +    return istate.inflateSetDictionary(dictionary, dictLength);
  19.137 +  }
  19.138 +  public boolean inflateFinished(){
  19.139 +    return istate.mode==12 /*DONE*/;
  19.140 +  }
  19.141 +
  19.142 +
  19.143 +  public long getAdler(){
  19.144 +    return adler.getValue();
  19.145 +  }
  19.146 +
  19.147 +  public void free(){
  19.148 +    next_in=null;
  19.149 +    next_out=null;
  19.150 +    msg=null;
  19.151 +  }
  19.152 +
  19.153 +  public void setOutput(byte[] buf){
  19.154 +    setOutput(buf, 0, buf.length); 
  19.155 +  }
  19.156 +
  19.157 +  public void setOutput(byte[] buf, int off, int len){
  19.158 +    next_out = buf;
  19.159 +    next_out_index = off;
  19.160 +    avail_out = len;
  19.161 +  }
  19.162 +
  19.163 +  public void setInput(byte[] buf){
  19.164 +    setInput(buf, 0, buf.length, false); 
  19.165 +  }
  19.166 +
  19.167 +  public void setInput(byte[] buf, boolean append){
  19.168 +    setInput(buf, 0, buf.length, append); 
  19.169 +  }
  19.170 +
  19.171 +  public void setInput(byte[] buf, int off, int len, boolean append){
  19.172 +    if(len<=0 && append && next_in!=null) return;
  19.173 +
  19.174 +    if(avail_in>0 && append){  
  19.175 +      byte[] tmp = new byte[avail_in+len];
  19.176 +      System.arraycopy(next_in, next_in_index, tmp, 0, avail_in);
  19.177 +      System.arraycopy(buf, off, tmp, avail_in, len);
  19.178 +      next_in=tmp;
  19.179 +      next_in_index=0;
  19.180 +      avail_in+=len;
  19.181 +    }
  19.182 +    else{
  19.183 +      next_in=buf;
  19.184 +      next_in_index=off;
  19.185 +      avail_in=len;
  19.186 +    }
  19.187 +  }
  19.188 +
  19.189 +  public byte[] getNextIn(){
  19.190 +    return next_in;
  19.191 +  }
  19.192 +
  19.193 +  public void setNextIn(byte[] next_in){
  19.194 +    this.next_in = next_in;
  19.195 +  }
  19.196 +
  19.197 +  public int getNextInIndex(){
  19.198 +    return next_in_index;
  19.199 +  }
  19.200 +
  19.201 +  public void setNextInIndex(int next_in_index){
  19.202 +    this.next_in_index = next_in_index;
  19.203 +  }
  19.204 +
  19.205 +  public int getAvailIn(){
  19.206 +    return avail_in;
  19.207 +  }
  19.208 +
  19.209 +  public void setAvailIn(int avail_in){
  19.210 +    this.avail_in = avail_in;
  19.211 +  }
  19.212 +
  19.213 +  public byte[] getNextOut(){
  19.214 +    return next_out;
  19.215 +  }
  19.216 +
  19.217 +  public void setNextOut(byte[] next_out){
  19.218 +    this.next_out = next_out;
  19.219 +  }
  19.220 +
  19.221 +  public int getNextOutIndex(){
  19.222 +    return next_out_index;
  19.223 +  }
  19.224 +
  19.225 +  public void setNextOutIndex(int next_out_index){
  19.226 +    this.next_out_index = next_out_index;
  19.227 +  }
  19.228 +
  19.229 +  public int getAvailOut(){
  19.230 +    return avail_out;
  19.231 +
  19.232 +  }
  19.233 +
  19.234 +  public void setAvailOut(int avail_out){
  19.235 +    this.avail_out = avail_out;
  19.236 +  }
  19.237 +
  19.238 +  public long getTotalOut(){
  19.239 +    return total_out;
  19.240 +  }
  19.241 +
  19.242 +  public long getTotalIn(){
  19.243 +    return total_in;
  19.244 +  }
  19.245 +
  19.246 +  public String getMessage(){
  19.247 +    return msg;
  19.248 +  }
  19.249 +
  19.250 +  /**
  19.251 +   * Those methods are expected to be override by Inflater and Deflater.
  19.252 +   * In the future, they will become abstract methods.
  19.253 +   */ 
  19.254 +  public int end(){ return Z_OK; }
  19.255 +  public boolean finished(){ return false; }
  19.256 +}
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/ZipConstants64.java	Thu Feb 07 12:58:12 2013 +0100
    20.3 @@ -0,0 +1,84 @@
    20.4 +/*
    20.5 + * Copyright (c) 1995, 1996, Oracle and/or its affiliates. All rights reserved.
    20.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    20.7 + *
    20.8 + * This code is free software; you can redistribute it and/or modify it
    20.9 + * under the terms of the GNU General Public License version 2 only, as
   20.10 + * published by the Free Software Foundation.  Oracle designates this
   20.11 + * particular file as subject to the "Classpath" exception as provided
   20.12 + * by Oracle in the LICENSE file that accompanied this code.
   20.13 + *
   20.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   20.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   20.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   20.17 + * version 2 for more details (a copy is included in the LICENSE file that
   20.18 + * accompanied this code).
   20.19 + *
   20.20 + * You should have received a copy of the GNU General Public License version
   20.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   20.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20.23 + *
   20.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   20.25 + * or visit www.oracle.com if you need additional information or have any
   20.26 + * questions.
   20.27 + */
   20.28 +
   20.29 +package org.apidesign.bck2brwsr.emul.zip;
   20.30 +
   20.31 +/*
   20.32 + * This class defines the constants that are used by the classes
   20.33 + * which manipulate Zip64 files.
   20.34 + */
   20.35 +
   20.36 +public class ZipConstants64 {
   20.37 +
   20.38 +    /*
   20.39 +     * ZIP64 constants
   20.40 +     */
   20.41 +    static final long ZIP64_ENDSIG = 0x06064b50L;  // "PK\006\006"
   20.42 +    static final long ZIP64_LOCSIG = 0x07064b50L;  // "PK\006\007"
   20.43 +    static final int  ZIP64_ENDHDR = 56;           // ZIP64 end header size
   20.44 +    static final int  ZIP64_LOCHDR = 20;           // ZIP64 end loc header size
   20.45 +    static final int  ZIP64_EXTHDR = 24;           // EXT header size
   20.46 +    static final int  ZIP64_EXTID  = 0x0001;       // Extra field Zip64 header ID
   20.47 +
   20.48 +    static final int  ZIP64_MAGICCOUNT = 0xFFFF;
   20.49 +    static final long ZIP64_MAGICVAL = 0xFFFFFFFFL;
   20.50 +
   20.51 +    /*
   20.52 +     * Zip64 End of central directory (END) header field offsets
   20.53 +     */
   20.54 +    static final int  ZIP64_ENDLEN = 4;       // size of zip64 end of central dir
   20.55 +    static final int  ZIP64_ENDVEM = 12;      // version made by
   20.56 +    static final int  ZIP64_ENDVER = 14;      // version needed to extract
   20.57 +    static final int  ZIP64_ENDNMD = 16;      // number of this disk
   20.58 +    static final int  ZIP64_ENDDSK = 20;      // disk number of start
   20.59 +    static final int  ZIP64_ENDTOD = 24;      // total number of entries on this disk
   20.60 +    static final int  ZIP64_ENDTOT = 32;      // total number of entries
   20.61 +    static final int  ZIP64_ENDSIZ = 40;      // central directory size in bytes
   20.62 +    static final int  ZIP64_ENDOFF = 48;      // offset of first CEN header
   20.63 +    static final int  ZIP64_ENDEXT = 56;      // zip64 extensible data sector
   20.64 +
   20.65 +    /*
   20.66 +     * Zip64 End of central directory locator field offsets
   20.67 +     */
   20.68 +    static final int  ZIP64_LOCDSK = 4;       // disk number start
   20.69 +    static final int  ZIP64_LOCOFF = 8;       // offset of zip64 end
   20.70 +    static final int  ZIP64_LOCTOT = 16;      // total number of disks
   20.71 +
   20.72 +    /*
   20.73 +     * Zip64 Extra local (EXT) header field offsets
   20.74 +     */
   20.75 +    static final int  ZIP64_EXTCRC = 4;       // uncompressed file crc-32 value
   20.76 +    static final int  ZIP64_EXTSIZ = 8;       // compressed size, 8-byte
   20.77 +    static final int  ZIP64_EXTLEN = 16;      // uncompressed size, 8-byte
   20.78 +
   20.79 +    /*
   20.80 +     * Language encoding flag EFS
   20.81 +     */
   20.82 +    static final int EFS = 0x800;       // If this bit is set the filename and
   20.83 +                                        // comment fields for this file must be
   20.84 +                                        // encoded using UTF-8.
   20.85 +
   20.86 +    private ZipConstants64() {}
   20.87 +}
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/ZipInputStream.java	Thu Feb 07 12:58:12 2013 +0100
    21.3 @@ -0,0 +1,468 @@
    21.4 +/*
    21.5 + * Copyright (c) 1996, 2009, Oracle and/or its affiliates. All rights reserved.
    21.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    21.7 + *
    21.8 + * This code is free software; you can redistribute it and/or modify it
    21.9 + * under the terms of the GNU General Public License version 2 only, as
   21.10 + * published by the Free Software Foundation.  Oracle designates this
   21.11 + * particular file as subject to the "Classpath" exception as provided
   21.12 + * by Oracle in the LICENSE file that accompanied this code.
   21.13 + *
   21.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   21.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   21.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   21.17 + * version 2 for more details (a copy is included in the LICENSE file that
   21.18 + * accompanied this code).
   21.19 + *
   21.20 + * You should have received a copy of the GNU General Public License version
   21.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   21.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   21.23 + *
   21.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   21.25 + * or visit www.oracle.com if you need additional information or have any
   21.26 + * questions.
   21.27 + */
   21.28 +
   21.29 +package org.apidesign.bck2brwsr.emul.zip;
   21.30 +
   21.31 +import java.util.zip.*;
   21.32 +import java.io.InputStream;
   21.33 +import java.io.IOException;
   21.34 +import java.io.EOFException;
   21.35 +import java.io.PushbackInputStream;
   21.36 +import static org.apidesign.bck2brwsr.emul.zip.ZipConstants64.*;
   21.37 +import static java.util.zip.ZipInputStream.*;
   21.38 +
   21.39 +/**
   21.40 + * This class implements an input stream filter for reading files in the
   21.41 + * ZIP file format. Includes support for both compressed and uncompressed
   21.42 + * entries.
   21.43 + *
   21.44 + * @author      David Connelly
   21.45 + */
   21.46 +public
   21.47 +class ZipInputStream extends InflaterInputStream  {
   21.48 +    private ZipEntry entry;
   21.49 +    private int flag;
   21.50 +    private CRC32 crc = new CRC32();
   21.51 +    private long remaining;
   21.52 +    private byte[] tmpbuf = new byte[512];
   21.53 +
   21.54 +    private static final int STORED = ZipEntry.STORED;
   21.55 +    private static final int DEFLATED = ZipEntry.DEFLATED;
   21.56 +
   21.57 +    private boolean closed = false;
   21.58 +    // this flag is set to true after EOF has reached for
   21.59 +    // one entry
   21.60 +    private boolean entryEOF = false;
   21.61 +
   21.62 +    /**
   21.63 +     * Check to make sure that this stream has not been closed
   21.64 +     */
   21.65 +    private void ensureOpen() throws IOException {
   21.66 +        if (closed) {
   21.67 +            throw new IOException("Stream closed");
   21.68 +        }
   21.69 +    }
   21.70 +
   21.71 +    /**
   21.72 +     * Creates a new ZIP input stream.
   21.73 +     *
   21.74 +     * <p>The UTF-8 {@link java.nio.charset.Charset charset} is used to
   21.75 +     * decode the entry names.
   21.76 +     *
   21.77 +     * @param in the actual input stream
   21.78 +     */
   21.79 +    public ZipInputStream(InputStream in) {
   21.80 +//        this(in, "UTF-8");
   21.81 +        super(new PushbackInputStream(in, 512), new Inflater(true), 512);
   21.82 +        //usesDefaultInflater = true;
   21.83 +        if(in == null) {
   21.84 +            throw new NullPointerException("in is null");
   21.85 +        }
   21.86 +    }
   21.87 +
   21.88 +    /**
   21.89 +     * Creates a new ZIP input stream.
   21.90 +     *
   21.91 +     * @param in the actual input stream
   21.92 +     *
   21.93 +     * @param charset
   21.94 +     *        The {@linkplain java.nio.charset.Charset charset} to be
   21.95 +     *        used to decode the ZIP entry name (ignored if the
   21.96 +     *        <a href="package-summary.html#lang_encoding"> language
   21.97 +     *        encoding bit</a> of the ZIP entry's general purpose bit
   21.98 +     *        flag is set).
   21.99 +     *
  21.100 +     * @since 1.7
  21.101 +     *
  21.102 +    public ZipInputStream(InputStream in, Charset charset) {
  21.103 +        super(new PushbackInputStream(in, 512), new Inflater(true), 512);
  21.104 +        usesDefaultInflater = true;
  21.105 +        if(in == null) {
  21.106 +            throw new NullPointerException("in is null");
  21.107 +        }
  21.108 +        if (charset == null)
  21.109 +            throw new NullPointerException("charset is null");
  21.110 +        this.zc = ZipCoder.get(charset);
  21.111 +    }
  21.112 +    */
  21.113 +
  21.114 +    /**
  21.115 +     * Reads the next ZIP file entry and positions the stream at the
  21.116 +     * beginning of the entry data.
  21.117 +     * @return the next ZIP file entry, or null if there are no more entries
  21.118 +     * @exception ZipException if a ZIP file error has occurred
  21.119 +     * @exception IOException if an I/O error has occurred
  21.120 +     */
  21.121 +    public ZipEntry getNextEntry() throws IOException {
  21.122 +        ensureOpen();
  21.123 +        if (entry != null) {
  21.124 +            closeEntry();
  21.125 +        }
  21.126 +        crc.reset();
  21.127 +        inf.reset();
  21.128 +        if ((entry = readLOC()) == null) {
  21.129 +            return null;
  21.130 +        }
  21.131 +        if (entry.getMethod() == STORED) {
  21.132 +            remaining = entry.getSize();
  21.133 +        }
  21.134 +        entryEOF = false;
  21.135 +        return entry;
  21.136 +    }
  21.137 +
  21.138 +    /**
  21.139 +     * Closes the current ZIP entry and positions the stream for reading the
  21.140 +     * next entry.
  21.141 +     * @exception ZipException if a ZIP file error has occurred
  21.142 +     * @exception IOException if an I/O error has occurred
  21.143 +     */
  21.144 +    public void closeEntry() throws IOException {
  21.145 +        ensureOpen();
  21.146 +        while (read(tmpbuf, 0, tmpbuf.length) != -1) ;
  21.147 +        entryEOF = true;
  21.148 +    }
  21.149 +
  21.150 +    /**
  21.151 +     * Returns 0 after EOF has reached for the current entry data,
  21.152 +     * otherwise always return 1.
  21.153 +     * <p>
  21.154 +     * Programs should not count on this method to return the actual number
  21.155 +     * of bytes that could be read without blocking.
  21.156 +     *
  21.157 +     * @return     1 before EOF and 0 after EOF has reached for current entry.
  21.158 +     * @exception  IOException  if an I/O error occurs.
  21.159 +     *
  21.160 +     */
  21.161 +    public int available() throws IOException {
  21.162 +        ensureOpen();
  21.163 +        if (entryEOF) {
  21.164 +            return 0;
  21.165 +        } else {
  21.166 +            return 1;
  21.167 +        }
  21.168 +    }
  21.169 +
  21.170 +    /**
  21.171 +     * Reads from the current ZIP entry into an array of bytes.
  21.172 +     * If <code>len</code> is not zero, the method
  21.173 +     * blocks until some input is available; otherwise, no
  21.174 +     * bytes are read and <code>0</code> is returned.
  21.175 +     * @param b the buffer into which the data is read
  21.176 +     * @param off the start offset in the destination array <code>b</code>
  21.177 +     * @param len the maximum number of bytes read
  21.178 +     * @return the actual number of bytes read, or -1 if the end of the
  21.179 +     *         entry is reached
  21.180 +     * @exception  NullPointerException if <code>b</code> is <code>null</code>.
  21.181 +     * @exception  IndexOutOfBoundsException if <code>off</code> is negative,
  21.182 +     * <code>len</code> is negative, or <code>len</code> is greater than
  21.183 +     * <code>b.length - off</code>
  21.184 +     * @exception ZipException if a ZIP file error has occurred
  21.185 +     * @exception IOException if an I/O error has occurred
  21.186 +     */
  21.187 +    public int read(byte[] b, int off, int len) throws IOException {
  21.188 +        ensureOpen();
  21.189 +        if (off < 0 || len < 0 || off > b.length - len) {
  21.190 +            throw new IndexOutOfBoundsException();
  21.191 +        } else if (len == 0) {
  21.192 +            return 0;
  21.193 +        }
  21.194 +
  21.195 +        if (entry == null) {
  21.196 +            return -1;
  21.197 +        }
  21.198 +        switch (entry.getMethod()) {
  21.199 +        case DEFLATED:
  21.200 +            len = super.read(b, off, len);
  21.201 +            if (len == -1) {
  21.202 +                readEnd(entry);
  21.203 +                entryEOF = true;
  21.204 +                entry = null;
  21.205 +            } else {
  21.206 +                crc.update(b, off, len);
  21.207 +            }
  21.208 +            return len;
  21.209 +        case STORED:
  21.210 +            if (remaining <= 0) {
  21.211 +                entryEOF = true;
  21.212 +                entry = null;
  21.213 +                return -1;
  21.214 +            }
  21.215 +            if (len > remaining) {
  21.216 +                len = (int)remaining;
  21.217 +            }
  21.218 +            len = in.read(b, off, len);
  21.219 +            if (len == -1) {
  21.220 +                throw new ZipException("unexpected EOF");
  21.221 +            }
  21.222 +            crc.update(b, off, len);
  21.223 +            remaining -= len;
  21.224 +            if (remaining == 0 && entry.getCrc() != crc.getValue()) {
  21.225 +                throw new ZipException(
  21.226 +                    "invalid entry CRC (expected 0x" + Long.toHexString(entry.getCrc()) +
  21.227 +                    " but got 0x" + Long.toHexString(crc.getValue()) + ")");
  21.228 +            }
  21.229 +            return len;
  21.230 +        default:
  21.231 +            throw new ZipException("invalid compression method");
  21.232 +        }
  21.233 +    }
  21.234 +
  21.235 +    /**
  21.236 +     * Skips specified number of bytes in the current ZIP entry.
  21.237 +     * @param n the number of bytes to skip
  21.238 +     * @return the actual number of bytes skipped
  21.239 +     * @exception ZipException if a ZIP file error has occurred
  21.240 +     * @exception IOException if an I/O error has occurred
  21.241 +     * @exception IllegalArgumentException if n < 0
  21.242 +     */
  21.243 +    public long skip(long n) throws IOException {
  21.244 +        if (n < 0) {
  21.245 +            throw new IllegalArgumentException("negative skip length");
  21.246 +        }
  21.247 +        ensureOpen();
  21.248 +        int max = (int)Math.min(n, Integer.MAX_VALUE);
  21.249 +        int total = 0;
  21.250 +        while (total < max) {
  21.251 +            int len = max - total;
  21.252 +            if (len > tmpbuf.length) {
  21.253 +                len = tmpbuf.length;
  21.254 +            }
  21.255 +            len = read(tmpbuf, 0, len);
  21.256 +            if (len == -1) {
  21.257 +                entryEOF = true;
  21.258 +                break;
  21.259 +            }
  21.260 +            total += len;
  21.261 +        }
  21.262 +        return total;
  21.263 +    }
  21.264 +
  21.265 +    /**
  21.266 +     * Closes this input stream and releases any system resources associated
  21.267 +     * with the stream.
  21.268 +     * @exception IOException if an I/O error has occurred
  21.269 +     */
  21.270 +    public void close() throws IOException {
  21.271 +        if (!closed) {
  21.272 +            super.close();
  21.273 +            closed = true;
  21.274 +        }
  21.275 +    }
  21.276 +
  21.277 +    private byte[] b = new byte[256];
  21.278 +
  21.279 +    /*
  21.280 +     * Reads local file (LOC) header for next entry.
  21.281 +     */
  21.282 +    private ZipEntry readLOC() throws IOException {
  21.283 +        try {
  21.284 +            readFully(tmpbuf, 0, LOCHDR);
  21.285 +        } catch (EOFException e) {
  21.286 +            return null;
  21.287 +        }
  21.288 +        if (get32(tmpbuf, 0) != LOCSIG) {
  21.289 +            return null;
  21.290 +        }
  21.291 +        // get flag first, we need check EFS.
  21.292 +        flag = get16(tmpbuf, LOCFLG);
  21.293 +        // get the entry name and create the ZipEntry first
  21.294 +        int len = get16(tmpbuf, LOCNAM);
  21.295 +        int blen = b.length;
  21.296 +        if (len > blen) {
  21.297 +            do
  21.298 +                blen = blen * 2;
  21.299 +            while (len > blen);
  21.300 +            b = new byte[blen];
  21.301 +        }
  21.302 +        readFully(b, 0, len);
  21.303 +        // Force to use UTF-8 if the EFS bit is ON, even the cs is NOT UTF-8
  21.304 +        ZipEntry e = createZipEntry(((flag & EFS) != 0)
  21.305 +                                    ? toStringUTF8(b, len)
  21.306 +                                    : toString(b, len));
  21.307 +        // now get the remaining fields for the entry
  21.308 +        if ((flag & 1) == 1) {
  21.309 +            throw new ZipException("encrypted ZIP entry not supported");
  21.310 +        }
  21.311 +        e.setMethod(get16(tmpbuf, LOCHOW));
  21.312 +        e.setTime(get32(tmpbuf, LOCTIM));
  21.313 +        if ((flag & 8) == 8) {
  21.314 +            /* "Data Descriptor" present */
  21.315 +            if (e.getMethod() != DEFLATED) {
  21.316 +                throw new ZipException(
  21.317 +                        "only DEFLATED entries can have EXT descriptor");
  21.318 +            }
  21.319 +        } else {
  21.320 +            e.setCrc(get32(tmpbuf, LOCCRC));
  21.321 +            e.setCompressedSize(get32(tmpbuf, LOCSIZ));
  21.322 +            e.setSize(get32(tmpbuf, LOCLEN));
  21.323 +        }
  21.324 +        len = get16(tmpbuf, LOCEXT);
  21.325 +        if (len > 0) {
  21.326 +            byte[] bb = new byte[len];
  21.327 +            readFully(bb, 0, len);
  21.328 +            e.setExtra(bb);
  21.329 +            // extra fields are in "HeaderID(2)DataSize(2)Data... format
  21.330 +            if (e.getCompressedSize() == ZIP64_MAGICVAL || e.getCompressedSize() == ZIP64_MAGICVAL) {
  21.331 +                int off = 0;
  21.332 +                while (off + 4 < len) {
  21.333 +                    int sz = get16(bb, off + 2);
  21.334 +                    if (get16(bb, off) == ZIP64_EXTID) {
  21.335 +                        off += 4;
  21.336 +                        // LOC extra zip64 entry MUST include BOTH original and
  21.337 +                        // compressed file size fields
  21.338 +                        if (sz < 16 || (off + sz) > len ) {
  21.339 +                            // Invalid zip64 extra fields, simply skip. Even it's
  21.340 +                            // rare, it's possible the entry size happens to be
  21.341 +                            // the magic value and it "accidnetly" has some bytes
  21.342 +                            // in extra match the id.
  21.343 +                            return e;
  21.344 +                        }
  21.345 +                        e.setSize(get64(bb, off));
  21.346 +                        e.setCompressedSize(get64(bb, off + 8));
  21.347 +                        break;
  21.348 +                    }
  21.349 +                    off += (sz + 4);
  21.350 +                }
  21.351 +            }
  21.352 +        }
  21.353 +        return e;
  21.354 +    }
  21.355 +
  21.356 +    /**
  21.357 +     * Creates a new <code>ZipEntry</code> object for the specified
  21.358 +     * entry name.
  21.359 +     *
  21.360 +     * @param name the ZIP file entry name
  21.361 +     * @return the ZipEntry just created
  21.362 +     */
  21.363 +    protected ZipEntry createZipEntry(String name) {
  21.364 +        return new ZipEntry(name);
  21.365 +    }
  21.366 +
  21.367 +    /*
  21.368 +     * Reads end of deflated entry as well as EXT descriptor if present.
  21.369 +     */
  21.370 +    private void readEnd(ZipEntry e) throws IOException {
  21.371 +        int n = inf.getRemaining();
  21.372 +        if (n > 0) {
  21.373 +            ((PushbackInputStream)in).unread(buf, len - n, n);
  21.374 +        }
  21.375 +        if ((flag & 8) == 8) {
  21.376 +            /* "Data Descriptor" present */
  21.377 +            if (inf.getBytesWritten() > ZIP64_MAGICVAL ||
  21.378 +                inf.getBytesRead() > ZIP64_MAGICVAL) {
  21.379 +                // ZIP64 format
  21.380 +                readFully(tmpbuf, 0, ZIP64_EXTHDR);
  21.381 +                long sig = get32(tmpbuf, 0);
  21.382 +                if (sig != EXTSIG) { // no EXTSIG present
  21.383 +                    e.setCrc(sig);
  21.384 +                    e.setCompressedSize(get64(tmpbuf, ZIP64_EXTSIZ - ZIP64_EXTCRC));
  21.385 +                    e.setSize(get64(tmpbuf, ZIP64_EXTLEN - ZIP64_EXTCRC));
  21.386 +                    ((PushbackInputStream)in).unread(
  21.387 +                        tmpbuf, ZIP64_EXTHDR - ZIP64_EXTCRC - 1, ZIP64_EXTCRC);
  21.388 +                } else {
  21.389 +                    e.setCrc(get32(tmpbuf, ZIP64_EXTCRC));
  21.390 +                    e.setCompressedSize(get64(tmpbuf, ZIP64_EXTSIZ));
  21.391 +                    e.setSize(get64(tmpbuf, ZIP64_EXTLEN));
  21.392 +                }
  21.393 +            } else {
  21.394 +                readFully(tmpbuf, 0, EXTHDR);
  21.395 +                long sig = get32(tmpbuf, 0);
  21.396 +                if (sig != EXTSIG) { // no EXTSIG present
  21.397 +                    e.setCrc(sig);
  21.398 +                    e.setCompressedSize(get32(tmpbuf, EXTSIZ - EXTCRC));
  21.399 +                    e.setSize(get32(tmpbuf, EXTLEN - EXTCRC));
  21.400 +                    ((PushbackInputStream)in).unread(
  21.401 +                                               tmpbuf, EXTHDR - EXTCRC - 1, EXTCRC);
  21.402 +                } else {
  21.403 +                    e.setCrc(get32(tmpbuf, EXTCRC));
  21.404 +                    e.setCompressedSize(get32(tmpbuf, EXTSIZ));
  21.405 +                    e.setSize(get32(tmpbuf, EXTLEN));
  21.406 +                }
  21.407 +            }
  21.408 +        }
  21.409 +        if (e.getSize() != inf.getBytesWritten()) {
  21.410 +            throw new ZipException(
  21.411 +                "invalid entry size (expected " + e.getSize() +
  21.412 +                " but got " + inf.getBytesWritten() + " bytes)");
  21.413 +        }
  21.414 +        if (e.getCompressedSize() != inf.getBytesRead()) {
  21.415 +            throw new ZipException(
  21.416 +                "invalid entry compressed size (expected " + e.getCompressedSize() +
  21.417 +                " but got " + inf.getBytesRead() + " bytes)");
  21.418 +        }
  21.419 +        if (e.getCrc() != crc.getValue()) {
  21.420 +            throw new ZipException(
  21.421 +                "invalid entry CRC (expected 0x" + Long.toHexString(e.getCrc()) +
  21.422 +                " but got 0x" + Long.toHexString(crc.getValue()) + ")");
  21.423 +        }
  21.424 +    }
  21.425 +
  21.426 +    /*
  21.427 +     * Reads bytes, blocking until all bytes are read.
  21.428 +     */
  21.429 +    private void readFully(byte[] b, int off, int len) throws IOException {
  21.430 +        while (len > 0) {
  21.431 +            int n = in.read(b, off, len);
  21.432 +            if (n == -1) {
  21.433 +                throw new EOFException();
  21.434 +            }
  21.435 +            off += n;
  21.436 +            len -= n;
  21.437 +        }
  21.438 +    }
  21.439 +
  21.440 +    /*
  21.441 +     * Fetches unsigned 16-bit value from byte array at specified offset.
  21.442 +     * The bytes are assumed to be in Intel (little-endian) byte order.
  21.443 +     */
  21.444 +    private static final int get16(byte b[], int off) {
  21.445 +        return (b[off] & 0xff) | ((b[off+1] & 0xff) << 8);
  21.446 +    }
  21.447 +
  21.448 +    /*
  21.449 +     * Fetches unsigned 32-bit value from byte array at specified offset.
  21.450 +     * The bytes are assumed to be in Intel (little-endian) byte order.
  21.451 +     */
  21.452 +    private static final long get32(byte b[], int off) {
  21.453 +        return (get16(b, off) | ((long)get16(b, off+2) << 16)) & 0xffffffffL;
  21.454 +    }
  21.455 +
  21.456 +    /*
  21.457 +     * Fetches signed 64-bit value from byte array at specified offset.
  21.458 +     * The bytes are assumed to be in Intel (little-endian) byte order.
  21.459 +     */
  21.460 +    private static final long get64(byte b[], int off) {
  21.461 +        return get32(b, off) | (get32(b, off+4) << 32);
  21.462 +    }
  21.463 +
  21.464 +    private static String toStringUTF8(byte[] arr, int len) {
  21.465 +        return new String(arr, 0, len);
  21.466 +    }
  21.467 +    
  21.468 +    private static String toString(byte[] b, int len) {
  21.469 +        return new String(b, 0, len);
  21.470 +    }
  21.471 +}