Data-HashMap
view release on metacpan or search on metacpan
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)
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 )