Skip to content

Instantly share code, notes, and snippets.

@k-tsj
Created December 8, 2013 06:55
Show Gist options
  • Save k-tsj/7854083 to your computer and use it in GitHub Desktop.
Save k-tsj/7854083 to your computer and use it in GitHub Desktop.
Extend rb_scan_args to get keyword arguments
diff --git a/array.c b/array.c
index 9a93d7f..b673c63 100644
--- a/array.c
+++ b/array.c
@@ -4429,7 +4429,7 @@ static VALUE sym_random;
static VALUE
rb_ary_shuffle_bang(int argc, VALUE *argv, VALUE ary)
{
- VALUE opts, randgen = rb_cRandom;
+ VALUE rnd, randgen = rb_cRandom;
long i, len;
static ID keyword_ids[1];
@@ -4437,14 +4437,10 @@ rb_ary_shuffle_bang(int argc, VALUE *argv, VALUE ary)
keyword_ids[0] = rb_intern("random");
}
- if (OPTHASH_GIVEN_P(opts)) {
- VALUE rnd;
- rb_get_kwargs(opts, keyword_ids, 0, 1, &rnd);
- if (rnd != Qundef) {
- randgen = rnd;
- }
+ rb_scan_args(argc, argv, "00:01", NULL, keyword_ids, &rnd);
+ if (rnd != Qundef) {
+ randgen = rnd;
}
- rb_check_arity(argc, 0, 0);
rb_ary_modify(ary);
i = len = RARRAY_LEN(ary);
RARRAY_PTR_USE(ary, ptr, {
diff --git a/class.c b/class.c
index 66495eb..c13f4b3 100644
--- a/class.c
+++ b/class.c
@@ -1727,8 +1727,9 @@ rb_scan_args(int argc, const VALUE *argv, const char *fmt, ...)
const char *p = fmt;
VALUE *var;
va_list vargs;
- int f_var = 0, f_hash = 0, f_block = 0;
+ int f_var = 0, f_hash = 0, f_get_kwargs = 0, f_block = 0;
int n_lead = 0, n_opt = 0, n_trail = 0, n_mand;
+ int n_keyword_required = 0, n_keyword_optional = 0;
int argi = 0;
VALUE hash = Qnil;
@@ -1757,6 +1758,18 @@ rb_scan_args(int argc, const VALUE *argv, const char *fmt, ...)
if (*p == ':') {
f_hash = 1;
p++;
+ if (ISDIGIT(*p)) {
+ f_get_kwargs = 1;
+ n_keyword_required = *p - '0';
+ p++;
+ if (ISDIGIT(*p)) {
+ n_keyword_optional = *p - '0';
+ p++;
+ }
+ else {
+ rb_fatal("bad scan arg format: %s", fmt);
+ }
+ }
}
if (*p == '&') {
f_block = 1;
@@ -1831,6 +1844,11 @@ rb_scan_args(int argc, const VALUE *argv, const char *fmt, ...)
/* capture an option hash - phase 2: assignment */
if (f_hash) {
var = va_arg(vargs, VALUE *);
+ if (f_get_kwargs) {
+ ID *ids = va_arg(vargs, ID *);
+ VALUE *values = va_arg(vargs, VALUE *);
+ rb_get_kwargs(NIL_P(hash) ? 0 : hash, ids, n_keyword_required, n_keyword_optional, values);
+ }
if (var) *var = hash;
}
/* capture iterator block */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment