Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   **** BEGIN LICENSE BLOCK *****
   * Version: EPL 1.0/GPL 2.0/LGPL 2.1
   *
   * The contents of this file are subject to the Eclipse Public
   * License Version 1.0 (the "License"); you may not use this file
   * except in compliance with the License. You may obtain a copy of
   * the License at http://www.eclipse.org/legal/epl-v10.html
   *
  * Software distributed under the License is distributed on an "AS
  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  * implied. See the License for the specific language governing
  * rights and limitations under the License.
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either of the GNU General Public License Version 2 or later (the "GPL"),
  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the EPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the EPL, the GPL or the LGPL.
  ***** END LICENSE BLOCK *****/
 package org.jruby.ext.zlib;
 
 import java.util.List;
 import static org.jruby.CompatVersion.RUBY1_8;
 import static org.jruby.CompatVersion.RUBY1_9;
 
 import org.jruby.Ruby;
 import static org.jruby.runtime.Visibility.PRIVATE;

Author(s):
enebo
 
 @JRubyClass(name = "Zlib::GzipReader", parent = "Zlib::GzipFile", include = "Enumerable")
 public class JZlibRubyGzipReader extends RubyGzipFile {
     @JRubyClass(name = "Zlib::GzipReader::Error", parent = "Zlib::GzipReader")
     public static class Error {}
     
     protected static final ObjectAllocator GZIPREADER_ALLOCATOR = new ObjectAllocator() {
         @Override
         public IRubyObject allocate(Ruby runtimeRubyClass klass) {
         return new JZlibRubyGzipReader(runtimeklass);
         }
     };
 
     @JRubyMethod(name = "new", rest = true, meta = true)
     public static JZlibRubyGzipReader newInstance(IRubyObject recvIRubyObject[] argsBlock block) {
         RubyClass klass = (RubyClassrecv;
         JZlibRubyGzipReader result = (JZlibRubyGzipReaderklass.allocate();
 
         result.callInit(argsblock);
 
         return result;
     }
 
     @JRubyMethod(name = "open", required = 1, optional = 1, meta = true, compat = )
     public static IRubyObject open18(final ThreadContext contextIRubyObject recvIRubyObject[] argsBlock block) {
         Ruby runtime = recv.getRuntime();
         IRubyObject io = Helpers.invoke(contextruntime.getFile(), "open"args[0], runtime.newString("rb"));
 
         JZlibRubyGzipReader gzio = newInstance(recvnew IRubyObject[]{io}, block);
 
         return RubyGzipFile.wrapBlock(contextgzioblock);
     }
 
    @JRubyMethod(name = "open", required = 1, optional = 1, meta = true, compat = )
    public static IRubyObject open19(final ThreadContext contextIRubyObject recvIRubyObject[] argsBlock block) {
        Ruby runtime = recv.getRuntime();
        args[0] = Helpers.invoke(contextruntime.getFile(), "open"args[0], runtime.newString("rb"));
        JZlibRubyGzipReader gzio = newInstance(recvargsblock);
        return RubyGzipFile.wrapBlock(contextgzioblock);
    }
    public JZlibRubyGzipReader(Ruby runtimeRubyClass type) {
        super(runtimetype);
    }
    @JRubyMethod(name = "initialize", visibility = , compat = )
    public IRubyObject initialize(ThreadContext contextIRubyObject stream) {
        Ruby runtime = context.runtime;
         = stream;
        try {
            // don't close realIO
             = new IOInputStream();
             = new GZIPInputStream(, 512, false);
            // JRUBY-4502
            // CRuby expects to parse gzip header in 'new'.
            .readHeader();
        } catch (IOException e) {
            RaiseException re = RubyZlib.newGzipFileError(runtime"not in gzip format");
            if (getRuntime().is1_9()) {
                byte[] input = .getAvailIn();
                if (input != null && input.length > 0) {
                    RubyException rubye = re.getException();
                    rubye.setInstanceVariable("@input"
                            RubyString.newString(runtimenew ByteList(input, 0, input.length)));
                }
            }
            throw re;
        }
         = 0;
         = 0;
         = new BufferedInputStream();
        return this;
    }
    @JRubyMethod(name = "initialize", required = 1, optional = 1, visibility = , compat = )
    public IRubyObject initialize19(ThreadContext contextIRubyObject[] args) {
        Ruby runtime = context.runtime;
        IRubyObject obj = initialize(contextargs[0]);
        IRubyObject opt = context.nil;
        
        if (args.length == 2) {
            opt = args[1];
            if (TypeConverter.checkHashType(runtimeopt).isNil()) {
                throw runtime.newArgumentError(2, 1);
            }
        }
        
        ecopts(contextopt);
        return obj;
    }
    // These methods are here to avoid defining a singleton #path on every instance, as in MRI
    @JRubyMethod(compat = )
    public IRubyObject path(ThreadContext context) {
        return this..callMethod(context"path");
    }
    @JRubyMethod(name = "respond_to?", frame = true, compat = )
    public IRubyObject respond_to(ThreadContext contextIRubyObject name) {
        if (name.asJavaString().equals("path")) {
            return this..callMethod(context"respond_to?"name);
        }
        return Helpers.invokeSuper(contextthisname.);
    }

    
Get position within this stream including that has been read by users calling read + what jzlib may have speculatively read in because of buffering.

Returns:
number of bytes
    private long internalPosition() {
        Inflater inflater = .getInflater();
        return inflater.getTotalIn() + inflater.getAvailIn();
    }
    public IRubyObject rewind(ThreadContext context) {
        Ruby runtime = context.runtime;
        // should invoke seek on realIo...
        .callMethod(context"seek",
                new IRubyObject[]{runtime.newFixnum(-internalPosition()), runtime.newFixnum(.)});
        // ... and then reinitialize
        initialize(context);
        return getRuntime().getNil();
    }
    @JRubyMethod(name = "lineno")
    public IRubyObject lineno() {
        return getRuntime().newFixnum();
    }
    @JRubyMethod(name = "readline", writes = .)
    public IRubyObject readline(ThreadContext context) {
        IRubyObject dst = gets_18(contextnew IRubyObject[0]);
        if (dst.isNil()) {
            throw getRuntime().newEOFError();
        }
        return dst;
    }
    private IRubyObject internalGets(IRubyObject[] argsthrows IOException {
        ByteList sep = ((RubyStringgetRuntime().getGlobalVariables().get("$/")).getByteList();
        int limit = -1;
        switch (args.length) {
            case 0:
                break;
            case 1:
                if (args[0].isNil()) {
                    return readAll();
                }
                IRubyObject tmp = args[0].checkStringType();
                if (tmp.isNil()) {
                    limit = RubyNumeric.fix2int(args[0]);
                } else {
                    sep = tmp.convertToString().getByteList();
                }
                break;
            case 2:
            default:
                limit = RubyNumeric.fix2int(args[1]);
                if (args[0].isNil()) {
                    return readAll(limit);
                }
                sep = args[0].convertToString().getByteList();
                break;
        }
        return internalSepGets(seplimit);
    }
    private IRubyObject internalSepGets(ByteList septhrows IOException {
        return internalSepGets(sep, -1);
    }
    private ByteList newReadByteList() {
        ByteList byteList = new ByteList();
        return byteList;
    }
    private ByteList newReadByteList(int size) {
        ByteList byteList = new ByteList(size);
        return byteList;
    }
    private IRubyObject internalSepGets(ByteList sepint limitthrows IOException {
        ByteList result = newReadByteList();
        if (sep.getRealSize() == 0) sep = .;
        int ce = -1;
        
        while (limit <= 0 || result.length() < limit) {
            int sepOffset = result.length() - sep.getRealSize();
            if (sepOffset >= 0 && result.startsWith(sepsepOffset)) break;
            ce = .read();
            if (ce == -1) break;
            result.append(ce);
        }
        
        if (getRuntime().is1_9()) fixBrokenTrailingCharacter(result);
        // io.available() only returns 0 after EOF is encountered
        // so we need to differentiate between the empty string and EOF
        if (0 == result.length() && -1 == cereturn getRuntime().getNil();
        ++;
         = result.length();
        return newStr(getRuntime(), result);
    }
    @JRubyMethod(name = "gets", optional = 1, writes = ., compat = )
    public IRubyObject gets_18(ThreadContext contextIRubyObject[] args) {
        return gets(contextargs);
    }
    @JRubyMethod(name = "gets", optional = 2, writes = ., compat = )
    public IRubyObject gets(ThreadContext contextIRubyObject[] args) {
        try {
            IRubyObject result = internalGets(args);
            if (!result.isNil()) context.setLastLine(result);
            
            return result;
        } catch (IOException ioe) {
            throw getRuntime().newIOErrorFromException(ioe);
        }
    }
    private final static int BUFF_SIZE = 4096;
    @JRubyMethod(name = "read", optional = 1)
    public IRubyObject read(ThreadContext contextIRubyObject[] args) {
        Ruby runtime = context.runtime;
        try {
            if (args.length == 0 || args[0].isNil()) return readAll();
            int len = RubyNumeric.fix2int(args[0]);
            
            if (len < 0) throw runtime.newArgumentError("negative length " + len + " given");
            if (len > 0) {
                // rb_gzfile_read
                ByteList buf = readSize(len);
                
                if (buf == nullreturn runtime.getNil();
                
                return runtime.newString(buf);
            }
            return RubyString.newEmptyString(runtime);
        } catch (IOException ioe) {
            String m = ioe.getMessage();
            if (m.startsWith("Unexpected end of ZLIB input stream")) {
                throw RubyZlib.newGzipFileError(runtimeioe.getMessage());
            } else if (m.startsWith("footer is not found")) {
                throw RubyZlib.newNoFooter(runtime"footer is not found");
            } else if (m.startsWith("incorrect data check")) {
                throw RubyZlib.newCRCError(runtime"invalid compressed data -- crc error");
            } else if (m.startsWith("incorrect length check")) {
                throw RubyZlib.newLengthError(runtime"invalid compressed data -- length error");
            } else {
                throw RubyZlib.newDataError(runtimeioe.getMessage());
            }
        }
    }
    @JRubyMethod(name = "readpartial", required = 1, optional = 1)
    public IRubyObject readpartial(IRubyObject[] args) {
        try {
            int len = RubyNumeric.fix2int(args[0]);
            if (len < 0) {
                throw getRuntime().newArgumentError("negative length " + len + " given");
            }
            if (args.length > 1) {
                if (!(args[1] instanceof RubyString)) {
                    throw getRuntime().newTypeError(
                            "wrong argument type " + args[1].getMetaClass().getName()
                            + " (expected String)");
                }
                return readPartial(len, (RubyStringargs[1]);
            }
            return readPartial(lennull);
        } catch (IOException ioe) {
            throw getRuntime().newIOErrorFromException(ioe);
        }
    }
    private IRubyObject readPartial(int lenRubyString outbufthrows IOException {
        ByteList val = newReadByteList(10);
        byte[] buffer = new byte[len];
        int read = .read(buffer, 0, len);
        if (read == -1) {
            return getRuntime().getNil();
        }
        val.append(buffer, 0, read);
        this. += val.length();
        if (outbuf != null) {
            outbuf.view(val);
        }
        return newStr(getRuntime(), val);
    }
    private IRubyObject readAll() throws IOException {
        return readAll(-1);
    }
    private IRubyObject readAll(int limitthrows IOException {
        ByteList val = newReadByteList(10);
        int rest = limit == -1 ?  : limit;
        byte[] buffer = new byte[rest];
        
        while (rest > 0) {
            int read = .read(buffer, 0, rest);
            if (read == -1) break;
            val.append(buffer, 0, read);
            if (limit != -1) rest -= read;
        }
        
        if (getRuntime().is1_9()) fixBrokenTrailingCharacter(val);
        
        this. += val.length();
        return newStr(getRuntime(), val);
    }
    // FIXME: I think offset == 0 should return empty bytelist and not null
    // mri: gzfile_read
    // This returns a bucket of bytes trying to read length bytes.
    private ByteList readSize(int lengththrows IOException {
        byte[] buffer = new byte[length];
        int toRead = length;
        int offset = 0;
        while (toRead > 0) {
            int read = .read(bufferoffsettoRead);
            
            if (read == -1) {
                if (offset == 0) return null// we're at EOF right away
                break;
            }
            
            toRead -= read;
            offset += read;
        } // hmm...
        this. += length - toRead;
        return new ByteList(buffer, 0, length - toReadfalse);
    }
    @JRubyMethod(name = "lineno=", required = 1)
    public IRubyObject set_lineno(IRubyObject lineArg) {
         = RubyNumeric.fix2int(lineArg);
        return lineArg;
    }
    @JRubyMethod(name = {"pos""tell"})
    public IRubyObject pos() {
        return RubyNumeric.int2fix(getRuntime(), );
    }
    @JRubyMethod(name = "readchar")
    public IRubyObject readchar() {
        try {
            int value = .read();
            if (value == -1) throw getRuntime().newEOFError();
            ++;
            
            return getRuntime().newFixnum(value);
        } catch (IOException ioe) {
            throw getRuntime().newIOErrorFromException(ioe);
        }
    }
    @JRubyMethod(name = {"getc""getbyte"}, compat = )
    public IRubyObject getc() {
        try {
            int value = .read();
            if (value == -1) return getRuntime().getNil();
            ++;
            
            return getRuntime().newFixnum(value);
        } catch (IOException ioe) {
            throw getRuntime().newIOErrorFromException(ioe);
        }
    }
    @JRubyMethod(name = "getbyte", compat = )
    public IRubyObject getbyte() {
        return getc();
    }
    @JRubyMethod(name = "getc", compat = )
    public IRubyObject getc_19() {
        try {
            int value = .read();
            if (value == -1) return getRuntime().getNil();
            ++;
            // TODO: must handle encoding. Move encoding handling methods to util class from RubyIO and use it.
            // TODO: StringIO needs a love, too.
            return getRuntime().newString("" + (char) (value & 0xFF));
        } catch (IOException ioe) {
            throw getRuntime().newIOErrorFromException(ioe);
        }
    }
    private boolean isEof() throws IOException {
        if (.available() == 0) return true;
        // Java's GZIPInputStream behavior is such
        // that it says that more bytes available even
        // when we are right before the EOF, but not yet
        // encountered the actual EOF during the reading.
        // So, we compensate for that to provide MRI
        // compatible behavior.
        .mark(16);
        .read();
        .reset();
        return .available() == 0;
    }
    @Override
    @JRubyMethod(name = "close")
    public IRubyObject close() {
        if (!) {
            try {
                
We call internal IO#close directly, not via IOInputStream#close. IOInputStream#close directly invoke IO.getOutputStream().close() for IO object instead of just calling IO#cloase of Ruby. It causes EBADF at OpenFile#finalize. CAUTION: bufferedStream.close() will not cause 'IO.getOutputStream().close()', becase 'false' has been given as third augument in constructing GZIPInputStream. TODO: implement this without IOInputStream? Not so hard.
                .close();
                if (.respondsTo("close")) {
                    .callMethod(.getRuntime().getCurrentContext(), "close");
                }
            } catch (IOException ioe) {
                throw getRuntime().newIOErrorFromException(ioe);
            }
        }
        this. = true;
        return getRuntime().getNil();
    }
    @JRubyMethod(name = "eof")
    public IRubyObject eof() {
        try {
            return isEof() ? getRuntime().getTrue() : getRuntime().getFalse();
        } catch (IOException ioe) {
            throw getRuntime().newIOErrorFromException(ioe);
        }
    }
    @JRubyMethod(name = "eof?")
    public IRubyObject eof_p() {
        return eof();
    }
    public IRubyObject unused() {
        byte[] tmp = .getAvailIn();
        
        if (tmp == nullreturn getRuntime().getNil();
        return RubyString.newString(getRuntime(), tmp);
    }
    @Override
    public IRubyObject crc() {
        long crc = 0;
        try {
            crc = .getCRC();
        } catch (GZIPException e) {
        }
        return getRuntime().newFixnum(crc);
    }
    @Override
    public IRubyObject os_code() {
        int os = .getOS();
        
        if (os == 255) os = (byte) 0x0b; // NTFS filesystem (NT), because CRuby's test_zlib expect it.
        
        return getRuntime().newFixnum(os & 0xff);
    }
    @Override
    public IRubyObject orig_name() {
        String name = .getName();
         = getRuntime().newString(name);
        return super.orig_name();
    }
    @Override
    public IRubyObject comment() {
        String comment = .getComment();
         = getRuntime().newString(comment);
        return super.comment();
    }
    @JRubyMethod(optional = 1)
    public IRubyObject each(ThreadContext contextIRubyObject[] argsBlock block) {
        ByteList sep = ((RubyStringgetRuntime().getGlobalVariables().get("$/")).getByteList();
        if (args.length > 0 && !args[0].isNil()) {
            sep = args[0].convertToString().getByteList();
        }
        try {
            for (IRubyObject result = internalSepGets(sep); !result.isNil(); result = internalSepGets(sep)) {
                block.yield(contextresult);
            }
        } catch (IOException ioe) {
            throw getRuntime().newIOErrorFromException(ioe);
        }
        return getRuntime().getNil();
    }
    @JRubyMethod(optional = 1)
    public IRubyObject each_line(ThreadContext contextIRubyObject[] argsBlock block) {
        return each(contextargsblock);
    }
    public IRubyObject ungetc(IRubyObject arg) {
        return getRuntime().getNil();
    }
    @JRubyMethod(optional = 1)
    public IRubyObject readlines(ThreadContext contextIRubyObject[] args) {
        List<IRubyObjectarray = new ArrayList<IRubyObject>();
        if (args.length != 0 && args[0].isNil()) {
            array.add(read(contextnew IRubyObject[0]));
        } else {
            ByteList sep = ((RubyStringgetRuntime().getGlobalVariables().get("$/")).getByteList();
            if (args.length > 0) sep = args[0].convertToString().getByteList();
            try {
                for (IRubyObject result = internalSepGets(sep); !result.isNil(); result = internalSepGets(sep)) {
                    array.add(result);
                }
            } catch (IOException ioe) {
                throw getRuntime().newIOErrorFromException(ioe);
            }
        }
        return getRuntime().newArray(array);
    }
    public IRubyObject each_byte(ThreadContext contextBlock block) {
        try {
            int value = .read();
            while (value != -1) {
                ++;
                block.yield(contextgetRuntime().newFixnum(value));
                value = .read();
            }
        } catch (IOException ioe) {
            throw getRuntime().newIOErrorFromException(ioe);
        }
        return getRuntime().getNil();
    }
    private void fixBrokenTrailingCharacter(ByteList resultthrows IOException {
        // fix broken trailing character
        int extraBytes = StringSupport.bytesToFixBrokenTrailingCharacter(result.getUnsafeBytes(), result.getBegin(), result.getRealSize(), getReadEncoding(), result.length());
        for (int i = 0; i < extraBytesi++) {
            int read = .read();
            if (read == -1) break;
            
            result.append(read);
        }
    }
    private int line = 0;
    private long position = 0;
    private IOInputStream ioInputStream;
    private GZIPInputStream io;
    private InputStream bufferedStream;