From df74d57857fb60cdf9970c32c237f71b4fd80874 Mon Sep 17 00:00:00 2001 From: dearblue Date: Fri, 8 May 2026 10:41:30 +0900 Subject: [PATCH] array.h: introduce ARY_GETMEM/RARRAY_GETMEM and type ARY_EMBED_PTR Adds two API helpers that mirror CRuby's RSTRING_GETMEM idiom: - ARY_GETMEM(a, ptr, len): inside-mruby helper that takes a struct RArray* and assigns ptr/len from the embed or heap form. - RARRAY_GETMEM(a, ptr, len): public wrapper on an mrb_value. Both expand to a single ARY_EMBED_P check, with a uniqued local so the array argument is evaluated only once (callers can safely pass expressions with side effects). Also type the ARY_NO_EMBED stub of ARY_EMBED_PTR as ((mrb_value*)NULL) instead of integer 0, so it composes cleanly in pointer expressions like the new ARY_GETMEM. The build-error issue this originated from (compilation with MRB_ARY_NO_EMBED) was already fixed differently in master via #ifndef guards (commit 78658d67e). These additions stand on their own as new API for downstream gems. Closes #6712, picked from PR by dearblue. Co-authored-by: Claude --- include/mruby/array.h | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/include/mruby/array.h b/include/mruby/array.h index 47f643243..6e63db557 100644 --- a/include/mruby/array.h +++ b/include/mruby/array.h @@ -67,7 +67,7 @@ struct RArray { #define ARY_UNSET_EMBED_FLAG(a) (void)0 #define ARY_EMBED_LEN(a) 0 #define ARY_SET_EMBED_LEN(a,len) (void)0 -#define ARY_EMBED_PTR(a) 0 +#define ARY_EMBED_PTR(a) ((mrb_value*)NULL) #else #define MRB_ARY_EMBED_MASK 7 #define ARY_EMBED_P(a) ((a)->flags & MRB_ARY_EMBED_MASK) @@ -81,6 +81,7 @@ struct RArray { #define ARY_PTR(a) (ARY_EMBED_P(a)?ARY_EMBED_PTR(a):(a)->as.heap.ptr) #define RARRAY_LEN(a) ARY_LEN(RARRAY(a)) #define RARRAY_PTR(a) ARY_PTR(RARRAY(a)) +#define RARRAY_GETMEM(a, ptr, len) ARY_GETMEM(RARRAY(a), ptr, len) #define ARY_SET_LEN(a,n) do {\ if (ARY_EMBED_P(a)) {\ mrb_assert((n) <= MRB_ARY_EMBED_LEN_MAX); \ @@ -94,6 +95,17 @@ struct RArray { #define ARY_SHARED_P(a) ((a)->flags & MRB_ARY_SHARED) #define ARY_SET_SHARED_FLAG(a) ((a)->flags |= MRB_ARY_SHARED) #define ARY_UNSET_SHARED_FLAG(a) ((a)->flags &= ~MRB_ARY_SHARED) +#define ARY_GETMEM(a, ptr, len) do { \ + struct RArray *MRB_UNIQNAME(_a_) = (a); \ + if (ARY_EMBED_P(MRB_UNIQNAME(_a_))) { \ + (len) = ARY_EMBED_LEN(MRB_UNIQNAME(_a_)); \ + (ptr) = ARY_EMBED_PTR(MRB_UNIQNAME(_a_)); \ + } \ + else { \ + (len) = MRB_UNIQNAME(_a_)->as.heap.len; \ + (ptr) = MRB_UNIQNAME(_a_)->as.heap.ptr; \ + } \ +} while (0) MRB_API void mrb_ary_modify(mrb_state*, struct RArray*); MRB_API mrb_value mrb_ary_dup(mrb_state*, mrb_value ary);