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 )