Moved runtime assignemnts
Separate assignemnts of dynamically given runtime values in `rb_scan_args_assign` from parsing statically given format in `rb_scan_args_parse`.
This commit is contained in:
parent
0fa43b0c1b
commit
48c851f868
104
class.c
104
class.c
@ -1952,8 +1952,7 @@ rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, V
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct rb_scan_args_t {
|
struct rb_scan_args_t {
|
||||||
int argc;
|
int kw_flag;
|
||||||
const VALUE *argv;
|
|
||||||
int f_var;
|
int f_var;
|
||||||
int f_hash;
|
int f_hash;
|
||||||
int f_block;
|
int f_block;
|
||||||
@ -1962,30 +1961,15 @@ struct rb_scan_args_t {
|
|||||||
int n_trail;
|
int n_trail;
|
||||||
int n_mand;
|
int n_mand;
|
||||||
int argi;
|
int argi;
|
||||||
VALUE hash;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
rb_scan_args_parse(int kw_flag, int argc, const VALUE *argv, const char *fmt, struct rb_scan_args_t *arg)
|
rb_scan_args_parse(int kw_flag, const char *fmt, struct rb_scan_args_t *arg)
|
||||||
{
|
{
|
||||||
const char *p = fmt;
|
const char *p = fmt;
|
||||||
int keyword_given = 0;
|
|
||||||
int last_hash_keyword = 0;
|
|
||||||
|
|
||||||
memset(arg, 0, sizeof(*arg));
|
memset(arg, 0, sizeof(*arg));
|
||||||
arg->hash = Qnil;
|
arg->kw_flag = kw_flag;
|
||||||
|
|
||||||
switch (kw_flag) {
|
|
||||||
case RB_SCAN_ARGS_PASS_CALLED_KEYWORDS:
|
|
||||||
keyword_given = rb_keyword_given_p();
|
|
||||||
break;
|
|
||||||
case RB_SCAN_ARGS_KEYWORDS:
|
|
||||||
keyword_given = 1;
|
|
||||||
break;
|
|
||||||
case RB_SCAN_ARGS_LAST_HASH_KEYWORDS:
|
|
||||||
last_hash_keyword = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ISDIGIT(*p)) {
|
if (ISDIGIT(*p)) {
|
||||||
arg->n_lead = *p - '0';
|
arg->n_lead = *p - '0';
|
||||||
@ -2015,42 +1999,49 @@ rb_scan_args_parse(int kw_flag, int argc, const VALUE *argv, const char *fmt, st
|
|||||||
rb_fatal("bad scan arg format: %s", fmt);
|
rb_fatal("bad scan arg format: %s", fmt);
|
||||||
}
|
}
|
||||||
arg->n_mand = arg->n_lead + arg->n_trail;
|
arg->n_mand = arg->n_lead + arg->n_trail;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
rb_scan_args_assign(const struct rb_scan_args_t *arg, int argc, const VALUE *const argv, va_list vargs)
|
||||||
|
{
|
||||||
|
int i, argi = 0;
|
||||||
|
VALUE *var, hash = Qnil;
|
||||||
|
|
||||||
if (arg->f_hash && argc > 0) {
|
if (arg->f_hash && argc > 0) {
|
||||||
VALUE last = argv[argc - 1];
|
VALUE last = argv[argc - 1];
|
||||||
|
int keyword_given = 0;
|
||||||
if (keyword_given || (last_hash_keyword && RB_TYPE_P(last, T_HASH))) {
|
switch (arg->kw_flag) {
|
||||||
arg->hash = rb_hash_dup(last);
|
case RB_SCAN_ARGS_PASS_CALLED_KEYWORDS:
|
||||||
|
keyword_given = rb_keyword_given_p();
|
||||||
|
break;
|
||||||
|
case RB_SCAN_ARGS_KEYWORDS:
|
||||||
|
keyword_given = 1;
|
||||||
|
break;
|
||||||
|
case RB_SCAN_ARGS_LAST_HASH_KEYWORDS:
|
||||||
|
keyword_given = RB_TYPE_P(last, T_HASH);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (keyword_given) {
|
||||||
|
hash = rb_hash_dup(last);
|
||||||
argc--;
|
argc--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
arg->argc = argc;
|
if (argc < arg->n_mand) {
|
||||||
arg->argv = argv;
|
goto argc_error;
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
rb_scan_args_assign(struct rb_scan_args_t *arg, va_list vargs)
|
|
||||||
{
|
|
||||||
int argi = 0;
|
|
||||||
int i;
|
|
||||||
VALUE *var;
|
|
||||||
|
|
||||||
if (arg->argc < arg->n_mand) {
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* capture leading mandatory arguments */
|
/* capture leading mandatory arguments */
|
||||||
for (i = arg->n_lead; i-- > 0; ) {
|
for (i = arg->n_lead; i-- > 0; ) {
|
||||||
var = va_arg(vargs, VALUE *);
|
var = va_arg(vargs, VALUE *);
|
||||||
if (var) *var = arg->argv[argi];
|
if (var) *var = argv[argi];
|
||||||
argi++;
|
argi++;
|
||||||
}
|
}
|
||||||
/* capture optional arguments */
|
/* capture optional arguments */
|
||||||
for (i = arg->n_opt; i-- > 0; ) {
|
for (i = arg->n_opt; i-- > 0; ) {
|
||||||
var = va_arg(vargs, VALUE *);
|
var = va_arg(vargs, VALUE *);
|
||||||
if (argi < arg->argc - arg->n_trail) {
|
if (argi < argc - arg->n_trail) {
|
||||||
if (var) *var = arg->argv[argi];
|
if (var) *var = argv[argi];
|
||||||
argi++;
|
argi++;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -2059,11 +2050,11 @@ rb_scan_args_assign(struct rb_scan_args_t *arg, va_list vargs)
|
|||||||
}
|
}
|
||||||
/* capture variable length arguments */
|
/* capture variable length arguments */
|
||||||
if (arg->f_var) {
|
if (arg->f_var) {
|
||||||
int n_var = arg->argc - argi - arg->n_trail;
|
int n_var = argc - argi - arg->n_trail;
|
||||||
|
|
||||||
var = va_arg(vargs, VALUE *);
|
var = va_arg(vargs, VALUE *);
|
||||||
if (0 < n_var) {
|
if (0 < n_var) {
|
||||||
if (var) *var = rb_ary_new4(n_var, &arg->argv[argi]);
|
if (var) *var = rb_ary_new4(n_var, &argv[argi]);
|
||||||
argi += n_var;
|
argi += n_var;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -2073,13 +2064,13 @@ rb_scan_args_assign(struct rb_scan_args_t *arg, va_list vargs)
|
|||||||
/* capture trailing mandatory arguments */
|
/* capture trailing mandatory arguments */
|
||||||
for (i = arg->n_trail; i-- > 0; ) {
|
for (i = arg->n_trail; i-- > 0; ) {
|
||||||
var = va_arg(vargs, VALUE *);
|
var = va_arg(vargs, VALUE *);
|
||||||
if (var) *var = arg->argv[argi];
|
if (var) *var = argv[argi];
|
||||||
argi++;
|
argi++;
|
||||||
}
|
}
|
||||||
/* capture an option hash - phase 2: assignment */
|
/* capture an option hash - phase 2: assignment */
|
||||||
if (arg->f_hash) {
|
if (arg->f_hash) {
|
||||||
var = va_arg(vargs, VALUE *);
|
var = va_arg(vargs, VALUE *);
|
||||||
if (var) *var = arg->hash;
|
if (var) *var = hash;
|
||||||
}
|
}
|
||||||
/* capture iterator block */
|
/* capture iterator block */
|
||||||
if (arg->f_block) {
|
if (arg->f_block) {
|
||||||
@ -2092,42 +2083,43 @@ rb_scan_args_assign(struct rb_scan_args_t *arg, va_list vargs)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argi < arg->argc) return 1;
|
if (argi < argc) {
|
||||||
|
argc_error:
|
||||||
|
return -(argc + 1);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return argc;
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef rb_scan_args
|
#undef rb_scan_args
|
||||||
int
|
int
|
||||||
rb_scan_args(int argc, const VALUE *argv, const char *fmt, ...)
|
rb_scan_args(int argc, const VALUE *argv, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
int error;
|
|
||||||
va_list vargs;
|
va_list vargs;
|
||||||
struct rb_scan_args_t arg;
|
struct rb_scan_args_t arg;
|
||||||
rb_scan_args_parse(RB_SCAN_ARGS_PASS_CALLED_KEYWORDS, argc, argv, fmt, &arg);
|
rb_scan_args_parse(RB_SCAN_ARGS_PASS_CALLED_KEYWORDS, fmt, &arg);
|
||||||
va_start(vargs,fmt);
|
va_start(vargs,fmt);
|
||||||
error = rb_scan_args_assign(&arg, vargs);
|
argc = rb_scan_args_assign(&arg, argc, argv, vargs);
|
||||||
va_end(vargs);
|
va_end(vargs);
|
||||||
if (error) {
|
if (argc < 0) {
|
||||||
rb_error_arity(arg.argc, arg.n_mand, arg.f_var ? UNLIMITED_ARGUMENTS : arg.n_mand + arg.n_opt);
|
rb_error_arity(-1-argc, arg.n_mand, arg.f_var ? UNLIMITED_ARGUMENTS : arg.n_mand + arg.n_opt);
|
||||||
}
|
}
|
||||||
return arg.argc;
|
return argc;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
rb_scan_args_kw(int kw_flag, int argc, const VALUE *argv, const char *fmt, ...)
|
rb_scan_args_kw(int kw_flag, int argc, const VALUE *argv, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
int error;
|
|
||||||
va_list vargs;
|
va_list vargs;
|
||||||
struct rb_scan_args_t arg;
|
struct rb_scan_args_t arg;
|
||||||
rb_scan_args_parse(kw_flag, argc, argv, fmt, &arg);
|
rb_scan_args_parse(kw_flag, fmt, &arg);
|
||||||
va_start(vargs,fmt);
|
va_start(vargs,fmt);
|
||||||
error = rb_scan_args_assign(&arg, vargs);
|
argc = rb_scan_args_assign(&arg, argc, argv, vargs);
|
||||||
va_end(vargs);
|
va_end(vargs);
|
||||||
if (error) {
|
if (argc < 0) {
|
||||||
rb_error_arity(arg.argc, arg.n_mand, arg.f_var ? UNLIMITED_ARGUMENTS : arg.n_mand + arg.n_opt);
|
rb_error_arity(-1-argc, arg.n_mand, arg.f_var ? UNLIMITED_ARGUMENTS : arg.n_mand + arg.n_opt);
|
||||||
}
|
}
|
||||||
return arg.argc;
|
return argc;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
Loading…
x
Reference in New Issue
Block a user