1 34 package org.jruby; 35 36 import org.jruby.runtime.CallbackFactory; 37 import org.jruby.runtime.ObjectAllocator; 38 import org.jruby.runtime.builtin.IRubyObject; 39 40 44 public class RubyMatchData extends RubyObject { 45 private String str; 46 private int[] begin; 47 private int[] end; 48 49 public RubyMatchData(Ruby runtime, String str, int[] begin, int[] end) { 50 super(runtime, runtime.getClass("MatchData")); 51 this.str = str; 52 this.begin = begin; 53 this.end = end; 54 } 55 56 public static RubyClass createMatchDataClass(Ruby runtime) { 57 RubyClass matchDataClass = runtime.defineClass("MatchData", runtime.getObject(), ObjectAllocator.NOT_ALLOCATABLE_ALLOCATOR); 59 runtime.defineGlobalConstant("MatchingData", matchDataClass); 60 61 CallbackFactory callbackFactory = runtime.callbackFactory(RubyMatchData.class); 62 63 matchDataClass.defineFastMethod("captures", callbackFactory.getFastMethod("captures")); 64 matchDataClass.defineFastMethod("inspect", callbackFactory.getFastMethod("inspect")); 65 matchDataClass.defineFastMethod("size", callbackFactory.getFastMethod("size")); 66 matchDataClass.defineFastMethod("length", callbackFactory.getFastMethod("size")); 67 matchDataClass.defineFastMethod("offset", callbackFactory.getFastMethod("offset", RubyFixnum.class)); 68 matchDataClass.defineFastMethod("begin", callbackFactory.getFastMethod("begin", RubyFixnum.class)); 69 matchDataClass.defineFastMethod("end", callbackFactory.getFastMethod("end", RubyFixnum.class)); 70 matchDataClass.defineFastMethod("to_a", callbackFactory.getFastMethod("to_a")); 71 matchDataClass.defineFastMethod("[]", callbackFactory.getFastOptMethod("aref")); 72 matchDataClass.defineFastMethod("pre_match", callbackFactory.getFastMethod("pre_match")); 73 matchDataClass.defineFastMethod("post_match", callbackFactory.getFastMethod("post_match")); 74 matchDataClass.defineFastMethod("to_s", callbackFactory.getFastMethod("to_s")); 75 matchDataClass.defineFastMethod("string", callbackFactory.getFastMethod("string")); 76 77 matchDataClass.getMetaClass().undefineMethod("new"); 78 79 return matchDataClass; 80 } 81 82 public IRubyObject captures() { 83 RubyArray arr = getRuntime().newArray(begin.length); 84 for (long i = 1; i < begin.length; i++) { 85 arr.append(group(i)); 86 } 87 return arr; 88 } 89 90 public IRubyObject subseq(long beg, long len) { 91 if (beg < 0 || beg > getSize() || len < 0) { 93 getRuntime().getNil(); 94 } 95 96 if (beg + len > getSize()) { 97 len = getSize() - beg; 98 } 99 if (len < 0) { 100 len = 0; 101 } 102 if (len == 0) { 103 return getRuntime().newArray(); 104 } 105 106 RubyArray arr = getRuntime().newArray(0); 107 for (long i = beg; i < beg + len; i++) { 108 arr.append(group(i)); 109 } 110 return arr; 111 } 112 113 public long getSize() { 114 return begin.length; 115 } 116 117 public IRubyObject group(long n) { 118 if (n < 0 || n >= getSize() || begin[(int) n] == -1) { 120 return getRuntime().getNil(); 121 } 122 return getRuntime().newString( 132 new String (str.substring(begin[(int) n], end[(int) n]))); 133 } 134 135 public int matchStartPosition() { 136 return begin[0]; 137 } 138 139 public int matchEndPosition() { 140 return end[0]; 141 } 142 143 private boolean outOfBounds(RubyFixnum index) { 144 return outOfBounds(index.getLongValue()); 145 } 146 147 private boolean outOfBounds(long n) { 149 return n < 0 || n >= getSize(); 150 } 151 152 156 159 public IRubyObject aref(IRubyObject[] args) { 160 int argc = checkArgumentCount(args, 1, 2); 161 if (argc == 2) { 162 int beg = RubyNumeric.fix2int(args[0]); 163 int len = RubyNumeric.fix2int(args[1]); 164 if (beg < 0) { 165 beg += getSize(); 166 } 167 return subseq(beg, len); 168 } 169 if (args[0] instanceof RubyFixnum) { 170 return group(RubyNumeric.fix2int(args[0])); 171 } 172 if (args[0] instanceof RubyBignum) { 173 throw getRuntime().newIndexError("index too big"); 174 } 175 if (args[0] instanceof RubyRange) { 176 long[] begLen = ((RubyRange) args[0]).getBeginLength(getSize(), true, false); 177 if (begLen == null) { 178 return getRuntime().getNil(); 179 } 180 return subseq(begLen[0], begLen[1]); 181 } 182 return group(RubyNumeric.num2long(args[0])); 183 } 184 185 188 public IRubyObject begin(RubyFixnum index) { 189 long lIndex = index.getLongValue(); 190 long answer = begin(lIndex); 191 192 return answer == -1 ? getRuntime().getNil() : getRuntime().newFixnum(answer); 193 } 194 195 public long begin(long index) { 196 return outOfBounds(index) ? -1 : begin[(int) index]; 197 } 198 199 202 public IRubyObject end(RubyFixnum index) { 203 int lIndex = RubyNumeric.fix2int(index); 204 long answer = end(lIndex); 205 206 return answer == -1 ? getRuntime().getNil() : getRuntime().newFixnum(answer); 207 } 208 209 public long end(long index) { 210 return outOfBounds(index) ? -1 : end[(int) index]; 211 } 212 213 public IRubyObject inspect() { 214 return anyToString(); 215 } 216 217 220 public RubyFixnum size() { 221 return getRuntime().newFixnum(getSize()); 222 } 223 224 227 public IRubyObject offset(RubyFixnum index) { 228 if (outOfBounds(index)) { 229 return getRuntime().getNil(); 230 } 231 return getRuntime().newArrayNoCopy(new IRubyObject[] { begin(index), end(index)}); 232 } 233 234 237 public RubyString pre_match() { 238 return getRuntime().newString(str.substring(0, begin[0])); 239 } 240 241 244 public RubyString post_match() { 245 return getRuntime().newString(str.substring(end[0])); 246 } 247 248 251 public RubyString string() { 252 RubyString frozenString = getRuntime().newString(str); 253 frozenString.freeze(); 254 return frozenString; 255 } 256 257 260 public RubyArray to_a() { 261 RubyArray arr = getRuntime().newArray(begin.length); 262 for (long i = 0; i < begin.length; i++) { 263 arr.append(group(i)); 264 } 265 return arr; 266 } 267 268 271 public IRubyObject to_s() { 272 return getRuntime().newString(str.substring(begin[0], end[0])); 273 } 274 275 public IRubyObject doClone() { 276 int len = (int) getSize(); 277 int[] begin_p = new int[len]; 278 int[] end_p = new int[len]; 279 System.arraycopy(begin, 0, begin_p, 0, len); 280 System.arraycopy(end, 0, end_p, 0, len); 281 return new RubyMatchData(getRuntime(), str, begin_p, end_p); 282 } 283 } 284 | Popular Tags |