ext/strscan/strscan.c

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

Generated on 19 Jul 2016 for Ruby by  doxygen 1.4.7