~ubuntu-branches/ubuntu/intrepid/ruby1.9/intrepid-updates

« back to all changes in this revision

Viewing changes to string.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2007-09-04 16:01:17 UTC
  • mfrom: (1.1.8 upstream)
  • Revision ID: james.westby@ubuntu.com-20070904160117-i15zckg2nhxe9fyw
Tags: 1.9.0+20070830-2ubuntu1
* Sync from Debian; remaining changes:
  - Add -g to CFLAGS.
* Fixes build failure on ia64.
* Fixes build failure with gcc-4.2 on lpia.
* Robustify check for target_os, fixing build failure on lpia.
* Set Ubuntu maintainer address.

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
 
3
3
  string.c -
4
4
 
5
 
  $Author: matz $
6
 
  $Date: 2007-02-23 11:49:41 +0900 (金, 23  2月 2007) $
 
5
  $Author: nobu $
 
6
  $Date: 2007-08-30 11:44:20 +0900 (木, 30  8月 2007) $
7
7
  created at: Mon Aug  9 17:12:58 JST 1993
8
8
 
9
 
  Copyright (C) 1993-2006 Yukihiro Matsumoto
 
9
  Copyright (C) 1993-2007 Yukihiro Matsumoto
10
10
  Copyright (C) 2000  Network Applied Communication Laboratory, Inc.
11
11
  Copyright (C) 2000  Information-technology Promotion Agency, Japan
12
12
 
13
13
**********************************************************************/
14
14
 
15
 
#include "ruby.h"
16
 
#include "re.h"
 
15
#include "ruby/ruby.h"
 
16
#include "ruby/re.h"
 
17
#include "ruby/encoding.h"
17
18
 
18
19
#define BEG(no) regs->beg[no]
19
20
#define END(no) regs->end[no]
30
31
 
31
32
#define STR_TMPLOCK FL_USER7
32
33
#define STR_NOEMBED FL_USER1
 
34
#define STR_SHARED  FL_USER2 /* = ELTS_SHARED */
33
35
#define STR_ASSOC   FL_USER3
34
36
#define STR_SHARED_P(s) FL_ALL(s, STR_NOEMBED|ELTS_SHARED)
35
37
#define STR_ASSOC_P(s)  FL_ALL(s, STR_NOEMBED|STR_ASSOC)
90
92
    }\
91
93
} while (0)
92
94
 
93
 
char *
94
 
rb_str_ptr(VALUE str) {
95
 
    return RSTRING_PTR(str);
96
 
}
97
 
 
98
95
VALUE rb_fs;
99
96
 
100
97
static inline void
160
157
}
161
158
 
162
159
VALUE
 
160
rb_enc_str_new(const char *ptr, long len, rb_encoding *enc)
 
161
{
 
162
    VALUE str = str_new(rb_cString, ptr, len);
 
163
 
 
164
    rb_enc_associate(str, enc);
 
165
    return str;
 
166
}
 
167
 
 
168
VALUE
163
169
rb_str_new2(const char *ptr)
164
170
{
165
171
    if (!ptr) {
201
207
        RSTRING(str2)->as.heap.len = RSTRING_LEN(str);
202
208
        RSTRING(str2)->as.heap.ptr = RSTRING_PTR(str);
203
209
        RSTRING(str2)->as.heap.aux.shared = str;
204
 
    FL_SET(str2, ELTS_SHARED);
 
210
        FL_SET(str2, ELTS_SHARED);
205
211
    }
 
212
    rb_enc_copy((VALUE)str2, str);
206
213
 
207
214
    return str2;
208
215
}
233
240
        FL_SET(str, ELTS_SHARED);
234
241
        RSTRING(str)->as.heap.aux.shared = str2;
235
242
    }
 
243
    rb_enc_copy(str2, str);
236
244
    OBJ_INFECT(str2, str);
237
245
    return str2;
238
246
}
392
400
    return str;
393
401
}
394
402
 
 
403
static long
 
404
str_strlen(VALUE str, rb_encoding *enc)
 
405
{
 
406
    long len;
 
407
 
 
408
    if (!enc) enc = rb_enc_get(str);
 
409
    len = rb_enc_strlen(RSTRING_PTR(str), RSTRING_END(str), enc);
 
410
    if (len < 0) {
 
411
        rb_raise(rb_eArgError, "invalid mbstring sequence");
 
412
    }
 
413
    return len;
 
414
}
 
415
 
395
416
/*
396
417
 *  call-seq:
397
418
 *     str.length   => integer
 
419
 *     str.size     => integer
398
420
 *  
399
 
 *  Returns the length of <i>str</i>.
 
421
 *  Returns the character length of <i>str</i>.
400
422
 */
401
423
 
402
 
static VALUE
 
424
VALUE
403
425
rb_str_length(VALUE str)
404
426
{
405
 
    long len = RSTRING_LEN(str);
406
 
    return LONG2NUM(len);
 
427
    int len;
 
428
 
 
429
    len = str_strlen(str, rb_enc_get(str));
 
430
    return INT2NUM(len);
 
431
}
 
432
 
 
433
/*
 
434
 *  call-seq:
 
435
 *     str.bytesize  => integer
 
436
 *  
 
437
 *  Returns the length of <i>str</i> in bytes.
 
438
 */
 
439
 
 
440
static VALUE
 
441
rb_str_bytesize(str)
 
442
    VALUE str;
 
443
{
 
444
    return INT2NUM(RSTRING_LEN(str));
407
445
}
408
446
 
409
447
/*
438
476
rb_str_plus(VALUE str1, VALUE str2)
439
477
{
440
478
    VALUE str3;
 
479
    rb_encoding *enc;
441
480
 
442
481
    StringValue(str2);
 
482
    enc = rb_enc_check(str1, str2);
443
483
    str3 = rb_str_new(0, RSTRING_LEN(str1)+RSTRING_LEN(str2));
444
484
    memcpy(RSTRING_PTR(str3), RSTRING_PTR(str1), RSTRING_LEN(str1));
445
485
    memcpy(RSTRING_PTR(str3) + RSTRING_LEN(str1),
448
488
 
449
489
    if (OBJ_TAINTED(str1) || OBJ_TAINTED(str2))
450
490
        OBJ_TAINT(str3);
 
491
    rb_enc_associate(str3, enc);
451
492
    return str3;
452
493
}
453
494
 
481
522
               RSTRING_PTR(str), RSTRING_LEN(str));
482
523
    }
483
524
    RSTRING_PTR(str2)[RSTRING_LEN(str2)] = '\0';
484
 
 
485
525
    OBJ_INFECT(str2, str);
 
526
    rb_enc_copy(str2, str);
486
527
 
487
528
    return str2;
488
529
}
504
545
static VALUE
505
546
rb_str_format_m(VALUE str, VALUE arg)
506
547
{
507
 
    if (TYPE(arg) == T_ARRAY) {
508
 
        return rb_str_format(RARRAY_LEN(arg), RARRAY_PTR(arg), str);
 
548
    VALUE tmp = rb_check_array_type(arg);
 
549
 
 
550
    if (!NIL_P(tmp)) {
 
551
        return rb_str_format(RARRAY_LEN(tmp), RARRAY_PTR(tmp), str);
509
552
    }
510
553
    return rb_str_format(1, &arg, str);
511
554
}
615
658
    return str;
616
659
}
617
660
 
 
661
/*
 
662
 *  call-seq:
 
663
 *     String.try_convert(obj) -> string or nil
 
664
 *
 
665
 *  Try to convert <i>obj</i> into a String, using to_str method.
 
666
 *  Returns converted regexp or nil if <i>obj</i> cannot be converted
 
667
 *  for any reason.
 
668
 *
 
669
 *     String.try_convert("str")     # => str
 
670
 *     String.try_convert(/re/)      # => nil
 
671
 */
 
672
static VALUE
 
673
rb_str_s_try_convert(VALUE dummy, VALUE str)
 
674
{
 
675
    return rb_check_string_type(str);
 
676
}
 
677
 
 
678
static char*
 
679
str_nth(const char *p, const char *e, int nth, rb_encoding *enc)
 
680
{
 
681
    p = rb_enc_nth(p, e, nth, enc);
 
682
    if (!p) {
 
683
        rb_raise(rb_eArgError, "invalid mbstring sequence");
 
684
    }
 
685
    if (p > e) {
 
686
        rb_raise(rb_eIndexError, "index out of range");
 
687
    }
 
688
    return (char*)p;
 
689
}
 
690
 
 
691
static int
 
692
str_offset(const char *p, const char *e, int nth, rb_encoding *enc)
 
693
{
 
694
    const char *pp = str_nth(p, e, nth, enc);
 
695
 
 
696
    return pp - p;
 
697
}
 
698
 
 
699
static long
 
700
str_sublen(VALUE str, long pos, rb_encoding *enc)
 
701
{
 
702
    if (rb_enc_mbmaxlen(enc) == 1 || pos < 0) return pos;
 
703
    else {
 
704
        char *p = RSTRING_PTR(str);
 
705
        char *e = p + pos;
 
706
        long i;
 
707
 
 
708
        i = 0;
 
709
        while (p < e) {
 
710
            p += rb_enc_mbclen(p, enc);
 
711
            i++;
 
712
        }
 
713
        return i;
 
714
    }
 
715
}
 
716
    
 
717
int
 
718
rb_str_sublen(VALUE str, int len)
 
719
{
 
720
    return str_sublen(str, len, rb_enc_get(str));
 
721
}
 
722
 
 
723
VALUE
 
724
rb_str_subseq(VALUE str, long beg, long len)
 
725
{
 
726
    VALUE str2 = rb_str_new5(str, RSTRING_PTR(str)+beg, len);
 
727
 
 
728
    rb_enc_copy(str2, str);
 
729
    OBJ_INFECT(str2, str);
 
730
 
 
731
    return str2;
 
732
}
 
733
 
618
734
VALUE
619
735
rb_str_substr(VALUE str, long beg, long len)
620
736
{
 
737
    rb_encoding *enc = rb_enc_get(str);
621
738
    VALUE str2;
 
739
    int slen = str_strlen(str, enc);
622
740
 
623
741
    if (len < 0) return Qnil;
624
 
    if (beg > RSTRING_LEN(str)) return Qnil;
 
742
    if (beg > slen) return Qnil;
625
743
    if (beg < 0) {
626
 
        beg += RSTRING_LEN(str);
 
744
        beg += slen;
627
745
        if (beg < 0) return Qnil;
628
746
    }
629
 
    if (beg + len > RSTRING_LEN(str)) {
630
 
        len = RSTRING_LEN(str) - beg;
 
747
    if (beg + len > slen) {
 
748
        len = slen - beg;
631
749
    }
632
750
    if (len < 0) {
633
751
        len = 0;
635
753
    if (len == 0) {
636
754
        str2 = rb_str_new5(str,0,0);
637
755
    }
638
 
    else if (len > RSTRING_EMBED_LEN_MAX &&
639
 
             beg + len == RSTRING_LEN(str) && !STR_ASSOC_P(str)) {
640
 
        str2 = rb_str_new4(str);
641
 
        str2 = str_new3(rb_obj_class(str2), str2);
642
 
        RSTRING(str2)->as.heap.ptr += RSTRING_LEN(str2) - len;
643
 
        RSTRING(str2)->as.heap.len = len;
644
 
    }
645
756
    else {
646
 
        str2 = rb_str_new5(str, RSTRING_PTR(str)+beg, len);
 
757
        char *p = str_nth(RSTRING_PTR(str), RSTRING_END(str), beg, enc);
 
758
        str2 = rb_str_new5(str, p, str_offset(p, RSTRING_END(str), len, enc));
647
759
    }
 
760
    rb_enc_copy(str2, str);
648
761
    OBJ_INFECT(str2, str);
649
762
 
650
763
    return str2;
719
832
            MEMCPY(ptr, RSTRING_PTR(str), char, RSTRING_LEN(str));
720
833
            RSTRING(str)->as.heap.ptr = ptr;
721
834
            STR_SET_NOEMBED(str);
722
 
            }
 
835
        }
723
836
        else if (RSTRING_LEN(str) < len || RSTRING_LEN(str) - len > 1024) {
724
837
            REALLOC_N(RSTRING(str)->as.heap.ptr, char, len+1);
725
838
        }
831
944
VALUE
832
945
rb_str_append(VALUE str, VALUE str2)
833
946
{
 
947
    rb_encoding *enc;
 
948
 
834
949
    StringValue(str2);
 
950
    enc = rb_enc_check(str, str2);
835
951
    rb_str_modify(str);
836
952
    if (RSTRING_LEN(str2) > 0) {
837
953
        if (STR_ASSOC_P(str)) {
846
962
        }
847
963
    }
848
964
    OBJ_INFECT(str, str2);
 
965
    rb_enc_associate(str, enc);
849
966
    return str;
850
967
}
851
968
 
858
975
 *     str.concat(obj)      => str
859
976
 *  
860
977
 *  Append---Concatenates the given object to <i>str</i>. If the object is a
861
 
 *  <code>Fixnum</code> between 0 and 255, it is converted to a character before
862
 
 *  concatenation.
 
978
 *  <code>Fixnum</code>, it is considered as a codepoint, and is converted
 
979
 *  to a character before concatenation.
863
980
 *     
864
981
 *     a = "hello "
865
982
 *     a << "world"   #=> "hello world"
870
987
rb_str_concat(VALUE str1, VALUE str2)
871
988
{
872
989
    if (FIXNUM_P(str2)) {
873
 
        int i = FIX2INT(str2);
874
 
        if (0 <= i && i <= 0xff) { /* byte */
875
 
            char c = i;
876
 
            return rb_str_cat(str1, &c, 1);
 
990
        rb_encoding *enc = rb_enc_get(str1);
 
991
        int c = FIX2INT(str2);
 
992
        int pos = RSTRING_LEN(str1);
 
993
        int len = rb_enc_codelen(c, enc);
 
994
 
 
995
        if (len == 0) {
 
996
            rb_raise(rb_eArgError, "invalid codepoint 0x%x", c);
877
997
        }
 
998
        rb_str_resize(str1, pos+len);
 
999
        rb_enc_mbcput(c, RSTRING_PTR(str1)+pos, enc);
 
1000
        return str1;
878
1001
    }
879
1002
    return rb_str_append(str1, str2);
880
1003
}
1031
1154
    long len;
1032
1155
    int retval;
1033
1156
 
 
1157
    rb_enc_check(str1, str2);   /* xxxx error-less encoding check? */
1034
1158
    len = lesser(RSTRING_LEN(str1), RSTRING_LEN(str2));
1035
1159
    retval = rb_memcmp(RSTRING_PTR(str1), RSTRING_PTR(str2), len);
1036
1160
    if (retval == 0) {
1062
1186
        }
1063
1187
        return rb_equal(str2, str1);
1064
1188
    }
 
1189
    rb_enc_check(str1, str2); /* need weak check */
1065
1190
    if (RSTRING_LEN(str1) == RSTRING_LEN(str2) &&
1066
1191
        rb_str_cmp(str1, str2) == 0) {
1067
1192
        return Qtrue;
1177
1302
rb_str_index(VALUE str, VALUE sub, long offset)
1178
1303
{
1179
1304
    long pos;
 
1305
    char *s;
 
1306
    long len, slen;
 
1307
    rb_encoding *enc;
1180
1308
 
 
1309
    enc = rb_enc_check(str, sub);
 
1310
    len = str_strlen(str, enc);
 
1311
    slen = str_strlen(sub, enc);
1181
1312
    if (offset < 0) {
1182
 
        offset += RSTRING_LEN(str);
 
1313
        offset += len;
1183
1314
        if (offset < 0) return -1;
1184
1315
    }
1185
 
    if (RSTRING_LEN(str) - offset < RSTRING_LEN(sub)) return -1;
1186
 
    if (RSTRING_LEN(sub) == 0) return offset;
 
1316
    if (len - offset < slen) return -1;
 
1317
    if (slen == 0) return offset;
 
1318
    s = offset ? str_nth(RSTRING_PTR(str), RSTRING_END(str), offset, enc) : RSTRING_PTR(str);
 
1319
    /* need proceed one character at a time */
1187
1320
    pos = rb_memsearch(RSTRING_PTR(sub), RSTRING_LEN(sub),
1188
 
                       RSTRING_PTR(str)+offset, RSTRING_LEN(str)-offset);
 
1321
                       s, RSTRING_LEN(str)-(s - RSTRING_PTR(str)));
1189
1322
    if (pos < 0) return pos;
1190
1323
    return pos + offset;
1191
1324
}
1223
1356
        pos = 0;
1224
1357
    }
1225
1358
    if (pos < 0) {
1226
 
        pos += RSTRING_LEN(str);
 
1359
        pos += str_strlen(str, rb_enc_get(str));
1227
1360
        if (pos < 0) {
1228
1361
            if (TYPE(sub) == T_REGEXP) {
1229
1362
                rb_backref_set(Qnil);
1236
1369
      case T_REGEXP:
1237
1370
        pos = rb_reg_adjust_startpos(sub, str, pos, 0);
1238
1371
        pos = rb_reg_search(sub, str, pos, 0);
 
1372
        pos = rb_str_sublen(str, pos);
1239
1373
        break;
1240
1374
 
1241
 
      case T_FIXNUM:
1242
 
      {
1243
 
          int c = FIX2INT(sub);
1244
 
          long len = RSTRING_LEN(str);
1245
 
          char *p = RSTRING_PTR(str);
1246
 
 
1247
 
          for (;pos<len;pos++) {
1248
 
              if ((unsigned char)p[pos] == c) return LONG2NUM(pos);
1249
 
          }
1250
 
          return Qnil;
1251
 
      }
1252
 
 
1253
1375
      default: {
1254
 
          VALUE tmp;
 
1376
        VALUE tmp;
1255
1377
 
1256
 
          tmp = rb_check_string_type(sub);
1257
 
          if (NIL_P(tmp)) {
1258
 
              rb_raise(rb_eTypeError, "type mismatch: %s given",
1259
 
                       rb_obj_classname(sub));
1260
 
          }
1261
 
          sub = tmp;
 
1378
        tmp = rb_check_string_type(sub);
 
1379
        if (NIL_P(tmp)) {
 
1380
            rb_raise(rb_eTypeError, "type mismatch: %s given",
 
1381
                     rb_obj_classname(sub));
 
1382
        }
 
1383
        sub = tmp;
1262
1384
      }
1263
1385
        /* fall through */
1264
1386
      case T_STRING:
1265
1387
        pos = rb_str_index(str, sub, pos);
 
1388
        pos = rb_str_sublen(str, pos);
1266
1389
        break;
1267
1390
    }
1268
1391
 
1273
1396
static long
1274
1397
rb_str_rindex(VALUE str, VALUE sub, long pos)
1275
1398
{
1276
 
    long len = RSTRING_LEN(sub);
1277
 
    char *s, *sbeg, *t;
 
1399
    long len, slen;
 
1400
    char *s, *sbeg, *e, *t;
 
1401
    rb_encoding *enc;
1278
1402
 
 
1403
    enc = rb_enc_check(str, sub);
 
1404
    len = str_strlen(str, enc);
 
1405
    slen = str_strlen(sub, enc);
1279
1406
    /* substring longer than string */
1280
 
    if (RSTRING_LEN(str) < len) return -1;
1281
 
    if (RSTRING_LEN(str) - pos < len) {
1282
 
        pos = RSTRING_LEN(str) - len;
 
1407
    if (len < slen) return -1;
 
1408
    if (len - pos < slen) {
 
1409
        pos = len - slen;
 
1410
    }
 
1411
    if (len == 0) {
 
1412
        return pos;
1283
1413
    }
1284
1414
    sbeg = RSTRING_PTR(str);
1285
 
    s = RSTRING_PTR(str) + pos;
 
1415
    e = RSTRING_END(str);
1286
1416
    t = RSTRING_PTR(sub);
1287
 
    if (len) {
1288
 
        while (sbeg <= s) {
1289
 
            if (rb_memcmp(s, t, len) == 0) {
1290
 
                return s - RSTRING_PTR(str);
1291
 
            }
1292
 
            s--;
 
1417
    for (;;) {
 
1418
        s = str_nth(sbeg, e, pos, enc);
 
1419
        if (rb_memcmp(s, t, slen) == 0) {
 
1420
            return pos;
1293
1421
        }
1294
 
        return -1;
1295
 
    }
1296
 
    else {
1297
 
        return pos;
1298
 
    }
 
1422
        if (pos == 0) break;
 
1423
        pos--;
 
1424
    }
 
1425
    return -1;
1299
1426
}
1300
1427
 
1301
1428
 
1322
1449
rb_str_rindex_m(int argc, VALUE *argv, VALUE str)
1323
1450
{
1324
1451
    VALUE sub;
1325
 
    VALUE position;
1326
 
    long pos;
 
1452
    VALUE vpos;
 
1453
    rb_encoding *enc = rb_enc_get(str);
 
1454
    long pos, len = str_strlen(str, enc);
1327
1455
 
1328
 
    if (rb_scan_args(argc, argv, "11", &sub, &position) == 2) {
1329
 
        pos = NUM2LONG(position);
 
1456
    if (rb_scan_args(argc, argv, "11", &sub, &vpos) == 2) {
 
1457
        pos = NUM2LONG(vpos);
1330
1458
        if (pos < 0) {
1331
 
            pos += RSTRING_LEN(str);
 
1459
            pos += len;
1332
1460
            if (pos < 0) {
1333
1461
                if (TYPE(sub) == T_REGEXP) {
1334
1462
                    rb_backref_set(Qnil);
1336
1464
                return Qnil;
1337
1465
            }
1338
1466
        }
1339
 
        if (pos > RSTRING_LEN(str)) pos = RSTRING_LEN(str);
 
1467
        if (pos > len) pos = len;
1340
1468
    }
1341
1469
    else {
1342
 
        pos = RSTRING_LEN(str);
 
1470
        pos = len;
1343
1471
    }
1344
1472
 
1345
1473
    switch (TYPE(sub)) {
1346
1474
      case T_REGEXP:
 
1475
        /* enc = rb_get_check(str, sub); */
1347
1476
        if (RREGEXP(sub)->len) {
1348
1477
            pos = rb_reg_adjust_startpos(sub, str, pos, 1);
1349
1478
            pos = rb_reg_search(sub, str, pos, 1);
 
1479
            pos = rb_str_sublen(str, pos);
1350
1480
        }
1351
1481
        if (pos >= 0) return LONG2NUM(pos);
1352
1482
        break;
1353
1483
 
 
1484
      default: {
 
1485
        VALUE tmp;
 
1486
 
 
1487
        tmp = rb_check_string_type(sub);
 
1488
        if (NIL_P(tmp)) {
 
1489
            rb_raise(rb_eTypeError, "type mismatch: %s given",
 
1490
                     rb_obj_classname(sub));
 
1491
        }
 
1492
        sub = tmp;
 
1493
      }
 
1494
        /* fall through */
1354
1495
      case T_STRING:
 
1496
        pos = str_sublen(str, pos, enc);
1355
1497
        pos = rb_str_rindex(str, sub, pos);
1356
1498
        if (pos >= 0) return LONG2NUM(pos);
1357
1499
        break;
1358
 
 
1359
 
      case T_FIXNUM:
1360
 
      {
1361
 
          int c = FIX2INT(sub);
1362
 
          char *p = RSTRING_PTR(str) + pos;
1363
 
          char *pbeg = RSTRING_PTR(str);
1364
 
 
1365
 
          if (pos == RSTRING_LEN(str)) {
1366
 
              if (pos == 0) return Qnil;
1367
 
              --p;
1368
 
          }
1369
 
          while (pbeg <= p) {
1370
 
              if ((unsigned char)*p == c)
1371
 
                  return LONG2NUM((char*)p - RSTRING_PTR(str));
1372
 
              p--;
1373
 
          }
1374
 
          return Qnil;
1375
 
      }
1376
 
 
1377
 
      default:
1378
 
        rb_raise(rb_eTypeError, "type mismatch: %s given",
1379
 
                 rb_obj_classname(sub));
1380
1500
    }
1381
1501
    return Qnil;
1382
1502
}
1423
1543
 *  parameter is present, it specifies the position in the string to begin the
1424
1544
 *  search.
1425
1545
 *     
1426
 
 *     'hello'.match('(.)\1')      #=> #<MatchData:0x401b3d30>
 
1546
 *     'hello'.match('(.)\1')      #=> #<MatchData "ll" "l">
1427
1547
 *     'hello'.match('(.)\1')[0]   #=> "ll"
1428
1548
 *     'hello'.match(/(.)\1/)[0]   #=> "ll"
1429
1549
 *     'hello'.match('xx')         #=> nil
1440
1560
    return rb_funcall2(get_pat(re, 0), rb_intern("match"), argc, argv);
1441
1561
}
1442
1562
 
1443
 
static char
 
1563
static int
1444
1564
succ_char(char *s)
1445
1565
{
1446
1566
    char c = *s;
1493
1613
VALUE
1494
1614
rb_str_succ(VALUE orig)
1495
1615
{
 
1616
    rb_encoding *enc;
1496
1617
    VALUE str;
1497
 
    char *sbeg, *s;
 
1618
    char *sbeg, *s, *e;
1498
1619
    int c = -1;
1499
1620
    long n = 0;
1500
1621
 
1502
1623
    OBJ_INFECT(str, orig);
1503
1624
    if (RSTRING_LEN(str) == 0) return str;
1504
1625
 
 
1626
    enc = rb_enc_get(orig);
1505
1627
    sbeg = RSTRING_PTR(str); s = sbeg + RSTRING_LEN(str) - 1;
 
1628
    e = RSTRING_END(str);
1506
1629
 
1507
1630
    while (sbeg <= s) {
1508
 
        if (ISALNUM(*s)) {
 
1631
        unsigned int cc = rb_enc_codepoint(s, e, enc);
 
1632
        if (rb_enc_isalnum(cc, enc)) {
1509
1633
            if ((c = succ_char(s)) == 0) break;
1510
1634
            n = s - sbeg;
1511
1635
        }
1549
1673
    return str;
1550
1674
}
1551
1675
 
1552
 
VALUE
1553
 
rb_str_upto(VALUE beg, VALUE end, int excl)
 
1676
 
 
1677
/*
 
1678
 *  call-seq:
 
1679
 *     str.upto(other_str, exclusive=false) {|s| block }   => str
 
1680
 *  
 
1681
 *  Iterates through successive values, starting at <i>str</i> and
 
1682
 *  ending at <i>other_str</i> inclusive, passing each value in turn to
 
1683
 *  the block. The <code>String#succ</code> method is used to generate
 
1684
 *  each value.  If optional second arguent excle is omitted or is <code>false</code>,
 
1685
 *  the last value will be included; otherwise it will be excluded.
 
1686
 *     
 
1687
 *     "a8".upto("b6") {|s| print s, ' ' }
 
1688
 *     for s in "a8".."b6"
 
1689
 *       print s, ' '
 
1690
 *     end
 
1691
 *     
 
1692
 *  <em>produces:</em>
 
1693
 *     
 
1694
 *     a8 a9 b0 b1 b2 b3 b4 b5 b6
 
1695
 *     a8 a9 b0 b1 b2 b3 b4 b5 b6
 
1696
 */
 
1697
 
 
1698
static VALUE
 
1699
rb_str_upto(int argc, VALUE *argv, VALUE beg)
1554
1700
{
 
1701
    VALUE end, exclusive;
1555
1702
    VALUE current, after_end;
1556
 
    ID succ = rb_intern("succ");
1557
 
    int n;
 
1703
    ID succ;
 
1704
    int n, excl;
1558
1705
 
 
1706
    rb_scan_args(argc, argv, "11", &end, &exclusive);
 
1707
    excl = RTEST(exclusive);
 
1708
    succ = rb_intern("succ");
1559
1709
    StringValue(end);
1560
1710
    n = rb_str_cmp(beg, end);
1561
1711
    if (n > 0 || (excl && n == 0)) return beg;
1575
1725
    return beg;
1576
1726
}
1577
1727
 
1578
 
 
1579
 
/*
1580
 
 *  call-seq:
1581
 
 *     str.upto(other_str) {|s| block }   => str
1582
 
 *  
1583
 
 *  Iterates through successive values, starting at <i>str</i> and
1584
 
 *  ending at <i>other_str</i> inclusive, passing each value in turn to
1585
 
 *  the block. The <code>String#succ</code> method is used to generate
1586
 
 *  each value.
1587
 
 *     
1588
 
 *     "a8".upto("b6") {|s| print s, ' ' }
1589
 
 *     for s in "a8".."b6"
1590
 
 *       print s, ' '
1591
 
 *     end
1592
 
 *     
1593
 
 *  <em>produces:</em>
1594
 
 *     
1595
 
 *     a8 a9 b0 b1 b2 b3 b4 b5 b6
1596
 
 *     a8 a9 b0 b1 b2 b3 b4 b5 b6
1597
 
 */
1598
 
 
1599
 
static VALUE
1600
 
rb_str_upto_m(VALUE beg, VALUE end)
1601
 
{
1602
 
    return rb_str_upto(beg, end, Qfalse);
1603
 
}
1604
 
 
1605
1728
static VALUE
1606
1729
rb_str_subpat(VALUE str, VALUE re, int nth)
1607
1730
{
1621
1744
        idx = FIX2LONG(indx);
1622
1745
 
1623
1746
      num_index:
1624
 
        if (idx < 0) {
1625
 
            idx = RSTRING_LEN(str) + idx;
1626
 
        }
1627
 
        if (idx < 0 || RSTRING_LEN(str) <= idx) {
1628
 
            return Qnil;
1629
 
        }
1630
 
        return rb_str_substr(str, idx, 1);
 
1747
        str = rb_str_substr(str, idx, 1);
 
1748
        if (!NIL_P(str) && RSTRING_LEN(str) == 0) return Qnil;
 
1749
        return str;
1631
1750
 
1632
1751
      case T_REGEXP:
1633
1752
        return rb_str_subpat(str, indx, 0);
1643
1762
            long beg, len;
1644
1763
            VALUE tmp;
1645
1764
 
1646
 
            switch (rb_range_beg_len(indx, &beg, &len, RSTRING_LEN(str), 0)) {
 
1765
            len = str_strlen(str, rb_enc_get(str));
 
1766
            switch (rb_range_beg_len(indx, &beg, &len, len, 0)) {
1647
1767
              case Qfalse:
1648
1768
                break;
1649
1769
              case Qnil:
1650
1770
                return Qnil;
1651
1771
              default:
1652
1772
                tmp = rb_str_substr(str, beg, len);
1653
 
                OBJ_INFECT(tmp, indx);
1654
1773
                return tmp;
1655
1774
            }
1656
1775
        }
1724
1843
}
1725
1844
 
1726
1845
static void
1727
 
rb_str_splice(VALUE str, long beg, long len, VALUE val)
 
1846
rb_str_splice_0(VALUE str, long beg, long len, VALUE val)
1728
1847
{
1729
 
    if (len < 0) rb_raise(rb_eIndexError, "negative length %ld", len);
1730
 
 
1731
 
    StringValue(val);
1732
1848
    rb_str_modify(str);
1733
 
 
1734
 
    if (RSTRING_LEN(str) < beg) {
1735
 
      out_of_range:
1736
 
        rb_raise(rb_eIndexError, "index %ld out of string", beg);
1737
 
    }
1738
 
    if (beg < 0) {
1739
 
        if (-beg > RSTRING_LEN(str)) {
1740
 
            goto out_of_range;
1741
 
        }
1742
 
        beg += RSTRING_LEN(str);
1743
 
    }
1744
 
    if (RSTRING_LEN(str) < beg + len) {
1745
 
        len = RSTRING_LEN(str) - beg;
1746
 
    }
1747
 
 
1748
1849
    if (len < RSTRING_LEN(val)) {
1749
1850
        /* expand string */
1750
1851
        RESIZE_CAPA(str, RSTRING_LEN(str) + RSTRING_LEN(val) - len + 1);
1755
1856
                RSTRING_PTR(str) + beg + len,
1756
1857
                RSTRING_LEN(str) - (beg + len));
1757
1858
    }
1758
 
    if (RSTRING_LEN(str) < beg && len < 0) {
 
1859
    if (RSTRING_LEN(val) < beg && len < 0) {
1759
1860
        MEMZERO(RSTRING_PTR(str) + RSTRING_LEN(str), char, -len);
1760
1861
    }
1761
1862
    if (RSTRING_LEN(val) > 0) {
1768
1869
    OBJ_INFECT(str, val);
1769
1870
}
1770
1871
 
 
1872
static void
 
1873
rb_str_splice(VALUE str, long beg, long len, VALUE val)
 
1874
{
 
1875
    long slen;
 
1876
    char *p, *e;
 
1877
    rb_encoding *enc;
 
1878
 
 
1879
    if (len < 0) rb_raise(rb_eIndexError, "negative length %ld", len);
 
1880
 
 
1881
    StringValue(val);
 
1882
    rb_str_modify(str);
 
1883
    enc = rb_enc_check(str, val);
 
1884
    slen = str_strlen(str, enc);
 
1885
 
 
1886
    if (slen < beg) {
 
1887
      out_of_range:
 
1888
        rb_raise(rb_eIndexError, "index %ld out of string", beg);
 
1889
    }
 
1890
    if (beg < 0) {
 
1891
        if (-beg > slen) {
 
1892
            goto out_of_range;
 
1893
        }
 
1894
        beg += slen;
 
1895
    }
 
1896
    if (slen < beg + len) {
 
1897
        len = slen - beg;
 
1898
    }
 
1899
    p = str_nth(RSTRING_PTR(str), RSTRING_END(str), beg, enc);
 
1900
    e = str_nth(p, RSTRING_END(str), len, enc);
 
1901
    /* error check */
 
1902
    beg = p - RSTRING_PTR(str); /* physical position */
 
1903
    len = e - p;                /* physical length */
 
1904
    rb_str_splice_0(str, beg, len, val);
 
1905
}
 
1906
 
1771
1907
void
1772
1908
rb_str_update(VALUE str, long beg, long len, VALUE val)
1773
1909
{
1801
1937
    }
1802
1938
    end = RMATCH(match)->END(nth);
1803
1939
    len = end - start;
1804
 
    rb_str_splice(str, start, len, val);
 
1940
    rb_enc_check(str, val);
 
1941
    rb_str_splice_0(str, start, len, val);
1805
1942
}
1806
1943
 
1807
1944
static VALUE
1813
1950
      case T_FIXNUM:
1814
1951
        idx = FIX2LONG(indx);
1815
1952
      num_index:
1816
 
        if (RSTRING_LEN(str) <= idx) {
1817
 
          out_of_range:
1818
 
            rb_raise(rb_eIndexError, "index %ld out of string", idx);
1819
 
        }
1820
 
        if (idx < 0) {
1821
 
            if (-idx > RSTRING_LEN(str))
1822
 
                goto out_of_range;
1823
 
            idx += RSTRING_LEN(str);
1824
 
        }
1825
 
            rb_str_splice(str, idx, 1, val);
 
1953
        rb_str_splice(str, idx, 1, val);
1826
1954
        return val;
1827
1955
 
1828
1956
      case T_REGEXP:
1834
1962
        if (beg < 0) {
1835
1963
            rb_raise(rb_eIndexError, "string not matched");
1836
1964
        }
1837
 
        rb_str_splice(str, beg, RSTRING_LEN(indx), val);
 
1965
        beg = rb_str_sublen(str, beg);
 
1966
        rb_str_splice(str, beg, str_strlen(indx, 0), val);
1838
1967
        return val;
1839
1968
 
1840
1969
      default:
1841
1970
        /* check if indx is Range */
1842
1971
        {
1843
1972
            long beg, len;
1844
 
            if (rb_range_beg_len(indx, &beg, &len, RSTRING_LEN(str), 2)) {
 
1973
            if (rb_range_beg_len(indx, &beg, &len, str_strlen(str, 0), 2)) {
1845
1974
                rb_str_splice(str, beg, len, val);
1846
1975
                return val;
1847
1976
            }
1958
2087
    for (i=0; i<argc; i++) {
1959
2088
        buf[i] = argv[i];
1960
2089
    }
 
2090
    rb_str_modify(str);
1961
2091
    buf[i] = rb_str_new(0,0);
1962
2092
    result = rb_str_aref_m(argc, buf, str);
1963
2093
    if (!NIL_P(result)) {
2114
2244
    int iter = 0;
2115
2245
    char *buf, *bp, *sp, *cp;
2116
2246
    int tainted = 0;
2117
 
 
 
2247
    rb_encoding *enc;
 
2248
    
2118
2249
    switch (argc) {
2119
2250
      case 1:
2120
2251
        RETURN_ENUMERATOR(str, argc, argv);
2130
2261
    }
2131
2262
 
2132
2263
    pat = get_pat(argv[0], 1);
 
2264
    enc = rb_enc_get(pat);
2133
2265
    offset=0; n=0;
2134
2266
    beg = rb_reg_search(pat, str, 0, 0);
2135
2267
    if (beg < 0) {
2145
2277
    slen = RSTRING_LEN(str);
2146
2278
 
2147
2279
    rb_str_locktmp(dest);
2148
 
    while (beg >= 0) {
 
2280
    do {
2149
2281
        n++;
2150
2282
        match = rb_backref_get();
2151
2283
        regs = RMATCH(match)->regs;
2184
2316
             * in order to prevent infinite loops.
2185
2317
             */
2186
2318
            if (RSTRING_LEN(str) <= END(0)) break;
2187
 
            len = mbclen2(RSTRING_PTR(str)[END(0)], pat);
 
2319
            len = rb_enc_mbclen(RSTRING_PTR(str)+END(0), enc);
2188
2320
            memcpy(bp, RSTRING_PTR(str)+END(0), len);
2189
2321
            bp += len;
2190
2322
            offset = END(0) + len;
2192
2324
        cp = RSTRING_PTR(str) + offset;
2193
2325
        if (offset > RSTRING_LEN(str)) break;
2194
2326
        beg = rb_reg_search(pat, str, offset, 0);
2195
 
    }
 
2327
    } while (beg >= 0);
2196
2328
    if (RSTRING_LEN(str) > offset) {
2197
2329
        len = bp - buf;
2198
2330
        if (blen - len < RSTRING_LEN(str) - offset) {
2331
2463
    }
2332
2464
 
2333
2465
    OBJ_INFECT(str, str2);
 
2466
    rb_enc_copy(str, str2);
2334
2467
    return str;
2335
2468
}
2336
2469
 
2348
2481
rb_str_clear(VALUE str)
2349
2482
{
2350
2483
    /* rb_str_modify() */       /* no need for str_make_independent */
2351
 
    if (str_independent(str)) {
 
2484
    if (str_independent(str) && !STR_EMBED_P(str)) {
2352
2485
        free(RSTRING_PTR(str));
2353
2486
    }
2354
2487
    STR_SET_EMBED(str);
2375
2508
 
2376
2509
/*
2377
2510
 *  call-seq:
2378
 
 *     str.reverse!   => str
2379
 
 *  
2380
 
 *  Reverses <i>str</i> in place.
2381
 
 */
2382
 
 
2383
 
static VALUE
2384
 
rb_str_reverse_bang(VALUE str)
2385
 
{
2386
 
    char *s, *e;
2387
 
    char c;
2388
 
 
2389
 
    if (RSTRING_LEN(str) > 1) {
2390
 
        rb_str_modify(str);
2391
 
        s = RSTRING_PTR(str);
2392
 
        e = s + RSTRING_LEN(str) - 1;
2393
 
        while (s < e) {
2394
 
            c = *s;
2395
 
            *s++ = *e;
2396
 
            *e-- = c;
2397
 
        }
2398
 
    }
2399
 
    return str;
2400
 
}
2401
 
 
2402
 
 
2403
 
/*
2404
 
 *  call-seq:
2405
2511
 *     str.reverse   => new_str
2406
2512
 *  
2407
2513
 *  Returns a new string with the characters from <i>str</i> in reverse order.
2412
2518
static VALUE
2413
2519
rb_str_reverse(VALUE str)
2414
2520
{
 
2521
    rb_encoding *enc;
2415
2522
    VALUE obj;
2416
2523
    char *s, *e, *p;
2417
2524
 
2418
2525
    if (RSTRING_LEN(str) <= 1) return rb_str_dup(str);
2419
 
 
 
2526
    enc = rb_enc_get(str);
2420
2527
    obj = rb_str_new5(str, 0, RSTRING_LEN(str));
2421
 
    s = RSTRING_PTR(str); e = s + RSTRING_LEN(str) - 1;
2422
 
    p = RSTRING_PTR(obj);
2423
 
 
2424
 
    while (e >= s) {
2425
 
        *p++ = *e--;
 
2528
    s = RSTRING_PTR(str); e = RSTRING_END(str);
 
2529
    p = RSTRING_END(obj);
 
2530
 
 
2531
    if (RSTRING_LEN(str) > 1) {
 
2532
        if (rb_enc_mbmaxlen(enc) == 1) {
 
2533
            while (s < e) {
 
2534
                *--p = *s++;
 
2535
            }
 
2536
        }
 
2537
        else {
 
2538
            while (s < e) {
 
2539
                int clen = rb_enc_mbclen(s, enc);
 
2540
 
 
2541
                if (clen == 0) {
 
2542
                    rb_raise(rb_eArgError, "invalid mbstring sequence");
 
2543
                }
 
2544
                p -= clen;
 
2545
                memcpy(p, s, clen);
 
2546
                s += clen;
 
2547
            }
 
2548
        }
2426
2549
    }
 
2550
    STR_SET_LEN(obj, RSTRING_LEN(str));
2427
2551
    OBJ_INFECT(obj, str);
 
2552
    rb_enc_associate(obj, enc);
2428
2553
 
2429
2554
    return obj;
2430
2555
}
2432
2557
 
2433
2558
/*
2434
2559
 *  call-seq:
 
2560
 *     str.reverse!   => str
 
2561
 *  
 
2562
 *  Reverses <i>str</i> in place.
 
2563
 */
 
2564
 
 
2565
static VALUE
 
2566
rb_str_reverse_bang(VALUE str)
 
2567
{
 
2568
    rb_encoding *enc = rb_enc_get(str);
 
2569
    char *s, *e, c;
 
2570
 
 
2571
    if (RSTRING_LEN(str) > 1) {
 
2572
        rb_str_modify(str);
 
2573
        s = RSTRING_PTR(str);
 
2574
        e = RSTRING_END(str) - 1;
 
2575
 
 
2576
        if (rb_enc_mbmaxlen(enc) == 1) {
 
2577
            while (s < e) {
 
2578
                c = *s;
 
2579
                *s++ = *e;
 
2580
                *e-- = c;
 
2581
            }
 
2582
        }
 
2583
        else {
 
2584
            rb_str_shared_replace(str, rb_str_reverse(str));
 
2585
        }
 
2586
    }
 
2587
    return str;
 
2588
}
 
2589
 
 
2590
 
 
2591
/*
 
2592
 *  call-seq:
2435
2593
 *     str.include? other_str   => true or false
2436
2594
 *     str.include? fixnum      => true or false
2437
2595
 *  
2448
2606
{
2449
2607
    long i;
2450
2608
 
2451
 
    if (FIXNUM_P(arg)) {
2452
 
        if (memchr(RSTRING_PTR(str), FIX2INT(arg), RSTRING_LEN(str)))
2453
 
            return Qtrue;
2454
 
        return Qfalse;
2455
 
    }
2456
 
 
2457
2609
    StringValue(arg);
2458
2610
    i = rb_str_index(str, arg, 0);
2459
2611
 
2540
2692
    return str;
2541
2693
}
2542
2694
 
2543
 
#define IS_EVSTR(p,e) ((p) < (e) && (*(p) == '$' || *(p) == '@' || *(p) == '{'))
 
2695
static void
 
2696
str_cat_char(VALUE str, int c, rb_encoding *enc)
 
2697
{
 
2698
    char s[16];
 
2699
    int n = rb_enc_codelen(c, enc);
 
2700
 
 
2701
    rb_enc_mbcput(c, s, enc);
 
2702
    rb_str_buf_cat(str, s, n);
 
2703
}
 
2704
 
 
2705
static void
 
2706
prefix_escape(VALUE str, int c, rb_encoding *enc)
 
2707
{
 
2708
    str_cat_char(str, '\\', enc);
 
2709
    str_cat_char(str, c, enc);
 
2710
}
2544
2711
 
2545
2712
/*
2546
2713
 * call-seq:
2557
2724
VALUE
2558
2725
rb_str_inspect(VALUE str)
2559
2726
{
 
2727
    rb_encoding *enc = rb_enc_get(str);
2560
2728
    char *p, *pend;
2561
 
    VALUE result = rb_str_buf_new2("\"");
2562
 
    char s[5];
 
2729
    VALUE result = rb_str_buf_new2("");
2563
2730
 
2564
 
    p = RSTRING_PTR(str); pend = p + RSTRING_LEN(str);
 
2731
    str_cat_char(result, '"', enc);
 
2732
    p = RSTRING_PTR(str); pend = RSTRING_END(str);
2565
2733
    while (p < pend) {
2566
 
        char c = *p++;
2567
 
        if (ismbchar(c) && p < pend) {
2568
 
            int len = mbclen(c);
2569
 
            rb_str_buf_cat(result, p - 1, len);
2570
 
            p += len - 1;
2571
 
        }
2572
 
        else if (c == '"'|| c == '\\' || (c == '#' && IS_EVSTR(p, pend))) {
2573
 
            s[0] = '\\'; s[1] = c;
2574
 
            rb_str_buf_cat(result, s, 2);
2575
 
        }
2576
 
        else if (ISPRINT(c)) {
2577
 
            s[0] = c;
2578
 
            rb_str_buf_cat(result, s, 1);
 
2734
        int c = rb_enc_codepoint(p, pend, enc);
 
2735
        int n = rb_enc_codelen(c, enc);
 
2736
        int cc;
 
2737
 
 
2738
        p += n;
 
2739
        if (c == '"'|| c == '\\' ||
 
2740
            (c == '#' && (cc = rb_enc_codepoint(p,pend,enc),
 
2741
                          (cc == '$' || cc == '@' || cc == '{')))) {
 
2742
            prefix_escape(result, c, enc);
2579
2743
        }
2580
2744
        else if (c == '\n') {
2581
 
            s[0] = '\\'; s[1] = 'n';
2582
 
            rb_str_buf_cat(result, s, 2);
 
2745
            prefix_escape(result, 'n', enc);
2583
2746
        }
2584
2747
        else if (c == '\r') {
2585
 
            s[0] = '\\'; s[1] = 'r';
2586
 
            rb_str_buf_cat(result, s, 2);
 
2748
            prefix_escape(result, 'r', enc);
2587
2749
        }
2588
2750
        else if (c == '\t') {
2589
 
            s[0] = '\\'; s[1] = 't';
2590
 
            rb_str_buf_cat(result, s, 2);
 
2751
            prefix_escape(result, 't', enc);
2591
2752
        }
2592
2753
        else if (c == '\f') {
2593
 
            s[0] = '\\'; s[1] = 'f';
2594
 
            rb_str_buf_cat(result, s, 2);
 
2754
            prefix_escape(result, 'f', enc);
2595
2755
        }
2596
2756
        else if (c == '\013') {
2597
 
            s[0] = '\\'; s[1] = 'v';
2598
 
            rb_str_buf_cat(result, s, 2);
 
2757
            prefix_escape(result, 'v', enc);
2599
2758
        }
2600
2759
        else if (c == '\010') {
2601
 
            s[0] = '\\'; s[1] = 'b';
2602
 
            rb_str_buf_cat(result, s, 2);
 
2760
            prefix_escape(result, 'b', enc);
2603
2761
        }
2604
2762
        else if (c == '\007') {
2605
 
            s[0] = '\\'; s[1] = 'a';
2606
 
            rb_str_buf_cat(result, s, 2);
 
2763
            prefix_escape(result, 'a', enc);
2607
2764
        }
2608
2765
        else if (c == 033) {
2609
 
            s[0] = '\\'; s[1] = 'e';
2610
 
            rb_str_buf_cat(result, s, 2);
 
2766
            prefix_escape(result, 'e', enc);
 
2767
        }
 
2768
        else if (rb_enc_isprint(c, enc)) {
 
2769
            char buf[5];
 
2770
 
 
2771
            rb_enc_mbcput(c, buf, enc);
 
2772
            rb_str_buf_cat(result, buf, n);
2611
2773
        }
2612
2774
        else {
2613
 
            sprintf(s, "\\%03o", c & 0377);
2614
 
            rb_str_buf_cat2(result, s);
 
2775
            char buf[5];
 
2776
            char *s = buf;
 
2777
 
 
2778
            sprintf(buf, "\\%03o", c & 0377);
 
2779
            while (*s) {
 
2780
                str_cat_char(result, *s++, enc);
 
2781
            }
2615
2782
        }
2616
2783
    }
2617
 
    rb_str_buf_cat2(result, "\"");
 
2784
    str_cat_char(result, '"', enc);
2618
2785
 
2619
2786
    OBJ_INFECT(result, str);
 
2787
    rb_enc_associate(result, enc);
2620
2788
    return result;
2621
2789
}
2622
2790
 
 
2791
#define IS_EVSTR(p,e) ((p) < (e) && (*(p) == '$' || *(p) == '@' || *(p) == '{'))
2623
2792
 
2624
2793
/*
2625
2794
 *  call-seq:
2632
2801
VALUE
2633
2802
rb_str_dump(VALUE str)
2634
2803
{
 
2804
    rb_encoding *enc = rb_enc_from_index(0);
2635
2805
    long len;
2636
2806
    char *p, *pend;
2637
2807
    char *q, *qend;
2654
2824
            break;
2655
2825
 
2656
2826
          default:
2657
 
            if (ISPRINT(c)) {
 
2827
            if (rb_enc_isprint(c, enc)) {
2658
2828
                len++;
2659
2829
            }
2660
2830
            else {
2680
2850
            if (IS_EVSTR(p, pend)) *q++ = '\\';
2681
2851
            *q++ = '#';
2682
2852
        }
2683
 
        else if (ISPRINT(c)) {
2684
 
            *q++ = c;
2685
 
        }
2686
2853
        else if (c == '\n') {
2687
2854
            *q++ = '\\';
2688
2855
            *q++ = 'n';
2715
2882
            *q++ = '\\';
2716
2883
            *q++ = 'e';
2717
2884
        }
 
2885
        else if (rb_enc_isprint(c, enc)) {
 
2886
            *q++ = c;
 
2887
        }
2718
2888
        else {
2719
2889
            *q++ = '\\';
2720
2890
            sprintf(q, "%03o", c&0xff);
2724
2894
    *q++ = '"';
2725
2895
 
2726
2896
    OBJ_INFECT(result, str);
 
2897
    /* result from dump is ASCII */
 
2898
    rb_enc_associate(result, enc);
2727
2899
    return result;
2728
2900
}
2729
2901
 
2740
2912
static VALUE
2741
2913
rb_str_upcase_bang(VALUE str)
2742
2914
{
 
2915
    rb_encoding *enc;
2743
2916
    char *s, *send;
2744
2917
    int modify = 0;
2745
2918
 
2746
2919
    rb_str_modify(str);
2747
 
    s = RSTRING_PTR(str); send = s + RSTRING_LEN(str);
 
2920
    enc = rb_enc_get(str);
 
2921
    s = RSTRING_PTR(str); send = RSTRING_END(str);
2748
2922
    while (s < send) {
2749
 
        if (ismbchar(*s)) {
2750
 
            s+=mbclen(*s) - 1;
2751
 
        }
2752
 
        else if (ISLOWER(*s)) {
2753
 
            *s = toupper(*s);
 
2923
        int c = rb_enc_codepoint(s, send, enc);
 
2924
 
 
2925
        if (rb_enc_islower(c, enc)) {
 
2926
            /* assuming toupper returns codepoint with same size */
 
2927
            rb_enc_mbcput(rb_enc_toupper(c, enc), s, enc);
2754
2928
            modify = 1;
2755
2929
        }
2756
 
        s++;
 
2930
        s += rb_enc_codelen(c, enc);
2757
2931
    }
2758
2932
 
2759
2933
    if (modify) return str;
2794
2968
static VALUE
2795
2969
rb_str_downcase_bang(VALUE str)
2796
2970
{
 
2971
    rb_encoding *enc;
2797
2972
    char *s, *send;
2798
2973
    int modify = 0;
2799
2974
 
2800
2975
    rb_str_modify(str);
2801
 
    s = RSTRING_PTR(str); send = s + RSTRING_LEN(str);
 
2976
    enc = rb_enc_get(str);
 
2977
    s = RSTRING_PTR(str); send = RSTRING_END(str);
2802
2978
    while (s < send) {
2803
 
        if (ismbchar(*s)) {
2804
 
            s+=mbclen(*s) - 1;
2805
 
        }
2806
 
        else if (ISUPPER(*s)) {
2807
 
            *s = tolower(*s);
 
2979
        int c = rb_enc_codepoint(s, send, enc);
 
2980
 
 
2981
        if (rb_enc_isupper(c, enc)) {
 
2982
            /* assuming toupper returns codepoint with same size */
 
2983
            rb_enc_mbcput(rb_enc_tolower(c, enc), s, enc);
2808
2984
            modify = 1;
2809
2985
        }
2810
 
        s++;
 
2986
        s += rb_enc_codelen(c, enc);
2811
2987
    }
2812
2988
 
2813
2989
    if (modify) return str;
2853
3029
static VALUE
2854
3030
rb_str_capitalize_bang(VALUE str)
2855
3031
{
 
3032
    rb_encoding *enc;
2856
3033
    char *s, *send;
2857
3034
    int modify = 0;
 
3035
    int c;
2858
3036
 
2859
3037
    rb_str_modify(str);
 
3038
    enc = rb_enc_get(str);
2860
3039
    if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str)) return Qnil;
2861
 
    s = RSTRING_PTR(str); send = s + RSTRING_LEN(str);
2862
 
    if (ISLOWER(*s)) {
2863
 
        *s = toupper(*s);
 
3040
    s = RSTRING_PTR(str); send = RSTRING_END(str);
 
3041
 
 
3042
    c = rb_enc_codepoint(s, send, enc);
 
3043
    if (rb_enc_islower(c, enc)) {
 
3044
        rb_enc_mbcput(rb_enc_toupper(c, enc), s, enc);
2864
3045
        modify = 1;
2865
3046
    }
2866
 
    while (++s < send) {
2867
 
        if (ismbchar(*s)) {
2868
 
            s+=mbclen(*s) - 1;
2869
 
        }
2870
 
        else if (ISUPPER(*s)) {
2871
 
            *s = tolower(*s);
 
3047
    s += rb_enc_codelen(c, enc);
 
3048
    while (s < send) {
 
3049
        c = rb_enc_codepoint(s, send, enc);
 
3050
        if (rb_enc_isupper(c, enc)) {
 
3051
            rb_enc_mbcput(rb_enc_tolower(c, enc), s, enc);
2872
3052
            modify = 1;
2873
3053
        }
 
3054
        s += rb_enc_codelen(c, enc);
2874
3055
    }
2875
3056
    if (modify) return str;
2876
3057
    return Qnil;
2911
3092
static VALUE
2912
3093
rb_str_swapcase_bang(VALUE str)
2913
3094
{
 
3095
    rb_encoding *enc;
2914
3096
    char *s, *send;
2915
3097
    int modify = 0;
2916
3098
 
2917
3099
    rb_str_modify(str);
2918
 
    s = RSTRING_PTR(str); send = s + RSTRING_LEN(str);
 
3100
    enc = rb_enc_get(str);
 
3101
    s = RSTRING_PTR(str); send = RSTRING_END(str);
2919
3102
    while (s < send) {
2920
 
        if (ismbchar(*s)) {
2921
 
            s+=mbclen(*s) - 1;
2922
 
        }
2923
 
        else if (ISUPPER(*s)) {
2924
 
            *s = tolower(*s);
2925
 
            modify = 1;
2926
 
        }
2927
 
        else if (ISLOWER(*s)) {
2928
 
            *s = toupper(*s);
2929
 
            modify = 1;
2930
 
        }
2931
 
        s++;
 
3103
        int c = rb_enc_codepoint(s, send, enc);
 
3104
 
 
3105
        if (rb_enc_isupper(c, enc)) {
 
3106
            /* assuming toupper returns codepoint with same size */
 
3107
            rb_enc_mbcput(rb_enc_tolower(c, enc), s, enc);
 
3108
            modify = 1;
 
3109
        }
 
3110
        else if (rb_enc_islower(c, enc)) {
 
3111
            /* assuming toupper returns codepoint with same size */
 
3112
            rb_enc_mbcput(rb_enc_toupper(c, enc), s, enc);
 
3113
            modify = 1;
 
3114
        }
 
3115
        s += rb_enc_codelen(c, enc);
2932
3116
    }
2933
3117
 
2934
3118
    if (modify) return str;
2964
3148
};
2965
3149
 
2966
3150
static int
2967
 
trnext(struct tr *t)
 
3151
trnext(struct tr *t, rb_encoding *enc)
2968
3152
{
2969
3153
    for (;;) {
2970
3154
        if (!t->gen) {
2971
3155
            if (t->p == t->pend) return -1;
2972
 
            if (t->p < t->pend - 1 && *t->p == '\\') {
2973
 
                t->p++;
2974
 
            }
2975
 
            t->now = *(USTR)t->p++;
 
3156
            t->now = rb_enc_codepoint(t->p, t->pend, enc);
 
3157
            t->p += rb_enc_codelen(t->now, enc);
2976
3158
            if (t->p < t->pend - 1 && *t->p == '-') {
2977
3159
                t->p++;
2978
3160
                if (t->p < t->pend) {
2979
 
                    if (t->now > *(USTR)t->p) {
2980
 
                        t->p++;
2981
 
                        continue;
2982
 
                    }
 
3161
                    int c = rb_enc_codepoint(t->p, t->pend, enc);
 
3162
                    t->p += rb_enc_codelen(c, enc);
 
3163
                    if (t->now > c) continue;
2983
3164
                    t->gen = 1;
2984
 
                    t->max = *(USTR)t->p++;
 
3165
                    t->max = c;
2985
3166
                }
2986
3167
            }
2987
3168
            return t->now;
3001
3182
static VALUE
3002
3183
tr_trans(VALUE str, VALUE src, VALUE repl, int sflag)
3003
3184
{
 
3185
    rb_encoding *enc;
3004
3186
    struct tr trsrc, trrepl;
3005
3187
    int cflag = 0;
3006
 
    int trans[256];
3007
 
    int i, c, modify = 0;
 
3188
    int c, last = 0, modify = 0;
3008
3189
    char *s, *send;
 
3190
    VALUE hash;
3009
3191
 
3010
3192
    StringValue(src);
3011
3193
    StringValue(repl);
3018
3200
    if (RSTRING_LEN(repl) == 0) {
3019
3201
        return rb_str_delete_bang(1, &src, str);
3020
3202
    }
 
3203
    enc = rb_enc_check(str, src);
 
3204
    if (rb_enc_check(str, repl) != enc) {
 
3205
        rb_raise(rb_eArgError, "character encodings differ");
 
3206
    }
3021
3207
    trrepl.p = RSTRING_PTR(repl);
3022
3208
    trrepl.pend = trrepl.p + RSTRING_LEN(repl);
3023
3209
    trsrc.gen = trrepl.gen = 0;
3024
3210
    trsrc.now = trrepl.now = 0;
3025
3211
    trsrc.max = trrepl.max = 0;
 
3212
    hash = rb_hash_new();
3026
3213
 
3027
3214
    if (cflag) {
3028
 
        for (i=0; i<256; i++) {
3029
 
            trans[i] = 1;
3030
 
        }
3031
 
        while ((c = trnext(&trsrc)) >= 0) {
3032
 
            trans[c & 0xff] = -1;
3033
 
        }
3034
 
        while ((c = trnext(&trrepl)) >= 0)
 
3215
        while ((c = trnext(&trsrc, enc)) >= 0) {
 
3216
            rb_hash_aset(hash, INT2NUM(c), Qtrue);
 
3217
        }
 
3218
        while ((c = trnext(&trrepl, enc)) >= 0)
3035
3219
            /* retrieve last replacer */;
3036
 
        for (i=0; i<256; i++) {
3037
 
            if (trans[i] >= 0) {
3038
 
                trans[i] = trrepl.now;
3039
 
            }
3040
 
        }
 
3220
        last = trrepl.now;
3041
3221
    }
3042
3222
    else {
3043
3223
        int r;
3044
3224
 
3045
 
        for (i=0; i<256; i++) {
3046
 
            trans[i] = -1;
3047
 
        }
3048
 
        while ((c = trnext(&trsrc)) >= 0) {
3049
 
            r = trnext(&trrepl);
 
3225
        while ((c = trnext(&trsrc, enc)) >= 0) {
 
3226
            r = trnext(&trrepl, enc);
3050
3227
            if (r == -1) r = trrepl.now;
3051
 
            trans[c & 0xff] = r;
 
3228
            rb_hash_aset(hash, INT2NUM(c), INT2NUM(r));
3052
3229
        }
3053
3230
    }
3054
3231
 
3055
3232
    rb_str_modify(str);
3056
 
    s = RSTRING_PTR(str); send = s + RSTRING_LEN(str);
 
3233
    s = RSTRING_PTR(str); send = RSTRING_END(str);
3057
3234
    if (sflag) {
3058
 
        char *t = s;
3059
 
        int c0, last = -1;
 
3235
        int clen, tlen, max = RSTRING_LEN(str);
 
3236
        int offset, save = -1;
 
3237
        char *buf = ALLOC_N(char, max), *t = buf;
 
3238
        VALUE v;
3060
3239
 
 
3240
        if (cflag) tlen = rb_enc_codelen(last, enc);
3061
3241
        while (s < send) {
3062
 
            c0 = *s++;
3063
 
            if ((c = trans[c0 & 0xff]) >= 0) {
3064
 
                if (last == c) continue;
3065
 
                last = c;
3066
 
                *t++ = c & 0xff;
 
3242
            c = rb_enc_codepoint(s, send, enc);
 
3243
            tlen = clen = rb_enc_codelen(c, enc);
 
3244
 
 
3245
            s += clen;
 
3246
            v = rb_hash_aref(hash, INT2NUM(c));
 
3247
            if (!NIL_P(v)) {
 
3248
                if (!cflag) {
 
3249
                    c = NUM2INT(v);
 
3250
                    if (save == c) continue;
 
3251
                    save = c;
 
3252
                    tlen = rb_enc_codelen(c, enc);
 
3253
                    modify = 1;
 
3254
                }
 
3255
            }
 
3256
            else if (cflag) {
 
3257
                save = c = last;
3067
3258
                modify = 1;
3068
3259
            }
3069
3260
            else {
3070
 
                last = -1;
3071
 
                *t++ = c0;
3072
 
            }
3073
 
        }
3074
 
        if (RSTRING_LEN(str) > (t - RSTRING_PTR(str))) {
3075
 
            STR_SET_LEN(str, (t - RSTRING_PTR(str)));
3076
 
            modify = 1;
3077
 
            *t = '\0';
3078
 
        }
 
3261
                save = -1;
 
3262
            }
 
3263
            while (t - buf + tlen >= max) {
 
3264
                offset = t - buf;
 
3265
                max *= 2;
 
3266
                REALLOC_N(buf, char, max);
 
3267
                t = buf + offset;
 
3268
            }
 
3269
            rb_enc_mbcput(c, t, enc);
 
3270
            t += tlen;
 
3271
        }
 
3272
        *t = '\0';
 
3273
        RSTRING(str)->as.heap.ptr = buf;
 
3274
        RSTRING(str)->as.heap.len = t - buf;
 
3275
        STR_SET_NOEMBED(str);
 
3276
        RSTRING(str)->as.heap.aux.capa = max;
3079
3277
    }
3080
 
    else {
 
3278
    else if (rb_enc_mbmaxlen(enc) == 1) {
3081
3279
        while (s < send) {
3082
 
            if ((c = trans[*s & 0xff]) >= 0) {
3083
 
                *s = c & 0xff;
 
3280
            VALUE v = rb_hash_aref(hash, INT2FIX(*s));
 
3281
            if (!NIL_P(v)) {
 
3282
                if (!cflag) {
 
3283
                    c = FIX2INT(v);
 
3284
                    *s = c & 0xff;
 
3285
                    modify = 1;
 
3286
                }
 
3287
            }
 
3288
            else if (cflag) {
 
3289
                *s = last;
3084
3290
                modify = 1;
3085
3291
            }
3086
3292
            s++;
3087
3293
        }
3088
3294
    }
 
3295
    else {
 
3296
        int clen, tlen, max = RSTRING_LEN(str) * 1.2;
 
3297
        int offset;
 
3298
        char *buf = ALLOC_N(char, max), *t = buf;
 
3299
        VALUE v;
 
3300
 
 
3301
        if (cflag) tlen = rb_enc_codelen(last, enc);
 
3302
        while (s < send) {
 
3303
            c = rb_enc_codepoint(s, send, enc);
 
3304
            tlen = clen = rb_enc_codelen(c, enc);
 
3305
 
 
3306
            v = rb_hash_aref(hash, INT2NUM(c));
 
3307
            if (!NIL_P(v)) {
 
3308
                if (!cflag) {
 
3309
                    c = NUM2INT(v);
 
3310
                    tlen = rb_enc_codelen(c, enc);
 
3311
                    modify = 1;
 
3312
                }
 
3313
            }
 
3314
            else if (cflag) {
 
3315
                c = last;
 
3316
                modify = 1;
 
3317
            }
 
3318
            while (t - buf + tlen >= max) {
 
3319
                offset = t - buf;
 
3320
                max *= 2;
 
3321
                REALLOC_N(buf, char, max);
 
3322
                t = buf + offset;
 
3323
            }
 
3324
            if (s != t) rb_enc_mbcput(c, t, enc);
 
3325
            s += clen;
 
3326
            t += tlen;
 
3327
        }
 
3328
        if (!STR_EMBED_P(str)) {
 
3329
            free(RSTRING(str)->as.heap.ptr);
 
3330
        }
 
3331
        *t = '\0';
 
3332
        RSTRING(str)->as.heap.ptr = buf;
 
3333
        RSTRING(str)->as.heap.len = t - buf;
 
3334
        STR_SET_NOEMBED(str);
 
3335
        RSTRING(str)->as.heap.aux.capa = max;
 
3336
    }
3089
3337
 
3090
3338
    if (modify) return str;
3091
3339
    return Qnil;
3134
3382
}
3135
3383
 
3136
3384
static void
3137
 
tr_setup_table(VALUE str, char table[256], int init)
 
3385
tr_setup_table(VALUE str, VALUE *tablep, VALUE *ctablep, rb_encoding *enc)
3138
3386
{
3139
 
    char buf[256];
3140
3387
    struct tr tr;
3141
 
    int i, c;
3142
 
    int cflag = 0;
 
3388
    int c;
 
3389
    VALUE table, ptable;
3143
3390
 
3144
3391
    tr.p = RSTRING_PTR(str); tr.pend = tr.p + RSTRING_LEN(str);
3145
3392
    tr.gen = tr.now = tr.max = 0;
 
3393
    table = rb_hash_new();
3146
3394
    if (RSTRING_LEN(str) > 1 && RSTRING_PTR(str)[0] == '^') {
3147
 
        cflag = 1;
3148
3395
        tr.p++;
3149
 
    }
3150
 
 
3151
 
    if (init) {
3152
 
        for (i=0; i<256; i++) {
3153
 
            table[i] = 1;
 
3396
        ptable = *ctablep;
 
3397
        *ctablep = table;
 
3398
    }
 
3399
    else {
 
3400
        ptable = *tablep;
 
3401
        *tablep = table;
 
3402
    }
 
3403
 
 
3404
    while ((c = trnext(&tr, enc)) >= 0) {
 
3405
        VALUE key = INT2NUM(c);
 
3406
 
 
3407
        if (!ptable || !NIL_P(rb_hash_aref(ptable, key))) {
 
3408
            rb_hash_aset(table, key, Qtrue);
3154
3409
        }
3155
3410
    }
3156
 
    for (i=0; i<256; i++) {
3157
 
        buf[i] = cflag;
3158
 
    }
3159
 
    while ((c = trnext(&tr)) >= 0) {
3160
 
        buf[c & 0xff] = !cflag;
3161
 
    }
3162
 
    for (i=0; i<256; i++) {
3163
 
        table[i] = table[i] && buf[i];
3164
 
    }
3165
3411
}
3166
3412
 
3167
3413
 
3176
3422
static VALUE
3177
3423
rb_str_delete_bang(int argc, VALUE *argv, VALUE str)
3178
3424
{
 
3425
    rb_encoding *enc;
3179
3426
    char *s, *send, *t;
3180
 
    char squeez[256];
 
3427
    VALUE del = 0, nodel = 0;
3181
3428
    int modify = 0;
3182
 
    int init = 1;
3183
3429
    int i;
3184
3430
 
3185
3431
    if (argc < 1) {
3189
3435
        VALUE s = argv[i];
3190
3436
 
3191
3437
        StringValue(s);
3192
 
        tr_setup_table(s, squeez, init);
3193
 
        init = 0;
 
3438
        enc = rb_enc_check(str, s);
 
3439
        tr_setup_table(s, &del, &nodel, enc);
3194
3440
    }
3195
3441
 
3196
3442
    rb_str_modify(str);
3197
3443
    s = t = RSTRING_PTR(str);
3198
3444
    if (!s || RSTRING_LEN(str) == 0) return Qnil;
3199
 
    send = s + RSTRING_LEN(str);
 
3445
    send = RSTRING_END(str);
3200
3446
    while (s < send) {
3201
 
        if (squeez[*s & 0xff])
 
3447
        int c = rb_enc_codepoint(s, send, enc);
 
3448
        int clen = rb_enc_codelen(c, enc);
 
3449
        VALUE v = INT2NUM(c);
 
3450
 
 
3451
        if ((del && !NIL_P(rb_hash_aref(del, v))) &&
 
3452
            (!nodel || NIL_P(rb_hash_aref(nodel, v)))) {
3202
3453
            modify = 1;
3203
 
        else
3204
 
            *t++ = *s;
3205
 
        s++;
 
3454
        }
 
3455
        else {
 
3456
            if (t != s) rb_enc_mbcput(c, t, enc);
 
3457
            t += clen;
 
3458
        }
 
3459
        s += clen;
3206
3460
    }
3207
3461
    *t = '\0';
3208
3462
    STR_SET_LEN(str, t - RSTRING_PTR(str));
3246
3500
static VALUE
3247
3501
rb_str_squeeze_bang(int argc, VALUE *argv, VALUE str)
3248
3502
{
3249
 
    char squeez[256];
 
3503
    rb_encoding *enc = 0;
 
3504
    VALUE del = 0, nodel = 0;
3250
3505
    char *s, *send, *t;
3251
 
    int c, save, modify = 0;
3252
 
    int init = 1;
 
3506
    int save, modify = 0;
3253
3507
    int i;
3254
3508
 
3255
3509
    if (argc == 0) {
3256
 
        for (i=0; i<256; i++) {
3257
 
            squeez[i] = 1;
3258
 
        }
 
3510
        enc = rb_enc_get(str);
3259
3511
    }
3260
3512
    else {
3261
3513
        for (i=0; i<argc; i++) {
3262
3514
            VALUE s = argv[i];
3263
3515
 
3264
3516
            StringValue(s);
3265
 
            tr_setup_table(s, squeez, init);
3266
 
            init = 0;
 
3517
            enc = rb_enc_check(str, s);
 
3518
            tr_setup_table(s, &del, &nodel, enc);
3267
3519
        }
3268
3520
    }
3269
3521
 
3270
3522
    rb_str_modify(str);
3271
3523
    s = t = RSTRING_PTR(str);
3272
3524
    if (!s || RSTRING_LEN(str) == 0) return Qnil;
3273
 
    send = s + RSTRING_LEN(str);
 
3525
    send = RSTRING_END(str);
3274
3526
    save = -1;
3275
3527
    while (s < send) {
3276
 
        c = *s++ & 0xff;
3277
 
        if (c != save || !squeez[c]) {
3278
 
            *t++ = save = c;
 
3528
        int c = rb_enc_codepoint(s, send, enc);
 
3529
        int clen = rb_enc_codelen(c, enc);
 
3530
        VALUE v = INT2NUM(c);
 
3531
 
 
3532
        if (c != save ||
 
3533
            ((del && NIL_P(rb_hash_aref(del, v))) &&
 
3534
             (!nodel || NIL_P(rb_hash_aref(nodel, v))))) {
 
3535
            if (t != s) rb_enc_mbcput(c, t, enc);
 
3536
            save = c;
 
3537
            t += clen;
3279
3538
        }
 
3539
        s += clen;
3280
3540
    }
3281
3541
    *t = '\0';
3282
3542
    if (t - RSTRING_PTR(str) != RSTRING_LEN(str)) {
3369
3629
static VALUE
3370
3630
rb_str_count(int argc, VALUE *argv, VALUE str)
3371
3631
{
3372
 
    char table[256];
 
3632
    rb_encoding *enc;
 
3633
    VALUE del = 0, nodel = 0;
3373
3634
    char *s, *send;
3374
 
    int init = 1;
3375
3635
    int i;
3376
3636
 
3377
3637
    if (argc < 1) {
3381
3641
        VALUE s = argv[i];
3382
3642
 
3383
3643
        StringValue(s);
3384
 
        tr_setup_table(s, table, init);
3385
 
        init = 0;
 
3644
        enc = rb_enc_check(str, s);
 
3645
        tr_setup_table(s, &del, &nodel, enc);
3386
3646
    }
3387
3647
 
3388
3648
    s = RSTRING_PTR(str);
3389
3649
    if (!s || RSTRING_LEN(str) == 0) return INT2FIX(0);
3390
 
    send = s + RSTRING_LEN(str);
 
3650
    send = RSTRING_END(str);
3391
3651
    i = 0;
3392
3652
    while (s < send) {
3393
 
        if (table[*s++ & 0xff]) {
 
3653
        int c = rb_enc_codepoint(s, send, enc);
 
3654
        int clen = rb_enc_codelen(c, enc);
 
3655
        VALUE v = INT2NUM(c);
 
3656
 
 
3657
        if ((del && !NIL_P(rb_hash_aref(del, v))) &&
 
3658
            (!nodel || NIL_P(rb_hash_aref(nodel, v)))) {
3394
3659
            i++;
3395
3660
        }
 
3661
        s += clen;
3396
3662
    }
3397
3663
    return INT2NUM(i);
3398
3664
}
3443
3709
static VALUE
3444
3710
rb_str_split_m(int argc, VALUE *argv, VALUE str)
3445
3711
{
 
3712
    rb_encoding *enc;
3446
3713
    VALUE spat;
3447
3714
    VALUE limit;
3448
3715
    int awk_split = Qfalse;
3461
3728
        i = 1;
3462
3729
    }
3463
3730
 
 
3731
    enc = rb_enc_get(str);
3464
3732
    if (NIL_P(spat)) {
3465
3733
        if (!NIL_P(rb_fs)) {
3466
3734
            spat = rb_fs;
3487
3755
    beg = 0;
3488
3756
    if (awk_split) {
3489
3757
        char *ptr = RSTRING_PTR(str);
3490
 
        long len = RSTRING_LEN(str);
3491
 
        char *eptr = ptr + len;
 
3758
        char *eptr = RSTRING_END(str);
3492
3759
        int skip = 1;
 
3760
        int c;
3493
3761
 
3494
 
        for (end = beg = 0; ptr<eptr; ptr++) {
 
3762
        end = beg;
 
3763
        while (ptr < eptr) {
 
3764
            c = rb_enc_codepoint(ptr, eptr, enc);
3495
3765
            if (skip) {
3496
 
                if (ISSPACE(*ptr)) {
 
3766
                if (rb_enc_isspace(c, enc)) {
3497
3767
                    beg++;
3498
3768
                }
3499
3769
                else {
3503
3773
                }
3504
3774
            }
3505
3775
            else {
3506
 
                if (ISSPACE(*ptr)) {
 
3776
                if (rb_enc_isspace(c, enc)) {
3507
3777
                    rb_ary_push(result, rb_str_substr(str, beg, end-beg));
3508
3778
                    skip = 1;
3509
3779
                    beg = end + 1;
3513
3783
                    end++;
3514
3784
                }
3515
3785
            }
 
3786
            ptr += rb_enc_codelen(c, enc);
3516
3787
        }
3517
3788
    }
3518
3789
    else {
3521
3792
        int last_null = 0;
3522
3793
        struct re_registers *regs;
3523
3794
 
 
3795
        enc = rb_enc_check(str, spat);
3524
3796
        while ((end = rb_reg_search(spat, str, start, 0)) >= 0) {
3525
3797
            regs = RMATCH(rb_backref_get())->regs;
3526
3798
            if (start == end && BEG(0) == END(0)) {
3529
3801
                    break;
3530
3802
                }
3531
3803
                else if (last_null == 1) {
3532
 
                    rb_ary_push(result, rb_str_substr(str, beg, mbclen2(RSTRING_PTR(str)[beg],spat)));
 
3804
                    rb_ary_push(result, rb_str_subseq(str, beg,
 
3805
                                                      rb_enc_mbclen(RSTRING_PTR(str)+beg,enc)));
3533
3806
                    beg = start;
3534
3807
                }
3535
3808
                else {
3536
 
                    start += mbclen2(RSTRING_PTR(str)[start],spat);
 
3809
                    start += rb_enc_mbclen(RSTRING_PTR(str)+start,enc);
3537
3810
                    last_null = 1;
3538
3811
                    continue;
3539
3812
                }
3540
3813
            }
3541
3814
            else {
3542
 
                rb_ary_push(result, rb_str_substr(str, beg, end-beg));
 
3815
                rb_ary_push(result, rb_str_subseq(str, beg, end-beg));
3543
3816
                beg = start = END(0);
3544
3817
            }
3545
3818
            last_null = 0;
3549
3822
                if (BEG(idx) == END(idx))
3550
3823
                    tmp = rb_str_new5(str, 0, 0);
3551
3824
                else
3552
 
                    tmp = rb_str_substr(str, BEG(idx), END(idx)-BEG(idx));
 
3825
                    tmp = rb_str_subseq(str, BEG(idx), END(idx)-BEG(idx));
3553
3826
                rb_ary_push(result, tmp);
3554
3827
            }
3555
3828
            if (!NIL_P(limit) && lim <= ++i) break;
3559
3832
        if (RSTRING_LEN(str) == beg)
3560
3833
            tmp = rb_str_new5(str, 0, 0);
3561
3834
        else
3562
 
            tmp = rb_str_substr(str, beg, RSTRING_LEN(str)-beg);
 
3835
            tmp = rb_str_subseq(str, beg, RSTRING_LEN(str)-beg);
3563
3836
        rb_ary_push(result, tmp);
3564
3837
    }
3565
3838
    if (NIL_P(limit) && lim == 0) {
3631
3904
static VALUE
3632
3905
rb_str_each_line(int argc, VALUE *argv, VALUE str)
3633
3906
{
 
3907
    rb_encoding *enc;
3634
3908
    VALUE rs;
3635
3909
    int newline;
3636
 
    char *p = RSTRING_PTR(str), *pend = p + RSTRING_LEN(str), *s;
 
3910
    char *p = RSTRING_PTR(str), *pend = p + RSTRING_LEN(str), *s = p;
3637
3911
    char *ptr = p;
3638
3912
    long len = RSTRING_LEN(str), rslen;
3639
3913
    VALUE line;
3641
3915
    if (rb_scan_args(argc, argv, "01", &rs) == 0) {
3642
3916
        rs = rb_rs;
3643
3917
    }
3644
 
 
3645
3918
    RETURN_ENUMERATOR(str, argc, argv);
3646
3919
 
3647
3920
    if (NIL_P(rs)) {
3649
3922
        return str;
3650
3923
    }
3651
3924
    StringValue(rs);
 
3925
    enc = rb_enc_check(str, rs);
3652
3926
    rslen = RSTRING_LEN(rs);
3653
3927
    if (rslen == 0) {
3654
3928
        newline = '\n';
3655
3929
    }
3656
3930
    else {
3657
 
        newline = RSTRING_PTR(rs)[rslen-1];
 
3931
        newline = rb_enc_codepoint(RSTRING_PTR(rs), RSTRING_END(rs), enc);
3658
3932
    }
3659
3933
 
3660
 
    for (s = p, p += rslen; p < pend; p++) {
3661
 
        if (rslen == 0 && *p == '\n') {
3662
 
            if (*++p != '\n') continue;
3663
 
            while (*p == '\n') p++;
 
3934
    while (p < pend) {
 
3935
        int c = rb_enc_codepoint(p, pend, enc);
 
3936
        int n = rb_enc_codelen(c, enc);
 
3937
 
 
3938
        if (rslen == 0 && c == newline) {
 
3939
            while (rb_enc_codepoint(p, pend, enc) == newline) {
 
3940
                p += n;
 
3941
            }
 
3942
            p -= n;
3664
3943
        }
3665
 
        if (RSTRING_PTR(str) < p && p[-1] == newline &&
3666
 
            (rslen <= 1 ||
3667
 
             rb_memcmp(RSTRING_PTR(rs), p-rslen, rslen) == 0)) {
3668
 
            line = rb_str_new5(str, s, p - s);
 
3944
        if (c == newline &&
 
3945
            (rslen <= 1 || rb_memcmp(RSTRING_PTR(rs), p, rslen) == 0)) {
 
3946
            line = rb_str_new5(str, s, p - s + (rslen ? rslen : n));
3669
3947
            OBJ_INFECT(line, str);
3670
3948
            rb_yield(line);
3671
3949
            str_mod_check(str, ptr, len);
3672
 
            s = p;
 
3950
            s = p + n;
3673
3951
        }
 
3952
        p += n;
3674
3953
    }
3675
3954
 
3676
3955
    if (s != pend) {
3724
4003
 
3725
4004
 
3726
4005
/*
 
4006
 *  Document-method: chars
 
4007
 *  call-seq:
 
4008
 *     str.chars                   => anEnumerator
 
4009
 *     str.chars {|substr| block } => str
 
4010
 *  
 
4011
 *  Returns an enumerator that gives each character in the string.
 
4012
 *  If a block is given, it iterates over each character in the string.
 
4013
 *     
 
4014
 *     "foo".chars.to_a   #=> ["f","o","o"]
 
4015
 */
 
4016
 
 
4017
/*
 
4018
 *  Document-method: each_char
 
4019
 *  call-seq:
 
4020
 *     str.each_char {|cstr| block }    => str
 
4021
 *  
 
4022
 *  Passes each character in <i>str</i> to the given block.
 
4023
 *     
 
4024
 *     "hello".each_char {|c| print c, ' ' }
 
4025
 *     
 
4026
 *  <em>produces:</em>
 
4027
 *     
 
4028
 *     h e l l o 
 
4029
 */
 
4030
 
 
4031
static VALUE
 
4032
rb_str_each_char(VALUE str)
 
4033
{
 
4034
    int i, len = str_strlen(str, 0);
 
4035
 
 
4036
    RETURN_ENUMERATOR(str, 0, 0);
 
4037
    for (i=0; i<len; i++) {
 
4038
        rb_yield(rb_str_substr(str, i, 1));
 
4039
    }
 
4040
    return str;
 
4041
}
 
4042
 
 
4043
/*
3727
4044
 *  call-seq:
3728
4045
 *     str.chop!   => str or nil
3729
4046
 *  
3897
4214
static VALUE
3898
4215
rb_str_lstrip_bang(VALUE str)
3899
4216
{
 
4217
    rb_encoding *enc;
3900
4218
    char *s, *t, *e;
3901
4219
 
 
4220
    rb_str_modify(str);
 
4221
    enc = rb_enc_get(str);
3902
4222
    s = RSTRING_PTR(str);
3903
4223
    if (!s || RSTRING_LEN(str) == 0) return Qnil;
3904
 
    e = t = s + RSTRING_LEN(str);
 
4224
    e = t = RSTRING_END(str);
3905
4225
    /* remove spaces at head */
3906
 
    while (s < t && ISSPACE(*s)) s++;
 
4226
    while (s < e) {
 
4227
        int cc = rb_enc_codepoint(s, e, enc);
 
4228
        
 
4229
        if (!rb_enc_isspace(cc, enc)) break;
 
4230
        s += rb_enc_codelen(cc, enc);
 
4231
    }
3907
4232
 
3908
4233
    if (s > RSTRING_PTR(str)) {
3909
4234
        rb_str_modify(str);
3951
4276
static VALUE
3952
4277
rb_str_rstrip_bang(VALUE str)
3953
4278
{
 
4279
    rb_encoding *enc;
3954
4280
    char *s, *t, *e;
 
4281
    int space_seen = Qfalse;
3955
4282
 
 
4283
    rb_str_modify(str);
 
4284
    enc = rb_enc_get(str);
3956
4285
    s = RSTRING_PTR(str);
3957
4286
    if (!s || RSTRING_LEN(str) == 0) return Qnil;
3958
 
    e = t = s + RSTRING_LEN(str);
3959
 
 
3960
 
    /* remove trailing '\0's */
3961
 
    while (s < t && t[-1] == '\0') t--;
3962
 
 
3963
 
    /* remove trailing spaces */
3964
 
    while (s < t && ISSPACE(*(t-1))) t--;
3965
 
 
 
4287
    t = e = RSTRING_END(str);
 
4288
    while (s < e) {
 
4289
        int cc = rb_enc_codepoint(s, e, enc);
 
4290
 
 
4291
        if (!cc || rb_enc_isspace(cc, enc)) {
 
4292
            if (!space_seen) t = s;
 
4293
            space_seen = Qtrue;
 
4294
        }
 
4295
        else {
 
4296
            space_seen = Qfalse;
 
4297
        }
 
4298
        s += rb_enc_codelen(cc, enc);
 
4299
    }
3966
4300
    if (t < e) {
3967
4301
        rb_str_modify(str);
3968
 
        STR_SET_LEN(str, t-s);
 
4302
        STR_SET_LEN(str, t-RSTRING_PTR(str));
3969
4303
        RSTRING_PTR(str)[RSTRING_LEN(str)] = '\0';
3970
4304
        return str;
3971
4305
    }
4033
4367
static VALUE
4034
4368
scan_once(VALUE str, VALUE pat, long *start)
4035
4369
{
 
4370
    rb_encoding *enc;
4036
4371
    VALUE result, match;
4037
4372
    struct re_registers *regs;
4038
4373
    long i;
4039
4374
 
 
4375
    enc = rb_enc_check(str, pat);
4040
4376
    if (rb_reg_search(pat, str, *start, 0) >= 0) {
4041
4377
        match = rb_backref_get();
4042
4378
        regs = RMATCH(match)->regs;
4045
4381
             * Always consume at least one character of the input string
4046
4382
             */
4047
4383
            if (RSTRING_LEN(str) > END(0))
4048
 
                *start = END(0)+mbclen2(RSTRING_PTR(str)[END(0)],pat);
 
4384
                *start = END(0)+rb_enc_mbclen(RSTRING_PTR(str)+END(0),enc);
4049
4385
            else
4050
4386
                *start = END(0)+1;
4051
4387
        }
4224
4560
VALUE
4225
4561
rb_str_intern(VALUE s)
4226
4562
{
4227
 
    volatile VALUE str = s;
 
4563
    VALUE str = RB_GC_GUARD(s);
4228
4564
    ID id;
4229
4565
 
4230
4566
    if (OBJ_TAINTED(str) && rb_safe_level() >= 1) {
4231
4567
        rb_raise(rb_eSecurityError, "Insecure: can't intern tainted string");
4232
4568
    }
4233
 
    id = rb_intern2(RSTRING_PTR(str), RSTRING_LEN(str));
 
4569
    id = rb_intern_str(str);
4234
4570
    return ID2SYM(id);
4235
4571
}
4236
4572
 
4314
4650
static VALUE
4315
4651
rb_str_justify(int argc, VALUE *argv, VALUE str, char jflag)
4316
4652
{
 
4653
    rb_encoding *enc;
4317
4654
    VALUE w;
4318
 
    long width, flen = 0;
 
4655
    long width, len, flen = 1, fclen = 1;
4319
4656
    VALUE res;
4320
 
    char *p, *pend, *f = " ";
4321
 
    long n;
4322
 
    VALUE pad;
 
4657
    char *p, *f = " ";
 
4658
    long n, llen, rlen;
 
4659
    volatile VALUE pad;
4323
4660
 
4324
4661
    rb_scan_args(argc, argv, "11", &w, &pad);
 
4662
    enc = rb_enc_get(str);
4325
4663
    width = NUM2LONG(w);
4326
4664
    if (argc == 2) {
4327
4665
        StringValue(pad);
 
4666
        rb_enc_check(str, pad);
4328
4667
        f = RSTRING_PTR(pad);
4329
4668
        flen = RSTRING_LEN(pad);
 
4669
        fclen = str_strlen(pad, enc);
4330
4670
        if (flen == 0) {
4331
4671
            rb_raise(rb_eArgError, "zero width padding");
4332
4672
        }
4333
4673
    }
4334
 
    if (width < 0 || RSTRING_LEN(str) >= width) return rb_str_dup(str);
4335
 
    res = rb_str_new5(str, 0, width);
 
4674
#if 0
 
4675
    else if (!m17n_asciicompat(enc)) {
 
4676
        rb_raise(rb_eArgError, "character encodings differ");
 
4677
    }
 
4678
#endif
 
4679
    len = str_strlen(str, enc);
 
4680
    if (width < 0 || len >= width) return rb_str_dup(str);
 
4681
    n = width - len;
 
4682
    llen = (jflag == 'l') ? 0 : ((jflag == 'r') ? n : n/2);
 
4683
    rlen = n - llen;
 
4684
    res = rb_str_new5(str, 0, RSTRING_LEN(str)+n*flen/fclen+2);
4336
4685
    p = RSTRING_PTR(res);
4337
 
    if (jflag != 'l') {
4338
 
        n = width - RSTRING_LEN(str);
4339
 
        pend = p + ((jflag == 'r') ? n : n/2);
4340
 
        if (flen <= 1) {
4341
 
            while (p < pend) {
4342
 
                *p++ = *f;
4343
 
            }
4344
 
        }
4345
 
        else {
4346
 
            char *q = f;
4347
 
            while (p + flen <= pend) {
4348
 
                memcpy(p,f,flen);
4349
 
                p += flen;
4350
 
            }
4351
 
            while (p < pend) {
4352
 
                *p++ = *q++;
4353
 
            }
4354
 
        }
4355
 
    }
4356
 
    memcpy(p, RSTRING_PTR(str), RSTRING_LEN(str)+1);
4357
 
    if (jflag != 'r') {
4358
 
        p += RSTRING_LEN(str); pend = RSTRING_PTR(res) + width;
4359
 
        if (flen <= 1) {
4360
 
            while (p < pend) {
4361
 
                *p++ = *f;
4362
 
            }
4363
 
        }
4364
 
        else {
4365
 
            while (p + flen <= pend) {
4366
 
                memcpy(p,f,flen);
4367
 
                p += flen;
4368
 
            }
4369
 
            while (p < pend) {
4370
 
                *p++ = *f++;
4371
 
            }
4372
 
        }
4373
 
    }
 
4686
    while (llen) {
 
4687
        if (flen <= 1) {
 
4688
            *p++ = *f;
 
4689
            llen--;
 
4690
        }
 
4691
        else if (llen > fclen) {
 
4692
            memcpy(p,f,flen);
 
4693
            p += flen;
 
4694
            llen -= fclen;
 
4695
        }
 
4696
        else {
 
4697
            char *fp = str_nth(f, f+flen, llen, enc);
 
4698
            n = fp - f;
 
4699
            memcpy(p,f,n);
 
4700
            p+=n;
 
4701
            break;
 
4702
        }
 
4703
    }
 
4704
    memcpy(p, RSTRING_PTR(str), RSTRING_LEN(str));
 
4705
    p+=RSTRING_LEN(str);
 
4706
    while (rlen) {
 
4707
        if (flen <= 1) {
 
4708
            *p++ = *f;
 
4709
            rlen--;
 
4710
        }
 
4711
        else if (rlen > fclen) {
 
4712
            memcpy(p,f,flen);
 
4713
            p += flen;
 
4714
            rlen -= fclen;
 
4715
        }
 
4716
        else {
 
4717
            char *fp = str_nth(f, f+flen, rlen, enc);
 
4718
            n = fp - f;
 
4719
            memcpy(p,f,n);
 
4720
            p+=n;
 
4721
            break;
 
4722
        }
 
4723
    }
 
4724
    *p = '\0';
 
4725
    STR_SET_LEN(res, p-RSTRING_PTR(res));
4374
4726
    OBJ_INFECT(res, str);
4375
 
    if (flen > 0) OBJ_INFECT(res, pad);
 
4727
    if (!NIL_P(pad)) OBJ_INFECT(res, pad);
4376
4728
    return res;
4377
4729
}
4378
4730
 
4472
4824
      failed:
4473
4825
        return rb_ary_new3(3, str, rb_str_new(0,0),rb_str_new(0,0));
4474
4826
    }
 
4827
    pos = rb_str_sublen(str, pos);
4475
4828
    if (regex) {
4476
4829
        sep = rb_str_subpat(str, sep, 0);
4477
4830
        if (pos == 0 && RSTRING_LEN(sep) == 0) goto failed;
4513
4866
            rb_raise(rb_eTypeError, "type mismatch: %s given",
4514
4867
                     rb_obj_classname(sep));
4515
4868
        }
 
4869
        pos = rb_str_sublen(str, pos);
4516
4870
        pos = rb_str_rindex(str, sep, pos);
4517
4871
    }
4518
4872
    if (pos < 0) {
4519
4873
        return rb_ary_new3(3, rb_str_new(0,0),rb_str_new(0,0), str);
4520
4874
    }
 
4875
    pos = rb_str_sublen(str, pos);
4521
4876
    if (regex) {
4522
4877
        sep = rb_reg_nth_match(0, rb_backref_get());
4523
4878
    }
4542
4897
    for (i=0; i<argc; i++) {
4543
4898
        VALUE tmp = rb_check_string_type(argv[i]);
4544
4899
        if (NIL_P(tmp)) continue;
 
4900
        rb_enc_check(str, tmp);
4545
4901
        if (RSTRING_LEN(str) < RSTRING_LEN(tmp)) continue;
4546
4902
        if (rb_memcmp(RSTRING_PTR(str), RSTRING_PTR(tmp), RSTRING_LEN(tmp)) == 0)
4547
4903
            return Qtrue;
4564
4920
    for (i=0; i<argc; i++) {
4565
4921
        VALUE tmp = rb_check_string_type(argv[i]);
4566
4922
        if (NIL_P(tmp)) continue;
 
4923
        rb_enc_check(str, tmp);
4567
4924
        if (RSTRING_LEN(str) < RSTRING_LEN(tmp)) continue;
4568
4925
        if (rb_memcmp(RSTRING_PTR(str) + RSTRING_LEN(str) - RSTRING_LEN(tmp),
4569
4926
                      RSTRING_PTR(tmp), RSTRING_LEN(tmp)) == 0)
4582
4939
}
4583
4940
 
4584
4941
 
 
4942
static VALUE
 
4943
str_encoding(VALUE str)
 
4944
{
 
4945
    return rb_str_new2(rb_enc_name(rb_enc_get(str)));
 
4946
}
 
4947
 
4585
4948
/**********************************************************************
4586
4949
 * Document-class: Symbol
4587
4950
 *
4618
4981
 
4619
4982
/*
4620
4983
 *  call-seq:
4621
 
 *     Symbol.intern(str)   => new_sym
4622
 
 *  
4623
 
 *  Returns a new symbol corresponding to <i>str</i>.
4624
 
 */
4625
 
 
4626
 
static VALUE
4627
 
rb_sym_s_intern(VALUE s)
4628
 
{
4629
 
    if (SYMBOL_P(s)) {
4630
 
        return s;
4631
 
    }
4632
 
    StringValue(s);
4633
 
    return rb_intern2(RSTRING_PTR(s), RSTRING_LEN(s));
4634
 
}
4635
 
 
4636
 
/*
4637
 
 *  call-seq:
4638
4984
 *     sym == obj   => true or false
4639
4985
 *  
4640
4986
 *  Equality---If <i>sym</i> and <i>obj</i> are exactly the same
4847
5193
    return rb_str_intern(rb_str_swapcase(rb_id2str(SYM2ID(sym))));
4848
5194
}
4849
5195
 
 
5196
static VALUE
 
5197
sym_encoding(VALUE sym)
 
5198
{
 
5199
    return str_encoding(rb_id2str(SYM2ID(sym)));
 
5200
}
 
5201
 
4850
5202
ID
4851
5203
rb_to_id(VALUE name)
4852
5204
{
4861
5213
                     RSTRING_PTR(rb_inspect(name)));
4862
5214
        }
4863
5215
        name = tmp;
 
5216
        /* fall through */
4864
5217
      case T_STRING:
4865
5218
        name = rb_str_intern(name);
4866
5219
        /* fall through */
4889
5242
    rb_cString  = rb_define_class("String", rb_cObject);
4890
5243
    rb_include_module(rb_cString, rb_mComparable);
4891
5244
    rb_define_alloc_func(rb_cString, str_alloc);
 
5245
    rb_define_singleton_method(rb_cString, "try_convert", rb_str_s_try_convert, 1);
4892
5246
    rb_define_method(rb_cString, "initialize", rb_str_init, -1);
4893
5247
    rb_define_method(rb_cString, "initialize_copy", rb_str_replace, 1);
4894
5248
    rb_define_method(rb_cString, "<=>", rb_str_cmp_m, 1);
4904
5258
    rb_define_method(rb_cString, "insert", rb_str_insert, 2);
4905
5259
    rb_define_method(rb_cString, "length", rb_str_length, 0);
4906
5260
    rb_define_method(rb_cString, "size", rb_str_length, 0);
 
5261
    rb_define_method(rb_cString, "bytesize", rb_str_bytesize, 0);
4907
5262
    rb_define_method(rb_cString, "empty?", rb_str_empty, 0);
4908
5263
    rb_define_method(rb_cString, "=~", rb_str_match, 1);
4909
5264
    rb_define_method(rb_cString, "match", rb_str_match_m, -1);
4911
5266
    rb_define_method(rb_cString, "succ!", rb_str_succ_bang, 0);
4912
5267
    rb_define_method(rb_cString, "next", rb_str_succ, 0);
4913
5268
    rb_define_method(rb_cString, "next!", rb_str_succ_bang, 0);
4914
 
    rb_define_method(rb_cString, "upto", rb_str_upto_m, 1);
 
5269
    rb_define_method(rb_cString, "upto", rb_str_upto, -1);
4915
5270
    rb_define_method(rb_cString, "index", rb_str_index_m, -1);
4916
5271
    rb_define_method(rb_cString, "rindex", rb_str_rindex_m, -1);
4917
5272
    rb_define_method(rb_cString, "replace", rb_str_replace, 1);
4988
5343
 
4989
5344
    rb_define_method(rb_cString, "each_line", rb_str_each_line, -1);
4990
5345
    rb_define_method(rb_cString, "each_byte", rb_str_each_byte, 0);
 
5346
    rb_define_method(rb_cString, "each_char", rb_str_each_char, 0);
4991
5347
 
4992
5348
    rb_define_method(rb_cString, "sum", rb_str_sum, -1);
4993
5349
 
4997
5353
    rb_define_method(rb_cString, "partition", rb_str_partition, 1);
4998
5354
    rb_define_method(rb_cString, "rpartition", rb_str_rpartition, 1);
4999
5355
 
 
5356
    rb_define_method(rb_cString, "encoding", str_encoding, 0);
 
5357
 
5000
5358
    id_to_s = rb_intern("to_s");
5001
5359
 
5002
5360
    rb_fs = Qnil;
5008
5366
    rb_undef_alloc_func(rb_cSymbol);
5009
5367
    rb_undef_method(CLASS_OF(rb_cSymbol), "new");
5010
5368
    rb_define_singleton_method(rb_cSymbol, "all_symbols", rb_sym_all_symbols, 0); /* in parse.y */
5011
 
    rb_define_singleton_method(rb_cSymbol, "intern", rb_sym_s_intern, 1);
5012
5369
 
5013
5370
    rb_define_method(rb_cSymbol, "==", sym_equal, 1);
5014
5371
    rb_define_method(rb_cSymbol, "to_i", sym_to_i, 0);
5020
5377
    rb_define_method(rb_cSymbol, "to_proc", sym_to_proc, 0);
5021
5378
    rb_define_method(rb_cSymbol, "succ", sym_succ, 0);
5022
5379
    rb_define_method(rb_cSymbol, "next", sym_succ, 0);
5023
 
    rb_define_method(rb_cSymbol, "dump", rb_str_dump, 0);
5024
5380
 
5025
5381
    rb_define_method(rb_cSymbol, "<=>", sym_cmp, 1);
5026
5382
    rb_define_method(rb_cSymbol, "casecmp", sym_casecmp, 1);
5038
5394
    rb_define_method(rb_cSymbol, "downcase", sym_downcase, 0);
5039
5395
    rb_define_method(rb_cSymbol, "capitalize", sym_capitalize, 0);
5040
5396
    rb_define_method(rb_cSymbol, "swapcase", sym_swapcase, 0);
 
5397
 
 
5398
    rb_define_method(rb_cSymbol, "encoding", sym_encoding, 0);
5041
5399
}