Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
BEGIN LICENSE BLOCK ***** Version: CPL 1.0/GPL 2.0/LGPL 2.1 The contents of this file are subject to the Common 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/cpl-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. Copyright (C) 2002-2004 Anders Bengtsson <ndrsbngtssn@yahoo.se> Copyright (C) 2002-2004 Jan Arne Petersen <jpetersen@uni-bonn.de> Copyright (C) 2004 Thomas E Enebo <enebo@acm.org> Copyright (C) 2004 Stefan Matthias Aust <sma@3plus4.de> Copyright (C) 2007 Ola Bini <ola@ologix.com> Copyright (C) 2008-2009 Joseph LaFata <joe@quibb.org> 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 CPL, 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 CPL, the GPL or the LGPL. END LICENSE BLOCK ***
 
 package org.jruby;
 
 import java.io.File;
 import static org.jruby.RubyEnumerator.enumeratorize;
 
 import static org.jruby.CompatVersion.*;
 
 public class RubyArgsFile {
     private static final class ArgsFileData {
         private final Ruby runtime;
         public ArgsFileData(Ruby runtime) {
             this. = runtime;
             this. = runtime.getNil();
         }
 
         public IRubyObject currentFile;
         public int currentLineNumber;
         public int minLineNumber;
         private boolean inited = false;
         public int next_p = 0;
 
         public boolean next_argv(ThreadContext context) {
             RubyArray args = (RubyArray).getGlobalVariables().get("$*");
             if (!) {
                 if (args.getLength() > 0) {
                      = 1;
                 } else {
                      = -1;
                 }
                  = true;
                  = 0;
             }
 
             if ( == 1) {
                  = 0;
                 if (args.getLength() > 0) {
                     IRubyObject arg = args.shift(context);
                     RubyString filename = (RubyString)((RubyObject)arg).to_s();
                     ByteList filenameBytes = filename.getByteList();
                     if (!filename.op_equal(context, (RubyString.getGlobalVariables().get("$FILENAME")).isTrue()) {
                         .defineReadonlyVariable("$FILENAME"filename);
                     }
 
                     if (filenameBytes.length() == 1 && filenameBytes.get(0) == '-') {
                          = .getGlobalVariables().get("$stdin");
                     } else {
                          = RubyFile.open(context.getFile(), new IRubyObject[]{filename}, .);
                         String extension = .getInstanceConfig().getInPlaceBackupExtension();
                         if (extension != null) {
                             if (.) {
                                 inplaceEditWindows(contextfilename.asJavaString(), extension);
                             } else {
                                 inplaceEdit(contextfilename.asJavaString(), extension);
                             }
                         }
                          = ;
                         .callMethod(context"lineno="context.runtime.newFixnum());
                    }
                } else {
                     = 1;
                    return false;
                }
            } else if ( == -1) {
                 = .getGlobalVariables().get("$stdin");
                if(!.getGlobalVariables().get("$FILENAME").asJavaString().equals("-")) {
                    .defineReadonlyVariable("$FILENAME".newString("-"));
                }
            }
            return true;
        }
        public static ArgsFileData getDataFrom(IRubyObject recv) {
            ArgsFileData data = (ArgsFileData)recv.dataGetStruct();
            if (data == null) {
                data = new ArgsFileData(recv.getRuntime());
                recv.dataWrapStruct(data);
            }
            return data;
        }
        private void createNewFile(File file) {
            try {
                file.createNewFile();
            } catch (IOException ex) {
                throw .newIOErrorFromException(ex);
            }
        }
        private void inplaceEditWindows(ThreadContext contextString filenameString extensionthrows RaiseException {
            File file = new File(filename);
            if (!extension.equals("")) {
                String backup = filename + extension;
                File backupFile = new File(backup);
                ((RubyIO).close(); // we can't rename a file while it's open in windows
                backupFile.delete();
                file.renameTo(backupFile);
                 = RubyFile.open(context.getFile(), //reopen
                        new IRubyObject[]{.newString(backup)}, .);
            } else {
                throw .newIOError("Windows doesn't support inplace editing without a backup");
            }
            createNewFile(file);
            .getGlobalVariables().set("$stdout", RubyFile.open(context.getFile(),
                    new IRubyObject[]{.newString(filename), .newString("w")}, .));
        }
        private void inplaceEdit(ThreadContext contextString filenameString extensionthrows RaiseException {
            File file = new File(filename);
            FileStat stat = .getPosix().stat(filename);
            if (!extension.equals("")) {
                file.renameTo(new File(filename + extension));
            } else {
                file.delete();
            }
            createNewFile(file);
            .getPosix().chmod(filenamestat.mode());
            .getPosix().chown(filenamestat.uid(), stat.gid());
            .getGlobalVariables().set("$stdout", (RubyIO) RubyFile.open(context.getFile(),
                    new IRubyObject[]{.newString(filename), .newString("w")}, .));
        }
    }    
    
    public static void setCurrentLineNumber(IRubyObject recvint newLineNumber) {
        ArgsFileData data = ArgsFileData.getDataFrom(recv);
        if (data != null) {
            data.currentLineNumber = newLineNumber;
        }
    }
    public static void initArgsFile(final Ruby runtime) {
        RubyObject argsFile = new RubyObject(runtimeruntime.getObject());
        runtime.getEnumerable().extend_object(argsFile);
        runtime.setArgsFile(argsFile);
        runtime.getGlobalVariables().defineReadonly("$<"new IAccessor() {
            public IRubyObject getValue() {
                return runtime.getArgsFile();
            }
            public IRubyObject setValue(IRubyObject newValue) {
                throw new UnsupportedOperationException("Not supported yet.");
            }
        });
        runtime.defineGlobalConstant("ARGF"argsFile);
        
        RubyClass argfClass = argsFile.getMetaClass();
        argfClass.defineAnnotatedMethods(RubyArgsFile.class);
        runtime.defineReadonlyVariable("$FILENAME"runtime.newString("-"));
    }
    @JRubyMethod(name = {"fileno""to_i"})
    public static IRubyObject fileno(ThreadContext contextIRubyObject recv) {
        return ((RubyIOgetData(contextrecv"no stream").).fileno(context);
    }
    @JRubyMethod(name = "to_io")
    public static IRubyObject to_io(ThreadContext contextIRubyObject recv) {
        return getData(contextrecv"no stream").;
    }
    private static IRubyObject argf_getline(ThreadContext contextIRubyObject recvIRubyObject[] args) {
        ArgsFileData data = ArgsFileData.getDataFrom(recv);
        boolean retry = true;
        IRubyObject line = null;
        while(retry) {
            retry = false;
            if (!data.next_argv(context)) {
                return context.runtime.getNil();
            }
            line = data.currentFile.callMethod(context"gets"args);
            if (line.isNil() && data.next_p != -1) {
                argf_close(contextdata.currentFile);
                data.next_p = 1;
                retry = true;
            }
        }
        if (!line.isNil()) {
            context.runtime.setCurrentLine(data.currentLineNumber);
        }
        return line;
    }
    // ARGF methods

    
Read a line.
    @JRubyMethod(name = "gets", optional = 1)
    public static IRubyObject gets(ThreadContext contextIRubyObject recvIRubyObject[] args) {
        ArgsFileData data = ArgsFileData.getDataFrom(recv);
        if(!data.next_argv(context)) {
            return context.runtime.getNil();
        }
        IRubyObject line;
        if (!(data.currentFile instanceof RubyIO)) {
            line = data.currentFile.callMethod(context"gets"args);
        } else {
            line = argf_getline(contextrecvargs);
        }
        context.getCurrentScope().setLastLine(line);
        context.runtime.getGlobalVariables().set("$_"line);
        
        return line;
    }
    
    
Read a line.
    @JRubyMethod(name = "readline", optional = 1)
    public static IRubyObject readline(ThreadContext contextIRubyObject recvIRubyObject[] args) {
        IRubyObject line = gets(contextrecvargs);
        if (line.isNil()) {
            throw context.runtime.newEOFError();
        }
        
        return line;
    }
    @JRubyMethod(optional = 1)
    public static IRubyObject readlines(ThreadContext contextIRubyObject recvIRubyObject[] args) {
        ArgsFileData data = ArgsFileData.getDataFrom(recv);
        Ruby runtime = context.runtime;
        
        if (!data.next_argv(context)) {
            return runtime.is1_9() ? runtime.newEmptyArray() : runtime.getNil();
        }
        if (!(data.currentFile instanceof RubyIO)) {
            return data.currentFile.callMethod(context"readlines"args);
        }
        
        RubyArray ary = runtime.newArray();
        IRubyObject line;
        while(!(line = argf_getline(contextrecvargs)).isNil()) {
            ary.append(line);
        }
        return ary;
    }
    @JRubyMethod(optional = 1)
    public static IRubyObject to_a(ThreadContext contextIRubyObject recvIRubyObject[] args) {
        ArgsFileData data = ArgsFileData.getDataFrom(recv);
        Ruby runtime = context.runtime;
        
        if (!data.next_argv(context)) {
            return runtime.is1_9() ? runtime.newEmptyArray() : runtime.getNil();
        }
        if (!(data.currentFile instanceof RubyIO)) {
            return data.currentFile.callMethod(context"to_a"args);
        }
        
        RubyArray ary = runtime.newArray();
        IRubyObject line;
        while(!(line = argf_getline(contextrecvargs)).isNil()) {
            ary.append(line);
        }
        return ary;
    }
    
    public static IRubyObject each_byte(ThreadContext contextIRubyObject recvBlock block) {
        IRubyObject bt;
        while(!(bt = getc(contextrecv)).isNil()) {
            block.yield(contextbt);
        }
        return recv;
    }
    @JRubyMethod(optional = 1)
    public static IRubyObject each_byte(final ThreadContext contextIRubyObject recvIRubyObject[] argsfinal Block block) {
        return block.isGiven() ? each_byte(contextrecvblock) : enumeratorize(context.runtimerecv"each_byte");
    }
    @JRubyMethod(optional = 1)
    public static IRubyObject bytes(final ThreadContext contextIRubyObject recvIRubyObject[] argsfinal Block block) {
        return block.isGiven() ? each_byte(contextrecvblock) : enumeratorize(context.runtimerecv"bytes");
    }
    public static IRubyObject each_char(final ThreadContext contextIRubyObject recvBlock block) {
        return block.isGiven() ? each_charCommon(contextrecvblock) : enumeratorize(context.runtimerecv"each_char");
    }
    public static IRubyObject chars(final ThreadContext contextIRubyObject recvBlock block) {
        return block.isGiven() ? each_charCommon(contextrecvblock) : enumeratorize(context.runtimerecv"chars");
    }
    public static IRubyObject each_charCommon(ThreadContext contextIRubyObject recvBlock block) {
        ArgsFileData data = ArgsFileData.getDataFrom(recv);
        Ruby runtime = context.runtime;
        IRubyObject ch;
        while(!(ch = getc(contextrecv)).isNil()) {
            boolean cont = true;
            while(cont) {
                cont = false;
                byte c = (byte)RubyNumeric.fix2int(ch);
                int n = runtime.getKCode().getEncoding().length(c);
                IRubyObject file = data.currentFile;
                RubyString str = runtime.newString();
                str.setTaint(true);
                str.cat(c);
                while(--n > 0) {
                    if((ch = getc(contextrecv)).isNil()) {
                        block.yield(contextstr);
                        return recv;
                    }
                    if (data.currentFile != file) {
                        block.yield(contextstr);
                        cont = true;
                        continue;
                    }
                    c = (byte)RubyNumeric.fix2int(ch);
                    str.cat(c);
                }
                block.yield(contextstr);
            }
        }
        return recv;
    }

    
Invoke a block for each line.
    @JRubyMethod(name = {"each_line""each"}, optional = 1)
    public static IRubyObject each_line(ThreadContext contextIRubyObject recvIRubyObject[] argsBlock block) {
        if (!block.isGiven()) return RubyEnumerator.enumeratorize(context.runtimerecv"each_line");
        ArgsFileData data = ArgsFileData.getDataFrom(recv);
        if (!data.next_argv(context)) {
            return context.runtime.getNil();
        }
        if (!(data.currentFile instanceof RubyIO)) {
            if (!data.next_argv(context)) return recv;
            data.currentFile.callMethod(context"each"new IRubyObject[0], block);
            data.next_p = 1;
        }
        IRubyObject str;
        while(!(str = argf_getline(contextrecvargs)).isNil()) {
        	block.yield(contextstr);
        }
        
        return recv;
    }
    @JRubyMethod(name = "each_line", optional = 1, compat = )
    public static IRubyObject each_line19(final ThreadContext contextIRubyObject recvIRubyObject[] argsfinal Block block) {
        return block.isGiven() ? each_line(contextrecvargsblock) : enumeratorize(context.runtimerecv"each_line"args);
    }
    @JRubyMethod(name = "each", optional = 1, compat = )
    public static IRubyObject each19(final ThreadContext contextIRubyObject recvIRubyObject[] argsfinal Block block) {
        return block.isGiven() ? each_line(contextrecvargsblock) : enumeratorize(context.runtimerecv"each"args);
    }
    @JRubyMethod(name = "file")
    public static IRubyObject file(ThreadContext contextIRubyObject recv) {
        ArgsFileData data = ArgsFileData.getDataFrom(recv);
        data.next_argv(context);
        return data.currentFile;
    }
    @JRubyMethod(name = "skip")
    public static IRubyObject skip(IRubyObject recv) {
        ArgsFileData data = ArgsFileData.getDataFrom(recv);
        if (data.next_p != -1) {
            argf_close(recv.getRuntime().getCurrentContext(), data.currentFile);
            data.next_p = 1;
        }
        return recv;
    }
    public static void argf_close(ThreadContext contextIRubyObject file) {
        if(file instanceof RubyIO) {
            ((RubyIO)file).close2(context.runtime);
        } else {
            file.callMethod(context"close");
        }
    }
    @JRubyMethod(name = "close")
    public static IRubyObject close(ThreadContext contextIRubyObject recv) {
        ArgsFileData data = ArgsFileData.getDataFrom(recv);
        data.next_argv(context);
        if (isClosed(contextdata.currentFile)) {
            throw context.runtime.newIOError("closed stream");
        }
        
        argf_close(contextdata.currentFile);
        if (data.next_p != -1) data.next_p = 1;
        data.currentLineNumber = 0;
        return recv;
    }
    @JRubyMethod(name = "closed?")
    public static IRubyObject closed_p(ThreadContext contextIRubyObject recv) {
        ArgsFileData data = ArgsFileData.getDataFrom(recv);
        data.next_argv(context);
        return RubyBoolean.newBoolean(context.runtimeisClosed(contextdata.currentFile));
    }
    
    private static boolean isClosed(ThreadContext contextIRubyObject currentFile) {
        boolean closed = false;
        if (!(currentFile instanceof RubyIO)) {
            closed = currentFile.callMethod(context"closed?").isTrue();
        } else {
            closed = ((RubyIO)currentFile).closed_p(context).isTrue();
        }
        return closed;
    }
    @JRubyMethod(name = "binmode")
    public static IRubyObject binmode(ThreadContext contextIRubyObject recv) {
        ArgsFileData data = getData(contextrecv"no stream");
        
        ((RubyIO)data.currentFile).binmode();
        return recv;
    }
    
    @JRubyMethod(name = "binmode?", compat = .)
    public static IRubyObject op_binmode(ThreadContext contextIRubyObject recv) {
        ArgsFileData data = getData(contextrecv"no stream");
        
        return ((RubyIO)data.currentFile).op_binmode(context);
    }
    @JRubyMethod(name = "lineno")
    public static IRubyObject lineno(ThreadContext contextIRubyObject recv) {
        return recv.getRuntime().newFixnum(ArgsFileData.getDataFrom(recv).);
    }
    @JRubyMethod(name = "lineno=")
    public static IRubyObject lineno_set(ThreadContext contextIRubyObject recvIRubyObject line) {
        ArgsFileData data = ArgsFileData.getDataFrom(recv);
        data.currentLineNumber = RubyNumeric.fix2int(line);
        context.runtime.setCurrentLine(data.currentLineNumber);
        return recv.getRuntime().getNil();
    }
    @JRubyMethod(name = "tell", alias = {"pos"})
    public static IRubyObject tell(ThreadContext contextIRubyObject recv) {
        ArgsFileData data = ArgsFileData.getDataFrom(recv);
        if(!data.next_argv(context)) {
            throw context.runtime.newArgumentError("no stream to tell");
        }
        return ((RubyIO)data.currentFile).pos(context);
    }
    @JRubyMethod(name = "rewind")
    public static IRubyObject rewind(ThreadContext contextIRubyObject recv) {
        ArgsFileData data = getData(contextrecv"no stream to rewind");
        
        RubyFixnum retVal = ((RubyIO)data.currentFile).rewind(context);
        ((RubyIO)data.currentFile).lineno_set(contextcontext.runtime.newFixnum(0));
        
        data.minLineNumber = 0;
        data.currentLineNumber = 0;
        return retVal;
    }
    @JRubyMethod(name = {"eof"})
    public static IRubyObject eof(ThreadContext contextIRubyObject recv) {
        ArgsFileData data = ArgsFileData.getDataFrom(recv);
        if(!data.inited) {
            return context.runtime.getTrue();
        }
        if(!(data.currentFile instanceof RubyIO)) return data.currentFile.callMethod(context"eof");
        return ((RubyIOdata.currentFile).eof_p(context);
    }
    @JRubyMethod(name = {"eof?"})
    public static IRubyObject eof_p(ThreadContext contextIRubyObject recv) {
        ArgsFileData data = ArgsFileData.getDataFrom(recv);
        if (!data.inited) {
            return context.runtime.getTrue();
        }
        if (!(data.currentFile instanceof RubyIO)) return data.currentFile.callMethod(context"eof?");
        return ((RubyIOdata.currentFile).eof_p(context);
    }
    @JRubyMethod(name = "pos=", required = 1)
    public static IRubyObject set_pos(ThreadContext contextIRubyObject recvIRubyObject offset) {
        ArgsFileData data = getData(contextrecv"no stream to set position");
        return ((RubyIO)data.currentFile).pos_set(contextoffset);
    }
    @JRubyMethod(name = "seek", required = 1, optional = 1)
    public static IRubyObject seek(ThreadContext contextIRubyObject recvIRubyObject[] args) {
        ArgsFileData data = getData(contextrecv"no stream to seek");
        return ((RubyIO)data.currentFile).seek(contextargs);
    }
    @JRubyMethod(name = "readchar")
    public static IRubyObject readchar(ThreadContext contextIRubyObject recv) {
        IRubyObject c = getc(contextrecv);
        
        if (c.isNil()) {
            throw context.runtime.newEOFError();
        }
        return c;
    }
    @JRubyMethod(name = "getc")
    public static IRubyObject getc(ThreadContext contextIRubyObject recv) {
        ArgsFileData data = ArgsFileData.getDataFrom(recv);
        while(true) {
            IRubyObject bt;
            if (!data.next_argv(context)) {
                return context.runtime.getNil();
            }
            if (!(data.currentFile instanceof RubyFile)) {
                bt = data.currentFile.callMethod(context,"getc");
            } else {
                bt = ((RubyIO)data.currentFile).getc();
            }
            if (bt.isNil()) {
                data.next_p = 1;
                continue;
            }
            return bt;
        }
    }
    @JRubyMethod(name = "read", optional = 2)
    public static IRubyObject read(ThreadContext contextIRubyObject recvIRubyObject[] args) {
        Ruby runtime = context.runtime;
        ArgsFileData data = ArgsFileData.getDataFrom(recv);
        IRubyObject tmpstrlength;
        long len = 0;
        if (args.length > 0) {
            length = args[0];
            str = args.length > 1 ? args[1] : runtime.getNil();
        } else {
            length = runtime.getNil();
            str = runtime.getNil();
        }
        if (!length.isNil()) len = RubyNumeric.num2long(length);
        if (!str.isNil()) {
            str = str.convertToString();
            ((RubyString)str).modify();
            ((RubyString)str).getByteList().length(0);
            args[1] = runtime.getNil();
        }
        while(true) {
            if (!data.next_argv(context)) return str;
            if (!(data.currentFile instanceof RubyIO)) {
                tmp = data.currentFile.callMethod(context"read"args);
            } else {
                tmp = ((RubyIO)data.currentFile).read(args);
            }
            if (str.isNil()) {
                str = tmp;
            } else if (!tmp.isNil()) {
                ((RubyString)str).append(tmp);
            }
            if (tmp.isNil() || length.isNil()) {
                if(data.next_p != -1) {
                    argf_close(contextdata.currentFile);
                    data.next_p = 1;
                    continue;
                }
            } else if(args.length >= 1) {
                if (((RubyString)str).getByteList().length() < len) {
                    len -= ((RubyString)str).getByteList().length();
                    args[0] = runtime.newFixnum(len);
                    continue;
                }
            }
            return str;
        }
    }
    @JRubyMethod(name = "filename", alias = {"path"})
    public static IRubyObject filename(ThreadContext contextIRubyObject recv) {
        ArgsFileData data = ArgsFileData.getDataFrom(recv);
        data.next_argv(context);
        return context.runtime.getGlobalVariables().get("$FILENAME");
    }
    @JRubyMethod(name = "to_s"
    public static IRubyObject to_s(IRubyObject recv) {
        return recv.getRuntime().newString("ARGF");
    }
    
    private static ArgsFileData getData(ThreadContext contextIRubyObject recvString errorMessage) {
        ArgsFileData data = ArgsFileData.getDataFrom(recv);
        
        if (!data.next_argv(context)) {
            throw context.runtime.newArgumentError(errorMessage);
        }
        return data;
    }
New to GrepCode? Check out our FAQ X