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 <noreply@anthropic.com>
This commit is contained in:
dearblue
2026-05-08 10:41:30 +09:00
committed by Yukihiro "Matz" Matsumoto
parent 91b60802db
commit df74d57857
+13 -1
View File
@@ -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);