00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "ruby/ruby.h"
00012 #include "ruby/re.h"
00013 #include "ruby/encoding.h"
00014
00015 #define STRSCAN_VERSION "0.7.0"
00016
00017
00018
00019
00020
00021 static VALUE StringScanner;
00022 static VALUE ScanError;
00023
00024 struct strscanner
00025 {
00026
00027 unsigned long flags;
00028 #define FLAG_MATCHED (1 << 0)
00029
00030
00031 VALUE str;
00032
00033
00034 long prev;
00035 long curr;
00036
00037
00038 struct re_registers regs;
00039 };
00040
00041 #define MATCHED_P(s) ((s)->flags & FLAG_MATCHED)
00042 #define MATCHED(s) (s)->flags |= FLAG_MATCHED
00043 #define CLEAR_MATCH_STATUS(s) (s)->flags &= ~FLAG_MATCHED
00044
00045 #define S_PBEG(s) (RSTRING_PTR((s)->str))
00046 #define S_LEN(s) (RSTRING_LEN((s)->str))
00047 #define S_PEND(s) (S_PBEG(s) + S_LEN(s))
00048 #define CURPTR(s) (S_PBEG(s) + (s)->curr)
00049 #define S_RESTLEN(s) (S_LEN(s) - (s)->curr)
00050
00051 #define EOS_P(s) ((s)->curr >= RSTRING_LEN(p->str))
00052
00053 #define GET_SCANNER(obj,var) do {\
00054 Data_Get_Struct(obj, struct strscanner, var);\
00055 if (NIL_P(var->str)) rb_raise(rb_eArgError, "uninitialized StringScanner object");\
00056 } while (0)
00057
00058
00059
00060
00061
00062 static VALUE infect _((VALUE str, struct strscanner *p));
00063 static VALUE extract_range _((struct strscanner *p, long beg_i, long end_i));
00064 static VALUE extract_beg_len _((struct strscanner *p, long beg_i, long len));
00065
00066 void check_strscan _((VALUE obj));
00067 static void strscan_mark _((struct strscanner *p));
00068 static void strscan_free _((struct strscanner *p));
00069 static VALUE strscan_s_allocate _((VALUE klass));
00070 static VALUE strscan_initialize _((int argc, VALUE *argv, VALUE self));
00071 static VALUE strscan_init_copy _((VALUE vself, VALUE vorig));
00072
00073 static VALUE strscan_s_mustc _((VALUE self));
00074 static VALUE strscan_terminate _((VALUE self));
00075 static VALUE strscan_clear _((VALUE self));
00076 static VALUE strscan_get_string _((VALUE self));
00077 static VALUE strscan_set_string _((VALUE self, VALUE str));
00078 static VALUE strscan_concat _((VALUE self, VALUE str));
00079 static VALUE strscan_get_pos _((VALUE self));
00080 static VALUE strscan_set_pos _((VALUE self, VALUE pos));
00081 static VALUE strscan_do_scan _((VALUE self, VALUE regex,
00082 int succptr, int getstr, int headonly));
00083 static VALUE strscan_scan _((VALUE self, VALUE re));
00084 static VALUE strscan_match_p _((VALUE self, VALUE re));
00085 static VALUE strscan_skip _((VALUE self, VALUE re));
00086 static VALUE strscan_check _((VALUE self, VALUE re));
00087 static VALUE strscan_scan_full _((VALUE self, VALUE re,
00088 VALUE succp, VALUE getp));
00089 static VALUE strscan_scan_until _((VALUE self, VALUE re));
00090 static VALUE strscan_skip_until _((VALUE self, VALUE re));
00091 static VALUE strscan_check_until _((VALUE self, VALUE re));
00092 static VALUE strscan_search_full _((VALUE self, VALUE re,
00093 VALUE succp, VALUE getp));
00094 static void adjust_registers_to_matched _((struct strscanner *p));
00095 static VALUE strscan_getch _((VALUE self));
00096 static VALUE strscan_get_byte _((VALUE self));
00097 static VALUE strscan_getbyte _((VALUE self));
00098 static VALUE strscan_peek _((VALUE self, VALUE len));
00099 static VALUE strscan_peep _((VALUE self, VALUE len));
00100 static VALUE strscan_unscan _((VALUE self));
00101 static VALUE strscan_bol_p _((VALUE self));
00102 static VALUE strscan_eos_p _((VALUE self));
00103 static VALUE strscan_empty_p _((VALUE self));
00104 static VALUE strscan_rest_p _((VALUE self));
00105 static VALUE strscan_matched_p _((VALUE self));
00106 static VALUE strscan_matched _((VALUE self));
00107 static VALUE strscan_matched_size _((VALUE self));
00108 static VALUE strscan_aref _((VALUE self, VALUE idx));
00109 static VALUE strscan_pre_match _((VALUE self));
00110 static VALUE strscan_post_match _((VALUE self));
00111 static VALUE strscan_rest _((VALUE self));
00112 static VALUE strscan_rest_size _((VALUE self));
00113
00114 static VALUE strscan_inspect _((VALUE self));
00115 static VALUE inspect1 _((struct strscanner *p));
00116 static VALUE inspect2 _((struct strscanner *p));
00117
00118
00119
00120
00121
00122 static VALUE
00123 infect(VALUE str, struct strscanner *p)
00124 {
00125 OBJ_INFECT(str, p->str);
00126 return str;
00127 }
00128
00129 static VALUE
00130 str_new(struct strscanner *p, const char *ptr, long len)
00131 {
00132 VALUE str = rb_str_new(ptr, len);
00133 rb_enc_copy(str, p->str);
00134 return str;
00135 }
00136
00137 static VALUE
00138 extract_range(struct strscanner *p, long beg_i, long end_i)
00139 {
00140 if (beg_i > S_LEN(p)) return Qnil;
00141 if (end_i > S_LEN(p))
00142 end_i = S_LEN(p);
00143 return infect(str_new(p, S_PBEG(p) + beg_i, end_i - beg_i), p);
00144 }
00145
00146 static VALUE
00147 extract_beg_len(struct strscanner *p, long beg_i, long len)
00148 {
00149 if (beg_i > S_LEN(p)) return Qnil;
00150 if (beg_i + len > S_LEN(p))
00151 len = S_LEN(p) - beg_i;
00152 return infect(str_new(p, S_PBEG(p) + beg_i, len), p);
00153 }
00154
00155
00156
00157
00158
00159 static void
00160 strscan_mark(struct strscanner *p)
00161 {
00162 rb_gc_mark(p->str);
00163 }
00164
00165 static void
00166 strscan_free(struct strscanner *p)
00167 {
00168 onig_region_free(&(p->regs), 0);
00169 ruby_xfree(p);
00170 }
00171
00172 static VALUE
00173 strscan_s_allocate(VALUE klass)
00174 {
00175 struct strscanner *p;
00176
00177 p = ALLOC(struct strscanner);
00178 MEMZERO(p, struct strscanner, 1);
00179 CLEAR_MATCH_STATUS(p);
00180 onig_region_init(&(p->regs));
00181 p->str = Qnil;
00182 return Data_Wrap_Struct(klass, strscan_mark, strscan_free, p);
00183 }
00184
00185
00186
00187
00188
00189
00190
00191 static VALUE
00192 strscan_initialize(int argc, VALUE *argv, VALUE self)
00193 {
00194 struct strscanner *p;
00195 VALUE str, need_dup;
00196
00197 Data_Get_Struct(self, struct strscanner, p);
00198 rb_scan_args(argc, argv, "11", &str, &need_dup);
00199 StringValue(str);
00200 p->str = str;
00201
00202 return self;
00203 }
00204
00205 void
00206 check_strscan(VALUE obj)
00207 {
00208 if (TYPE(obj) != T_DATA || RDATA(obj)->dmark != (RUBY_DATA_FUNC)strscan_mark) {
00209 rb_raise(rb_eTypeError,
00210 "wrong argument type %s (expected StringScanner)",
00211 rb_obj_classname(obj));
00212 }
00213 }
00214
00215
00216
00217
00218
00219
00220
00221
00222 static VALUE
00223 strscan_init_copy(VALUE vself, VALUE vorig)
00224 {
00225 struct strscanner *self, *orig;
00226
00227 Data_Get_Struct(vself, struct strscanner, self);
00228 check_strscan(vorig);
00229 Data_Get_Struct(vorig, struct strscanner, orig);
00230 if (self != orig) {
00231 self->flags = orig->flags;
00232 self->str = orig->str;
00233 self->prev = orig->prev;
00234 self->curr = orig->curr;
00235 onig_region_copy(&self->regs, &orig->regs);
00236 }
00237
00238 return vself;
00239 }
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250 static VALUE
00251 strscan_s_mustc(VALUE self)
00252 {
00253 return self;
00254 }
00255
00256
00257
00258
00259 static VALUE
00260 strscan_reset(VALUE self)
00261 {
00262 struct strscanner *p;
00263
00264 GET_SCANNER(self, p);
00265 p->curr = 0;
00266 CLEAR_MATCH_STATUS(p);
00267 return self;
00268 }
00269
00270
00271
00272
00273
00274
00275
00276
00277 static VALUE
00278 strscan_terminate(VALUE self)
00279 {
00280 struct strscanner *p;
00281
00282 GET_SCANNER(self, p);
00283 p->curr = S_LEN(p);
00284 CLEAR_MATCH_STATUS(p);
00285 return self;
00286 }
00287
00288
00289
00290
00291
00292 static VALUE
00293 strscan_clear(VALUE self)
00294 {
00295 rb_warning("StringScanner#clear is obsolete; use #terminate instead");
00296 return strscan_terminate(self);
00297 }
00298
00299
00300
00301
00302 static VALUE
00303 strscan_get_string(VALUE self)
00304 {
00305 struct strscanner *p;
00306
00307 GET_SCANNER(self, p);
00308 return p->str;
00309 }
00310
00311
00312
00313
00314
00315
00316
00317 static VALUE
00318 strscan_set_string(VALUE self, VALUE str)
00319 {
00320 struct strscanner *p;
00321
00322 Data_Get_Struct(self, struct strscanner, p);
00323 StringValue(str);
00324 p->str = str;
00325 p->curr = 0;
00326 CLEAR_MATCH_STATUS(p);
00327 return str;
00328 }
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344 static VALUE
00345 strscan_concat(VALUE self, VALUE str)
00346 {
00347 struct strscanner *p;
00348
00349 GET_SCANNER(self, p);
00350 StringValue(str);
00351 rb_str_append(p->str, str);
00352 return self;
00353 }
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369 static VALUE
00370 strscan_get_pos(VALUE self)
00371 {
00372 struct strscanner *p;
00373
00374 GET_SCANNER(self, p);
00375 return INT2FIX(p->curr);
00376 }
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387 static VALUE
00388 strscan_set_pos(VALUE self, VALUE v)
00389 {
00390 struct strscanner *p;
00391 long i;
00392
00393 GET_SCANNER(self, p);
00394 i = NUM2INT(v);
00395 if (i < 0) i += S_LEN(p);
00396 if (i < 0) rb_raise(rb_eRangeError, "index out of range");
00397 if (i > S_LEN(p)) rb_raise(rb_eRangeError, "index out of range");
00398 p->curr = i;
00399 return INT2NUM(i);
00400 }
00401
00402 static VALUE
00403 strscan_do_scan(VALUE self, VALUE regex, int succptr, int getstr, int headonly)
00404 {
00405 regex_t *rb_reg_prepare_re(VALUE re, VALUE str);
00406 struct strscanner *p;
00407 regex_t *re;
00408 int ret;
00409 int tmpreg;
00410
00411 Check_Type(regex, T_REGEXP);
00412 GET_SCANNER(self, p);
00413
00414 CLEAR_MATCH_STATUS(p);
00415 if (S_RESTLEN(p) < 0) {
00416 return Qnil;
00417 }
00418 re = rb_reg_prepare_re(regex, p->str);
00419 tmpreg = re != RREGEXP(regex)->ptr;
00420 if (!tmpreg) RREGEXP(regex)->usecnt++;
00421
00422 if (headonly) {
00423 ret = onig_match(re, (UChar* )CURPTR(p),
00424 (UChar* )(CURPTR(p) + S_RESTLEN(p)),
00425 (UChar* )CURPTR(p), &(p->regs), ONIG_OPTION_NONE);
00426 }
00427 else {
00428 ret = onig_search(re,
00429 (UChar* )CURPTR(p), (UChar* )(CURPTR(p) + S_RESTLEN(p)),
00430 (UChar* )CURPTR(p), (UChar* )(CURPTR(p) + S_RESTLEN(p)),
00431 &(p->regs), ONIG_OPTION_NONE);
00432 }
00433 if (!tmpreg) RREGEXP(regex)->usecnt--;
00434 if (tmpreg) {
00435 if (RREGEXP(regex)->usecnt) {
00436 onig_free(re);
00437 }
00438 else {
00439 onig_free(RREGEXP(regex)->ptr);
00440 RREGEXP(regex)->ptr = re;
00441 }
00442 }
00443
00444 if (ret == -2) rb_raise(ScanError, "regexp buffer overflow");
00445 if (ret < 0) {
00446
00447 return Qnil;
00448 }
00449
00450 MATCHED(p);
00451 p->prev = p->curr;
00452 if (succptr) {
00453 p->curr += p->regs.end[0];
00454 }
00455 if (getstr) {
00456 return extract_beg_len(p, p->prev, p->regs.end[0]);
00457 }
00458 else {
00459 return INT2FIX(p->regs.end[0]);
00460 }
00461 }
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478 static VALUE
00479 strscan_scan(VALUE self, VALUE re)
00480 {
00481 return strscan_do_scan(self, re, 1, 1, 1);
00482 }
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495 static VALUE
00496 strscan_match_p(VALUE self, VALUE re)
00497 {
00498 return strscan_do_scan(self, re, 0, 0, 1);
00499 }
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518 static VALUE
00519 strscan_skip(VALUE self, VALUE re)
00520 {
00521 return strscan_do_scan(self, re, 1, 0, 1);
00522 }
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539 static VALUE
00540 strscan_check(VALUE self, VALUE re)
00541 {
00542 return strscan_do_scan(self, re, 0, 1, 1);
00543 }
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555 static VALUE
00556 strscan_scan_full(VALUE self, VALUE re, VALUE s, VALUE f)
00557 {
00558 return strscan_do_scan(self, re, RTEST(s), RTEST(f), 1);
00559 }
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573 static VALUE
00574 strscan_scan_until(VALUE self, VALUE re)
00575 {
00576 return strscan_do_scan(self, re, 1, 1, 0);
00577 }
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592 static VALUE
00593 strscan_exist_p(VALUE self, VALUE re)
00594 {
00595 return strscan_do_scan(self, re, 0, 0, 0);
00596 }
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614 static VALUE
00615 strscan_skip_until(VALUE self, VALUE re)
00616 {
00617 return strscan_do_scan(self, re, 1, 0, 0);
00618 }
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633 static VALUE
00634 strscan_check_until(VALUE self, VALUE re)
00635 {
00636 return strscan_do_scan(self, re, 0, 1, 0);
00637 }
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648 static VALUE
00649 strscan_search_full(VALUE self, VALUE re, VALUE s, VALUE f)
00650 {
00651 return strscan_do_scan(self, re, RTEST(s), RTEST(f), 0);
00652 }
00653
00654 static void
00655 adjust_registers_to_matched(struct strscanner *p)
00656 {
00657 onig_region_clear(&(p->regs));
00658 onig_region_set(&(p->regs), 0, 0, p->curr - p->prev);
00659 }
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675 static VALUE
00676 strscan_getch(VALUE self)
00677 {
00678 struct strscanner *p;
00679 long len;
00680
00681 GET_SCANNER(self, p);
00682 CLEAR_MATCH_STATUS(p);
00683 if (EOS_P(p))
00684 return Qnil;
00685
00686 len = rb_enc_mbclen(CURPTR(p), S_PEND(p), rb_enc_get(p->str));
00687 if (p->curr + len > S_LEN(p)) {
00688 len = S_LEN(p) - p->curr;
00689 }
00690 p->prev = p->curr;
00691 p->curr += len;
00692 MATCHED(p);
00693 adjust_registers_to_matched(p);
00694 return extract_range(p, p->prev + p->regs.beg[0],
00695 p->prev + p->regs.end[0]);
00696 }
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714 static VALUE
00715 strscan_get_byte(VALUE self)
00716 {
00717 struct strscanner *p;
00718
00719 GET_SCANNER(self, p);
00720 CLEAR_MATCH_STATUS(p);
00721 if (EOS_P(p))
00722 return Qnil;
00723
00724 p->prev = p->curr;
00725 p->curr++;
00726 MATCHED(p);
00727 adjust_registers_to_matched(p);
00728 return extract_range(p, p->prev + p->regs.beg[0],
00729 p->prev + p->regs.end[0]);
00730 }
00731
00732
00733
00734
00735
00736 static VALUE
00737 strscan_getbyte(VALUE self)
00738 {
00739 rb_warning("StringScanner#getbyte is obsolete; use #get_byte instead");
00740 return strscan_get_byte(self);
00741 }
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754 static VALUE
00755 strscan_peek(VALUE self, VALUE vlen)
00756 {
00757 struct strscanner *p;
00758 long len;
00759
00760 GET_SCANNER(self, p);
00761
00762 len = NUM2LONG(vlen);
00763 if (EOS_P(p))
00764 return infect(str_new(p, "", 0), p);
00765
00766 if (p->curr + len > S_LEN(p))
00767 len = S_LEN(p) - p->curr;
00768 return extract_beg_len(p, p->curr, len);
00769 }
00770
00771
00772
00773
00774
00775 static VALUE
00776 strscan_peep(VALUE self, VALUE vlen)
00777 {
00778 rb_warning("StringScanner#peep is obsolete; use #peek instead");
00779 return strscan_peek(self, vlen);
00780 }
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793 static VALUE
00794 strscan_unscan(VALUE self)
00795 {
00796 struct strscanner *p;
00797
00798 GET_SCANNER(self, p);
00799 if (! MATCHED_P(p))
00800 rb_raise(ScanError, "unscan failed: previous match record not exist");
00801 p->curr = p->prev;
00802 CLEAR_MATCH_STATUS(p);
00803 return self;
00804 }
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818 static VALUE
00819 strscan_bol_p(VALUE self)
00820 {
00821 struct strscanner *p;
00822
00823 GET_SCANNER(self, p);
00824 if (CURPTR(p) > S_PEND(p)) return Qnil;
00825 if (p->curr == 0) return Qtrue;
00826 return (*(CURPTR(p) - 1) == '\n') ? Qtrue : Qfalse;
00827 }
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839 static VALUE
00840 strscan_eos_p(VALUE self)
00841 {
00842 struct strscanner *p;
00843
00844 GET_SCANNER(self, p);
00845 return EOS_P(p) ? Qtrue : Qfalse;
00846 }
00847
00848
00849
00850
00851
00852 static VALUE
00853 strscan_empty_p(VALUE self)
00854 {
00855 rb_warning("StringScanner#empty? is obsolete; use #eos? instead");
00856 return strscan_eos_p(self);
00857 }
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867 static VALUE
00868 strscan_rest_p(VALUE self)
00869 {
00870 struct strscanner *p;
00871
00872 GET_SCANNER(self, p);
00873 return EOS_P(p) ? Qfalse : Qtrue;
00874 }
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885 static VALUE
00886 strscan_matched_p(VALUE self)
00887 {
00888 struct strscanner *p;
00889
00890 GET_SCANNER(self, p);
00891 return MATCHED_P(p) ? Qtrue : Qfalse;
00892 }
00893
00894
00895
00896
00897
00898
00899
00900
00901 static VALUE
00902 strscan_matched(VALUE self)
00903 {
00904 struct strscanner *p;
00905
00906 GET_SCANNER(self, p);
00907 if (! MATCHED_P(p)) return Qnil;
00908 return extract_range(p, p->prev + p->regs.beg[0],
00909 p->prev + p->regs.end[0]);
00910 }
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922 static VALUE
00923 strscan_matched_size(VALUE self)
00924 {
00925 struct strscanner *p;
00926
00927 GET_SCANNER(self, p);
00928 if (! MATCHED_P(p)) return Qnil;
00929 return INT2NUM(p->regs.end[0] - p->regs.beg[0]);
00930 }
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946 static VALUE
00947 strscan_aref(VALUE self, VALUE idx)
00948 {
00949 struct strscanner *p;
00950 long i;
00951
00952 GET_SCANNER(self, p);
00953 if (! MATCHED_P(p)) return Qnil;
00954
00955 i = NUM2LONG(idx);
00956 if (i < 0)
00957 i += p->regs.num_regs;
00958 if (i < 0) return Qnil;
00959 if (i >= p->regs.num_regs) return Qnil;
00960 if (p->regs.beg[i] == -1) return Qnil;
00961
00962 return extract_range(p, p->prev + p->regs.beg[i],
00963 p->prev + p->regs.end[i]);
00964 }
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975 static VALUE
00976 strscan_pre_match(VALUE self)
00977 {
00978 struct strscanner *p;
00979
00980 GET_SCANNER(self, p);
00981 if (! MATCHED_P(p)) return Qnil;
00982 return extract_range(p, 0, p->prev + p->regs.beg[0]);
00983 }
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994 static VALUE
00995 strscan_post_match(VALUE self)
00996 {
00997 struct strscanner *p;
00998
00999 GET_SCANNER(self, p);
01000 if (! MATCHED_P(p)) return Qnil;
01001 return extract_range(p, p->prev + p->regs.end[0], S_LEN(p));
01002 }
01003
01004
01005
01006
01007
01008 static VALUE
01009 strscan_rest(VALUE self)
01010 {
01011 struct strscanner *p;
01012
01013 GET_SCANNER(self, p);
01014 if (EOS_P(p)) {
01015 return infect(str_new(p, "", 0), p);
01016 }
01017 return extract_range(p, p->curr, S_LEN(p));
01018 }
01019
01020
01021
01022
01023 static VALUE
01024 strscan_rest_size(VALUE self)
01025 {
01026 struct strscanner *p;
01027 long i;
01028
01029 GET_SCANNER(self, p);
01030 if (EOS_P(p)) {
01031 return INT2FIX(0);
01032 }
01033 i = S_LEN(p) - p->curr;
01034 return INT2FIX(i);
01035 }
01036
01037
01038
01039
01040
01041 static VALUE
01042 strscan_restsize(VALUE self)
01043 {
01044 rb_warning("StringScanner#restsize is obsolete; use #rest_size instead");
01045 return strscan_rest_size(self);
01046 }
01047
01048 #define INSPECT_LENGTH 5
01049 #define BUFSIZE 256
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062 static VALUE
01063 strscan_inspect(VALUE self)
01064 {
01065 struct strscanner *p;
01066 char buf[BUFSIZE];
01067 long len;
01068 VALUE a, b;
01069
01070 Data_Get_Struct(self, struct strscanner, p);
01071 if (NIL_P(p->str)) {
01072 len = snprintf(buf, BUFSIZE, "#<%s (uninitialized)>",
01073 rb_class2name(CLASS_OF(self)));
01074 return infect(rb_str_new(buf, len), p);
01075 }
01076 if (EOS_P(p)) {
01077 len = snprintf(buf, BUFSIZE, "#<%s fin>",
01078 rb_class2name(CLASS_OF(self)));
01079 return infect(rb_str_new(buf, len), p);
01080 }
01081 if (p->curr == 0) {
01082 b = inspect2(p);
01083 len = snprintf(buf, BUFSIZE, "#<%s %ld/%ld @ %s>",
01084 rb_class2name(CLASS_OF(self)),
01085 p->curr, S_LEN(p),
01086 RSTRING_PTR(b));
01087 return infect(rb_str_new(buf, len), p);
01088 }
01089 a = inspect1(p);
01090 b = inspect2(p);
01091 len = snprintf(buf, BUFSIZE, "#<%s %ld/%ld %s @ %s>",
01092 rb_class2name(CLASS_OF(self)),
01093 p->curr, S_LEN(p),
01094 RSTRING_PTR(a),
01095 RSTRING_PTR(b));
01096 return infect(rb_str_new(buf, len), p);
01097 }
01098
01099 static VALUE
01100 inspect1(struct strscanner *p)
01101 {
01102 char buf[BUFSIZE];
01103 char *bp = buf;
01104 long len;
01105
01106 if (p->curr == 0) return rb_str_new2("");
01107 if (p->curr > INSPECT_LENGTH) {
01108 strcpy(bp, "..."); bp += 3;
01109 len = INSPECT_LENGTH;
01110 }
01111 else {
01112 len = p->curr;
01113 }
01114 memcpy(bp, CURPTR(p) - len, len); bp += len;
01115 return rb_str_dump(rb_str_new(buf, bp - buf));
01116 }
01117
01118 static VALUE
01119 inspect2(struct strscanner *p)
01120 {
01121 char buf[BUFSIZE];
01122 char *bp = buf;
01123 long len;
01124
01125 if (EOS_P(p)) return rb_str_new2("");
01126 len = S_LEN(p) - p->curr;
01127 if (len > INSPECT_LENGTH) {
01128 len = INSPECT_LENGTH;
01129 memcpy(bp, CURPTR(p), len); bp += len;
01130 strcpy(bp, "..."); bp += 3;
01131 }
01132 else {
01133 memcpy(bp, CURPTR(p), len); bp += len;
01134 }
01135 return rb_str_dump(rb_str_new(buf, bp - buf));
01136 }
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245 void
01246 Init_strscan()
01247 {
01248 ID id_scanerr = rb_intern("ScanError");
01249 VALUE tmp;
01250
01251 StringScanner = rb_define_class("StringScanner", rb_cObject);
01252 ScanError = rb_define_class_under(StringScanner, "Error", rb_eStandardError);
01253 if (!rb_const_defined(rb_cObject, id_scanerr)) {
01254 rb_const_set(rb_cObject, id_scanerr, ScanError);
01255 }
01256 tmp = rb_str_new2(STRSCAN_VERSION);
01257 rb_obj_freeze(tmp);
01258 rb_const_set(StringScanner, rb_intern("Version"), tmp);
01259 tmp = rb_str_new2("$Id: strscan.c 27437 2010-04-22 08:04:13Z nobu $");
01260 rb_obj_freeze(tmp);
01261 rb_const_set(StringScanner, rb_intern("Id"), tmp);
01262
01263 rb_define_alloc_func(StringScanner, strscan_s_allocate);
01264 rb_define_private_method(StringScanner, "initialize", strscan_initialize, -1);
01265 rb_define_private_method(StringScanner, "initialize_copy", strscan_init_copy, 1);
01266 rb_define_singleton_method(StringScanner, "must_C_version", strscan_s_mustc, 0);
01267 rb_define_method(StringScanner, "reset", strscan_reset, 0);
01268 rb_define_method(StringScanner, "terminate", strscan_terminate, 0);
01269 rb_define_method(StringScanner, "clear", strscan_clear, 0);
01270 rb_define_method(StringScanner, "string", strscan_get_string, 0);
01271 rb_define_method(StringScanner, "string=", strscan_set_string, 1);
01272 rb_define_method(StringScanner, "concat", strscan_concat, 1);
01273 rb_define_method(StringScanner, "<<", strscan_concat, 1);
01274 rb_define_method(StringScanner, "pos", strscan_get_pos, 0);
01275 rb_define_method(StringScanner, "pos=", strscan_set_pos, 1);
01276 rb_define_method(StringScanner, "pointer", strscan_get_pos, 0);
01277 rb_define_method(StringScanner, "pointer=", strscan_set_pos, 1);
01278
01279 rb_define_method(StringScanner, "scan", strscan_scan, 1);
01280 rb_define_method(StringScanner, "skip", strscan_skip, 1);
01281 rb_define_method(StringScanner, "match?", strscan_match_p, 1);
01282 rb_define_method(StringScanner, "check", strscan_check, 1);
01283 rb_define_method(StringScanner, "scan_full", strscan_scan_full, 3);
01284
01285 rb_define_method(StringScanner, "scan_until", strscan_scan_until, 1);
01286 rb_define_method(StringScanner, "skip_until", strscan_skip_until, 1);
01287 rb_define_method(StringScanner, "exist?", strscan_exist_p, 1);
01288 rb_define_method(StringScanner, "check_until", strscan_check_until, 1);
01289 rb_define_method(StringScanner, "search_full", strscan_search_full, 3);
01290
01291 rb_define_method(StringScanner, "getch", strscan_getch, 0);
01292 rb_define_method(StringScanner, "get_byte", strscan_get_byte, 0);
01293 rb_define_method(StringScanner, "getbyte", strscan_getbyte, 0);
01294 rb_define_method(StringScanner, "peek", strscan_peek, 1);
01295 rb_define_method(StringScanner, "peep", strscan_peep, 1);
01296
01297 rb_define_method(StringScanner, "unscan", strscan_unscan, 0);
01298
01299 rb_define_method(StringScanner, "beginning_of_line?", strscan_bol_p, 0);
01300 rb_alias(StringScanner, rb_intern("bol?"), rb_intern("beginning_of_line?"));
01301 rb_define_method(StringScanner, "eos?", strscan_eos_p, 0);
01302 rb_define_method(StringScanner, "empty?", strscan_empty_p, 0);
01303 rb_define_method(StringScanner, "rest?", strscan_rest_p, 0);
01304
01305 rb_define_method(StringScanner, "matched?", strscan_matched_p, 0);
01306 rb_define_method(StringScanner, "matched", strscan_matched, 0);
01307 rb_define_method(StringScanner, "matched_size", strscan_matched_size, 0);
01308 rb_define_method(StringScanner, "[]", strscan_aref, 1);
01309 rb_define_method(StringScanner, "pre_match", strscan_pre_match, 0);
01310 rb_define_method(StringScanner, "post_match", strscan_post_match, 0);
01311
01312 rb_define_method(StringScanner, "rest", strscan_rest, 0);
01313 rb_define_method(StringScanner, "rest_size", strscan_rest_size, 0);
01314 rb_define_method(StringScanner, "restsize", strscan_restsize, 0);
01315
01316 rb_define_method(StringScanner, "inspect", strscan_inspect, 0);
01317 }
01318