001: package org.jruby;
002:
003: import org.jruby.runtime.Arity;
004: import org.jruby.runtime.Block;
005: import org.jruby.runtime.CallbackFactory;
006: import org.jruby.runtime.ObjectAllocator;
007: import org.jruby.runtime.builtin.IRubyObject;
008: import org.jruby.util.StringScanner;
009:
010: /**
011: * @author kscott
012: *
013: */
014: public class RubyStringScanner extends RubyObject {
015:
016: private StringScanner scanner;
017:
018: private static ObjectAllocator STRINGSCANNER_ALLOCATOR = new ObjectAllocator() {
019: public IRubyObject allocate(Ruby runtime, RubyClass klass) {
020: return new RubyStringScanner(runtime, klass);
021: }
022: };
023:
024: public static RubyClass createScannerClass(final Ruby runtime) {
025: RubyClass scannerClass = runtime.defineClass("StringScanner",
026: runtime.getObject(), STRINGSCANNER_ALLOCATOR);
027: CallbackFactory callbackFactory = runtime
028: .callbackFactory(RubyStringScanner.class);
029:
030: scannerClass.defineMethod("initialize", callbackFactory
031: .getOptMethod("initialize"));
032: scannerClass.defineFastMethod("<<", callbackFactory
033: .getFastMethod("concat", RubyKernel.IRUBY_OBJECT));
034: scannerClass.defineFastMethod("concat", callbackFactory
035: .getFastMethod("concat", RubyKernel.IRUBY_OBJECT));
036: scannerClass.defineFastMethod("[]", callbackFactory
037: .getFastMethod("group", RubyFixnum.class));
038: scannerClass.defineFastMethod("beginning_of_line?",
039: callbackFactory.getFastMethod("bol_p"));
040: scannerClass.defineFastMethod("bol?", callbackFactory
041: .getFastMethod("bol_p"));
042: scannerClass.defineFastMethod("check", callbackFactory
043: .getFastMethod("check", RubyRegexp.class));
044: scannerClass.defineFastMethod("check_until", callbackFactory
045: .getFastMethod("check_until", RubyRegexp.class));
046: scannerClass.defineFastMethod("clear", callbackFactory
047: .getFastMethod("terminate"));
048: scannerClass.defineFastMethod("empty?", callbackFactory
049: .getFastMethod("eos_p"));
050: scannerClass.defineFastMethod("eos?", callbackFactory
051: .getFastMethod("eos_p"));
052: scannerClass.defineFastMethod("exist?", callbackFactory
053: .getFastMethod("exist_p", RubyRegexp.class));
054: scannerClass.defineFastMethod("get_byte", callbackFactory
055: .getFastMethod("getch"));
056: scannerClass.defineFastMethod("getbyte", callbackFactory
057: .getFastMethod("getch"));
058: scannerClass.defineFastMethod("getch", callbackFactory
059: .getFastMethod("getch"));
060: scannerClass.defineFastMethod("inspect", callbackFactory
061: .getFastMethod("inspect"));
062: scannerClass.defineFastMethod("match?", callbackFactory
063: .getFastMethod("match_p", RubyRegexp.class));
064: scannerClass.defineFastMethod("matched", callbackFactory
065: .getFastMethod("matched"));
066: scannerClass.defineFastMethod("matched?", callbackFactory
067: .getFastMethod("matched_p"));
068: scannerClass.defineFastMethod("matched_size", callbackFactory
069: .getFastMethod("matched_size"));
070: scannerClass.defineFastMethod("matchedsize", callbackFactory
071: .getFastMethod("matched_size"));
072: scannerClass.defineFastMethod("peek", callbackFactory
073: .getFastMethod("peek", RubyFixnum.class));
074: scannerClass.defineFastMethod("peep", callbackFactory
075: .getFastMethod("peek", RubyFixnum.class));
076: scannerClass.defineFastMethod("pointer", callbackFactory
077: .getFastMethod("pos"));
078: scannerClass.defineFastMethod("pointer=", callbackFactory
079: .getFastMethod("set_pos", RubyFixnum.class));
080: scannerClass.defineFastMethod("pos=", callbackFactory
081: .getFastMethod("set_pos", RubyFixnum.class));
082: scannerClass.defineFastMethod("pos", callbackFactory
083: .getFastMethod("pos"));
084: scannerClass.defineFastMethod("post_match", callbackFactory
085: .getFastMethod("post_match"));
086: scannerClass.defineFastMethod("pre_match", callbackFactory
087: .getFastMethod("pre_match"));
088: scannerClass.defineFastMethod("reset", callbackFactory
089: .getFastMethod("reset"));
090: scannerClass.defineFastMethod("rest", callbackFactory
091: .getFastMethod("rest"));
092: scannerClass.defineFastMethod("rest?", callbackFactory
093: .getFastMethod("rest_p"));
094: scannerClass.defineFastMethod("rest_size", callbackFactory
095: .getFastMethod("rest_size"));
096: scannerClass.defineFastMethod("restsize", callbackFactory
097: .getFastMethod("rest_size"));
098: scannerClass.defineFastMethod("scan", callbackFactory
099: .getFastMethod("scan", RubyRegexp.class));
100: scannerClass.defineFastMethod("scan_full", callbackFactory
101: .getFastMethod("scan_full", RubyRegexp.class,
102: RubyBoolean.class, RubyBoolean.class));
103: scannerClass.defineFastMethod("scan_until", callbackFactory
104: .getFastMethod("scan_until", RubyRegexp.class));
105: scannerClass.defineFastMethod("search_full", callbackFactory
106: .getFastMethod("search_full", RubyRegexp.class,
107: RubyBoolean.class, RubyBoolean.class));
108: scannerClass.defineFastMethod("skip", callbackFactory
109: .getFastMethod("skip", RubyRegexp.class));
110: scannerClass.defineFastMethod("skip_until", callbackFactory
111: .getFastMethod("skip_until", RubyRegexp.class));
112: scannerClass.defineFastMethod("string", callbackFactory
113: .getFastMethod("string"));
114: scannerClass.defineFastMethod("string=", callbackFactory
115: .getFastMethod("set_string", RubyString.class));
116: scannerClass.defineFastMethod("terminate", callbackFactory
117: .getFastMethod("terminate"));
118: scannerClass.defineFastMethod("unscan", callbackFactory
119: .getFastMethod("unscan"));
120:
121: return scannerClass;
122: }
123:
124: protected RubyStringScanner(Ruby runtime, RubyClass type) {
125: super (runtime, type);
126: }
127:
128: public IRubyObject initialize(IRubyObject[] args, Block unusedBlock) {
129: if (Arity.checkArgumentCount(getRuntime(), args, 0, 2) > 0) {
130: scanner = new StringScanner(args[0].convertToString()
131: .getValue());
132: } else {
133: scanner = new StringScanner();
134: }
135: return this ;
136: }
137:
138: public IRubyObject concat(IRubyObject obj) {
139: scanner.append(obj.convertToString().getValue());
140: return this ;
141: }
142:
143: private RubyBoolean trueOrFalse(boolean p) {
144: if (p) {
145: return getRuntime().getTrue();
146: } else {
147: return getRuntime().getFalse();
148: }
149: }
150:
151: private IRubyObject positiveFixnumOrNil(int val) {
152: if (val > -1) {
153: return RubyFixnum.newFixnum(getRuntime(), (long) val);
154: } else {
155: return getRuntime().getNil();
156: }
157: }
158:
159: private IRubyObject stringOrNil(CharSequence cs) {
160: if (cs == null) {
161: return getRuntime().getNil();
162: } else {
163: return RubyString.newString(getRuntime(), cs);
164: }
165: }
166:
167: public IRubyObject group(RubyFixnum num) {
168: return stringOrNil(scanner.group(RubyFixnum.fix2int(num)));
169: }
170:
171: public RubyBoolean bol_p() {
172: return trueOrFalse(scanner.isBeginningOfLine());
173: }
174:
175: public IRubyObject check(RubyRegexp rx) {
176: return stringOrNil(scanner.check(rx.getPattern()));
177: }
178:
179: public IRubyObject check_until(RubyRegexp rx) {
180: return stringOrNil(scanner.checkUntil(rx.getPattern()));
181: }
182:
183: public IRubyObject terminate() {
184: scanner.terminate();
185: return this ;
186: }
187:
188: public RubyBoolean eos_p() {
189: return trueOrFalse(scanner.isEndOfString());
190: }
191:
192: public IRubyObject exist_p(RubyRegexp rx) {
193: return positiveFixnumOrNil(scanner.exists(rx.getPattern()));
194: }
195:
196: public IRubyObject getch() {
197: char c = scanner.getChar();
198: if (c == 0) {
199: return getRuntime().getNil();
200: } else {
201: return RubyString.newString(getRuntime(), new Character(c)
202: .toString());
203: }
204: }
205:
206: public IRubyObject inspect() {
207: return super .inspect();
208: }
209:
210: public IRubyObject match_p(RubyRegexp rx) {
211: return positiveFixnumOrNil(scanner.matches(rx.getPattern()));
212: }
213:
214: public IRubyObject matched() {
215: return stringOrNil(scanner.matchedValue());
216: }
217:
218: public RubyBoolean matched_p() {
219: return trueOrFalse(scanner.matched());
220: }
221:
222: public IRubyObject matched_size() {
223: return positiveFixnumOrNil(scanner.matchedSize());
224: }
225:
226: public IRubyObject peek(RubyFixnum length) {
227: return RubyString.newString(getRuntime(), scanner
228: .peek(RubyFixnum.fix2int(length)));
229: }
230:
231: public RubyFixnum pos() {
232: return RubyFixnum.newFixnum(getRuntime(), (long) scanner
233: .getPos());
234: }
235:
236: public RubyFixnum set_pos(RubyFixnum pos) {
237: try {
238: scanner.setPos(RubyFixnum.fix2int(pos));
239: } catch (IllegalArgumentException e) {
240: throw getRuntime().newRangeError("index out of range");
241: }
242: return pos;
243: }
244:
245: public IRubyObject post_match() {
246: return stringOrNil(scanner.postMatch());
247: }
248:
249: public IRubyObject pre_match() {
250: return stringOrNil(scanner.preMatch());
251: }
252:
253: public IRubyObject reset() {
254: scanner.reset();
255: return this ;
256: }
257:
258: public RubyString rest() {
259: return RubyString.newString(getRuntime(), scanner.rest());
260: }
261:
262: public RubyBoolean rest_p() {
263: return trueOrFalse(!scanner.isEndOfString());
264: }
265:
266: public RubyFixnum rest_size() {
267: return RubyFixnum.newFixnum(getRuntime(), (long) scanner.rest()
268: .length());
269: }
270:
271: public IRubyObject scan(RubyRegexp rx) {
272: return stringOrNil(scanner.scan(rx.getPattern()));
273: }
274:
275: public IRubyObject scan_full(RubyRegexp rx, RubyBoolean adv_ptr,
276: RubyBoolean ret_str) {
277: if (adv_ptr.isTrue()) {
278: if (ret_str.isTrue()) {
279: return stringOrNil(scanner.scan(rx.getPattern()));
280: } else {
281: return positiveFixnumOrNil(scanner
282: .skip(rx.getPattern()));
283: }
284: } else {
285: if (ret_str.isTrue()) {
286: return stringOrNil(scanner.check(rx.getPattern()));
287: } else {
288: return positiveFixnumOrNil(scanner.matches(rx
289: .getPattern()));
290: }
291: }
292: }
293:
294: public IRubyObject scan_until(RubyRegexp rx) {
295: return stringOrNil(scanner.scanUntil(rx.getPattern()));
296: }
297:
298: public IRubyObject search_full(RubyRegexp rx, RubyBoolean adv_ptr,
299: RubyBoolean ret_str) {
300: if (adv_ptr.isTrue()) {
301: if (ret_str.isTrue()) {
302: return stringOrNil(scanner.scanUntil(rx.getPattern()));
303: } else {
304: return positiveFixnumOrNil(scanner.skipUntil(rx
305: .getPattern()));
306: }
307: } else {
308: if (ret_str.isTrue()) {
309: return stringOrNil(scanner.checkUntil(rx.getPattern()));
310: } else {
311: return positiveFixnumOrNil(scanner.exists(rx
312: .getPattern()));
313: }
314: }
315: }
316:
317: public IRubyObject skip(RubyRegexp rx) {
318: return positiveFixnumOrNil(scanner.skip(rx.getPattern()));
319: }
320:
321: public IRubyObject skip_until(RubyRegexp rx) {
322: return positiveFixnumOrNil(scanner.skipUntil(rx.getPattern()));
323: }
324:
325: public RubyString string() {
326: return RubyString.newString(getRuntime(), scanner.getString());
327: }
328:
329: public RubyString set_string(RubyString str) {
330: scanner.setString(str.getValue());
331: return str;
332: }
333:
334: public IRubyObject unscan() {
335: scanner.unscan();
336: return this;
337: }
338: }
|