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.
  *
  * 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.ext.strscan;
 
 import org.joni.Regex;
 import org.jruby.Ruby;
 import static org.jruby.runtime.Visibility.*;

Author(s):
kscott
 
 @JRubyClass(name="StringScanner")
 public class RubyStringScanner extends RubyObject {
 
     private RubyString str;
     private int pos = 0;
     private int lastPos = -1;
 
     private Region regs;
     private int beg = -1;
     private int end = -1;
     // not to be confused with RubyObject's flags
     private int scannerFlags;
 
     private static final int MATCHED_STR_SCN_F = 1 << 11;     
     
     private static ObjectAllocator STRINGSCANNER_ALLOCATOR = new ObjectAllocator() {
         public IRubyObject allocate(Ruby runtimeRubyClass klass) {
             return new RubyStringScanner(runtimeklass);
         }
     };
 
     public static RubyClass createScannerClass(final Ruby runtime) {
         RubyClass scannerClass = runtime.defineClass("StringScanner"runtime.getObject(), );
         scannerClass.defineAnnotatedMethods(RubyStringScanner.class);
         ThreadContext context = runtime.getCurrentContext();
         scannerClass.setConstant("Version"runtime.newString("0.7.0").freeze(context));
         scannerClass.setConstant("Id"runtime.newString("$Id: strscan.c 13506 2007-09-24 08:56:24Z nobu $").freeze(context));
 
         RubyClass standardError = runtime.getStandardError();
         RubyClass error = scannerClass.defineClassUnder(
                 "Error"standardErrorstandardError.getAllocator());
 
         RubyClass objClass = runtime.getObject();
         if (!objClass.isConstantDefined("ScanError")) {
             objClass.defineConstant("ScanError"error);
         }
 
         return scannerClass;
     }
 
    private void clearMatched() {
         &= ~;
    }
    private void setMatched() {
         |= ;
    }
    private boolean isMatched() {
        return ( & ) != 0;
    }
    
    private void check() {
        if ( == nullthrow getRuntime().newArgumentError("uninitialized StringScanner object");
    }
    protected RubyStringScanner(Ruby runtimeRubyClass type) {
        super(runtimetype);
    }
    // second argument is allowed, but ignored (MRI)
    @JRubyMethod(required = 1, optional = 1, visibility = )
    public IRubyObject initialize(IRubyObject[] argsBlock unusedBlock) {
         = args[0].convertToString();        
        return this;
    }
    
    @JRubyMethod(visibility = )
    @Override
    public IRubyObject initialize_copy(IRubyObject other) {
        if (this == otherreturn this;
        if (!(other instanceof RubyStringScanner)) {
            throw getRuntime().newTypeError("wrong argument type "
                    + other.getMetaClass() + " (expected StringScanner)");
        }
        RubyStringScanner otherScanner = (RubyStringScanner)other;
         = otherScanner.str;
         = otherScanner.pos;
         = otherScanner.lastPos;
         = otherScanner.scannerFlags;
         = otherScanner.regs != null ? otherScanner.regs.clone() : null;
         = otherScanner.beg;
         = otherScanner.end;
        return this;
    }
    
    @JRubyMethod(name = "reset")
    public IRubyObject reset() {
        check();
         = 0;
        clearMatched();
        return this;
    }
    
    @JRubyMethod(name = "terminate")
    public IRubyObject terminate() {
        check();
         = .getByteList().getRealSize();
        clearMatched();
        return this;
    }
    
    @JRubyMethod(name = "clear")
    public IRubyObject clear(ThreadContext context) {
        check();
        Ruby runtime = context.runtime;
        if (runtime.isVerbose()) {
            runtime.getWarnings().warning(."StringScanner#clear is obsolete; use #terminate instead");
        }
        return terminate();
    }
    
    @JRubyMethod(name = "string")
    public RubyString string() {
        return ;
    }
    @JRubyMethod(name = "string=", required = 1)
    public IRubyObject set_string(ThreadContext contextIRubyObject str) {
        this. = (RubyStringstr.convertToString().strDup(context.runtime).freeze(context);
         = 0;
        clearMatched();
        return str;
    }
    @JRubyMethod(name = {"concat""<<"}, required = 1)
    public IRubyObject concat(IRubyObject obj) {
        check();
        .append(obj); // append will call convertToString()
        return this;
    }
    
    @JRubyMethod(name = {"pos""pointer"})
    public RubyFixnum pos() {
        check();
        return RubyFixnum.newFixnum(getRuntime(), );
    }
    @JRubyMethod(name = {"pos=""pointer="})
    public IRubyObject set_pos(IRubyObject pos) {
        check();
        int i = RubyNumeric.num2int(pos);
        int size = .getByteList().getRealSize();
        if (i < 0) i += size;
        if (i < 0 || i > sizethrow getRuntime().newRangeError("index out of range.");
        this. = i;
        return RubyFixnum.newFixnum(getRuntime(), i);
    }
    private IRubyObject extractRange(Ruby runtimeint begint end) {
        int size = .getByteList().getRealSize();
        if (beg > sizereturn getRuntime().getNil();
        if (end > sizeend = size;
        return runtime.is1_9() ? .makeSharedString19(runtimebegend - beg) :
                .makeSharedString(runtimebegend - beg);
    }
    
    private IRubyObject extractBegLen(Ruby runtimeint begint len) {
        assert len >= 0;
        int size = .getByteList().getRealSize();
        if (beg > sizereturn getRuntime().getNil();
        if (beg + len > sizelen = size - beg;
        return runtime.is1_9() ? .makeSharedString19(runtimebeglen) :
                .makeSharedString(runtimebeglen);
    }
    
    private IRubyObject scan(IRubyObject regexboolean succptrboolean getstrboolean headonly) {
        Ruby runtime = getRuntime();
        if (!(regex instanceof RubyRegexp)) throw runtime.newTypeError("wrong argument type " + regex.getMetaClass() + " (expected Regexp)");
        check();
        
        Regex pattern = ((RubyRegexp)regex).preparePattern();
        clearMatched();
        int rest = .getByteList().getRealSize() - ;
        if (rest < 0) return getRuntime().getNil();
        ByteList value = .getByteList();
        Matcher matcher = pattern.matcher(value.getUnsafeBytes(), value.getBegin() + value.getBegin() + value.getRealSize());
        final int ret;
        if (headonly) {
            ret = matcher.match(value.getBegin() + value.getBegin() + value.getRealSize(), .);
        } else {
            ret = matcher.search(value.getBegin() + value.getBegin() + value.getRealSize(), .);
        }
         = matcher.getRegion(); 
        if ( == null) {
             = matcher.getBegin();
             = matcher.getEnd();
        } else {
             = .[0];
             = .[0];
        }
        if (ret < 0) return getRuntime().getNil();
        setMatched();
         = ;
        if (succptr += ;
        return  getstr ? extractBegLen(getRuntime(), ) : RubyFixnum.newFixnum(getRuntime(), );
    }
    
    @JRubyMethod(name = "scan", required = 1)
    public IRubyObject scan(IRubyObject regex) {
        return scan(regextruetruetrue);
    }
    
    @JRubyMethod(name = "match?", required = 1)
    public IRubyObject match_p(IRubyObject regex) {
        return scan(regexfalsefalsetrue);
    }
    
    @JRubyMethod(name = "skip", required = 1)
    public IRubyObject skip(IRubyObject regex) {
        return scan(regextruefalsetrue);
    }
    
    @JRubyMethod(name = "check", required = 1)
    public IRubyObject check(IRubyObject regex) {
        return scan(regexfalsetruetrue);
    }
    
    @JRubyMethod(name = "scan_full", required = 3)
    public IRubyObject scan_full(IRubyObject regexIRubyObject sIRubyObject f) {
        return scan(regexs.isTrue(), f.isTrue(), true);
    }
    @JRubyMethod(name = "scan_until", required = 1)
    public IRubyObject scan_until(IRubyObject regex) {
        return scan(regextruetruefalse);
    }
    
    @JRubyMethod(name = "exist?", required = 1)
    public IRubyObject exist_p(IRubyObject regex) {
        return scan(regexfalsefalsefalse);        
    }
    
    @JRubyMethod(name = "skip_until", required = 1)
    public IRubyObject skip_until(IRubyObject regex) {
        return scan(regextruefalsefalse);
    }
    @JRubyMethod(name = "check_until", required = 1)
    public IRubyObject check_until(IRubyObject regex) {
        return scan(regexfalsetruefalse);        
    }
    
    @JRubyMethod(name = "search_full", required = 3)
    public IRubyObject search_full(IRubyObject regexIRubyObject sIRubyObject f) {
        return scan(regexs.isTrue(), f.isTrue(), false);
    }
    private void adjustRegisters() {
         = 0;
         =  - ;
         = null;
    }
    @JRubyMethod(name = "getch", compat = .)
    public IRubyObject getch(ThreadContext context) {
        return getchCommon(contextfalse);
    }
    @JRubyMethod(name = "getch", compat = .)
    public IRubyObject getch19(ThreadContext context) {
        return getchCommon(contexttrue);
    }
    public IRubyObject getchCommon(ThreadContext contextboolean is1_9) {
        check();
        clearMatched();
        Ruby runtime = context.runtime;
        ByteList value = .getByteList();
        if ( >= value.getRealSize()) return runtime.getNil();
        int len;
        if (is1_9) {
            Encoding enc = .getEncoding();
            len = enc.isSingleByte() ? 1 : StringSupport.length(encvalue.getUnsafeBytes(), value.getBegin() + value.getBegin() + value.getRealSize());
        } else {
            Encoding enc = runtime.getKCode().getEncoding();
            len = enc.isSingleByte() ? 1 : enc.length(value.getUnsafeBytes(), value.getBegin() + value.getBegin() + value.getRealSize());
        }
        if ( + len > value.getRealSize()) len = value.getRealSize() - ;
         = ;
         += len;
        setMatched();
        adjustRegisters();
        return extractRange(runtime +  + );
    }
    
    @JRubyMethod(name = "get_byte")
    public IRubyObject get_byte(ThreadContext context) {
        check();
        clearMatched();
        if ( >= .getByteList().getRealSize()) return getRuntime().getNil();
        
         = ;
        ++;
        
        setMatched();
        adjustRegisters();
        return extractRange(context.runtime +  + );
    }
    
    @JRubyMethod(name = "getbyte")
    public IRubyObject getbyte(ThreadContext context) {
        Ruby runtime = context.runtime;
        if (runtime.isVerbose()) { 
            runtime.getWarnings().warning(.,
                    "StringScanner#getbyte is obsolete; use #get_byte instead");
        }
        return get_byte(context);
    }
    @JRubyMethod(name = "peek", required = 1)
    public IRubyObject peek(ThreadContext contextIRubyObject length) {
        check();
        int len = RubyNumeric.num2int(length);
        if (len < 0) {
            throw context.runtime.newArgumentError("negative string size (or size too big)");
        }
        ByteList value = .getByteList();
        if ( >= value.getRealSize()) return RubyString.newEmptyString(getRuntime()).infectBy();
        if ( + len > value.getRealSize()) len = value.getRealSize() - ;
        return extractBegLen(context.runtimelen);
    }
    @JRubyMethod(name = "peep", required = 1)
    public IRubyObject peep(ThreadContext contextIRubyObject length) {
        Ruby runtime = context.runtime;
        if (runtime.isVerbose()) {
            runtime.getWarnings().warning(
                    ."StringScanner#peep is obsolete; use #peek instead");
        }
        return peek(contextlength);
    }
    
    @JRubyMethod(name = "unscan")
    public IRubyObject unscan() {
        check();
        Ruby runtime = getRuntime();
        if (!isMatched()) {
            RubyClass errorClass = runtime.getClass("StringScanner").getClass("Error");
            throw new RaiseException(RubyException.newException(
                    runtimeerrorClass"unscan failed: previous match had failed"));
        }
         = ;
        clearMatched();
        return this;
    }
    
    @JRubyMethod(name = "beginning_of_line?", alias = "bol?")
    public IRubyObject bol_p() {
        check();
        ByteList value = .getByteList();
        if ( > value.getRealSize()) return getRuntime().getNil();
        if ( == 0) return getRuntime().getTrue();
        return value.getUnsafeBytes()[(value.getBegin() + ) - 1] == (byte)'\n' ? getRuntime().getTrue() : getRuntime().getFalse();
    }
    
    @JRubyMethod(name = "eos?")
    public RubyBoolean eos_p(ThreadContext context) {
        check();
        return  >= .getByteList().getRealSize() ? context.runtime.getTrue() : context.runtime.getFalse();
    }
    
    @JRubyMethod(name = "empty?")
    public RubyBoolean empty_p(ThreadContext context) {
        Ruby runtime = context.runtime;
        if (runtime.isVerbose()) {
            runtime.getWarnings().warning(."StringScanner#empty? is obsolete; use #eos? instead");
        }
        return eos_p(context);
    }
    
    @JRubyMethod(name = "rest?")
    public RubyBoolean rest_p(ThreadContext context) {
        check();
        return  >= .getByteList().getRealSize() ? context.runtime.getFalse() : context.runtime.getTrue();
    }
    @JRubyMethod(name = "matched?")
    public RubyBoolean matched_p(ThreadContext context) {
        check();
        return isMatched() ? context.runtime.getTrue() : context.runtime.getFalse();
    }
    @JRubyMethod(name = "matched")
    public IRubyObject matched(ThreadContext context) {
        check();
        if (!isMatched()) return getRuntime().getNil();
        return extractRange(context.runtime +  + );
    }
    
    @JRubyMethod(name = "matched_size")
    public IRubyObject matched_size() {
        check();
        if (!isMatched()) return getRuntime().getNil();
        return RubyFixnum.newFixnum(getRuntime(),  - );
    }
    @JRubyMethod(name = "matchedsize")
    public IRubyObject matchedsize(ThreadContext context) {
        Ruby runtime = context.runtime;
        if (runtime.isVerbose()) {
            runtime.getWarnings().warning(."StringScanner#matchedsize is obsolete; use #matched_size instead");
        }
        return matched_size();        
    }
    @JRubyMethod(name = "[]", required = 1)
    public IRubyObject op_aref(ThreadContext contextIRubyObject idx) {
        check();
        if (!isMatched()) {
            return context.runtime.getNil();
        }
        int i = RubyNumeric.num2int(idx);
        
        int numRegs =  == null ? 1 : .;
        if (i < 0) i += numRegs;
        if (i < 0 || i >= numRegs) {
            return context.runtime.getNil();
        }
        
        if ( == null) {
            assert i == 0;
            if ( == -1) return getRuntime().getNil();
            return extractRange(context.runtime +  + );
        } else {
            if (.[i] == -1) return getRuntime().getNil();
            return extractRange(context.runtime + .[i],  + .[i]);
        }
    }
    @JRubyMethod(name = "pre_match")
    public IRubyObject pre_match(ThreadContext context) {
        check();
        if (!isMatched()) {
            return context.runtime.getNil();
        }
        return extractRange(context.runtime, 0,  + );
    }
    
    @JRubyMethod(name = "post_match")
    public IRubyObject post_match(ThreadContext context) {
        check();
        if (!isMatched()) {
            return context.runtime.getNil();
        }
        return extractRange(context.runtime + .getByteList().getRealSize());
    }
    
    @JRubyMethod(name = "rest")
    public IRubyObject rest(ThreadContext context) {
        check();
        ByteList value = .getByteList();
        if ( >= value.getRealSize()) {
            return RubyString.newEmptyString(context.runtime).infectBy();
        }
        return extractRange(context.runtimevalue.getRealSize());
    }
    
    @JRubyMethod(name = "rest_size")
    public RubyFixnum rest_size() {
        check();
        ByteList value = .getByteList();
        if ( >= value.getRealSize()) return RubyFixnum.zero(getRuntime());
        return RubyFixnum.newFixnum(getRuntime(), value.getRealSize() - );
    }
    @JRubyMethod(name = "restsize")
    public RubyFixnum restsize(ThreadContext context) {
        Ruby runtime = context.runtime;
        if (runtime.isVerbose()) {
            runtime.getWarnings().warning(."StringScanner#restsize is obsolete; use #rest_size instead");
        }
        return rest_size();
    }
    
    @JRubyMethod(name = "inspect")
    @Override
    public IRubyObject inspect() {
        if ( == nullreturn inspect("(uninitialized)");
        if ( >= .getByteList().getRealSize()) return inspect("fin");
        if ( == 0) return inspect( + "/" + .getByteList().getRealSize() + " @ " + inspect2());
        return inspect( + "/" + .getByteList().getRealSize() + " " + inspect1() + " @ " + inspect2());
    }
    
    private IRubyObject inspect(String msg) {
        RubyString result = getRuntime().newString("#<" + getMetaClass() + " " + msg + ">"); 
        if ( != nullresult.infectBy();
        return result;
    }
    
    private static final int INSPECT_LENGTH = 5;
    
    private IRubyObject inspect1() {
        if ( == 0) return RubyString.newEmptyString(getRuntime());
        if ( > ) {
            return RubyString.newStringNoCopy(getRuntime(), "...".getBytes()).
            append(.substr(getRuntime(),  - )).inspect();
        } else {
            return .substr(getRuntime(), 0, ).inspect();
        }
    }
    
    private IRubyObject inspect2() {
        if ( >= .getByteList().getRealSize()) return RubyString.newEmptyString(getRuntime());
        int len = .getByteList().getRealSize() - ;
        if (len > ) {
            return ((RubyString).substr(getRuntime(), )).cat("...".getBytes()).inspect();
        } else {
            return .substr(getRuntime(), len).inspect();
        }
    }
    @JRubyMethod(name = "must_C_version", meta = true)
    public static IRubyObject mustCversion(IRubyObject recv) {
        return recv;
    }
New to GrepCode? Check out our FAQ X