Ancient

 view release on metacpan or  search on metacpan

xs/util/util.c  view on Meta::CPAN

    register_export(aTHX_ "pluck", xs_pluck, NULL);
    register_export(aTHX_ "omit", xs_omit, NULL);
    register_export(aTHX_ "uniq", xs_uniq, NULL);
    register_export(aTHX_ "partition", xs_partition, NULL);
    register_export(aTHX_ "defaults", xs_defaults, NULL);
    register_export(aTHX_ "count", xs_count, NULL);
    register_export(aTHX_ "replace_all", xs_replace_all, NULL);

    /* Type predicates */
    register_export(aTHX_ "is_ref", xs_is_ref, is_ref_call_checker);
    register_export(aTHX_ "is_array", xs_is_array, is_array_call_checker);
    register_export(aTHX_ "is_hash", xs_is_hash, is_hash_call_checker);
    register_export(aTHX_ "is_code", xs_is_code, is_code_call_checker);
    register_export(aTHX_ "is_defined", xs_is_defined, is_defined_call_checker);
    register_export(aTHX_ "is_string", xs_is_string, is_string_call_checker);

    /* String predicates */
    register_export(aTHX_ "is_empty", xs_is_empty, is_empty_call_checker);
    register_export(aTHX_ "starts_with", xs_starts_with, starts_with_call_checker);
    register_export(aTHX_ "ends_with", xs_ends_with, ends_with_call_checker);
    register_export(aTHX_ "trim", xs_trim, trim_call_checker);
    register_export(aTHX_ "ltrim", xs_ltrim, ltrim_call_checker);
    register_export(aTHX_ "rtrim", xs_rtrim, rtrim_call_checker);

    /* Boolean predicates */
    register_export(aTHX_ "is_true", xs_is_true, is_true_call_checker);
    register_export(aTHX_ "is_false", xs_is_false, is_false_call_checker);
    register_export(aTHX_ "bool", xs_bool, bool_call_checker);

    /* Extended type predicates */
    register_export(aTHX_ "is_num", xs_is_num, is_num_call_checker);
    register_export(aTHX_ "is_int", xs_is_int, is_int_call_checker);
    register_export(aTHX_ "is_blessed", xs_is_blessed, is_blessed_call_checker);
    register_export(aTHX_ "is_scalar_ref", xs_is_scalar_ref, is_scalar_ref_call_checker);
    register_export(aTHX_ "is_regex", xs_is_regex, is_regex_call_checker);
    register_export(aTHX_ "is_glob", xs_is_glob, is_glob_call_checker);

    /* Numeric predicates */
    register_export(aTHX_ "is_positive", xs_is_positive, is_positive_call_checker);
    register_export(aTHX_ "is_negative", xs_is_negative, is_negative_call_checker);
    register_export(aTHX_ "is_zero", xs_is_zero, is_zero_call_checker);
    register_export(aTHX_ "is_even", xs_is_even, is_even_call_checker);
    register_export(aTHX_ "is_odd", xs_is_odd, is_odd_call_checker);
    register_export(aTHX_ "is_between", xs_is_between, is_between_call_checker);

    /* Collection predicates */
    register_export(aTHX_ "is_empty_array", xs_is_empty_array, is_empty_array_call_checker);
    register_export(aTHX_ "is_empty_hash", xs_is_empty_hash, is_empty_hash_call_checker);
    register_export(aTHX_ "array_len", xs_array_len, array_len_call_checker);
    register_export(aTHX_ "hash_size", xs_hash_size, hash_size_call_checker);
    register_export(aTHX_ "array_first", xs_array_first, array_first_call_checker);
    register_export(aTHX_ "array_last", xs_array_last, array_last_call_checker);

    /* Conditional/numeric ops */
    register_export(aTHX_ "maybe", xs_maybe, maybe_call_checker);
    register_export(aTHX_ "sign", xs_sign, sign_call_checker);
    register_export(aTHX_ "min2", xs_min2, min2_call_checker);
    register_export(aTHX_ "max2", xs_max2, max2_call_checker);
}

static char* get_caller(pTHX) {
    return HvNAME((HV*)CopSTASH(PL_curcop));
}

/* Fast O(1) import using hash lookup */
static XS(xs_import) {
    dXSARGS;
    char *pkg = get_caller(aTHX);
    IV i;
    STRLEN name_len;
    char full[512];

    for (i = 1; i < items; i++) {
        char *name = SvPV(ST(i), name_len);
        SV **entry_sv = hv_fetch(g_export_hash, name, name_len, 0);

        if (!entry_sv || !*entry_sv) {
            croak("util: unknown export '%s'", name);
        }

        ExportEntry *entry = INT2PTR(ExportEntry*, SvIV(*entry_sv));
        snprintf(full, sizeof(full), "%s::%s", pkg, name);

        if (entry->xs_func) {
            /* XS function: create XS stub in caller's namespace.
             * Note: We intentionally do NOT install call checkers on exported
             * functions. Call checkers are compile-time optimizations that work
             * by transforming the op tree. They work on util::* functions because
             * those are installed at boot time before any user code compiles.
             * Users who want compile-time optimization should call util::func()
             * directly instead of importing. */
            CV *cv = newXS(full, entry->xs_func, __FILE__);
            PERL_UNUSED_VAR(cv);
        } else if (entry->perl_cv) {
            /* Perl coderef: create alias in caller's namespace */
            GV *gv = gv_fetchpv(full, GV_ADD, SVt_PVCV);
            if (gv) {
                /* Get the actual CV from the reference */
                CV *src_cv = (CV*)SvRV(entry->perl_cv);
                /* Assign the CV to the glob's CODE slot */
                SvREFCNT_inc((SV*)src_cv);
                GvCV_set(gv, src_cv);
            }
        }
    }

    XSRETURN_EMPTY;
}

/* ============================================
   Boot
   ============================================ */

XS_EXTERNAL(boot_util) {
    dXSBOOTARGSXSAPIVERCHK;
    PERL_UNUSED_VAR(items);

    /* Initialize built-in loop callbacks */
    init_builtin_callbacks(aTHX);

    /* Register custom ops */
    XopENTRY_set(&identity_xop, xop_name, "identity");
    XopENTRY_set(&identity_xop, xop_desc, "identity passthrough");
    Perl_custom_op_register(aTHX_ pp_identity, &identity_xop);

    XopENTRY_set(&always_xop, xop_name, "always");
    XopENTRY_set(&always_xop, xop_desc, "always return stored value");
    Perl_custom_op_register(aTHX_ pp_always, &always_xop);



( run in 2.248 seconds using v1.01-cache-2.11-cpan-97f6503c9c8 )