Data-HashMap

 view release on metacpan or  search on metacpan

HashMap.xs  view on Meta::CPAN

    const char *func = (const char *)hookdata;
    OP *map_op = args[0]->op;
    OP *key_op = args[1]->op;
    OP *val_op = args[2]->op;
    OP *cvref = newCVREF(0, newGVOP(OP_GV, 0, gv_fetchpv(func, GV_ADD, SVt_PVCV)));
    OP *arglist = op_append_elem(OP_LIST, map_op, key_op);
    arglist = op_append_elem(OP_LIST, arglist, val_op);
    arglist = op_append_elem(OP_LIST, arglist, cvref);
    *out = op_convert_list(OP_ENTERSUB, OPf_STACKED, arglist);
    return KEYWORD_PLUGIN_EXPR;
}


static int build_kw_4arg(pTHX_ OP **out, XSParseKeywordPiece *args[], size_t nargs, void *hookdata) {
    (void)nargs;
    const char *func = (const char *)hookdata;
    OP *map_op = args[0]->op;
    OP *key_op = args[1]->op;
    OP *val_op = args[2]->op;
    OP *ttl_op = args[3]->op;
    OP *cvref = newCVREF(0, newGVOP(OP_GV, 0, gv_fetchpv(func, GV_ADD, SVt_PVCV)));
    OP *arglist = op_append_elem(OP_LIST, map_op, key_op);
    arglist = op_append_elem(OP_LIST, arglist, val_op);
    arglist = op_append_elem(OP_LIST, arglist, ttl_op);
    arglist = op_append_elem(OP_LIST, arglist, cvref);
    *out = op_convert_list(OP_ENTERSUB, OPf_STACKED, arglist);
    return KEYWORD_PLUGIN_EXPR;
}

/* list-returning variant for keys/values/items */
static int build_kw_1arg_list(pTHX_ OP **out, XSParseKeywordPiece *args[], size_t nargs, void *hookdata) {
    (void)nargs;
    const char *func = (const char *)hookdata;
    OP *map_op = args[0]->op;
    OP *cvref = newCVREF(0, newGVOP(OP_GV, 0, gv_fetchpv(func, GV_ADD, SVt_PVCV)));
    OP *arglist = op_append_elem(OP_LIST, map_op, cvref);
    *out = op_convert_list(OP_ENTERSUB, OPf_STACKED | OPf_WANT_LIST, arglist);
    return KEYWORD_PLUGIN_EXPR;
}

/* ---- Keyword pieces ---- */

static const struct XSParseKeywordPieceType pieces_1expr[] = {
    XPK_TERMEXPR, {0}
};

static const struct XSParseKeywordPieceType pieces_2expr[] = {
    XPK_TERMEXPR, XPK_COMMA, XPK_TERMEXPR, {0}
};

static const struct XSParseKeywordPieceType pieces_3expr[] = {
    XPK_TERMEXPR, XPK_COMMA, XPK_TERMEXPR, XPK_COMMA, XPK_TERMEXPR, {0}
};
static const struct XSParseKeywordPieceType pieces_4expr[] = {
    XPK_TERMEXPR, XPK_COMMA, XPK_TERMEXPR, XPK_COMMA, XPK_TERMEXPR, XPK_COMMA, XPK_TERMEXPR, {0}
};


/* ---- Keyword hook definitions ----
 *
 * Macro to define a keyword hook struct.
 * variant = i16, i16a, i16s, i32, i32a, i32s, ia, ii, is, sa, si16, si32, si, ss
 * kw = keyword name (e.g., put, get)
 * nargs = 1, 2, or 3
 * builder = build function (build_kw_1arg, build_kw_2arg, etc.)
 */
#define DEFINE_KW_HOOK(variant, PKG, kw, nargs, builder) \
    static const struct XSParseKeywordHooks hooks_hm_##variant##_##kw = { \
        .flags = XPK_FLAG_EXPR, \
        .permit_hintkey = "Data::HashMap::" PKG "/hm_" #variant "_" #kw, \
        .pieces = pieces_##nargs##expr, \
        .build = builder, \
    };

/* I16 keywords */
DEFINE_KW_HOOK(i16, "I16", put,      3, build_kw_3arg)
DEFINE_KW_HOOK(i16, "I16", get,      2, build_kw_2arg)
DEFINE_KW_HOOK(i16, "I16", remove,   2, build_kw_2arg)
DEFINE_KW_HOOK(i16, "I16", take,    2, build_kw_2arg)
DEFINE_KW_HOOK(i16, "I16", drain,   2, build_kw_2arg)
DEFINE_KW_HOOK(i16, "I16", pop,     1, build_kw_1arg)
DEFINE_KW_HOOK(i16, "I16", shift,   1, build_kw_1arg)
DEFINE_KW_HOOK(i16, "I16", reserve, 2, build_kw_2arg)
DEFINE_KW_HOOK(i16, "I16", purge,   1, build_kw_1arg)
DEFINE_KW_HOOK(i16, "I16", capacity, 1, build_kw_1arg)
DEFINE_KW_HOOK(i16, "I16", persist,  2, build_kw_2arg)
DEFINE_KW_HOOK(i16, "I16", swap,    3, build_kw_3arg)
DEFINE_KW_HOOK(i16, "I16", cas,     4, build_kw_4arg)
DEFINE_KW_HOOK(i16, "I16", exists,   2, build_kw_2arg)
DEFINE_KW_HOOK(i16, "I16", incr,     2, build_kw_2arg)
DEFINE_KW_HOOK(i16, "I16", decr,     2, build_kw_2arg)
DEFINE_KW_HOOK(i16, "I16", incr_by,  3, build_kw_3arg)
DEFINE_KW_HOOK(i16, "I16", size,     1, build_kw_1arg)
DEFINE_KW_HOOK(i16, "I16", keys,     1, build_kw_1arg_list)
DEFINE_KW_HOOK(i16, "I16", values,   1, build_kw_1arg_list)
DEFINE_KW_HOOK(i16, "I16", items,    1, build_kw_1arg_list)
DEFINE_KW_HOOK(i16, "I16", max_size, 1, build_kw_1arg)
DEFINE_KW_HOOK(i16, "I16", ttl,      1, build_kw_1arg)
DEFINE_KW_HOOK(i16, "I16", lru_skip, 1, build_kw_1arg)
DEFINE_KW_HOOK(i16, "I16", each,       1, build_kw_1arg_list)
DEFINE_KW_HOOK(i16, "I16", iter_reset, 1, build_kw_1arg)
DEFINE_KW_HOOK(i16, "I16", clear,      1, build_kw_1arg)
DEFINE_KW_HOOK(i16, "I16", to_hash,    1, build_kw_1arg)
DEFINE_KW_HOOK(i16, "I16", put_ttl,    4, build_kw_4arg)
DEFINE_KW_HOOK(i16, "I16", get_or_set, 3, build_kw_3arg)

/* I16S keywords (int16 -> string) */
DEFINE_KW_HOOK(i16s, "I16S", put,      3, build_kw_3arg)
DEFINE_KW_HOOK(i16s, "I16S", get,      2, build_kw_2arg)
DEFINE_KW_HOOK(i16s, "I16S", remove,   2, build_kw_2arg)
DEFINE_KW_HOOK(i16s, "I16S", take,    2, build_kw_2arg)
DEFINE_KW_HOOK(i16s, "I16S", drain,   2, build_kw_2arg)
DEFINE_KW_HOOK(i16s, "I16S", pop,     1, build_kw_1arg)
DEFINE_KW_HOOK(i16s, "I16S", shift,   1, build_kw_1arg)
DEFINE_KW_HOOK(i16s, "I16S", reserve, 2, build_kw_2arg)
DEFINE_KW_HOOK(i16s, "I16S", purge,   1, build_kw_1arg)
DEFINE_KW_HOOK(i16s, "I16S", capacity, 1, build_kw_1arg)
DEFINE_KW_HOOK(i16s, "I16S", persist,  2, build_kw_2arg)
DEFINE_KW_HOOK(i16s, "I16S", swap,    3, build_kw_3arg)
DEFINE_KW_HOOK(i16s, "I16S", exists,   2, build_kw_2arg)
DEFINE_KW_HOOK(i16s, "I16S", size,     1, build_kw_1arg)

HashMap.xs  view on Meta::CPAN

DEFINE_KW_HOOK(i16a, "I16A", to_hash,    1, build_kw_1arg)
DEFINE_KW_HOOK(i16a, "I16A", put_ttl,    4, build_kw_4arg)
DEFINE_KW_HOOK(i16a, "I16A", get_or_set, 3, build_kw_3arg)

/* IA keywords (int64 -> SV*) */
DEFINE_KW_HOOK(ia, "IA", put,      3, build_kw_3arg)
DEFINE_KW_HOOK(ia, "IA", get,      2, build_kw_2arg)
DEFINE_KW_HOOK(ia, "IA", remove,   2, build_kw_2arg)
DEFINE_KW_HOOK(ia, "IA", take,    2, build_kw_2arg)
DEFINE_KW_HOOK(ia, "IA", drain,   2, build_kw_2arg)
DEFINE_KW_HOOK(ia, "IA", pop,     1, build_kw_1arg)
DEFINE_KW_HOOK(ia, "IA", shift,   1, build_kw_1arg)
DEFINE_KW_HOOK(ia, "IA", reserve, 2, build_kw_2arg)
DEFINE_KW_HOOK(ia, "IA", purge,   1, build_kw_1arg)
DEFINE_KW_HOOK(ia, "IA", capacity, 1, build_kw_1arg)
DEFINE_KW_HOOK(ia, "IA", persist,  2, build_kw_2arg)
DEFINE_KW_HOOK(ia, "IA", swap,    3, build_kw_3arg)
DEFINE_KW_HOOK(ia, "IA", exists,   2, build_kw_2arg)
DEFINE_KW_HOOK(ia, "IA", size,     1, build_kw_1arg)
DEFINE_KW_HOOK(ia, "IA", keys,     1, build_kw_1arg_list)
DEFINE_KW_HOOK(ia, "IA", values,   1, build_kw_1arg_list)
DEFINE_KW_HOOK(ia, "IA", items,    1, build_kw_1arg_list)
DEFINE_KW_HOOK(ia, "IA", max_size, 1, build_kw_1arg)
DEFINE_KW_HOOK(ia, "IA", ttl,      1, build_kw_1arg)
DEFINE_KW_HOOK(ia, "IA", lru_skip, 1, build_kw_1arg)
DEFINE_KW_HOOK(ia, "IA", each,       1, build_kw_1arg_list)
DEFINE_KW_HOOK(ia, "IA", iter_reset, 1, build_kw_1arg)
DEFINE_KW_HOOK(ia, "IA", clear,      1, build_kw_1arg)
DEFINE_KW_HOOK(ia, "IA", to_hash,    1, build_kw_1arg)
DEFINE_KW_HOOK(ia, "IA", put_ttl,    4, build_kw_4arg)
DEFINE_KW_HOOK(ia, "IA", get_or_set, 3, build_kw_3arg)

/* SA keywords (string -> SV*) */
DEFINE_KW_HOOK(sa, "SA", put,      3, build_kw_3arg)
DEFINE_KW_HOOK(sa, "SA", get,      2, build_kw_2arg)
DEFINE_KW_HOOK(sa, "SA", remove,   2, build_kw_2arg)
DEFINE_KW_HOOK(sa, "SA", take,    2, build_kw_2arg)
DEFINE_KW_HOOK(sa, "SA", drain,   2, build_kw_2arg)
DEFINE_KW_HOOK(sa, "SA", pop,     1, build_kw_1arg)
DEFINE_KW_HOOK(sa, "SA", shift,   1, build_kw_1arg)
DEFINE_KW_HOOK(sa, "SA", reserve, 2, build_kw_2arg)
DEFINE_KW_HOOK(sa, "SA", purge,   1, build_kw_1arg)
DEFINE_KW_HOOK(sa, "SA", capacity, 1, build_kw_1arg)
DEFINE_KW_HOOK(sa, "SA", persist,  2, build_kw_2arg)
DEFINE_KW_HOOK(sa, "SA", swap,    3, build_kw_3arg)
DEFINE_KW_HOOK(sa, "SA", exists,   2, build_kw_2arg)
DEFINE_KW_HOOK(sa, "SA", size,     1, build_kw_1arg)
DEFINE_KW_HOOK(sa, "SA", keys,     1, build_kw_1arg_list)
DEFINE_KW_HOOK(sa, "SA", values,   1, build_kw_1arg_list)
DEFINE_KW_HOOK(sa, "SA", items,    1, build_kw_1arg_list)
DEFINE_KW_HOOK(sa, "SA", max_size, 1, build_kw_1arg)
DEFINE_KW_HOOK(sa, "SA", ttl,      1, build_kw_1arg)
DEFINE_KW_HOOK(sa, "SA", lru_skip, 1, build_kw_1arg)
DEFINE_KW_HOOK(sa, "SA", each,       1, build_kw_1arg_list)
DEFINE_KW_HOOK(sa, "SA", iter_reset, 1, build_kw_1arg)
DEFINE_KW_HOOK(sa, "SA", clear,      1, build_kw_1arg)
DEFINE_KW_HOOK(sa, "SA", to_hash,    1, build_kw_1arg)
DEFINE_KW_HOOK(sa, "SA", put_ttl,    4, build_kw_4arg)
DEFINE_KW_HOOK(sa, "SA", get_or_set, 3, build_kw_3arg)

/* ---- Macro to register a keyword ---- */
#define REGISTER_KW(variant, kw, func_name) \
    register_xs_parse_keyword("hm_" #variant "_" #kw, \
        &hooks_hm_##variant##_##kw, (void*)func_name)

/* ---- Live node checks ---- */
#define I16_NODE_LIVE(n)  ((n).key != INT16_MIN && (n).key != (INT16_MIN + 1))
#define I16S_NODE_LIVE(n) I16_NODE_LIVE(n)  /* I16S keys are int16_t */
#define I32_NODE_LIVE(n)  ((n).key != INT32_MIN && (n).key != (INT32_MIN + 1))
#define I32S_NODE_LIVE(n) I32_NODE_LIVE(n)  /* I32S keys are int32_t */
#define II_NODE_LIVE(n)   ((n).key != INT64_MIN && (n).key != (INT64_MIN + 1))
#define IS_NODE_LIVE(n)   II_NODE_LIVE(n)   /* IS keys are int64_t */
#define STR_NODE_LIVE(n)  ((n).key != NULL && (n).key != &hm_str_tombstone_marker)
#define SI16_NODE_LIVE(n) STR_NODE_LIVE(n)
#define SI32_NODE_LIVE(n) STR_NODE_LIVE(n)
#define SI_NODE_LIVE(n)   STR_NODE_LIVE(n)
#define SS_NODE_LIVE(n)   STR_NODE_LIVE(n)
#define I32A_NODE_LIVE(n) I32_NODE_LIVE(n)  /* I32A keys are int32_t */
#define I16A_NODE_LIVE(n) I16_NODE_LIVE(n) /* I16A keys are int16_t */
#define IA_NODE_LIVE(n)   II_NODE_LIVE(n)   /* IA keys are int64_t */
#define SA_NODE_LIVE(n)   STR_NODE_LIVE(n)

/* ---- TTL-aware iteration helper ---- */
#define HM_TTL_SKIP_EXPIRED(self, i, now) \
    (self->expires_at && self->expires_at[i] && (now) > self->expires_at[i])

/* Compaction policy after drain/pop/shift in XS. Variant-agnostic: caller
 * supplies the variant-prefixed compact function. Mirrors the C-template's
 * HM_MAYBE_COMPACT macro so the threshold lives in one place per layer. */
#define HM_MAYBE_COMPACT_XS(self, compact_fn) do { \
    if ((self)->tombstones > (self)->capacity / 4 || \
        ((self)->size > 0 && (self)->tombstones > (self)->size)) \
        compact_fn(self); \
} while (0)


MODULE = Data::HashMap    PACKAGE = Data::HashMap::I32
PROTOTYPES: DISABLE

BOOT:
    boot_xs_parse_keyword(0.40);
    stash_i16  = gv_stashpvn("Data::HashMap::I16",  18, GV_ADD);
    stash_i16a = gv_stashpvn("Data::HashMap::I16A", 19, GV_ADD);
    stash_i16s = gv_stashpvn("Data::HashMap::I16S", 19, GV_ADD);
    stash_i32  = gv_stashpvn("Data::HashMap::I32",  18, GV_ADD);
    stash_i32a = gv_stashpvn("Data::HashMap::I32A", 19, GV_ADD);
    stash_i32s = gv_stashpvn("Data::HashMap::I32S", 19, GV_ADD);
    stash_ia   = gv_stashpvn("Data::HashMap::IA",   17, GV_ADD);
    stash_ii   = gv_stashpvn("Data::HashMap::II",   17, GV_ADD);
    stash_is   = gv_stashpvn("Data::HashMap::IS",   17, GV_ADD);
    stash_sa   = gv_stashpvn("Data::HashMap::SA",   17, GV_ADD);
    stash_si16 = gv_stashpvn("Data::HashMap::SI16", 19, GV_ADD);
    stash_si32 = gv_stashpvn("Data::HashMap::SI32", 19, GV_ADD);
    stash_si   = gv_stashpvn("Data::HashMap::SI",   17, GV_ADD);
    stash_ss   = gv_stashpvn("Data::HashMap::SS",   17, GV_ADD);
    REGISTER_KW(i16, put,      "Data::HashMap::I16::put");
    REGISTER_KW(i16, get,      "Data::HashMap::I16::get");
    REGISTER_KW(i16, remove,   "Data::HashMap::I16::remove");
    REGISTER_KW(i16, take,   "Data::HashMap::I16::take");
    REGISTER_KW(i16, drain,  "Data::HashMap::I16::drain");
    REGISTER_KW(i16, pop,    "Data::HashMap::I16::pop");



( run in 0.815 second using v1.01-cache-2.11-cpan-483215c6ad5 )