2011-10-19 22:42:26 -04:00
|
|
|
#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
|
2017-12-03 03:02:56 -05:00
|
|
|
Init_string_qsort(VALUE klass)
|
2011-10-19 22:42:26 -04:00
|
|
|
{
|
|
|
|
rb_define_method(klass, "qsort!", bug_str_qsort_bang, -1);
|
|
|
|
}
|