Affix
view release on metacpan or search on metacpan
lib/Affix/marshal.c view on Meta::CPAN
IV RETVAL;
dXSTARG;
RETVAL = get_mock_cxx_dtor();
TARGi((IV)RETVAL, 1);
ST(0) = TARG;
}
XSRETURN(1);
}
XS_INTERNAL(XS_main_mock_cxx_delete) {
dVAR;
dXSARGS;
if (items != 1)
croak_xs_usage(cv, "ptr");
mock_cxx_delete(INT2PTR(void *, SvIV(ST(0))));
XSRETURN_EMPTY;
}
XS_INTERNAL(XS_main_get_mock_cxx_dtor_calls) {
dVAR;
dXSARGS;
if (items != 0)
croak_xs_usage(cv, "");
{
int RETVAL;
dXSTARG;
RETVAL = get_mock_cxx_dtor_calls();
TARGi((IV)RETVAL, 1);
ST(0) = TARG;
}
XSRETURN(1);
}
/**
* @brief Helper to verify if a VTable belongs to the Affix system (v1 or v2).
*/
int is_v2_vtable(MGVTBL * v) {
if (!v)
return 0;
return (v == &vtbl_sint8 || v == &vtbl_uint8 || v == &vtbl_sint16 || v == &vtbl_uint16 || v == &vtbl_sint32 ||
v == &vtbl_uint32 || v == &vtbl_sint64 || v == &vtbl_uint64 || v == &vtbl_sint128 || v == &vtbl_uint128 ||
v == &vtbl_float || v == &vtbl_double || v == &vtbl_float16 || v == &vtbl_bool || v == &vtbl_void ||
v == &vtbl_bitfield || v == &vtbl_pointer || v == &vtbl_array || v == &string_vtable ||
v == &wstring_vtable || v == &vtbl_lazy_aggregate || v == &vtbl_enum || v == &vtbl_buffer);
}
/**
* @brief Internal helper to safely extract a pointer address from a Perl scalar.
* @details This function handles Affix::Memory objects, v2.0 magical Pins, and
* raw integers. It includes logic to handle Pointer[Void] correctly by
* suppressing the dereference that is normally required for typed pointers.
*
* @param sv The Perl Scalar to inspect.
* @param ignore_mg A specific magic pointer to skip (prevents self-extraction during assignment).
* @return The raw C pointer address, or NULL if extraction fails.
*/
void * _extract_pointer_value(pTHX_ SV * sv, MAGIC * ignore_mg) {
if (!sv)
return nullptr;
// Use a secondary pointer for unwrapping to preserve the original SV (the potential object)
SV * target = sv;
if (SvROK(sv))
target = SvRV(sv);
/* Handle Magic Pins (even inside blessed objects) */
if (SvMAGICAL(target)) {
MAGIC * mg = mg_find(target, PERL_MAGIC_ext);
while (mg) {
if (is_v2_vtable(mg->mg_virtual) && mg != ignore_mg) {
Affix_Pin_2_Point_Oh * im = (Affix_Pin_2_Point_Oh *)mg->mg_ptr;
if (mg->mg_virtual == &vtbl_pointer)
return im->absolute ? im->ptr : (im->ptr ? *(void **)im->ptr : nullptr);
return im->ptr;
}
mg = mg->mg_moremagic;
}
}
/* Handle Affix::Memory Handles */
if (sv_isobject(sv) && sv_derived_from(sv, "Affix::Memory")) {
SV * rv = SvRV(sv);
if (SvTYPE(rv) == SVt_PVAV) {
SV ** p = av_fetch((AV *)rv, 0, 0);
return (p && *p) ? INT2PTR(void *, SvUV(*p)) : nullptr;
}
return INT2PTR(void *, SvUV(rv));
}
/* Fallback: Raw Integers */
if (SvIOK(sv))
return INT2PTR(void *, SvUV(sv));
return nullptr;
}
/**
* @brief The internal C function to extract a pointer from the 2.0 memory system.
* @param sv The SV to inspect (Handle or Magical Variable).
* @return The raw C pointer, or nullptr if not found.
*/
void * get_address_v2(pTHX_ SV * sv) { return _extract_pointer_value(aTHX_ sv, nullptr); }
/**
* @brief Determines the underlying type for a pointer pin.
* @details Prevents unwrapping char* (which should remain a string) but unwraps others
* so that $$ptr reads the correct data type.
*/
const infix_type * _unwrap_pin_type(const infix_type * type) {
if (type->category == INFIX_TYPE_POINTER) {
const infix_type * pointee = type->meta.pointer_info.pointee_type;
/* Do not unwrap char*; it's handled as a terminal String */
if (pointee->category == INFIX_TYPE_PRIMITIVE && (pointee->meta.primitive_id <= INFIX_PRIMITIVE_UINT8))
return type;
/* Do not unwrap Void; we want Pointer[Void] pins for raw addresses */
if (pointee->category == INFIX_TYPE_VOID)
return type;
return pointee;
}
return type;
}
( run in 0.592 second using v1.01-cache-2.11-cpan-d01c6094234 )