Ruby  2.0.0p247(2013-06-27revision41674)
ext/strscan/strscan.c
Go to the documentation of this file.
00001 /*
00002     $Id: strscan.c 37916 2012-11-28 00:17:33Z ryan $
00003 
00004     Copyright (c) 1999-2006 Minero Aoki
00005 
00006     This program is free software.
00007     You can distribute/modify this program under the terms of
00008     the Ruby License. For details, see the file COPYING.
00009 */
00010 
00011 #include "ruby/ruby.h"
00012 #include "ruby/re.h"
00013 #include "ruby/encoding.h"
00014 #include "regint.h"
00015 
00016 #define STRSCAN_VERSION "0.7.0"
00017 
00018 /* =======================================================================
00019                          Data Type Definitions
00020    ======================================================================= */
00021 
00022 static VALUE StringScanner;
00023 static VALUE ScanError;
00024 static ID id_byteslice;
00025 
00026 struct strscanner
00027 {
00028     /* multi-purpose flags */
00029     unsigned long flags;
00030 #define FLAG_MATCHED (1 << 0)
00031 
00032     /* the string to scan */
00033     VALUE str;
00034 
00035     /* scan pointers */
00036     long prev;   /* legal only when MATCHED_P(s) */
00037     long curr;   /* always legal */
00038 
00039     /* the regexp register; legal only when MATCHED_P(s) */
00040     struct re_registers regs;
00041 };
00042 
00043 #define MATCHED_P(s)          ((s)->flags & FLAG_MATCHED)
00044 #define MATCHED(s)             (s)->flags |= FLAG_MATCHED
00045 #define CLEAR_MATCH_STATUS(s)  (s)->flags &= ~FLAG_MATCHED
00046 
00047 #define S_PBEG(s)  (RSTRING_PTR((s)->str))
00048 #define S_LEN(s)  (RSTRING_LEN((s)->str))
00049 #define S_PEND(s)  (S_PBEG(s) + S_LEN(s))
00050 #define CURPTR(s) (S_PBEG(s) + (s)->curr)
00051 #define S_RESTLEN(s) (S_LEN(s) - (s)->curr)
00052 
00053 #define EOS_P(s) ((s)->curr >= RSTRING_LEN(p->str))
00054 
00055 #define GET_SCANNER(obj,var) do {\
00056     (var) = check_strscan(obj);\
00057     if (NIL_P((var)->str)) rb_raise(rb_eArgError, "uninitialized StringScanner object");\
00058 } while (0)
00059 
00060 /* =======================================================================
00061                             Function Prototypes
00062    ======================================================================= */
00063 
00064 static VALUE infect _((VALUE str, struct strscanner *p));
00065 static VALUE extract_range _((struct strscanner *p, long beg_i, long end_i));
00066 static VALUE extract_beg_len _((struct strscanner *p, long beg_i, long len));
00067 
00068 static struct strscanner *check_strscan _((VALUE obj));
00069 static void strscan_mark _((void *p));
00070 static void strscan_free _((void *p));
00071 static size_t strscan_memsize _((const void *p));
00072 static VALUE strscan_s_allocate _((VALUE klass));
00073 static VALUE strscan_initialize _((int argc, VALUE *argv, VALUE self));
00074 static VALUE strscan_init_copy _((VALUE vself, VALUE vorig));
00075 
00076 static VALUE strscan_s_mustc _((VALUE self));
00077 static VALUE strscan_terminate _((VALUE self));
00078 static VALUE strscan_clear _((VALUE self));
00079 static VALUE strscan_get_string _((VALUE self));
00080 static VALUE strscan_set_string _((VALUE self, VALUE str));
00081 static VALUE strscan_concat _((VALUE self, VALUE str));
00082 static VALUE strscan_get_pos _((VALUE self));
00083 static VALUE strscan_set_pos _((VALUE self, VALUE pos));
00084 static VALUE strscan_do_scan _((VALUE self, VALUE regex,
00085                                 int succptr, int getstr, int headonly));
00086 static VALUE strscan_scan _((VALUE self, VALUE re));
00087 static VALUE strscan_match_p _((VALUE self, VALUE re));
00088 static VALUE strscan_skip _((VALUE self, VALUE re));
00089 static VALUE strscan_check _((VALUE self, VALUE re));
00090 static VALUE strscan_scan_full _((VALUE self, VALUE re,
00091                                   VALUE succp, VALUE getp));
00092 static VALUE strscan_scan_until _((VALUE self, VALUE re));
00093 static VALUE strscan_skip_until _((VALUE self, VALUE re));
00094 static VALUE strscan_check_until _((VALUE self, VALUE re));
00095 static VALUE strscan_search_full _((VALUE self, VALUE re,
00096                                     VALUE succp, VALUE getp));
00097 static void adjust_registers_to_matched _((struct strscanner *p));
00098 static VALUE strscan_getch _((VALUE self));
00099 static VALUE strscan_get_byte _((VALUE self));
00100 static VALUE strscan_getbyte _((VALUE self));
00101 static VALUE strscan_peek _((VALUE self, VALUE len));
00102 static VALUE strscan_peep _((VALUE self, VALUE len));
00103 static VALUE strscan_unscan _((VALUE self));
00104 static VALUE strscan_bol_p _((VALUE self));
00105 static VALUE strscan_eos_p _((VALUE self));
00106 static VALUE strscan_empty_p _((VALUE self));
00107 static VALUE strscan_rest_p _((VALUE self));
00108 static VALUE strscan_matched_p _((VALUE self));
00109 static VALUE strscan_matched _((VALUE self));
00110 static VALUE strscan_matched_size _((VALUE self));
00111 static VALUE strscan_aref _((VALUE self, VALUE idx));
00112 static VALUE strscan_pre_match _((VALUE self));
00113 static VALUE strscan_post_match _((VALUE self));
00114 static VALUE strscan_rest _((VALUE self));
00115 static VALUE strscan_rest_size _((VALUE self));
00116 
00117 static VALUE strscan_inspect _((VALUE self));
00118 static VALUE inspect1 _((struct strscanner *p));
00119 static VALUE inspect2 _((struct strscanner *p));
00120 
00121 /* =======================================================================
00122                                    Utils
00123    ======================================================================= */
00124 
00125 static VALUE
00126 infect(VALUE str, struct strscanner *p)
00127 {
00128     OBJ_INFECT(str, p->str);
00129     return str;
00130 }
00131 
00132 static VALUE
00133 str_new(struct strscanner *p, const char *ptr, long len)
00134 {
00135     VALUE str = rb_str_new(ptr, len);
00136     rb_enc_copy(str, p->str);
00137     return str;
00138 }
00139 
00140 static VALUE
00141 extract_range(struct strscanner *p, long beg_i, long end_i)
00142 {
00143     if (beg_i > S_LEN(p)) return Qnil;
00144     if (end_i > S_LEN(p))
00145         end_i = S_LEN(p);
00146     return infect(str_new(p, S_PBEG(p) + beg_i, end_i - beg_i), p);
00147 }
00148 
00149 static VALUE
00150 extract_beg_len(struct strscanner *p, long beg_i, long len)
00151 {
00152     if (beg_i > S_LEN(p)) return Qnil;
00153     if (beg_i + len > S_LEN(p))
00154         len = S_LEN(p) - beg_i;
00155     return infect(str_new(p, S_PBEG(p) + beg_i, len), p);
00156 }
00157 
00158 /* =======================================================================
00159                                Constructor
00160    ======================================================================= */
00161 
00162 static void
00163 strscan_mark(void *ptr)
00164 {
00165     struct strscanner *p = ptr;
00166     rb_gc_mark(p->str);
00167 }
00168 
00169 static void
00170 strscan_free(void *ptr)
00171 {
00172     struct strscanner *p = ptr;
00173     onig_region_free(&(p->regs), 0);
00174     ruby_xfree(p);
00175 }
00176 
00177 static size_t
00178 strscan_memsize(const void *ptr)
00179 {
00180     const struct strscanner *p = ptr;
00181     size_t size = 0;
00182     if (p) {
00183         size = sizeof(*p) - sizeof(p->regs) + onig_region_memsize(&p->regs);
00184     }
00185     return size;
00186 }
00187 
00188 static const rb_data_type_t strscanner_type = {
00189     "StringScanner",
00190     {strscan_mark, strscan_free, strscan_memsize}
00191 };
00192 
00193 static VALUE
00194 strscan_s_allocate(VALUE klass)
00195 {
00196     struct strscanner *p;
00197 
00198     p = ALLOC(struct strscanner);
00199     MEMZERO(p, struct strscanner, 1);
00200     CLEAR_MATCH_STATUS(p);
00201     onig_region_init(&(p->regs));
00202     p->str = Qnil;
00203     return TypedData_Wrap_Struct(klass, &strscanner_type, p);
00204 }
00205 
00206 /*
00207  * call-seq: StringScanner.new(string, dup = false)
00208  *
00209  * Creates a new StringScanner object to scan over the given +string+.
00210  * +dup+ argument is obsolete and not used now.
00211  */
00212 static VALUE
00213 strscan_initialize(int argc, VALUE *argv, VALUE self)
00214 {
00215     struct strscanner *p;
00216     VALUE str, need_dup;
00217 
00218     p = check_strscan(self);
00219     rb_scan_args(argc, argv, "11", &str, &need_dup);
00220     StringValue(str);
00221     p->str = str;
00222 
00223     return self;
00224 }
00225 
00226 static struct strscanner *
00227 check_strscan(VALUE obj)
00228 {
00229     return rb_check_typeddata(obj, &strscanner_type);
00230 }
00231 
00232 /*
00233  * call-seq:
00234  *   dup
00235  *   clone
00236  *
00237  * Duplicates a StringScanner object.
00238  */
00239 static VALUE
00240 strscan_init_copy(VALUE vself, VALUE vorig)
00241 {
00242     struct strscanner *self, *orig;
00243 
00244     self = check_strscan(vself);
00245     orig = check_strscan(vorig);
00246     if (self != orig) {
00247         self->flags = orig->flags;
00248         self->str = orig->str;
00249         self->prev = orig->prev;
00250         self->curr = orig->curr;
00251         onig_region_copy(&self->regs, &orig->regs);
00252     }
00253 
00254     return vself;
00255 }
00256 
00257 /* =======================================================================
00258                           Instance Methods
00259    ======================================================================= */
00260 
00261 /*
00262  * call-seq: StringScanner.must_C_version
00263  *
00264  * This method is defined for backward compatibility.
00265  */
00266 static VALUE
00267 strscan_s_mustc(VALUE self)
00268 {
00269     return self;
00270 }
00271 
00272 /*
00273  * Reset the scan pointer (index 0) and clear matching data.
00274  */
00275 static VALUE
00276 strscan_reset(VALUE self)
00277 {
00278     struct strscanner *p;
00279 
00280     GET_SCANNER(self, p);
00281     p->curr = 0;
00282     CLEAR_MATCH_STATUS(p);
00283     return self;
00284 }
00285 
00286 /*
00287  * call-seq:
00288  *   terminate
00289  *   clear
00290  *
00291  * Set the scan pointer to the end of the string and clear matching data.
00292  */
00293 static VALUE
00294 strscan_terminate(VALUE self)
00295 {
00296     struct strscanner *p;
00297 
00298     GET_SCANNER(self, p);
00299     p->curr = S_LEN(p);
00300     CLEAR_MATCH_STATUS(p);
00301     return self;
00302 }
00303 
00304 /*
00305  * Equivalent to #terminate.
00306  * This method is obsolete; use #terminate instead.
00307  */
00308 static VALUE
00309 strscan_clear(VALUE self)
00310 {
00311     rb_warning("StringScanner#clear is obsolete; use #terminate instead");
00312     return strscan_terminate(self);
00313 }
00314 
00315 /*
00316  * Returns the string being scanned.
00317  */
00318 static VALUE
00319 strscan_get_string(VALUE self)
00320 {
00321     struct strscanner *p;
00322 
00323     GET_SCANNER(self, p);
00324     return p->str;
00325 }
00326 
00327 /*
00328  * call-seq: string=(str)
00329  *
00330  * Changes the string being scanned to +str+ and resets the scanner.
00331  * Returns +str+.
00332  */
00333 static VALUE
00334 strscan_set_string(VALUE self, VALUE str)
00335 {
00336     struct strscanner *p = check_strscan(self);
00337 
00338     StringValue(str);
00339     p->str = str;
00340     p->curr = 0;
00341     CLEAR_MATCH_STATUS(p);
00342     return str;
00343 }
00344 
00345 /*
00346  * call-seq:
00347  *   concat(str)
00348  *   <<(str)
00349  *
00350  * Appends +str+ to the string being scanned.
00351  * This method does not affect scan pointer.
00352  *
00353  *   s = StringScanner.new("Fri Dec 12 1975 14:39")
00354  *   s.scan(/Fri /)
00355  *   s << " +1000 GMT"
00356  *   s.string            # -> "Fri Dec 12 1975 14:39 +1000 GMT"
00357  *   s.scan(/Dec/)       # -> "Dec"
00358  */
00359 static VALUE
00360 strscan_concat(VALUE self, VALUE str)
00361 {
00362     struct strscanner *p;
00363 
00364     GET_SCANNER(self, p);
00365     StringValue(str);
00366     rb_str_append(p->str, str);
00367     return self;
00368 }
00369 
00370 /*
00371  * Returns the byte position of the scan pointer.  In the 'reset' position, this
00372  * value is zero.  In the 'terminated' position (i.e. the string is exhausted),
00373  * this value is the bytesize of the string.
00374  *
00375  * In short, it's a 0-based index into bytes of the string.
00376  *
00377  *   s = StringScanner.new('test string')
00378  *   s.pos               # -> 0
00379  *   s.scan_until /str/  # -> "test str"
00380  *   s.pos               # -> 8
00381  *   s.terminate         # -> #<StringScanner fin>
00382  *   s.pos               # -> 11
00383  */
00384 static VALUE
00385 strscan_get_pos(VALUE self)
00386 {
00387     struct strscanner *p;
00388 
00389     GET_SCANNER(self, p);
00390     return INT2FIX(p->curr);
00391 }
00392 
00393 /*
00394  * Returns the character position of the scan pointer.  In the 'reset' position, this
00395  * value is zero.  In the 'terminated' position (i.e. the string is exhausted),
00396  * this value is the size of the string.
00397  *
00398  * In short, it's a 0-based index into the string.
00399  *
00400  *   s = StringScanner.new("abcädeföghi")
00401  *   s.charpos           # -> 0
00402  *   s.scan_until(/ä/)   # -> "abcä"
00403  *   s.pos               # -> 5
00404  *   s.charpos           # -> 4
00405  */
00406 static VALUE
00407 strscan_get_charpos(VALUE self)
00408 {
00409     struct strscanner *p;
00410     VALUE substr;
00411 
00412     GET_SCANNER(self, p);
00413 
00414     substr = rb_funcall(p->str, id_byteslice, 2, INT2FIX(0), INT2NUM(p->curr));
00415 
00416     return rb_str_length(substr);
00417 }
00418 
00419 /*
00420  * call-seq: pos=(n)
00421  *
00422  * Set the byte position of the scan pointer.
00423  *
00424  *   s = StringScanner.new('test string')
00425  *   s.pos = 7            # -> 7
00426  *   s.rest               # -> "ring"
00427  */
00428 static VALUE
00429 strscan_set_pos(VALUE self, VALUE v)
00430 {
00431     struct strscanner *p;
00432     long i;
00433 
00434     GET_SCANNER(self, p);
00435     i = NUM2INT(v);
00436     if (i < 0) i += S_LEN(p);
00437     if (i < 0) rb_raise(rb_eRangeError, "index out of range");
00438     if (i > S_LEN(p)) rb_raise(rb_eRangeError, "index out of range");
00439     p->curr = i;
00440     return INT2NUM(i);
00441 }
00442 
00443 static VALUE
00444 strscan_do_scan(VALUE self, VALUE regex, int succptr, int getstr, int headonly)
00445 {
00446     regex_t *rb_reg_prepare_re(VALUE re, VALUE str);
00447     struct strscanner *p;
00448     regex_t *re;
00449     long ret;
00450     int tmpreg;
00451 
00452     Check_Type(regex, T_REGEXP);
00453     GET_SCANNER(self, p);
00454 
00455     CLEAR_MATCH_STATUS(p);
00456     if (S_RESTLEN(p) < 0) {
00457         return Qnil;
00458     }
00459     re = rb_reg_prepare_re(regex, p->str);
00460     tmpreg = re != RREGEXP(regex)->ptr;
00461     if (!tmpreg) RREGEXP(regex)->usecnt++;
00462 
00463     if (headonly) {
00464         ret = onig_match(re, (UChar* )CURPTR(p),
00465                          (UChar* )(CURPTR(p) + S_RESTLEN(p)),
00466                          (UChar* )CURPTR(p), &(p->regs), ONIG_OPTION_NONE);
00467     }
00468     else {
00469         ret = onig_search(re,
00470                           (UChar* )CURPTR(p), (UChar* )(CURPTR(p) + S_RESTLEN(p)),
00471                           (UChar* )CURPTR(p), (UChar* )(CURPTR(p) + S_RESTLEN(p)),
00472                           &(p->regs), ONIG_OPTION_NONE);
00473     }
00474     if (!tmpreg) RREGEXP(regex)->usecnt--;
00475     if (tmpreg) {
00476         if (RREGEXP(regex)->usecnt) {
00477             onig_free(re);
00478         }
00479         else {
00480             onig_free(RREGEXP(regex)->ptr);
00481             RREGEXP(regex)->ptr = re;
00482         }
00483     }
00484 
00485     if (ret == -2) rb_raise(ScanError, "regexp buffer overflow");
00486     if (ret < 0) {
00487         /* not matched */
00488         return Qnil;
00489     }
00490 
00491     MATCHED(p);
00492     p->prev = p->curr;
00493     if (succptr) {
00494         p->curr += p->regs.end[0];
00495     }
00496     if (getstr) {
00497         return extract_beg_len(p, p->prev, p->regs.end[0]);
00498     }
00499     else {
00500         return INT2FIX(p->regs.end[0]);
00501     }
00502 }
00503 
00504 /*
00505  * call-seq: scan(pattern) => String
00506  *
00507  * Tries to match with +pattern+ at the current position. If there's a match,
00508  * the scanner advances the "scan pointer" and returns the matched string.
00509  * Otherwise, the scanner returns +nil+.
00510  *
00511  *   s = StringScanner.new('test string')
00512  *   p s.scan(/\w+/)   # -> "test"
00513  *   p s.scan(/\w+/)   # -> nil
00514  *   p s.scan(/\s+/)   # -> " "
00515  *   p s.scan(/\w+/)   # -> "string"
00516  *   p s.scan(/./)     # -> nil
00517  *
00518  */
00519 static VALUE
00520 strscan_scan(VALUE self, VALUE re)
00521 {
00522     return strscan_do_scan(self, re, 1, 1, 1);
00523 }
00524 
00525 /*
00526  * call-seq: match?(pattern)
00527  *
00528  * Tests whether the given +pattern+ is matched from the current scan pointer.
00529  * Returns the length of the match, or +nil+.  The scan pointer is not advanced.
00530  *
00531  *   s = StringScanner.new('test string')
00532  *   p s.match?(/\w+/)   # -> 4
00533  *   p s.match?(/\w+/)   # -> 4
00534  *   p s.match?(/\s+/)   # -> nil
00535  */
00536 static VALUE
00537 strscan_match_p(VALUE self, VALUE re)
00538 {
00539     return strscan_do_scan(self, re, 0, 0, 1);
00540 }
00541 
00542 /*
00543  * call-seq: skip(pattern)
00544  *
00545  * Attempts to skip over the given +pattern+ beginning with the scan pointer.
00546  * If it matches, the scan pointer is advanced to the end of the match, and the
00547  * length of the match is returned.  Otherwise, +nil+ is returned.
00548  *
00549  * It's similar to #scan, but without returning the matched string.
00550  *
00551  *   s = StringScanner.new('test string')
00552  *   p s.skip(/\w+/)   # -> 4
00553  *   p s.skip(/\w+/)   # -> nil
00554  *   p s.skip(/\s+/)   # -> 1
00555  *   p s.skip(/\w+/)   # -> 6
00556  *   p s.skip(/./)     # -> nil
00557  *
00558  */
00559 static VALUE
00560 strscan_skip(VALUE self, VALUE re)
00561 {
00562     return strscan_do_scan(self, re, 1, 0, 1);
00563 }
00564 
00565 /*
00566  * call-seq: check(pattern)
00567  *
00568  * This returns the value that #scan would return, without advancing the scan
00569  * pointer.  The match register is affected, though.
00570  *
00571  *   s = StringScanner.new("Fri Dec 12 1975 14:39")
00572  *   s.check /Fri/               # -> "Fri"
00573  *   s.pos                       # -> 0
00574  *   s.matched                   # -> "Fri"
00575  *   s.check /12/                # -> nil
00576  *   s.matched                   # -> nil
00577  *
00578  * Mnemonic: it "checks" to see whether a #scan will return a value.
00579  */
00580 static VALUE
00581 strscan_check(VALUE self, VALUE re)
00582 {
00583     return strscan_do_scan(self, re, 0, 1, 1);
00584 }
00585 
00586 /*
00587  * call-seq: scan_full(pattern, advance_pointer_p, return_string_p)
00588  *
00589  * Tests whether the given +pattern+ is matched from the current scan pointer.
00590  * Advances the scan pointer if +advance_pointer_p+ is true.
00591  * Returns the matched string if +return_string_p+ is true.
00592  * The match register is affected.
00593  *
00594  * "full" means "#scan with full parameters".
00595  */
00596 static VALUE
00597 strscan_scan_full(VALUE self, VALUE re, VALUE s, VALUE f)
00598 {
00599     return strscan_do_scan(self, re, RTEST(s), RTEST(f), 1);
00600 }
00601 
00602 /*
00603  * call-seq: scan_until(pattern)
00604  *
00605  * Scans the string _until_ the +pattern+ is matched.  Returns the substring up
00606  * to and including the end of the match, advancing the scan pointer to that
00607  * location. If there is no match, +nil+ is returned.
00608  *
00609  *   s = StringScanner.new("Fri Dec 12 1975 14:39")
00610  *   s.scan_until(/1/)        # -> "Fri Dec 1"
00611  *   s.pre_match              # -> "Fri Dec "
00612  *   s.scan_until(/XYZ/)      # -> nil
00613  */
00614 static VALUE
00615 strscan_scan_until(VALUE self, VALUE re)
00616 {
00617     return strscan_do_scan(self, re, 1, 1, 0);
00618 }
00619 
00620 /*
00621  * call-seq: exist?(pattern)
00622  *
00623  * Looks _ahead_ to see if the +pattern+ exists _anywhere_ in the string,
00624  * without advancing the scan pointer.  This predicates whether a #scan_until
00625  * will return a value.
00626  *
00627  *   s = StringScanner.new('test string')
00628  *   s.exist? /s/            # -> 3
00629  *   s.scan /test/           # -> "test"
00630  *   s.exist? /s/            # -> 2
00631  *   s.exist? /e/            # -> nil
00632  */
00633 static VALUE
00634 strscan_exist_p(VALUE self, VALUE re)
00635 {
00636     return strscan_do_scan(self, re, 0, 0, 0);
00637 }
00638 
00639 /*
00640  * call-seq: skip_until(pattern)
00641  *
00642  * Advances the scan pointer until +pattern+ is matched and consumed.  Returns
00643  * the number of bytes advanced, or +nil+ if no match was found.
00644  *
00645  * Look ahead to match +pattern+, and advance the scan pointer to the _end_
00646  * of the match.  Return the number of characters advanced, or +nil+ if the
00647  * match was unsuccessful.
00648  *
00649  * It's similar to #scan_until, but without returning the intervening string.
00650  *
00651  *   s = StringScanner.new("Fri Dec 12 1975 14:39")
00652  *   s.skip_until /12/           # -> 10
00653  *   s                           #
00654  */
00655 static VALUE
00656 strscan_skip_until(VALUE self, VALUE re)
00657 {
00658     return strscan_do_scan(self, re, 1, 0, 0);
00659 }
00660 
00661 /*
00662  * call-seq: check_until(pattern)
00663  *
00664  * This returns the value that #scan_until would return, without advancing the
00665  * scan pointer.  The match register is affected, though.
00666  *
00667  *   s = StringScanner.new("Fri Dec 12 1975 14:39")
00668  *   s.check_until /12/          # -> "Fri Dec 12"
00669  *   s.pos                       # -> 0
00670  *   s.matched                   # -> 12
00671  *
00672  * Mnemonic: it "checks" to see whether a #scan_until will return a value.
00673  */
00674 static VALUE
00675 strscan_check_until(VALUE self, VALUE re)
00676 {
00677     return strscan_do_scan(self, re, 0, 1, 0);
00678 }
00679 
00680 /*
00681  * call-seq: search_full(pattern, advance_pointer_p, return_string_p)
00682  *
00683  * Scans the string _until_ the +pattern+ is matched.
00684  * Advances the scan pointer if +advance_pointer_p+, otherwise not.
00685  * Returns the matched string if +return_string_p+ is true, otherwise
00686  * returns the number of bytes advanced.
00687  * This method does affect the match register.
00688  */
00689 static VALUE
00690 strscan_search_full(VALUE self, VALUE re, VALUE s, VALUE f)
00691 {
00692     return strscan_do_scan(self, re, RTEST(s), RTEST(f), 0);
00693 }
00694 
00695 static void
00696 adjust_registers_to_matched(struct strscanner *p)
00697 {
00698     onig_region_clear(&(p->regs));
00699     onig_region_set(&(p->regs), 0, 0, (int)(p->curr - p->prev));
00700 }
00701 
00702 /*
00703  * Scans one character and returns it.
00704  * This method is multibyte character sensitive.
00705  *
00706  *   s = StringScanner.new("ab")
00707  *   s.getch           # => "a"
00708  *   s.getch           # => "b"
00709  *   s.getch           # => nil
00710  *
00711  *   $KCODE = 'EUC'
00712  *   s = StringScanner.new("\244\242")
00713  *   s.getch           # => "\244\242"   # Japanese hira-kana "A" in EUC-JP
00714  *   s.getch           # => nil
00715  */
00716 static VALUE
00717 strscan_getch(VALUE self)
00718 {
00719     struct strscanner *p;
00720     long len;
00721 
00722     GET_SCANNER(self, p);
00723     CLEAR_MATCH_STATUS(p);
00724     if (EOS_P(p))
00725         return Qnil;
00726 
00727     len = rb_enc_mbclen(CURPTR(p), S_PEND(p), rb_enc_get(p->str));
00728     if (p->curr + len > S_LEN(p)) {
00729         len = S_LEN(p) - p->curr;
00730     }
00731     p->prev = p->curr;
00732     p->curr += len;
00733     MATCHED(p);
00734     adjust_registers_to_matched(p);
00735     return extract_range(p, p->prev + p->regs.beg[0],
00736                             p->prev + p->regs.end[0]);
00737 }
00738 
00739 /*
00740  * Scans one byte and returns it.
00741  * This method is not multibyte character sensitive.
00742  * See also: #getch.
00743  *
00744  *   s = StringScanner.new('ab')
00745  *   s.get_byte         # => "a"
00746  *   s.get_byte         # => "b"
00747  *   s.get_byte         # => nil
00748  *
00749  *   $KCODE = 'EUC'
00750  *   s = StringScanner.new("\244\242")
00751  *   s.get_byte         # => "\244"
00752  *   s.get_byte         # => "\242"
00753  *   s.get_byte         # => nil
00754  */
00755 static VALUE
00756 strscan_get_byte(VALUE self)
00757 {
00758     struct strscanner *p;
00759 
00760     GET_SCANNER(self, p);
00761     CLEAR_MATCH_STATUS(p);
00762     if (EOS_P(p))
00763         return Qnil;
00764 
00765     p->prev = p->curr;
00766     p->curr++;
00767     MATCHED(p);
00768     adjust_registers_to_matched(p);
00769     return extract_range(p, p->prev + p->regs.beg[0],
00770                             p->prev + p->regs.end[0]);
00771 }
00772 
00773 /*
00774  * Equivalent to #get_byte.
00775  * This method is obsolete; use #get_byte instead.
00776  */
00777 static VALUE
00778 strscan_getbyte(VALUE self)
00779 {
00780     rb_warning("StringScanner#getbyte is obsolete; use #get_byte instead");
00781     return strscan_get_byte(self);
00782 }
00783 
00784 /*
00785  * call-seq: peek(len)
00786  *
00787  * Extracts a string corresponding to <tt>string[pos,len]</tt>, without
00788  * advancing the scan pointer.
00789  *
00790  *   s = StringScanner.new('test string')
00791  *   s.peek(7)          # => "test st"
00792  *   s.peek(7)          # => "test st"
00793  *
00794  */
00795 static VALUE
00796 strscan_peek(VALUE self, VALUE vlen)
00797 {
00798     struct strscanner *p;
00799     long len;
00800 
00801     GET_SCANNER(self, p);
00802 
00803     len = NUM2LONG(vlen);
00804     if (EOS_P(p))
00805         return infect(str_new(p, "", 0), p);
00806 
00807     if (p->curr + len > S_LEN(p))
00808         len = S_LEN(p) - p->curr;
00809     return extract_beg_len(p, p->curr, len);
00810 }
00811 
00812 /*
00813  * Equivalent to #peek.
00814  * This method is obsolete; use #peek instead.
00815  */
00816 static VALUE
00817 strscan_peep(VALUE self, VALUE vlen)
00818 {
00819     rb_warning("StringScanner#peep is obsolete; use #peek instead");
00820     return strscan_peek(self, vlen);
00821 }
00822 
00823 /*
00824  * Set the scan pointer to the previous position.  Only one previous position is
00825  * remembered, and it changes with each scanning operation.
00826  *
00827  *   s = StringScanner.new('test string')
00828  *   s.scan(/\w+/)        # => "test"
00829  *   s.unscan
00830  *   s.scan(/../)         # => "te"
00831  *   s.scan(/\d/)         # => nil
00832  *   s.unscan             # ScanError: unscan failed: previous match record not exist
00833  */
00834 static VALUE
00835 strscan_unscan(VALUE self)
00836 {
00837     struct strscanner *p;
00838 
00839     GET_SCANNER(self, p);
00840     if (! MATCHED_P(p))
00841         rb_raise(ScanError, "unscan failed: previous match record not exist");
00842     p->curr = p->prev;
00843     CLEAR_MATCH_STATUS(p);
00844     return self;
00845 }
00846 
00847 /*
00848  * Returns +true+ iff the scan pointer is at the beginning of the line.
00849  *
00850  *   s = StringScanner.new("test\ntest\n")
00851  *   s.bol?           # => true
00852  *   s.scan(/te/)
00853  *   s.bol?           # => false
00854  *   s.scan(/st\n/)
00855  *   s.bol?           # => true
00856  *   s.terminate
00857  *   s.bol?           # => true
00858  */
00859 static VALUE
00860 strscan_bol_p(VALUE self)
00861 {
00862     struct strscanner *p;
00863 
00864     GET_SCANNER(self, p);
00865     if (CURPTR(p) > S_PEND(p)) return Qnil;
00866     if (p->curr == 0) return Qtrue;
00867     return (*(CURPTR(p) - 1) == '\n') ? Qtrue : Qfalse;
00868 }
00869 
00870 /*
00871  * Returns +true+ if the scan pointer is at the end of the string.
00872  *
00873  *   s = StringScanner.new('test string')
00874  *   p s.eos?          # => false
00875  *   s.scan(/test/)
00876  *   p s.eos?          # => false
00877  *   s.terminate
00878  *   p s.eos?          # => true
00879  */
00880 static VALUE
00881 strscan_eos_p(VALUE self)
00882 {
00883     struct strscanner *p;
00884 
00885     GET_SCANNER(self, p);
00886     return EOS_P(p) ? Qtrue : Qfalse;
00887 }
00888 
00889 /*
00890  * Equivalent to #eos?.
00891  * This method is obsolete, use #eos? instead.
00892  */
00893 static VALUE
00894 strscan_empty_p(VALUE self)
00895 {
00896     rb_warning("StringScanner#empty? is obsolete; use #eos? instead");
00897     return strscan_eos_p(self);
00898 }
00899 
00900 /*
00901  * Returns true iff there is more data in the string.  See #eos?.
00902  * This method is obsolete; use #eos? instead.
00903  *
00904  *   s = StringScanner.new('test string')
00905  *   s.eos?              # These two
00906  *   s.rest?             # are opposites.
00907  */
00908 static VALUE
00909 strscan_rest_p(VALUE self)
00910 {
00911     struct strscanner *p;
00912 
00913     GET_SCANNER(self, p);
00914     return EOS_P(p) ? Qfalse : Qtrue;
00915 }
00916 
00917 /*
00918  * Returns +true+ iff the last match was successful.
00919  *
00920  *   s = StringScanner.new('test string')
00921  *   s.match?(/\w+/)     # => 4
00922  *   s.matched?          # => true
00923  *   s.match?(/\d+/)     # => nil
00924  *   s.matched?          # => false
00925  */
00926 static VALUE
00927 strscan_matched_p(VALUE self)
00928 {
00929     struct strscanner *p;
00930 
00931     GET_SCANNER(self, p);
00932     return MATCHED_P(p) ? Qtrue : Qfalse;
00933 }
00934 
00935 /*
00936  * Returns the last matched string.
00937  *
00938  *   s = StringScanner.new('test string')
00939  *   s.match?(/\w+/)     # -> 4
00940  *   s.matched           # -> "test"
00941  */
00942 static VALUE
00943 strscan_matched(VALUE self)
00944 {
00945     struct strscanner *p;
00946 
00947     GET_SCANNER(self, p);
00948     if (! MATCHED_P(p)) return Qnil;
00949     return extract_range(p, p->prev + p->regs.beg[0],
00950                             p->prev + p->regs.end[0]);
00951 }
00952 
00953 /*
00954  * Returns the size of the most recent match (see #matched), or +nil+ if there
00955  * was no recent match.
00956  *
00957  *   s = StringScanner.new('test string')
00958  *   s.check /\w+/           # -> "test"
00959  *   s.matched_size          # -> 4
00960  *   s.check /\d+/           # -> nil
00961  *   s.matched_size          # -> nil
00962  */
00963 static VALUE
00964 strscan_matched_size(VALUE self)
00965 {
00966     struct strscanner *p;
00967 
00968     GET_SCANNER(self, p);
00969     if (! MATCHED_P(p)) return Qnil;
00970     return INT2NUM(p->regs.end[0] - p->regs.beg[0]);
00971 }
00972 
00973 /*
00974  * call-seq: [](n)
00975  *
00976  * Return the n-th subgroup in the most recent match.
00977  *
00978  *   s = StringScanner.new("Fri Dec 12 1975 14:39")
00979  *   s.scan(/(\w+) (\w+) (\d+) /)       # -> "Fri Dec 12 "
00980  *   s[0]                               # -> "Fri Dec 12 "
00981  *   s[1]                               # -> "Fri"
00982  *   s[2]                               # -> "Dec"
00983  *   s[3]                               # -> "12"
00984  *   s.post_match                       # -> "1975 14:39"
00985  *   s.pre_match                        # -> ""
00986  */
00987 static VALUE
00988 strscan_aref(VALUE self, VALUE idx)
00989 {
00990     struct strscanner *p;
00991     long i;
00992 
00993     GET_SCANNER(self, p);
00994     if (! MATCHED_P(p))        return Qnil;
00995 
00996     i = NUM2LONG(idx);
00997     if (i < 0)
00998         i += p->regs.num_regs;
00999     if (i < 0)                 return Qnil;
01000     if (i >= p->regs.num_regs) return Qnil;
01001     if (p->regs.beg[i] == -1)  return Qnil;
01002 
01003     return extract_range(p, p->prev + p->regs.beg[i],
01004                             p->prev + p->regs.end[i]);
01005 }
01006 
01007 /*
01008  * Return the <i><b>pre</b>-match</i> (in the regular expression sense) of the last scan.
01009  *
01010  *   s = StringScanner.new('test string')
01011  *   s.scan(/\w+/)           # -> "test"
01012  *   s.scan(/\s+/)           # -> " "
01013  *   s.pre_match             # -> "test"
01014  *   s.post_match            # -> "string"
01015  */
01016 static VALUE
01017 strscan_pre_match(VALUE self)
01018 {
01019     struct strscanner *p;
01020 
01021     GET_SCANNER(self, p);
01022     if (! MATCHED_P(p)) return Qnil;
01023     return extract_range(p, 0, p->prev + p->regs.beg[0]);
01024 }
01025 
01026 /*
01027  * Return the <i><b>post</b>-match</i> (in the regular expression sense) of the last scan.
01028  *
01029  *   s = StringScanner.new('test string')
01030  *   s.scan(/\w+/)           # -> "test"
01031  *   s.scan(/\s+/)           # -> " "
01032  *   s.pre_match             # -> "test"
01033  *   s.post_match            # -> "string"
01034  */
01035 static VALUE
01036 strscan_post_match(VALUE self)
01037 {
01038     struct strscanner *p;
01039 
01040     GET_SCANNER(self, p);
01041     if (! MATCHED_P(p)) return Qnil;
01042     return extract_range(p, p->prev + p->regs.end[0], S_LEN(p));
01043 }
01044 
01045 /*
01046  * Returns the "rest" of the string (i.e. everything after the scan pointer).
01047  * If there is no more data (eos? = true), it returns <tt>""</tt>.
01048  */
01049 static VALUE
01050 strscan_rest(VALUE self)
01051 {
01052     struct strscanner *p;
01053 
01054     GET_SCANNER(self, p);
01055     if (EOS_P(p)) {
01056         return infect(str_new(p, "", 0), p);
01057     }
01058     return extract_range(p, p->curr, S_LEN(p));
01059 }
01060 
01061 /*
01062  * <tt>s.rest_size</tt> is equivalent to <tt>s.rest.size</tt>.
01063  */
01064 static VALUE
01065 strscan_rest_size(VALUE self)
01066 {
01067     struct strscanner *p;
01068     long i;
01069 
01070     GET_SCANNER(self, p);
01071     if (EOS_P(p)) {
01072         return INT2FIX(0);
01073     }
01074     i = S_LEN(p) - p->curr;
01075     return INT2FIX(i);
01076 }
01077 
01078 /*
01079  * <tt>s.restsize</tt> is equivalent to <tt>s.rest_size</tt>.
01080  * This method is obsolete; use #rest_size instead.
01081  */
01082 static VALUE
01083 strscan_restsize(VALUE self)
01084 {
01085     rb_warning("StringScanner#restsize is obsolete; use #rest_size instead");
01086     return strscan_rest_size(self);
01087 }
01088 
01089 #define INSPECT_LENGTH 5
01090 #define BUFSIZE 256
01091 
01092 /*
01093  * Returns a string that represents the StringScanner object, showing:
01094  * - the current position
01095  * - the size of the string
01096  * - the characters surrounding the scan pointer
01097  *
01098  *   s = StringScanner.new("Fri Dec 12 1975 14:39")
01099  *   s.inspect            # -> '#<StringScanner 0/21 @ "Fri D...">'
01100  *   s.scan_until /12/    # -> "Fri Dec 12"
01101  *   s.inspect            # -> '#<StringScanner 10/21 "...ec 12" @ " 1975...">'
01102  */
01103 static VALUE
01104 strscan_inspect(VALUE self)
01105 {
01106     struct strscanner *p;
01107     char buf[BUFSIZE];
01108     long len;
01109     VALUE a, b;
01110 
01111     p = check_strscan(self);
01112     if (NIL_P(p->str)) {
01113         len = snprintf(buf, BUFSIZE, "#<%s (uninitialized)>",
01114                        rb_class2name(CLASS_OF(self)));
01115         return infect(rb_str_new(buf, len), p);
01116     }
01117     if (EOS_P(p)) {
01118         len = snprintf(buf, BUFSIZE, "#<%s fin>",
01119                        rb_class2name(CLASS_OF(self)));
01120         return infect(rb_str_new(buf, len), p);
01121     }
01122     if (p->curr == 0) {
01123         b = inspect2(p);
01124         len = snprintf(buf, BUFSIZE, "#<%s %ld/%ld @ %s>",
01125                        rb_class2name(CLASS_OF(self)),
01126                        p->curr, S_LEN(p),
01127                        RSTRING_PTR(b));
01128         return infect(rb_str_new(buf, len), p);
01129     }
01130     a = inspect1(p);
01131     b = inspect2(p);
01132     len = snprintf(buf, BUFSIZE, "#<%s %ld/%ld %s @ %s>",
01133                    rb_class2name(CLASS_OF(self)),
01134                    p->curr, S_LEN(p),
01135                    RSTRING_PTR(a),
01136                    RSTRING_PTR(b));
01137     return infect(rb_str_new(buf, len), p);
01138 }
01139 
01140 static VALUE
01141 inspect1(struct strscanner *p)
01142 {
01143     char buf[BUFSIZE];
01144     char *bp = buf;
01145     long len;
01146 
01147     if (p->curr == 0) return rb_str_new2("");
01148     if (p->curr > INSPECT_LENGTH) {
01149         strcpy(bp, "..."); bp += 3;
01150         len = INSPECT_LENGTH;
01151     }
01152     else {
01153         len = p->curr;
01154     }
01155     memcpy(bp, CURPTR(p) - len, len); bp += len;
01156     return rb_str_dump(rb_str_new(buf, bp - buf));
01157 }
01158 
01159 static VALUE
01160 inspect2(struct strscanner *p)
01161 {
01162     char buf[BUFSIZE];
01163     char *bp = buf;
01164     long len;
01165 
01166     if (EOS_P(p)) return rb_str_new2("");
01167     len = S_LEN(p) - p->curr;
01168     if (len > INSPECT_LENGTH) {
01169         len = INSPECT_LENGTH;
01170         memcpy(bp, CURPTR(p), len); bp += len;
01171         strcpy(bp, "..."); bp += 3;
01172     }
01173     else {
01174         memcpy(bp, CURPTR(p), len); bp += len;
01175     }
01176     return rb_str_dump(rb_str_new(buf, bp - buf));
01177 }
01178 
01179 /* =======================================================================
01180                               Ruby Interface
01181    ======================================================================= */
01182 
01183 /*
01184  * Document-class: StringScanner
01185  *
01186  * StringScanner provides for lexical scanning operations on a String.  Here is
01187  * an example of its usage:
01188  *
01189  *   s = StringScanner.new('This is an example string')
01190  *   s.eos?               # -> false
01191  *
01192  *   p s.scan(/\w+/)      # -> "This"
01193  *   p s.scan(/\w+/)      # -> nil
01194  *   p s.scan(/\s+/)      # -> " "
01195  *   p s.scan(/\s+/)      # -> nil
01196  *   p s.scan(/\w+/)      # -> "is"
01197  *   s.eos?               # -> false
01198  *
01199  *   p s.scan(/\s+/)      # -> " "
01200  *   p s.scan(/\w+/)      # -> "an"
01201  *   p s.scan(/\s+/)      # -> " "
01202  *   p s.scan(/\w+/)      # -> "example"
01203  *   p s.scan(/\s+/)      # -> " "
01204  *   p s.scan(/\w+/)      # -> "string"
01205  *   s.eos?               # -> true
01206  *
01207  *   p s.scan(/\s+/)      # -> nil
01208  *   p s.scan(/\w+/)      # -> nil
01209  *
01210  * Scanning a string means remembering the position of a <i>scan pointer</i>,
01211  * which is just an index.  The point of scanning is to move forward a bit at
01212  * a time, so matches are sought after the scan pointer; usually immediately
01213  * after it.
01214  *
01215  * Given the string "test string", here are the pertinent scan pointer
01216  * positions:
01217  *
01218  *     t e s t   s t r i n g
01219  *   0 1 2 ...             1
01220  *                         0
01221  *
01222  * When you #scan for a pattern (a regular expression), the match must occur
01223  * at the character after the scan pointer.  If you use #scan_until, then the
01224  * match can occur anywhere after the scan pointer.  In both cases, the scan
01225  * pointer moves <i>just beyond</i> the last character of the match, ready to
01226  * scan again from the next character onwards.  This is demonstrated by the
01227  * example above.
01228  *
01229  * == Method Categories
01230  *
01231  * There are other methods besides the plain scanners.  You can look ahead in
01232  * the string without actually scanning.  You can access the most recent match.
01233  * You can modify the string being scanned, reset or terminate the scanner,
01234  * find out or change the position of the scan pointer, skip ahead, and so on.
01235  *
01236  * === Advancing the Scan Pointer
01237  *
01238  * - #getch
01239  * - #get_byte
01240  * - #scan
01241  * - #scan_until
01242  * - #skip
01243  * - #skip_until
01244  *
01245  * === Looking Ahead
01246  *
01247  * - #check
01248  * - #check_until
01249  * - #exist?
01250  * - #match?
01251  * - #peek
01252  *
01253  * === Finding Where we Are
01254  *
01255  * - #beginning_of_line? (#bol?)
01256  * - #eos?
01257  * - #rest?
01258  * - #rest_size
01259  * - #pos
01260  *
01261  * === Setting Where we Are
01262  *
01263  * - #reset
01264  * - #terminate
01265  * - #pos=
01266  *
01267  * === Match Data
01268  *
01269  * - #matched
01270  * - #matched?
01271  * - #matched_size
01272  * - []
01273  * - #pre_match
01274  * - #post_match
01275  *
01276  * === Miscellaneous
01277  *
01278  * - <<
01279  * - #concat
01280  * - #string
01281  * - #string=
01282  * - #unscan
01283  *
01284  * There are aliases to several of the methods.
01285  */
01286 void
01287 Init_strscan()
01288 {
01289     ID id_scanerr = rb_intern("ScanError");
01290     VALUE tmp;
01291 
01292     id_byteslice = rb_intern("byteslice");
01293 
01294     StringScanner = rb_define_class("StringScanner", rb_cObject);
01295     ScanError = rb_define_class_under(StringScanner, "Error", rb_eStandardError);
01296     if (!rb_const_defined(rb_cObject, id_scanerr)) {
01297         rb_const_set(rb_cObject, id_scanerr, ScanError);
01298     }
01299     tmp = rb_str_new2(STRSCAN_VERSION);
01300     rb_obj_freeze(tmp);
01301     rb_const_set(StringScanner, rb_intern("Version"), tmp);
01302     tmp = rb_str_new2("$Id: strscan.c 37916 2012-11-28 00:17:33Z ryan $");
01303     rb_obj_freeze(tmp);
01304     rb_const_set(StringScanner, rb_intern("Id"), tmp);
01305 
01306     rb_define_alloc_func(StringScanner, strscan_s_allocate);
01307     rb_define_private_method(StringScanner, "initialize", strscan_initialize, -1);
01308     rb_define_private_method(StringScanner, "initialize_copy", strscan_init_copy, 1);
01309     rb_define_singleton_method(StringScanner, "must_C_version", strscan_s_mustc, 0);
01310     rb_define_method(StringScanner, "reset",       strscan_reset,       0);
01311     rb_define_method(StringScanner, "terminate",   strscan_terminate,   0);
01312     rb_define_method(StringScanner, "clear",       strscan_clear,       0);
01313     rb_define_method(StringScanner, "string",      strscan_get_string,  0);
01314     rb_define_method(StringScanner, "string=",     strscan_set_string,  1);
01315     rb_define_method(StringScanner, "concat",      strscan_concat,      1);
01316     rb_define_method(StringScanner, "<<",          strscan_concat,      1);
01317     rb_define_method(StringScanner, "pos",         strscan_get_pos,     0);
01318     rb_define_method(StringScanner, "pos=",        strscan_set_pos,     1);
01319     rb_define_method(StringScanner, "charpos",     strscan_get_charpos, 0);
01320     rb_define_method(StringScanner, "pointer",     strscan_get_pos,     0);
01321     rb_define_method(StringScanner, "pointer=",    strscan_set_pos,     1);
01322 
01323     rb_define_method(StringScanner, "scan",        strscan_scan,        1);
01324     rb_define_method(StringScanner, "skip",        strscan_skip,        1);
01325     rb_define_method(StringScanner, "match?",      strscan_match_p,     1);
01326     rb_define_method(StringScanner, "check",       strscan_check,       1);
01327     rb_define_method(StringScanner, "scan_full",   strscan_scan_full,   3);
01328 
01329     rb_define_method(StringScanner, "scan_until",  strscan_scan_until,  1);
01330     rb_define_method(StringScanner, "skip_until",  strscan_skip_until,  1);
01331     rb_define_method(StringScanner, "exist?",      strscan_exist_p,     1);
01332     rb_define_method(StringScanner, "check_until", strscan_check_until, 1);
01333     rb_define_method(StringScanner, "search_full", strscan_search_full, 3);
01334 
01335     rb_define_method(StringScanner, "getch",       strscan_getch,       0);
01336     rb_define_method(StringScanner, "get_byte",    strscan_get_byte,    0);
01337     rb_define_method(StringScanner, "getbyte",     strscan_getbyte,     0);
01338     rb_define_method(StringScanner, "peek",        strscan_peek,        1);
01339     rb_define_method(StringScanner, "peep",        strscan_peep,        1);
01340 
01341     rb_define_method(StringScanner, "unscan",      strscan_unscan,      0);
01342 
01343     rb_define_method(StringScanner, "beginning_of_line?", strscan_bol_p, 0);
01344     rb_alias(StringScanner, rb_intern("bol?"), rb_intern("beginning_of_line?"));
01345     rb_define_method(StringScanner, "eos?",        strscan_eos_p,       0);
01346     rb_define_method(StringScanner, "empty?",      strscan_empty_p,     0);
01347     rb_define_method(StringScanner, "rest?",       strscan_rest_p,      0);
01348 
01349     rb_define_method(StringScanner, "matched?",    strscan_matched_p,   0);
01350     rb_define_method(StringScanner, "matched",     strscan_matched,     0);
01351     rb_define_method(StringScanner, "matched_size", strscan_matched_size, 0);
01352     rb_define_method(StringScanner, "[]",          strscan_aref,        1);
01353     rb_define_method(StringScanner, "pre_match",   strscan_pre_match,   0);
01354     rb_define_method(StringScanner, "post_match",  strscan_post_match,  0);
01355 
01356     rb_define_method(StringScanner, "rest",        strscan_rest,        0);
01357     rb_define_method(StringScanner, "rest_size",   strscan_rest_size,   0);
01358     rb_define_method(StringScanner, "restsize",    strscan_restsize,    0);
01359 
01360     rb_define_method(StringScanner, "inspect",     strscan_inspect,     0);
01361 }
01362