Affix
view release on metacpan or search on metacpan
lib/Affix/marshal.c view on Meta::CPAN
}
size_t n, step;
const infix_type * el_type;
if (cat == INFIX_TYPE_COMPLEX) {
n = 2;
el_type = res->meta.complex_info.base_type;
step = el_type->size;
}
else if (cat == INFIX_TYPE_ARRAY) {
n = res->meta.array_info.num_elements;
el_type = res->meta.array_info.element_type;
step = resolve_type(aTHX_ el_type)->size;
}
else {
n = res->meta.vector_info.num_elements;
el_type = res->meta.vector_info.element_type;
step = el_type->size;
}
if (!eager && n > LAZY_ARRAY_THRESHOLD) {
SV * lazy_placeholder = newSV(0);
bind_placeholder(aTHX_ lazy_placeholder, ptr, type, 0, 0, false, owner, arena, readonly, false);
return lazy_placeholder;
}
AV * av = newAV();
Affix_Pin_2_Point_Oh am = {.ptr = ptr, .type = type, .arena = arena, .readonly = readonly};
sv_magicext((SV *)av, owner, PERL_MAGIC_ext, &vtbl_array, (char *)&am, sizeof(Affix_Pin_2_Point_Oh));
for (size_t i = 0; i < n; i++) {
SV * el = newSV(0);
void * child_ptr = ptr ? ((char *)ptr + (i * step)) : nullptr;
bind_placeholder(aTHX_ el, child_ptr, el_type, 0, 0, true, (SV *)av, nullptr, readonly, false);
av_push(av, el);
}
return newRV_noinc((SV *)av);
}
return newSV(0);
}
/**
* @brief Recursively constructs a Perl tree (Hash/Array) mapping to a C aggregate.
* @param ptr Pointer to the raw C memory.
* @param type The aggregate (struct/union/array) type.
* @param owner The "root" SV that owns the C memory (lifeline).
* @return A new reference to the constructed Perl aggregate.
*/
SV * bind_aggregate(pTHX_ void * ptr, const infix_type * type, SV * owner, bool readonly) {
return _bind_aggregate_internal(aTHX_ ptr, type, owner, nullptr, false, readonly);
}
/**
* @brief Public Strategy: Used by cast() to handle anonymous type lifecycle.
*/
SV * bind_aggregate_anon(pTHX_ void * ptr, const infix_type * type, SV * owner, infix_arena_t * arena, bool readonly) {
return _bind_aggregate_internal(aTHX_ ptr, type, owner, arena, false, readonly);
}
/**
* @brief Registers multiple types into the global Infix Type Registry.
* @param defs The Infix type definition string.
*/
void define_types(pTHX_ const char * defs) {
dMY_CXT;
if (infix_register_types(MY_CXT.registry, defs) != INFIX_SUCCESS)
croak("Parse Error");
}
/**
* @brief Returns the layout size of a type by name.
* @param name Type name or AST signature.
* @return Size in bytes.
*/
IV sizeof_type(pTHX_ const char * name) {
dMY_CXT;
const infix_type * t = infix_registry_lookup_type(MY_CXT.registry, name);
if (!t) {
infix_arena_t * ta;
infix_type * tt;
if (infix_type_from_signature(&tt, &ta, name, MY_CXT.registry) == INFIX_SUCCESS) {
size_t s = tt->size;
infix_arena_destroy(ta);
return s;
}
}
return t ? t->size : 0;
}
/**
* @brief Returns the byte offset of a member in a struct/union.
* @param type_name The aggregate type name.
* @param member_name The member field name.
* @return Offset in bytes, or -1 if not found.
*/
IV offsetof_member(pTHX_ const char * type_name, const char * member_name) {
dMY_CXT;
const infix_type * t = resolve_type(aTHX_ infix_registry_lookup_type(MY_CXT.registry, type_name));
if (!t || (t->category != INFIX_TYPE_STRUCT && t->category != INFIX_TYPE_UNION))
return -1;
for (size_t i = 0; i < t->meta.aggregate_info.num_members; i++)
if (strEQ(t->meta.aggregate_info.members[i].name, member_name))
return (IV)t->meta.aggregate_info.members[i].offset;
return -1;
}
/**
* @brief Casts a raw pointer (or memory block) to a magic-bound Perl variable mapping its layout.
* @param in The input SV (integer address or Affix::Memory managed object).
* @param name The struct or primitive type name to cast the memory into.
* @return A magic-bound SV tracking the memory block natively.
*/
SV * cast(pTHX_ SV * in, const char * name) {
dMY_CXT;
void * addr = get_address_v2(aTHX_ in);
if (!addr)
return &PL_sv_undef;
SV * owner = (SvROK(in) && sv_derived_from(in, "Affix::Memory")) ? SvRV(in) : nullptr;
infix_type * new_type = nullptr;
infix_arena_t * local_arena = nullptr;
( run in 1.602 second using v1.01-cache-2.11-cpan-84de2e75c66 )