1 package org.jruby; 2 3 import org.jruby.runtime.Block; 4 import org.jruby.runtime.CallbackFactory; 5 import org.jruby.runtime.ObjectAllocator; 6 import org.jruby.runtime.builtin.IRubyObject; 7 import org.jruby.util.StringScanner; 8 9 13 public class RubyStringScanner extends RubyObject { 14 15 private StringScanner scanner; 16 17 private static ObjectAllocator STRINGSCANNER_ALLOCATOR = new ObjectAllocator() { 18 public IRubyObject allocate(Ruby runtime, RubyClass klass) { 19 return new RubyStringScanner(runtime, klass); 20 } 21 }; 22 23 public static RubyClass createScannerClass(final Ruby runtime) { 24 RubyClass scannerClass = runtime.defineClass("StringScanner", runtime.getObject(), STRINGSCANNER_ALLOCATOR); 25 CallbackFactory callbackFactory = runtime.callbackFactory(RubyStringScanner.class); 26 27 scannerClass.defineMethod("initialize", callbackFactory.getOptMethod("initialize")); 28 scannerClass.defineFastMethod("<<", callbackFactory.getFastMethod("concat", RubyKernel.IRUBY_OBJECT)); 29 scannerClass.defineFastMethod("concat", callbackFactory.getFastMethod("concat", RubyKernel.IRUBY_OBJECT)); 30 scannerClass.defineFastMethod("[]", callbackFactory.getFastMethod("group", RubyFixnum.class)); 31 scannerClass.defineFastMethod("beginning_of_line?", callbackFactory.getFastMethod("bol_p")); 32 scannerClass.defineFastMethod("bol?", callbackFactory.getFastMethod("bol_p")); 33 scannerClass.defineFastMethod("check", callbackFactory.getFastMethod("check", RubyRegexp.class)); 34 scannerClass.defineFastMethod("check_until", callbackFactory.getFastMethod("check_until", RubyRegexp.class)); 35 scannerClass.defineFastMethod("clear", callbackFactory.getFastMethod("terminate")); 36 scannerClass.defineFastMethod("empty?", callbackFactory.getFastMethod("eos_p")); 37 scannerClass.defineFastMethod("eos?", callbackFactory.getFastMethod("eos_p")); 38 scannerClass.defineFastMethod("exist?", callbackFactory.getFastMethod("exist_p", RubyRegexp.class)); 39 scannerClass.defineFastMethod("get_byte", callbackFactory.getFastMethod("getch")); 40 scannerClass.defineFastMethod("getbyte", callbackFactory.getFastMethod("getch")); 41 scannerClass.defineFastMethod("getch", callbackFactory.getFastMethod("getch")); 42 scannerClass.defineFastMethod("inspect", callbackFactory.getFastMethod("inspect")); 43 scannerClass.defineFastMethod("match?", callbackFactory.getFastMethod("match_p", RubyRegexp.class)); 44 scannerClass.defineFastMethod("matched", callbackFactory.getFastMethod("matched")); 45 scannerClass.defineFastMethod("matched?", callbackFactory.getFastMethod("matched_p")); 46 scannerClass.defineFastMethod("matched_size", callbackFactory.getFastMethod("matched_size")); 47 scannerClass.defineFastMethod("matchedsize", callbackFactory.getFastMethod("matched_size")); 48 scannerClass.defineFastMethod("peek", callbackFactory.getFastMethod("peek", RubyFixnum.class)); 49 scannerClass.defineFastMethod("peep", callbackFactory.getFastMethod("peek", RubyFixnum.class)); 50 scannerClass.defineFastMethod("pointer", callbackFactory.getFastMethod("pos")); 51 scannerClass.defineFastMethod("pointer=", callbackFactory.getFastMethod("set_pos", RubyFixnum.class)); 52 scannerClass.defineFastMethod("pos=", callbackFactory.getFastMethod("set_pos", RubyFixnum.class)); 53 scannerClass.defineFastMethod("pos", callbackFactory.getFastMethod("pos")); 54 scannerClass.defineFastMethod("post_match", callbackFactory.getFastMethod("post_match")); 55 scannerClass.defineFastMethod("pre_match", callbackFactory.getFastMethod("pre_match")); 56 scannerClass.defineFastMethod("reset", callbackFactory.getFastMethod("reset")); 57 scannerClass.defineFastMethod("rest", callbackFactory.getFastMethod("rest")); 58 scannerClass.defineFastMethod("rest?", callbackFactory.getFastMethod("rest_p")); 59 scannerClass.defineFastMethod("rest_size", callbackFactory.getFastMethod("rest_size")); 60 scannerClass.defineFastMethod("restsize", callbackFactory.getFastMethod("rest_size")); 61 scannerClass.defineFastMethod("scan", callbackFactory.getFastMethod("scan", RubyRegexp.class)); 62 scannerClass.defineFastMethod("scan_full", callbackFactory.getFastMethod("scan_full", RubyRegexp.class, RubyBoolean.class, RubyBoolean.class)); 63 scannerClass.defineFastMethod("scan_until", callbackFactory.getFastMethod("scan_until", RubyRegexp.class)); 64 scannerClass.defineFastMethod("search_full", callbackFactory.getFastMethod("search_full", RubyRegexp.class, RubyBoolean.class, RubyBoolean.class)); 65 scannerClass.defineFastMethod("skip", callbackFactory.getFastMethod("skip", RubyRegexp.class)); 66 scannerClass.defineFastMethod("skip_until", callbackFactory.getFastMethod("skip_until", RubyRegexp.class)); 67 scannerClass.defineFastMethod("string", callbackFactory.getFastMethod("string")); 68 scannerClass.defineFastMethod("string=", callbackFactory.getFastMethod("set_string", RubyString.class)); 69 scannerClass.defineFastMethod("terminate", callbackFactory.getFastMethod("terminate")); 70 scannerClass.defineFastMethod("unscan", callbackFactory.getFastMethod("unscan")); 71 72 return scannerClass; 73 } 74 75 protected RubyStringScanner(Ruby runtime, RubyClass type) { 76 super(runtime, type); 77 } 78 79 public IRubyObject initialize(IRubyObject[] args, Block unusedBlock) { 80 if (checkArgumentCount(args, 0, 2) > 0) { 81 scanner = new StringScanner(args[0].convertToString().getValue()); 82 } else { 83 scanner = new StringScanner(); 84 } 85 return this; 86 } 87 88 public IRubyObject concat(IRubyObject obj) { 89 scanner.append(obj.convertToString().getValue()); 90 return this; 91 } 92 93 private RubyBoolean trueOrFalse(boolean p) { 94 if (p) { 95 return getRuntime().getTrue(); 96 } else { 97 return getRuntime().getFalse(); 98 } 99 } 100 101 private IRubyObject positiveFixnumOrNil(int val) { 102 if (val > -1) { 103 return RubyFixnum.newFixnum(getRuntime(), (long)val); 104 } else { 105 return getRuntime().getNil(); 106 } 107 } 108 109 private IRubyObject stringOrNil(CharSequence cs) { 110 if (cs == null) { 111 return getRuntime().getNil(); 112 } else { 113 return RubyString.newString(getRuntime(), cs); 114 } 115 } 116 117 public IRubyObject group(RubyFixnum num) { 118 return stringOrNil(scanner.group(RubyFixnum.fix2int(num))); 119 } 120 121 public RubyBoolean bol_p() { 122 return trueOrFalse(scanner.isBeginningOfLine()); 123 } 124 125 public IRubyObject check(RubyRegexp rx) { 126 return stringOrNil(scanner.check(rx.getPattern())); 127 } 128 129 public IRubyObject check_until(RubyRegexp rx) { 130 return stringOrNil(scanner.checkUntil(rx.getPattern())); 131 } 132 133 public IRubyObject terminate() { 134 scanner.terminate(); 135 return this; 136 } 137 138 public RubyBoolean eos_p() { 139 return trueOrFalse(scanner.isEndOfString()); 140 } 141 142 public IRubyObject exist_p(RubyRegexp rx) { 143 return positiveFixnumOrNil(scanner.exists(rx.getPattern())); 144 } 145 146 public IRubyObject getch() { 147 char c = scanner.getChar(); 148 if (c == 0) { 149 return getRuntime().getNil(); 150 } else { 151 return RubyString.newString(getRuntime(), new Character (c).toString()); 152 } 153 } 154 155 public IRubyObject inspect() { 156 return super.inspect(); 157 } 158 159 public IRubyObject match_p(RubyRegexp rx) { 160 return positiveFixnumOrNil(scanner.matches(rx.getPattern())); 161 } 162 163 public IRubyObject matched() { 164 return stringOrNil(scanner.matchedValue()); 165 } 166 167 public RubyBoolean matched_p() { 168 return trueOrFalse(scanner.matched()); 169 } 170 171 public IRubyObject matched_size() { 172 return positiveFixnumOrNil(scanner.matchedSize()); 173 } 174 175 public IRubyObject peek(RubyFixnum length) { 176 return RubyString.newString(getRuntime(), scanner.peek(RubyFixnum.fix2int(length))); 177 } 178 179 public RubyFixnum pos() { 180 return RubyFixnum.newFixnum(getRuntime(), (long)scanner.getPos()); 181 } 182 183 public RubyFixnum set_pos(RubyFixnum pos) { 184 try { 185 scanner.setPos(RubyFixnum.fix2int(pos)); 186 } catch (IllegalArgumentException e) { 187 throw getRuntime().newRangeError("index out of range"); 188 } 189 return pos; 190 } 191 192 public IRubyObject post_match() { 193 return stringOrNil(scanner.postMatch()); 194 } 195 196 public IRubyObject pre_match() { 197 return stringOrNil(scanner.preMatch()); 198 } 199 200 public IRubyObject reset() { 201 scanner.reset(); 202 return this; 203 } 204 205 public RubyString rest() { 206 return RubyString.newString(getRuntime(), scanner.rest()); 207 } 208 209 public RubyBoolean rest_p() { 210 return trueOrFalse(!scanner.isEndOfString()); 211 } 212 213 public RubyFixnum rest_size() { 214 return RubyFixnum.newFixnum(getRuntime(), (long)scanner.rest().length()); 215 } 216 217 public IRubyObject scan(RubyRegexp rx) { 218 return stringOrNil(scanner.scan(rx.getPattern())); 219 } 220 221 public IRubyObject scan_full(RubyRegexp rx, RubyBoolean adv_ptr, RubyBoolean ret_str) { 222 if (adv_ptr.isTrue()) { 223 if (ret_str.isTrue()) { 224 return stringOrNil(scanner.scan(rx.getPattern())); 225 } else { 226 return positiveFixnumOrNil(scanner.skip(rx.getPattern())); 227 } 228 } else { 229 if (ret_str.isTrue()) { 230 return stringOrNil(scanner.check(rx.getPattern())); 231 } else { 232 return positiveFixnumOrNil(scanner.matches(rx.getPattern())); 233 } 234 } 235 } 236 237 public IRubyObject scan_until(RubyRegexp rx) { 238 return stringOrNil(scanner.scanUntil(rx.getPattern())); 239 } 240 241 public IRubyObject search_full(RubyRegexp rx, RubyBoolean adv_ptr, RubyBoolean ret_str) { 242 if (adv_ptr.isTrue()) { 243 if (ret_str.isTrue()) { 244 return stringOrNil(scanner.scanUntil(rx.getPattern())); 245 } else { 246 return positiveFixnumOrNil(scanner.skipUntil(rx.getPattern())); 247 } 248 } else { 249 if (ret_str.isTrue()) { 250 return stringOrNil(scanner.checkUntil(rx.getPattern())); 251 } else { 252 return positiveFixnumOrNil(scanner.exists(rx.getPattern())); 253 } 254 } 255 } 256 257 public IRubyObject skip(RubyRegexp rx) { 258 return positiveFixnumOrNil(scanner.skip(rx.getPattern())); 259 } 260 261 public IRubyObject skip_until(RubyRegexp rx) { 262 return positiveFixnumOrNil(scanner.skipUntil(rx.getPattern())); 263 } 264 265 public RubyString string() { 266 return RubyString.newString(getRuntime(), scanner.getString()); 267 } 268 269 public RubyString set_string(RubyString str) { 270 scanner.setString(str.getValue()); 271 return str; 272 } 273 274 public IRubyObject unscan() { 275 scanner.unscan(); 276 return this; 277 } 278 } 279 | Popular Tags |