なかだです。

[ruby-talk:69145](のサブジェクト)を見て、なんとなくString#to_i
とInteger#to_sの基数に2から36まで使えるようにしてみました。使い
途があるかないのかよく分かりませんが。


Index: bignum.c =================================================================== RCS file: /pub/cvs/ruby/src/ruby/bignum.c,v retrieving revision 1.89 diff -u -2 -p -r1.89 bignum.c --- bignum.c 9 Apr 2003 06:49:51 -0000 1.89 +++ bignum.c 11 Apr 2003 09:52:23 -0000 @@ -376,15 +376,20 @@ rb_cstr_to_inum(str, base, badcheck) } break; + case 3: + len = 2; + break; case 8: - len = 3; if (str[0] == '0' && (str[1] == 'o'||str[1] == 'O')) { str += 2; } + case 4: case 5: case 6: case 7: + len = 3; break; case 10: - len = 4; if (str[0] == '0' && (str[1] == 'd'||str[1] == 'D')) { str += 2; } + case 11: case 12: case 13: case 14: case 15: + len = 4; break; case 16: @@ -394,4 +399,15 @@ rb_cstr_to_inum(str, base, badcheck) } break; + default: + if (base < 2 || 36 < base) { + rb_raise(rb_eArgError, "illegal radix %d", base); + } + if (base <= 32) { + len = 5; + } + else { + len = 6; + } + break; } if (*str == '0') { /* squeeze preceeding 0s */ @@ -408,8 +424,5 @@ rb_cstr_to_inum(str, base, badcheck) if (end == str) goto bad; /* no number */ while (*end && ISSPACE(*end)) end++; - if (*end) { /* trailing garbage */ - bad: - rb_invalid_str(s, "Integer"); - } + if (*end) goto bad; /* trailing garbage */ } @@ -435,30 +448,5 @@ rb_cstr_to_inum(str, base, badcheck) for (i=len;i--;) zds[i]=0; while (c = *str++) { - switch (c) { - case '8': case '9': - if (base == 8) { - c = base; - break; - } - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': - c = c - '0'; - nondigit = 0; - break; - case 'a': case 'b': case 'c': - case 'd': case 'e': case 'f': - c -= 'a' - 'A'; - case 'A': case 'B': case 'C': - case 'D': case 'E': case 'F': - if (base != 16) { - nondigit = c; - c = base; - } - else { - c = c - 'A' + 10; - nondigit = 0; - } - break; - case '_': + if (c == '_') { if (badcheck) { if (nondigit) goto bad; @@ -466,9 +454,19 @@ rb_cstr_to_inum(str, base, badcheck) } continue; - default: - c = base; + } + else if (isdigit(c)) { + c -= '0'; + } + else if (islower(c)) { + c -= 'a' - 10; + } + else if (isupper(c)) { + c -= 'A' - 10; + } + else { break; } if (c >= base) break; + nondigit = 0; i = 0; num = c; @@ -490,5 +488,8 @@ rb_cstr_to_inum(str, base, badcheck) if (s+1 < str && str[-1] == '_') goto bad; while (*str && ISSPACE(*str)) str++; - if (*str) goto bad; + if (*str) { + bad: + rb_invalid_str(s, "Integer"); + } } @@ -599,5 +600,5 @@ rb_str2inum(str, base) } -static char hexmap[] = "0123456789abcdef"; +static const char digitmap[] = "0123456789abcdefghijklmnopqrstuvwxyz"; VALUE rb_big2str(x, base) @@ -618,23 +619,34 @@ rb_big2str(x, base) return rb_str_new2("0"); } - if (base == 10) { - j = (SIZEOF_BDIGITS/sizeof(char)*CHAR_BIT*i*241L)/800+2; - hbase = 10000; - } - else if (base == 16) { - j = (SIZEOF_BDIGITS/sizeof(char)*CHAR_BIT*i)/4+2; - hbase = 0x10000; - } - else if (base == 8) { - j = (SIZEOF_BDIGITS/sizeof(char)*CHAR_BIT*i)+2; - hbase = 010000; - } - else if (base == 2) { - j = (SIZEOF_BDIGITS*CHAR_BIT*i)+2; - hbase = 020; - } - else { + j = SIZEOF_BDIGITS*CHAR_BIT*i; + switch (base) { + case 2: break; + case 3: + j = j * 647L / 1024; + break; + case 4: case 5: case 6: case 7: + j /= 2; + break; + case 8: case 9: + j /= 3; + break; + case 10: case 11: case 12: case 13: case 14: case 15: + j = j * 241L / 800; + break; + case 16: case 17: case 18: case 19: case 20: case 21: + case 22: case 23: case 24: case 25: case 26: case 27: + case 28: case 29: case 30: case 31: + j /= 4; + break; + case 32: case 33: case 34: case 35: case 36: + j /= 5; + break; + default: rb_raise(rb_eArgError, "illegal radix %d", base); + break; } + j += 2; + hbase = base * base; + hbase *= hbase; t = rb_big_clone(x); @@ -657,5 +669,5 @@ rb_big2str(x, base) while (k--) { c = (char)(num % base); - s[--j] = hexmap[(int)c]; + s[--j] = digitmap[(int)c]; num /= base; if (i == 0 && num == 0) break; Index: numeric.c =================================================================== RCS file: /pub/cvs/ruby/src/ruby/numeric.c,v retrieving revision 1.76 diff -u -2 -p -r1.76 numeric.c --- numeric.c 11 Apr 2003 06:37:48 -0000 1.76 +++ numeric.c 11 Apr 2003 08:33:12 -0000 @@ -1174,4 +1174,5 @@ fix_uminus(num) } +static const char digitmap[] = "0123456789abcdefghijklmnopqrstuvwxyz"; VALUE rb_fix2str(x, base) @@ -1179,19 +1180,27 @@ rb_fix2str(x, base) int base; { - char fmt[4], buf[22], *b = buf; + char buf[SIZEOF_LONG/2 + 2], *b = buf + sizeof b; long val = FIX2LONG(x); + int neg = 0; - fmt[0] = '%'; fmt[1] = 'l'; fmt[3] = '\0'; - if (base == 10) fmt[2] = 'd'; - else if (base == 16) fmt[2] = 'x'; - else if (base == 8) fmt[2] = 'o'; - else rb_raise(rb_eArgError, "illegal radix %d", base); + if (base < 2 || 36 < base) { + rb_raise(rb_eArgError, "illegal radix %d", base); + } + if (val == 0) { + return rb_str_new2("0"); + } if (val < 0) { val = -val; - *b++ = '-'; + neg = 1; + } + *--b = '\0'; + do { + *--b = digitmap[(int)(val % base)]; + } while (val /= base); + if (neg) { + *--b = '-'; } - sprintf(b, fmt, val); - return rb_str_new2(buf); + return rb_str_new2(b); } Index: string.c =================================================================== RCS file: /pub/cvs/ruby/src/ruby/string.c,v retrieving revision 1.149 diff -u -2 -p -r1.149 string.c --- string.c 26 Mar 2003 18:26:45 -0000 1.149 +++ string.c 11 Apr 2003 08:53:39 -0000 @@ -1837,10 +1837,4 @@ rb_str_to_i(argc, argv, str) else base = NUM2INT(b); - switch (base) { - case 0: case 2: case 8: case 10: case 16: - break; - default: - rb_raise(rb_eArgError, "illegal radix %d", base); - } return rb_str_to_inum(str, base, Qfalse); }
-- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦