diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2011-10-20 02:42:26 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2011-10-20 02:42:26 +0000 |
commit | 72cbec3f6d5335d0119c859df53c459e16bc9df9 (patch) | |
tree | ab4058b23681a040b4cadebe236cfdf10c98da00 /ext/-test-/string | |
parent | 2e32ad816398bba5557e4e5bbd7fa50b5d96aced (diff) |
* util.c (mmprepare): fix for fragmental size.
* util.c (mmswap_, mmrot3_): portability improvement.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@33489 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext/-test-/string')
-rw-r--r-- | ext/-test-/string/qsort.c | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/ext/-test-/string/qsort.c b/ext/-test-/string/qsort.c new file mode 100644 index 0000000000..0b34936d38 --- /dev/null +++ b/ext/-test-/string/qsort.c @@ -0,0 +1,61 @@ +#include "ruby.h" +#include "ruby/util.h" +#include "ruby/encoding.h" + +struct sort_data { + rb_encoding *enc; + long elsize; +}; + +static int +cmp_1(const void *ap, const void *bp, void *dummy) +{ + struct sort_data *d = dummy; + VALUE a = rb_enc_str_new(ap, d->elsize, d->enc); + VALUE b = rb_enc_str_new(bp, d->elsize, d->enc); + VALUE retval = rb_yield_values(2, a, b); + return rb_cmpint(retval, a, b); +} + +static int +cmp_2(const void *ap, const void *bp, void *dummy) +{ + int a = *(const unsigned char *)ap; + int b = *(const unsigned char *)bp; + return a - b; +} + +static VALUE +bug_str_qsort_bang(int argc, VALUE *argv, VALUE str) +{ + VALUE beg, len, size; + long l, b = 0, n, s = 1; + struct sort_data d; + + rb_scan_args(argc, argv, "03", &beg, &len, &size); + l = RSTRING_LEN(str); + if (!NIL_P(beg) && (b = NUM2INT(beg)) < 0 && (b += l) < 0) { + rb_raise(rb_eArgError, "out of bounds"); + } + if (!NIL_P(size) && (s = NUM2INT(size)) < 0) { + rb_raise(rb_eArgError, "negative size"); + } + if (NIL_P(len) || + (((n = NUM2INT(len)) < 0) ? + (rb_raise(rb_eArgError, "negative length"), 0) : + (b + n * s > l))) { + n = (l - b) / s; + } + rb_str_modify(str); + d.enc = rb_enc_get(str); + d.elsize = s; + ruby_qsort(RSTRING_PTR(str) + b, n, s, + rb_block_given_p() ? cmp_1 : cmp_2, &d); + return str; +} + +void +Init_qsort(VALUE klass) +{ + rb_define_method(klass, "qsort!", bug_str_qsort_bang, -1); +} |