Affix

 view release on metacpan or  search on metacpan

lib/Affix.c  view on Meta::CPAN

    }
    XSRETURN_UNDEF;
}

XS_INTERNAL(Affix_pin_size) {
    dXSARGS;
    if (items != 1)
        croak_xs_usage(cv, "pin");
    Affix_Pin * pin = _get_pin_from_sv(aTHX_ ST(0));
    if (pin) {
        ST(0) = sv_2mortal(newSVuv(pin->size));
        XSRETURN(1);
    }
    XSRETURN_UNDEF;
}

XS_INTERNAL(Affix_pin_get_at) {
    dXSARGS;
    if (items != 2)
        croak_xs_usage(cv, "pin, index");
    Affix_Pin * pin = _get_pin_from_sv(aTHX_ ST(0));
    IV index = SvIV(ST(1));
    if (!pin || !pin->type)
        croak("Not a valid pinned pointer");
    const infix_type * type = pin->type;
    const infix_type * elem_type = type;
    if (type->category == INFIX_TYPE_ARRAY)
        elem_type = type->meta.array_info.element_type;
    else if (type->category == INFIX_TYPE_POINTER && type->meta.pointer_info.pointee_type->category == INFIX_TYPE_VOID)
        elem_type = type->meta.pointer_info.pointee_type;
    else
        croak("Cannot index into non-aggregate type");

    size_t elem_size = infix_type_get_size(elem_type);
    if (elem_size == 0 && elem_type->category == INFIX_TYPE_VOID) {
        elem_size = 1;  // Byte-indexed for void*
        elem_type = infix_type_create_primitive(INFIX_PRIMITIVE_UINT8);
    }
    if (elem_size == 0)
        croak("Cannot index into zero-sized type");
    void * target = (char *)pin->pointer + (index * elem_size);

    if (elem_type->category == INFIX_TYPE_STRUCT || elem_type->category == INFIX_TYPE_UNION) {
        HV * hv = newHV();
        SV * rv = newRV_noinc(MUTABLE_SV(hv));
        sv_bless(rv, gv_stashpv("Affix::Live", GV_ADD));
        // We might need to pass the owner here too, but let's start with pins
        _populate_hv_from_c_struct(aTHX_ nullptr, hv, elem_type, target, true, pin->owner_sv ? pin->owner_sv : ST(0));
        ST(0) = sv_2mortal(rv);
    }
    else if (elem_type->category == INFIX_TYPE_ARRAY) {
        // Return a new Affix::Pointer for this sub-array (Live view)
        Affix_Pin * new_pin;
        Newxz(new_pin, 1, Affix_Pin);
        new_pin->pointer = target;
        new_pin->managed = false;

        new_pin->owner_sv = pin->owner_sv ? pin->owner_sv : ST(0);
        SvREFCNT_inc(new_pin->owner_sv);

        // We need to keep the type info alive. For now, copy it.
        new_pin->type_arena = infix_arena_create(256);
        new_pin->type = _copy_type_graph_to_arena(new_pin->type_arena, elem_type);

        ST(0) = sv_2mortal(_new_pointer_obj(aTHX_ new_pin));
    }
    else {
        SV * res = sv_newmortal();
        ptr2sv(aTHX_ nullptr, target, res, elem_type);
        ST(0) = res;
    }
    XSRETURN(1);
}

XS_INTERNAL(Affix_pin_set_at) {
    dXSARGS;
    if (items != 3)
        croak_xs_usage(cv, "pin, index, value");
    Affix_Pin * pin = _get_pin_from_sv(aTHX_ ST(0));
    IV index = SvIV(ST(1));
    SV * val_sv = ST(2);
    if (!pin || !pin->type)
        croak("Not a valid pinned pointer");
    const infix_type * type = pin->type;
    const infix_type * elem_type = type;
    if (type->category == INFIX_TYPE_ARRAY)
        elem_type = type->meta.array_info.element_type;
    else if (type->category == INFIX_TYPE_POINTER && type->meta.pointer_info.pointee_type->category == INFIX_TYPE_VOID)
        elem_type = type->meta.pointer_info.pointee_type;
    else
        croak("Cannot index into non-aggregate type");

    size_t elem_size = infix_type_get_size(elem_type);
    if (elem_size == 0 && elem_type->category == INFIX_TYPE_VOID) {
        elem_size = 1;
        elem_type = infix_type_create_primitive(INFIX_PRIMITIVE_UINT8);
    }
    if (elem_size == 0)
        croak("Cannot index into zero-sized type");
    void * target = (char *)pin->pointer + (index * elem_size);
    sv2ptr(aTHX_ nullptr, val_sv, target, elem_type);
    XSRETURN_EMPTY;
}

// Helper to register core internal types
static void _register_core_types(infix_registry_t * registry) {
    // Register SV as a named type (dummy struct ensures it keeps the name in the registry).
    // This allows signature parsing of "@SV" or "SV" (via hack) to map to a named opaque type.
    // Direct usage of this type is blocked in get_opcode_for_type; it must be wrapped in Pointer[].
    if (infix_register_types(registry, "@SV = { __sv_opaque: uint8 };") != INFIX_SUCCESS)
        croak("Failed to register internal type alias '@SV'");

    // We register File and PerlIO as opaque structs.
    // This semantically matches C's FILE struct which (for now) will remain opaque to the user.
    // We require "Pointer[File]" to mean "FILE*"
    if (infix_register_types(registry, "@File = { _opaque: [0:uchar] };") != INFIX_SUCCESS)
        croak("Failed to register internal type alias '@File'");
    if (infix_register_types(registry, "@PerlIO = { _opaque: [0:uchar] };") != INFIX_SUCCESS)
        croak("Failed to register internal type alias '@PerlIO'");

    // Other special types are opaque structs too. ...but they don't always mean anything in particular.



( run in 0.541 second using v1.01-cache-2.11-cpan-df04353d9ac )