- Timestamp:
- Jan 21, 2018, 12:10:09 AM (6 years ago)
- Location:
- EcnlProtoTool/trunk/mruby-1.3.0
- Files:
-
- 1 edited
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
EcnlProtoTool/trunk/mruby-1.3.0/mrbgems/mruby-string-ext/src/string.c
r321 r331 1 1 #include <string.h> 2 #include "mruby.h"3 #include "mruby/array.h"4 #include "mruby/class.h"5 #include "mruby/string.h"6 #include "mruby/range.h"2 #include <mruby.h> 3 #include <mruby/array.h> 4 #include <mruby/class.h> 5 #include <mruby/string.h> 6 #include <mruby/range.h> 7 7 8 8 static mrb_value … … 24 24 { 25 25 mrb_int pos, byte; 26 long len = RSTRING_LEN(str);26 long len; 27 27 28 28 mrb_get_args(mrb, "ii", &pos, &byte); 29 29 30 len = RSTRING_LEN(str); 30 31 if (pos < -len || len <= pos) 31 32 mrb_raisef(mrb, E_INDEX_ERROR, "index %S is out of array", mrb_fixnum_value(pos)); … … 56 57 57 58 len = RSTRING_LEN(str); 58 if (mrb_range_beg_len(mrb, a1, &beg, &len, len)) { 59 switch (mrb_range_beg_len(mrb, a1, &beg, &len, len, TRUE)) { 60 case 0: /* not range */ 61 break; 62 case 1: /* range */ 59 63 return mrb_str_substr(mrb, str, beg, len); 64 case 2: /* out of range */ 65 mrb_raisef(mrb, E_RANGE_ERROR, "%S out of range", a1); 66 break; 60 67 } 61 68 return mrb_nil_value(); … … 128 135 } 129 136 137 static mrb_value mrb_fixnum_chr(mrb_state *mrb, mrb_value num); 138 130 139 /* 131 140 * call-seq: … … 147 156 { 148 157 mrb_value str; 149 mrb_get_args(mrb, "S", &str); 158 159 mrb_get_args(mrb, "o", &str); 160 if (mrb_fixnum_p(str)) 161 str = mrb_fixnum_chr(mrb, str); 162 else 163 str = mrb_string_type(mrb, str); 150 164 mrb_str_concat(mrb, self, str); 151 165 return self; … … 308 322 mrb_int len; 309 323 mrb_value arg; 310 char *p = RSTRING_PTR(self), *t; 311 char *e = p + RSTRING_LEN(self); 324 char *b = RSTRING_PTR(self); 325 char *p = b, *t; 326 char *e = b + RSTRING_LEN(self); 312 327 313 328 mrb_get_args(mrb, "&", &blk); 314 329 315 330 result = mrb_ary_new(mrb); 316 331 ai = mrb_gc_arena_save(mrb); 317 332 if (!mrb_nil_p(blk)) { 318 333 while (p < e) { … … 323 338 arg = mrb_str_new(mrb, t, len); 324 339 mrb_yield_argv(mrb, blk, 1, &arg); 340 mrb_gc_arena_restore(mrb, ai); 341 if (b != RSTRING_PTR(self)) { 342 ptrdiff_t diff = p - b; 343 b = RSTRING_PTR(self); 344 p = b + diff; 345 } 346 e = b + RSTRING_LEN(self); 325 347 } 326 348 return self; 327 349 } 328 350 while (p < e) { 329 ai = mrb_gc_arena_save(mrb);330 351 t = p; 331 352 while (p < e && *p != '\n') p++; … … 354 375 const char *prepend; 355 376 struct RString *s = mrb_str_ptr(self); 356 size_t l;377 mrb_int l; 357 378 358 379 if (RSTRING_LEN(self) == 0) … … 374 395 e = p + l - 1; 375 396 result = mrb_str_new_lit(mrb, ""); 376 } else { 397 } 398 else { 377 399 // find leading letter of the ascii/number 378 400 b = e; … … 392 414 mrb_str_cat_lit(mrb, result, "\x01"); 393 415 (*e) = 0; 394 } else 416 } 417 else 395 418 (*e)++; 396 419 break; … … 400 423 if (e == b) prepend = "1"; 401 424 *e = '0'; 402 } else if (*e == 'z') { 425 } 426 else if (*e == 'z') { 403 427 if (e == b) prepend = "a"; 404 428 *e = 'a'; 405 } else if (*e == 'Z') { 429 } 430 else if (*e == 'Z') { 406 431 if (e == b) prepend = "A"; 407 432 *e = 'A'; 408 } else { 433 } 434 else { 409 435 (*e)++; 410 436 break; … … 428 454 mrb_str_succ_bang(mrb, str); 429 455 return str; 430 }431 432 /*433 * call-seq:434 * str.prepend(other_str) -> str435 *436 * Prepend---Prepend the given string to <i>str</i>.437 *438 * a = "world"439 * a.prepend("hello ") #=> "hello world"440 * a #=> "hello world"441 */442 static mrb_value443 mrb_str_prepend(mrb_state *mrb, mrb_value self)444 {445 struct RString *s1 = mrb_str_ptr(self), *s2, *temp_s;446 mrb_int len;447 mrb_value other, temp_str;448 449 mrb_get_args(mrb, "S", &other);450 451 mrb_str_modify(mrb, s1);452 if (!mrb_string_p(other)) {453 other = mrb_str_to_str(mrb, other);454 }455 s2 = mrb_str_ptr(other);456 len = RSTR_LEN(s1) + RSTR_LEN(s2);457 temp_str = mrb_str_new(mrb, NULL, RSTR_LEN(s1));458 temp_s = mrb_str_ptr(temp_str);459 memcpy(RSTR_PTR(temp_s), RSTR_PTR(s1), RSTR_LEN(s1));460 if (RSTRING_CAPA(self) < len) {461 mrb_str_resize(mrb, self, len);462 }463 memcpy(RSTR_PTR(s1), RSTR_PTR(s2), RSTR_LEN(s2));464 memcpy(RSTR_PTR(s1) + RSTR_LEN(s2), RSTR_PTR(temp_s), RSTR_LEN(temp_s));465 RSTR_SET_LEN(s1, len);466 RSTR_PTR(s1)[len] = '\0';467 return self;468 456 } 469 457 … … 530 518 if (RSTRING_LEN(str) == 0) 531 519 mrb_raise(mrb, E_ARGUMENT_ERROR, "empty string"); 532 return mrb_fixnum_value( RSTRING_PTR(str)[0]);520 return mrb_fixnum_value((unsigned char)RSTRING_PTR(str)[0]); 533 521 } 534 522 #endif 523 524 static mrb_bool 525 all_digits_p(const char *s, mrb_int len) 526 { 527 while (len-- > 0) { 528 if (!ISDIGIT(*s)) return FALSE; 529 s++; 530 } 531 return TRUE; 532 } 533 534 /* 535 * call-seq: 536 * str.upto(other_str, exclusive=false) {|s| block } -> str 537 * str.upto(other_str, exclusive=false) -> an_enumerator 538 * 539 * Iterates through successive values, starting at <i>str</i> and 540 * ending at <i>other_str</i> inclusive, passing each value in turn to 541 * the block. The <code>String#succ</code> method is used to generate 542 * each value. If optional second argument exclusive is omitted or is false, 543 * the last value will be included; otherwise it will be excluded. 544 * 545 * If no block is given, an enumerator is returned instead. 546 * 547 * "a8".upto("b6") {|s| print s, ' ' } 548 * for s in "a8".."b6" 549 * print s, ' ' 550 * end 551 * 552 * <em>produces:</em> 553 * 554 * a8 a9 b0 b1 b2 b3 b4 b5 b6 555 * a8 a9 b0 b1 b2 b3 b4 b5 b6 556 * 557 * If <i>str</i> and <i>other_str</i> contains only ascii numeric characters, 558 * both are recognized as decimal numbers. In addition, the width of 559 * string (e.g. leading zeros) is handled appropriately. 560 * 561 * "9".upto("11").to_a #=> ["9", "10", "11"] 562 * "25".upto("5").to_a #=> [] 563 * "07".upto("11").to_a #=> ["07", "08", "09", "10", "11"] 564 */ 565 static mrb_value 566 mrb_str_upto(mrb_state *mrb, mrb_value beg) 567 { 568 mrb_value end; 569 mrb_value exclusive = mrb_false_value(); 570 mrb_value block = mrb_nil_value(); 571 mrb_value current, after_end; 572 mrb_int n; 573 mrb_bool excl; 574 575 mrb_get_args(mrb, "o|o&", &end, &exclusive, &block); 576 577 if (mrb_nil_p(block)) { 578 return mrb_funcall(mrb, beg, "to_enum", 3, mrb_symbol_value(mrb_intern_lit(mrb, "upto")), end, exclusive); 579 } 580 end = mrb_string_type(mrb, end); 581 excl = mrb_test(exclusive); 582 583 /* single character */ 584 if (RSTRING_LEN(beg) == 1 && RSTRING_LEN(end) == 1 && 585 ISASCII(RSTRING_PTR(beg)[0]) && ISASCII(RSTRING_PTR(end)[0])) { 586 char c = RSTRING_PTR(beg)[0]; 587 char e = RSTRING_PTR(end)[0]; 588 int ai = mrb_gc_arena_save(mrb); 589 590 if (c > e || (excl && c == e)) return beg; 591 for (;;) { 592 mrb_yield(mrb, block, mrb_str_new(mrb, &c, 1)); 593 mrb_gc_arena_restore(mrb, ai); 594 if (!excl && c == e) break; 595 c++; 596 if (excl && c == e) break; 597 } 598 return beg; 599 } 600 /* both edges are all digits */ 601 if (ISDIGIT(RSTRING_PTR(beg)[0]) && ISDIGIT(RSTRING_PTR(end)[0]) && 602 all_digits_p(RSTRING_PTR(beg), RSTRING_LEN(beg)) && 603 all_digits_p(RSTRING_PTR(end), RSTRING_LEN(end))) { 604 int ai = mrb_gc_arena_save(mrb); 605 mrb_int min_width = RSTRING_LEN(beg); 606 mrb_int max_width = RSTRING_LEN(end); 607 mrb_int bi = mrb_int(mrb, mrb_str_to_inum(mrb, beg, 10, FALSE)); 608 mrb_int ei = mrb_int(mrb, mrb_str_to_inum(mrb, end, 10, FALSE)); 609 mrb_value str = mrb_str_new(mrb, NULL, max_width); 610 char *buf = RSTRING_PTR(str); 611 612 while (bi <= ei) { 613 if (excl && bi == ei) break; 614 snprintf(buf, max_width+1, "%.*" MRB_PRId, (int)min_width, bi); 615 mrb_yield(mrb, block, mrb_str_new(mrb, buf, strlen(buf))); 616 mrb_gc_arena_restore(mrb, ai); 617 bi++; 618 } 619 620 return beg; 621 } 622 /* normal case */ 623 n = mrb_int(mrb, mrb_funcall(mrb, beg, "<=>", 1, end)); 624 if (n > 0 || (excl && n == 0)) return beg; 625 626 after_end = mrb_funcall(mrb, end, "succ", 0); 627 current = mrb_str_dup(mrb, beg); 628 while (!mrb_str_equal(mrb, current, after_end)) { 629 int ai = mrb_gc_arena_save(mrb); 630 mrb_value next = mrb_nil_value(); 631 if (excl || !mrb_str_equal(mrb, current, end)) 632 next = mrb_funcall(mrb, current, "succ", 0); 633 mrb_yield(mrb, block, current); 634 if (mrb_nil_p(next)) break; 635 current = mrb_str_to_str(mrb, next); 636 if (excl && mrb_str_equal(mrb, current, end)) break; 637 if (RSTRING_LEN(current) > RSTRING_LEN(end) || RSTRING_LEN(current) == 0) 638 break; 639 mrb_gc_arena_restore(mrb, ai); 640 } 641 642 return beg; 643 } 535 644 536 645 void … … 555 664 mrb_define_method(mrb, s, "succ", mrb_str_succ, MRB_ARGS_NONE()); 556 665 mrb_define_method(mrb, s, "succ!", mrb_str_succ_bang, MRB_ARGS_NONE()); 557 mrb_define_method(mrb, s, "prepend", mrb_str_prepend, MRB_ARGS_REQ(1));558 666 mrb_alias_method(mrb, s, mrb_intern_lit(mrb, "next"), mrb_intern_lit(mrb, "succ")); 559 667 mrb_alias_method(mrb, s, mrb_intern_lit(mrb, "next!"), mrb_intern_lit(mrb, "succ!")); 560 668 mrb_define_method(mrb, s, "ord", mrb_str_ord, MRB_ARGS_NONE()); 669 mrb_define_method(mrb, s, "upto", mrb_str_upto, MRB_ARGS_ANY()); 561 670 562 671 mrb_define_method(mrb, mrb->fixnum_class, "chr", mrb_fixnum_chr, MRB_ARGS_NONE());
Note:
See TracChangeset
for help on using the changeset viewer.