File Coverage

HashMap.xs
Criterion Covered Total %
statement 1504 1662 90.4
branch 1848 3958 46.6
condition n/a
subroutine n/a
pod n/a
total 3352 5620 59.6


line stmt bran cond sub pod time code
1             #define PERL_NO_GET_CONTEXT
2             #include "EXTERN.h"
3             #include "perl.h"
4             #include "XSUB.h"
5              
6             #include "ppport.h"
7              
8             #include "hashmap_i16.h"
9             #include "hashmap_i16s.h"
10             #include "hashmap_si16.h"
11             #include "hashmap_i32.h"
12             #include "hashmap_ii.h"
13             #include "hashmap_is.h"
14             #include "hashmap_si.h"
15             #include "hashmap_ss.h"
16             #include "hashmap_i32s.h"
17             #include "hashmap_si32.h"
18             #include "hashmap_i32a.h"
19             #include "hashmap_i16a.h"
20             #include "hashmap_ia.h"
21             #include "hashmap_sa.h"
22              
23             #include "XSParseKeyword.h"
24              
25             /* ---- Cached stash pointers for fast type checking ---- */
26              
27             static HV* stash_i16;
28             static HV* stash_i16a;
29             static HV* stash_i16s;
30             static HV* stash_i32;
31             static HV* stash_i32a;
32             static HV* stash_i32s;
33             static HV* stash_ia;
34             static HV* stash_ii;
35             static HV* stash_is;
36             static HV* stash_sa;
37             static HV* stash_si16;
38             static HV* stash_si32;
39             static HV* stash_si;
40             static HV* stash_ss;
41              
42             /* ---- Helper macros ---- */
43              
44             #define EXTRACT_MAP(type, stash_var, classname, sv) \
45             if (!SvROK(sv) || !SvOBJECT(SvRV(sv)) || SvSTASH(SvRV(sv)) != stash_var) \
46             croak("Expected a %s object", classname); \
47             type* self = INT2PTR(type*, SvIV(SvRV(sv))); \
48             if (!self) croak("Attempted to use a destroyed %s object", classname)
49              
50             #define HM_MAX_STR_LEN 0x7FFFFFFFU
51              
52             /* Range-check helpers for typemap (called from generated INPUT code) */
53 5           static void croak_i16(IV val) {
54             dTHX;
55 5           Perl_croak(aTHX_ "%" IVdf " out of int16 range [-32768, 32767]", val);
56             }
57 2           static void croak_i32(IV val) {
58             dTHX;
59 2           Perl_croak(aTHX_ "%" IVdf " out of int32 range [-2147483648, 2147483647]", val);
60             }
61              
62             /* SV* value free callback for IA/SA variants */
63 243796           static void hm_sv_free(void* sv) {
64             dTHX;
65 243796           SvREFCNT_dec((SV*)sv);
66 243796           }
67              
68             /* Zero-copy SV from internal string buffer (opt-in via get_direct).
69             * Returns a read-only SV pointing directly at the map's internal buffer.
70             * SvLEN=0 tells Perl not to free the buffer; SvREADONLY prevents writes.
71             * Caller must not hold the SV past any map mutation (put/remove/clear). */
72 9           static inline SV* hm_zerocopy_sv(pTHX_ const char* buf, uint32_t len, bool is_utf8) {
73 9           SV* sv = newSV_type(SVt_PV);
74 9           SvPV_set(sv, (char*)buf);
75 9           SvCUR_set(sv, len);
76 9           SvLEN_set(sv, 0);
77 9           SvPOK_on(sv);
78 9           SvREADONLY_on(sv);
79 9 100         if (is_utf8) SvUTF8_on(sv);
80 9           return sv;
81             }
82              
83             #define EXTRACT_STR_KEY(sv) \
84             STRLEN _klen; \
85             const char* _kstr = SvPV(sv, _klen); \
86             if (_klen > HM_MAX_STR_LEN) croak("key too long (max 2GB)"); \
87             bool _kutf8 = SvUTF8(sv) ? true : false; \
88             uint32_t _khash = hm_hash_string(_kstr, (uint32_t)_klen); \
89             (void)_kutf8
90              
91             #define EXTRACT_STR_VAL(sv) \
92             STRLEN _vlen; \
93             const char* _vstr = SvPV(sv, _vlen); \
94             if (_vlen > HM_MAX_STR_LEN) croak("value too long (max 2GB)"); \
95             bool _vutf8 = SvUTF8(sv) ? true : false
96              
97             /* ---- Extract optional (max_size, default_ttl) from new() args ---- */
98              
99             #define EXTRACT_NEW_ARGS(max_size_var, ttl_var) \
100             size_t max_size_var = 0; \
101             uint32_t ttl_var = 0; \
102             if (items > 1) max_size_var = (size_t)SvUV(ST(1)); \
103             if (items > 2) ttl_var = (uint32_t)SvUV(ST(2))
104              
105             /* ---- Generic keyword build functions ---- */
106              
107 181           static int build_kw_1arg(pTHX_ OP **out, XSParseKeywordPiece *args[], size_t nargs, void *hookdata) {
108             (void)nargs;
109 181           const char *func = (const char *)hookdata;
110 181           OP *map_op = args[0]->op;
111 181           OP *cvref = newCVREF(0, newGVOP(OP_GV, 0, gv_fetchpv(func, GV_ADD, SVt_PVCV)));
112 181           OP *arglist = op_append_elem(OP_LIST, map_op, cvref);
113 181           *out = op_convert_list(OP_ENTERSUB, OPf_STACKED, arglist);
114 181           return KEYWORD_PLUGIN_EXPR;
115             }
116              
117 497           static int build_kw_2arg(pTHX_ OP **out, XSParseKeywordPiece *args[], size_t nargs, void *hookdata) {
118             (void)nargs;
119 497           const char *func = (const char *)hookdata;
120 497           OP *map_op = args[0]->op;
121 497           OP *key_op = args[1]->op;
122 497           OP *cvref = newCVREF(0, newGVOP(OP_GV, 0, gv_fetchpv(func, GV_ADD, SVt_PVCV)));
123 497           OP *arglist = op_append_elem(OP_LIST, map_op, key_op);
124 497           arglist = op_append_elem(OP_LIST, arglist, cvref);
125 497           *out = op_convert_list(OP_ENTERSUB, OPf_STACKED, arglist);
126 497           return KEYWORD_PLUGIN_EXPR;
127             }
128              
129 575           static int build_kw_3arg(pTHX_ OP **out, XSParseKeywordPiece *args[], size_t nargs, void *hookdata) {
130             (void)nargs;
131 575           const char *func = (const char *)hookdata;
132 575           OP *map_op = args[0]->op;
133 575           OP *key_op = args[1]->op;
134 575           OP *val_op = args[2]->op;
135 575           OP *cvref = newCVREF(0, newGVOP(OP_GV, 0, gv_fetchpv(func, GV_ADD, SVt_PVCV)));
136 575           OP *arglist = op_append_elem(OP_LIST, map_op, key_op);
137 575           arglist = op_append_elem(OP_LIST, arglist, val_op);
138 575           arglist = op_append_elem(OP_LIST, arglist, cvref);
139 575           *out = op_convert_list(OP_ENTERSUB, OPf_STACKED, arglist);
140 575           return KEYWORD_PLUGIN_EXPR;
141             }
142              
143              
144 17           static int build_kw_4arg(pTHX_ OP **out, XSParseKeywordPiece *args[], size_t nargs, void *hookdata) {
145             (void)nargs;
146 17           const char *func = (const char *)hookdata;
147 17           OP *map_op = args[0]->op;
148 17           OP *key_op = args[1]->op;
149 17           OP *val_op = args[2]->op;
150 17           OP *ttl_op = args[3]->op;
151 17           OP *cvref = newCVREF(0, newGVOP(OP_GV, 0, gv_fetchpv(func, GV_ADD, SVt_PVCV)));
152 17           OP *arglist = op_append_elem(OP_LIST, map_op, key_op);
153 17           arglist = op_append_elem(OP_LIST, arglist, val_op);
154 17           arglist = op_append_elem(OP_LIST, arglist, ttl_op);
155 17           arglist = op_append_elem(OP_LIST, arglist, cvref);
156 17           *out = op_convert_list(OP_ENTERSUB, OPf_STACKED, arglist);
157 17           return KEYWORD_PLUGIN_EXPR;
158             }
159              
160             /* list-returning variant for keys/values/items */
161 112           static int build_kw_1arg_list(pTHX_ OP **out, XSParseKeywordPiece *args[], size_t nargs, void *hookdata) {
162             (void)nargs;
163 112           const char *func = (const char *)hookdata;
164 112           OP *map_op = args[0]->op;
165 112           OP *cvref = newCVREF(0, newGVOP(OP_GV, 0, gv_fetchpv(func, GV_ADD, SVt_PVCV)));
166 112           OP *arglist = op_append_elem(OP_LIST, map_op, cvref);
167 112           *out = op_convert_list(OP_ENTERSUB, OPf_STACKED | OPf_WANT_LIST, arglist);
168 112           return KEYWORD_PLUGIN_EXPR;
169             }
170              
171             /* ---- Keyword pieces ---- */
172              
173             static const struct XSParseKeywordPieceType pieces_1expr[] = {
174             XPK_TERMEXPR, {0}
175             };
176              
177             static const struct XSParseKeywordPieceType pieces_2expr[] = {
178             XPK_TERMEXPR, XPK_COMMA, XPK_TERMEXPR, {0}
179             };
180              
181             static const struct XSParseKeywordPieceType pieces_3expr[] = {
182             XPK_TERMEXPR, XPK_COMMA, XPK_TERMEXPR, XPK_COMMA, XPK_TERMEXPR, {0}
183             };
184             static const struct XSParseKeywordPieceType pieces_4expr[] = {
185             XPK_TERMEXPR, XPK_COMMA, XPK_TERMEXPR, XPK_COMMA, XPK_TERMEXPR, XPK_COMMA, XPK_TERMEXPR, {0}
186             };
187              
188              
189             /* ---- Keyword hook definitions ----
190             *
191             * Macro to define a keyword hook struct.
192             * variant = i16, i16a, i16s, i32, i32a, i32s, ia, ii, is, sa, si16, si32, si, ss
193             * kw = keyword name (e.g., put, get)
194             * nargs = 1, 2, or 3
195             * builder = build function (build_kw_1arg, build_kw_2arg, etc.)
196             */
197             #define DEFINE_KW_HOOK(variant, PKG, kw, nargs, builder) \
198             static const struct XSParseKeywordHooks hooks_hm_##variant##_##kw = { \
199             .flags = XPK_FLAG_EXPR, \
200             .permit_hintkey = "Data::HashMap::" PKG "/hm_" #variant "_" #kw, \
201             .pieces = pieces_##nargs##expr, \
202             .build = builder, \
203             };
204              
205             /* I16 keywords */
206             DEFINE_KW_HOOK(i16, "I16", put, 3, build_kw_3arg)
207             DEFINE_KW_HOOK(i16, "I16", get, 2, build_kw_2arg)
208             DEFINE_KW_HOOK(i16, "I16", remove, 2, build_kw_2arg)
209             DEFINE_KW_HOOK(i16, "I16", exists, 2, build_kw_2arg)
210             DEFINE_KW_HOOK(i16, "I16", incr, 2, build_kw_2arg)
211             DEFINE_KW_HOOK(i16, "I16", decr, 2, build_kw_2arg)
212             DEFINE_KW_HOOK(i16, "I16", incr_by, 3, build_kw_3arg)
213             DEFINE_KW_HOOK(i16, "I16", size, 1, build_kw_1arg)
214             DEFINE_KW_HOOK(i16, "I16", keys, 1, build_kw_1arg_list)
215             DEFINE_KW_HOOK(i16, "I16", values, 1, build_kw_1arg_list)
216             DEFINE_KW_HOOK(i16, "I16", items, 1, build_kw_1arg_list)
217             DEFINE_KW_HOOK(i16, "I16", max_size, 1, build_kw_1arg)
218             DEFINE_KW_HOOK(i16, "I16", ttl, 1, build_kw_1arg)
219             DEFINE_KW_HOOK(i16, "I16", each, 1, build_kw_1arg_list)
220             DEFINE_KW_HOOK(i16, "I16", iter_reset, 1, build_kw_1arg)
221             DEFINE_KW_HOOK(i16, "I16", clear, 1, build_kw_1arg)
222             DEFINE_KW_HOOK(i16, "I16", to_hash, 1, build_kw_1arg)
223             DEFINE_KW_HOOK(i16, "I16", put_ttl, 4, build_kw_4arg)
224             DEFINE_KW_HOOK(i16, "I16", get_or_set, 3, build_kw_3arg)
225              
226             /* I16S keywords (int16 -> string) */
227             DEFINE_KW_HOOK(i16s, "I16S", put, 3, build_kw_3arg)
228             DEFINE_KW_HOOK(i16s, "I16S", get, 2, build_kw_2arg)
229             DEFINE_KW_HOOK(i16s, "I16S", remove, 2, build_kw_2arg)
230             DEFINE_KW_HOOK(i16s, "I16S", exists, 2, build_kw_2arg)
231             DEFINE_KW_HOOK(i16s, "I16S", size, 1, build_kw_1arg)
232             DEFINE_KW_HOOK(i16s, "I16S", keys, 1, build_kw_1arg_list)
233             DEFINE_KW_HOOK(i16s, "I16S", values, 1, build_kw_1arg_list)
234             DEFINE_KW_HOOK(i16s, "I16S", items, 1, build_kw_1arg_list)
235             DEFINE_KW_HOOK(i16s, "I16S", max_size, 1, build_kw_1arg)
236             DEFINE_KW_HOOK(i16s, "I16S", ttl, 1, build_kw_1arg)
237             DEFINE_KW_HOOK(i16s, "I16S", each, 1, build_kw_1arg_list)
238             DEFINE_KW_HOOK(i16s, "I16S", iter_reset, 1, build_kw_1arg)
239             DEFINE_KW_HOOK(i16s, "I16S", clear, 1, build_kw_1arg)
240             DEFINE_KW_HOOK(i16s, "I16S", to_hash, 1, build_kw_1arg)
241             DEFINE_KW_HOOK(i16s, "I16S", put_ttl, 4, build_kw_4arg)
242             DEFINE_KW_HOOK(i16s, "I16S", get_or_set, 3, build_kw_3arg)
243             DEFINE_KW_HOOK(i16s, "I16S", get_direct, 2, build_kw_2arg)
244              
245             /* SI16 keywords (string -> int16) */
246             DEFINE_KW_HOOK(si16, "SI16", put, 3, build_kw_3arg)
247             DEFINE_KW_HOOK(si16, "SI16", get, 2, build_kw_2arg)
248             DEFINE_KW_HOOK(si16, "SI16", remove, 2, build_kw_2arg)
249             DEFINE_KW_HOOK(si16, "SI16", exists, 2, build_kw_2arg)
250             DEFINE_KW_HOOK(si16, "SI16", incr, 2, build_kw_2arg)
251             DEFINE_KW_HOOK(si16, "SI16", decr, 2, build_kw_2arg)
252             DEFINE_KW_HOOK(si16, "SI16", incr_by, 3, build_kw_3arg)
253             DEFINE_KW_HOOK(si16, "SI16", size, 1, build_kw_1arg)
254             DEFINE_KW_HOOK(si16, "SI16", keys, 1, build_kw_1arg_list)
255             DEFINE_KW_HOOK(si16, "SI16", values, 1, build_kw_1arg_list)
256             DEFINE_KW_HOOK(si16, "SI16", items, 1, build_kw_1arg_list)
257             DEFINE_KW_HOOK(si16, "SI16", max_size, 1, build_kw_1arg)
258             DEFINE_KW_HOOK(si16, "SI16", ttl, 1, build_kw_1arg)
259             DEFINE_KW_HOOK(si16, "SI16", each, 1, build_kw_1arg_list)
260             DEFINE_KW_HOOK(si16, "SI16", iter_reset, 1, build_kw_1arg)
261             DEFINE_KW_HOOK(si16, "SI16", clear, 1, build_kw_1arg)
262             DEFINE_KW_HOOK(si16, "SI16", to_hash, 1, build_kw_1arg)
263             DEFINE_KW_HOOK(si16, "SI16", put_ttl, 4, build_kw_4arg)
264             DEFINE_KW_HOOK(si16, "SI16", get_or_set, 3, build_kw_3arg)
265              
266             /* I32 keywords */
267             DEFINE_KW_HOOK(i32, "I32", put, 3, build_kw_3arg)
268             DEFINE_KW_HOOK(i32, "I32", get, 2, build_kw_2arg)
269             DEFINE_KW_HOOK(i32, "I32", remove, 2, build_kw_2arg)
270             DEFINE_KW_HOOK(i32, "I32", exists, 2, build_kw_2arg)
271             DEFINE_KW_HOOK(i32, "I32", incr, 2, build_kw_2arg)
272             DEFINE_KW_HOOK(i32, "I32", decr, 2, build_kw_2arg)
273             DEFINE_KW_HOOK(i32, "I32", incr_by, 3, build_kw_3arg)
274             DEFINE_KW_HOOK(i32, "I32", size, 1, build_kw_1arg)
275             DEFINE_KW_HOOK(i32, "I32", keys, 1, build_kw_1arg_list)
276             DEFINE_KW_HOOK(i32, "I32", values, 1, build_kw_1arg_list)
277             DEFINE_KW_HOOK(i32, "I32", items, 1, build_kw_1arg_list)
278             DEFINE_KW_HOOK(i32, "I32", max_size, 1, build_kw_1arg)
279             DEFINE_KW_HOOK(i32, "I32", ttl, 1, build_kw_1arg)
280             DEFINE_KW_HOOK(i32, "I32", each, 1, build_kw_1arg_list)
281             DEFINE_KW_HOOK(i32, "I32", iter_reset, 1, build_kw_1arg)
282             DEFINE_KW_HOOK(i32, "I32", clear, 1, build_kw_1arg)
283             DEFINE_KW_HOOK(i32, "I32", to_hash, 1, build_kw_1arg)
284             DEFINE_KW_HOOK(i32, "I32", put_ttl, 4, build_kw_4arg)
285             DEFINE_KW_HOOK(i32, "I32", get_or_set, 3, build_kw_3arg)
286              
287             /* II keywords */
288             DEFINE_KW_HOOK(ii, "II", put, 3, build_kw_3arg)
289             DEFINE_KW_HOOK(ii, "II", get, 2, build_kw_2arg)
290             DEFINE_KW_HOOK(ii, "II", remove, 2, build_kw_2arg)
291             DEFINE_KW_HOOK(ii, "II", exists, 2, build_kw_2arg)
292             DEFINE_KW_HOOK(ii, "II", incr, 2, build_kw_2arg)
293             DEFINE_KW_HOOK(ii, "II", decr, 2, build_kw_2arg)
294             DEFINE_KW_HOOK(ii, "II", incr_by, 3, build_kw_3arg)
295             DEFINE_KW_HOOK(ii, "II", size, 1, build_kw_1arg)
296             DEFINE_KW_HOOK(ii, "II", keys, 1, build_kw_1arg_list)
297             DEFINE_KW_HOOK(ii, "II", values, 1, build_kw_1arg_list)
298             DEFINE_KW_HOOK(ii, "II", items, 1, build_kw_1arg_list)
299             DEFINE_KW_HOOK(ii, "II", max_size, 1, build_kw_1arg)
300             DEFINE_KW_HOOK(ii, "II", ttl, 1, build_kw_1arg)
301             DEFINE_KW_HOOK(ii, "II", each, 1, build_kw_1arg_list)
302             DEFINE_KW_HOOK(ii, "II", iter_reset, 1, build_kw_1arg)
303             DEFINE_KW_HOOK(ii, "II", clear, 1, build_kw_1arg)
304             DEFINE_KW_HOOK(ii, "II", to_hash, 1, build_kw_1arg)
305             DEFINE_KW_HOOK(ii, "II", put_ttl, 4, build_kw_4arg)
306             DEFINE_KW_HOOK(ii, "II", get_or_set, 3, build_kw_3arg)
307              
308             /* IS keywords */
309             DEFINE_KW_HOOK(is, "IS", put, 3, build_kw_3arg)
310             DEFINE_KW_HOOK(is, "IS", get, 2, build_kw_2arg)
311             DEFINE_KW_HOOK(is, "IS", remove, 2, build_kw_2arg)
312             DEFINE_KW_HOOK(is, "IS", exists, 2, build_kw_2arg)
313             DEFINE_KW_HOOK(is, "IS", size, 1, build_kw_1arg)
314             DEFINE_KW_HOOK(is, "IS", keys, 1, build_kw_1arg_list)
315             DEFINE_KW_HOOK(is, "IS", values, 1, build_kw_1arg_list)
316             DEFINE_KW_HOOK(is, "IS", items, 1, build_kw_1arg_list)
317             DEFINE_KW_HOOK(is, "IS", max_size, 1, build_kw_1arg)
318             DEFINE_KW_HOOK(is, "IS", ttl, 1, build_kw_1arg)
319             DEFINE_KW_HOOK(is, "IS", each, 1, build_kw_1arg_list)
320             DEFINE_KW_HOOK(is, "IS", iter_reset, 1, build_kw_1arg)
321             DEFINE_KW_HOOK(is, "IS", clear, 1, build_kw_1arg)
322             DEFINE_KW_HOOK(is, "IS", to_hash, 1, build_kw_1arg)
323             DEFINE_KW_HOOK(is, "IS", put_ttl, 4, build_kw_4arg)
324             DEFINE_KW_HOOK(is, "IS", get_or_set, 3, build_kw_3arg)
325             DEFINE_KW_HOOK(is, "IS", get_direct, 2, build_kw_2arg)
326              
327             /* SI keywords */
328             DEFINE_KW_HOOK(si, "SI", put, 3, build_kw_3arg)
329             DEFINE_KW_HOOK(si, "SI", get, 2, build_kw_2arg)
330             DEFINE_KW_HOOK(si, "SI", remove, 2, build_kw_2arg)
331             DEFINE_KW_HOOK(si, "SI", exists, 2, build_kw_2arg)
332             DEFINE_KW_HOOK(si, "SI", incr, 2, build_kw_2arg)
333             DEFINE_KW_HOOK(si, "SI", decr, 2, build_kw_2arg)
334             DEFINE_KW_HOOK(si, "SI", incr_by, 3, build_kw_3arg)
335             DEFINE_KW_HOOK(si, "SI", size, 1, build_kw_1arg)
336             DEFINE_KW_HOOK(si, "SI", keys, 1, build_kw_1arg_list)
337             DEFINE_KW_HOOK(si, "SI", values, 1, build_kw_1arg_list)
338             DEFINE_KW_HOOK(si, "SI", items, 1, build_kw_1arg_list)
339             DEFINE_KW_HOOK(si, "SI", max_size, 1, build_kw_1arg)
340             DEFINE_KW_HOOK(si, "SI", ttl, 1, build_kw_1arg)
341             DEFINE_KW_HOOK(si, "SI", each, 1, build_kw_1arg_list)
342             DEFINE_KW_HOOK(si, "SI", iter_reset, 1, build_kw_1arg)
343             DEFINE_KW_HOOK(si, "SI", clear, 1, build_kw_1arg)
344             DEFINE_KW_HOOK(si, "SI", to_hash, 1, build_kw_1arg)
345             DEFINE_KW_HOOK(si, "SI", put_ttl, 4, build_kw_4arg)
346             DEFINE_KW_HOOK(si, "SI", get_or_set, 3, build_kw_3arg)
347              
348             /* SS keywords */
349             DEFINE_KW_HOOK(ss, "SS", put, 3, build_kw_3arg)
350             DEFINE_KW_HOOK(ss, "SS", get, 2, build_kw_2arg)
351             DEFINE_KW_HOOK(ss, "SS", remove, 2, build_kw_2arg)
352             DEFINE_KW_HOOK(ss, "SS", exists, 2, build_kw_2arg)
353             DEFINE_KW_HOOK(ss, "SS", size, 1, build_kw_1arg)
354             DEFINE_KW_HOOK(ss, "SS", keys, 1, build_kw_1arg_list)
355             DEFINE_KW_HOOK(ss, "SS", values, 1, build_kw_1arg_list)
356             DEFINE_KW_HOOK(ss, "SS", items, 1, build_kw_1arg_list)
357             DEFINE_KW_HOOK(ss, "SS", max_size, 1, build_kw_1arg)
358             DEFINE_KW_HOOK(ss, "SS", ttl, 1, build_kw_1arg)
359             DEFINE_KW_HOOK(ss, "SS", each, 1, build_kw_1arg_list)
360             DEFINE_KW_HOOK(ss, "SS", iter_reset, 1, build_kw_1arg)
361             DEFINE_KW_HOOK(ss, "SS", clear, 1, build_kw_1arg)
362             DEFINE_KW_HOOK(ss, "SS", to_hash, 1, build_kw_1arg)
363             DEFINE_KW_HOOK(ss, "SS", put_ttl, 4, build_kw_4arg)
364             DEFINE_KW_HOOK(ss, "SS", get_or_set, 3, build_kw_3arg)
365             DEFINE_KW_HOOK(ss, "SS", get_direct, 2, build_kw_2arg)
366              
367             /* I32S keywords (int32 -> string) */
368             DEFINE_KW_HOOK(i32s, "I32S", put, 3, build_kw_3arg)
369             DEFINE_KW_HOOK(i32s, "I32S", get, 2, build_kw_2arg)
370             DEFINE_KW_HOOK(i32s, "I32S", remove, 2, build_kw_2arg)
371             DEFINE_KW_HOOK(i32s, "I32S", exists, 2, build_kw_2arg)
372             DEFINE_KW_HOOK(i32s, "I32S", size, 1, build_kw_1arg)
373             DEFINE_KW_HOOK(i32s, "I32S", keys, 1, build_kw_1arg_list)
374             DEFINE_KW_HOOK(i32s, "I32S", values, 1, build_kw_1arg_list)
375             DEFINE_KW_HOOK(i32s, "I32S", items, 1, build_kw_1arg_list)
376             DEFINE_KW_HOOK(i32s, "I32S", max_size, 1, build_kw_1arg)
377             DEFINE_KW_HOOK(i32s, "I32S", ttl, 1, build_kw_1arg)
378             DEFINE_KW_HOOK(i32s, "I32S", each, 1, build_kw_1arg_list)
379             DEFINE_KW_HOOK(i32s, "I32S", iter_reset, 1, build_kw_1arg)
380             DEFINE_KW_HOOK(i32s, "I32S", clear, 1, build_kw_1arg)
381             DEFINE_KW_HOOK(i32s, "I32S", to_hash, 1, build_kw_1arg)
382             DEFINE_KW_HOOK(i32s, "I32S", put_ttl, 4, build_kw_4arg)
383             DEFINE_KW_HOOK(i32s, "I32S", get_or_set, 3, build_kw_3arg)
384             DEFINE_KW_HOOK(i32s, "I32S", get_direct, 2, build_kw_2arg)
385              
386             /* SI32 keywords (string -> int32) */
387             DEFINE_KW_HOOK(si32, "SI32", put, 3, build_kw_3arg)
388             DEFINE_KW_HOOK(si32, "SI32", get, 2, build_kw_2arg)
389             DEFINE_KW_HOOK(si32, "SI32", remove, 2, build_kw_2arg)
390             DEFINE_KW_HOOK(si32, "SI32", exists, 2, build_kw_2arg)
391             DEFINE_KW_HOOK(si32, "SI32", incr, 2, build_kw_2arg)
392             DEFINE_KW_HOOK(si32, "SI32", decr, 2, build_kw_2arg)
393             DEFINE_KW_HOOK(si32, "SI32", incr_by, 3, build_kw_3arg)
394             DEFINE_KW_HOOK(si32, "SI32", size, 1, build_kw_1arg)
395             DEFINE_KW_HOOK(si32, "SI32", keys, 1, build_kw_1arg_list)
396             DEFINE_KW_HOOK(si32, "SI32", values, 1, build_kw_1arg_list)
397             DEFINE_KW_HOOK(si32, "SI32", items, 1, build_kw_1arg_list)
398             DEFINE_KW_HOOK(si32, "SI32", max_size, 1, build_kw_1arg)
399             DEFINE_KW_HOOK(si32, "SI32", ttl, 1, build_kw_1arg)
400             DEFINE_KW_HOOK(si32, "SI32", each, 1, build_kw_1arg_list)
401             DEFINE_KW_HOOK(si32, "SI32", iter_reset, 1, build_kw_1arg)
402             DEFINE_KW_HOOK(si32, "SI32", clear, 1, build_kw_1arg)
403             DEFINE_KW_HOOK(si32, "SI32", to_hash, 1, build_kw_1arg)
404             DEFINE_KW_HOOK(si32, "SI32", put_ttl, 4, build_kw_4arg)
405             DEFINE_KW_HOOK(si32, "SI32", get_or_set, 3, build_kw_3arg)
406              
407             /* I32A keywords (int32 -> SV*) */
408             DEFINE_KW_HOOK(i32a, "I32A", put, 3, build_kw_3arg)
409             DEFINE_KW_HOOK(i32a, "I32A", get, 2, build_kw_2arg)
410             DEFINE_KW_HOOK(i32a, "I32A", remove, 2, build_kw_2arg)
411             DEFINE_KW_HOOK(i32a, "I32A", exists, 2, build_kw_2arg)
412             DEFINE_KW_HOOK(i32a, "I32A", size, 1, build_kw_1arg)
413             DEFINE_KW_HOOK(i32a, "I32A", keys, 1, build_kw_1arg_list)
414             DEFINE_KW_HOOK(i32a, "I32A", values, 1, build_kw_1arg_list)
415             DEFINE_KW_HOOK(i32a, "I32A", items, 1, build_kw_1arg_list)
416             DEFINE_KW_HOOK(i32a, "I32A", max_size, 1, build_kw_1arg)
417             DEFINE_KW_HOOK(i32a, "I32A", ttl, 1, build_kw_1arg)
418             DEFINE_KW_HOOK(i32a, "I32A", each, 1, build_kw_1arg_list)
419             DEFINE_KW_HOOK(i32a, "I32A", iter_reset, 1, build_kw_1arg)
420             DEFINE_KW_HOOK(i32a, "I32A", clear, 1, build_kw_1arg)
421             DEFINE_KW_HOOK(i32a, "I32A", to_hash, 1, build_kw_1arg)
422             DEFINE_KW_HOOK(i32a, "I32A", put_ttl, 4, build_kw_4arg)
423             DEFINE_KW_HOOK(i32a, "I32A", get_or_set, 3, build_kw_3arg)
424              
425             /* I16A keywords (int16 -> SV*) */
426             DEFINE_KW_HOOK(i16a, "I16A", put, 3, build_kw_3arg)
427             DEFINE_KW_HOOK(i16a, "I16A", get, 2, build_kw_2arg)
428             DEFINE_KW_HOOK(i16a, "I16A", remove, 2, build_kw_2arg)
429             DEFINE_KW_HOOK(i16a, "I16A", exists, 2, build_kw_2arg)
430             DEFINE_KW_HOOK(i16a, "I16A", size, 1, build_kw_1arg)
431             DEFINE_KW_HOOK(i16a, "I16A", keys, 1, build_kw_1arg_list)
432             DEFINE_KW_HOOK(i16a, "I16A", values, 1, build_kw_1arg_list)
433             DEFINE_KW_HOOK(i16a, "I16A", items, 1, build_kw_1arg_list)
434             DEFINE_KW_HOOK(i16a, "I16A", max_size, 1, build_kw_1arg)
435             DEFINE_KW_HOOK(i16a, "I16A", ttl, 1, build_kw_1arg)
436             DEFINE_KW_HOOK(i16a, "I16A", each, 1, build_kw_1arg_list)
437             DEFINE_KW_HOOK(i16a, "I16A", iter_reset, 1, build_kw_1arg)
438             DEFINE_KW_HOOK(i16a, "I16A", clear, 1, build_kw_1arg)
439             DEFINE_KW_HOOK(i16a, "I16A", to_hash, 1, build_kw_1arg)
440             DEFINE_KW_HOOK(i16a, "I16A", put_ttl, 4, build_kw_4arg)
441             DEFINE_KW_HOOK(i16a, "I16A", get_or_set, 3, build_kw_3arg)
442              
443             /* IA keywords (int64 -> SV*) */
444             DEFINE_KW_HOOK(ia, "IA", put, 3, build_kw_3arg)
445             DEFINE_KW_HOOK(ia, "IA", get, 2, build_kw_2arg)
446             DEFINE_KW_HOOK(ia, "IA", remove, 2, build_kw_2arg)
447             DEFINE_KW_HOOK(ia, "IA", exists, 2, build_kw_2arg)
448             DEFINE_KW_HOOK(ia, "IA", size, 1, build_kw_1arg)
449             DEFINE_KW_HOOK(ia, "IA", keys, 1, build_kw_1arg_list)
450             DEFINE_KW_HOOK(ia, "IA", values, 1, build_kw_1arg_list)
451             DEFINE_KW_HOOK(ia, "IA", items, 1, build_kw_1arg_list)
452             DEFINE_KW_HOOK(ia, "IA", max_size, 1, build_kw_1arg)
453             DEFINE_KW_HOOK(ia, "IA", ttl, 1, build_kw_1arg)
454             DEFINE_KW_HOOK(ia, "IA", each, 1, build_kw_1arg_list)
455             DEFINE_KW_HOOK(ia, "IA", iter_reset, 1, build_kw_1arg)
456             DEFINE_KW_HOOK(ia, "IA", clear, 1, build_kw_1arg)
457             DEFINE_KW_HOOK(ia, "IA", to_hash, 1, build_kw_1arg)
458             DEFINE_KW_HOOK(ia, "IA", put_ttl, 4, build_kw_4arg)
459             DEFINE_KW_HOOK(ia, "IA", get_or_set, 3, build_kw_3arg)
460              
461             /* SA keywords (string -> SV*) */
462             DEFINE_KW_HOOK(sa, "SA", put, 3, build_kw_3arg)
463             DEFINE_KW_HOOK(sa, "SA", get, 2, build_kw_2arg)
464             DEFINE_KW_HOOK(sa, "SA", remove, 2, build_kw_2arg)
465             DEFINE_KW_HOOK(sa, "SA", exists, 2, build_kw_2arg)
466             DEFINE_KW_HOOK(sa, "SA", size, 1, build_kw_1arg)
467             DEFINE_KW_HOOK(sa, "SA", keys, 1, build_kw_1arg_list)
468             DEFINE_KW_HOOK(sa, "SA", values, 1, build_kw_1arg_list)
469             DEFINE_KW_HOOK(sa, "SA", items, 1, build_kw_1arg_list)
470             DEFINE_KW_HOOK(sa, "SA", max_size, 1, build_kw_1arg)
471             DEFINE_KW_HOOK(sa, "SA", ttl, 1, build_kw_1arg)
472             DEFINE_KW_HOOK(sa, "SA", each, 1, build_kw_1arg_list)
473             DEFINE_KW_HOOK(sa, "SA", iter_reset, 1, build_kw_1arg)
474             DEFINE_KW_HOOK(sa, "SA", clear, 1, build_kw_1arg)
475             DEFINE_KW_HOOK(sa, "SA", to_hash, 1, build_kw_1arg)
476             DEFINE_KW_HOOK(sa, "SA", put_ttl, 4, build_kw_4arg)
477             DEFINE_KW_HOOK(sa, "SA", get_or_set, 3, build_kw_3arg)
478              
479             /* ---- Macro to register a keyword ---- */
480             #define REGISTER_KW(variant, kw, func_name) \
481             register_xs_parse_keyword("hm_" #variant "_" #kw, \
482             &hooks_hm_##variant##_##kw, (void*)func_name)
483              
484             /* ---- Live node checks ---- */
485             #define I16_NODE_LIVE(n) ((n).key != INT16_MIN && (n).key != (INT16_MIN + 1))
486             #define I16S_NODE_LIVE(n) I16_NODE_LIVE(n) /* I16S keys are int16_t */
487             #define I32_NODE_LIVE(n) ((n).key != INT32_MIN && (n).key != (INT32_MIN + 1))
488             #define I32S_NODE_LIVE(n) I32_NODE_LIVE(n) /* I32S keys are int32_t */
489             #define II_NODE_LIVE(n) ((n).key != INT64_MIN && (n).key != (INT64_MIN + 1))
490             #define IS_NODE_LIVE(n) II_NODE_LIVE(n) /* IS keys are int64_t */
491             #define STR_NODE_LIVE(n) ((n).key != NULL && (n).key != &hm_str_tombstone_marker)
492             #define SI16_NODE_LIVE(n) STR_NODE_LIVE(n)
493             #define SI32_NODE_LIVE(n) STR_NODE_LIVE(n)
494             #define SI_NODE_LIVE(n) STR_NODE_LIVE(n)
495             #define SS_NODE_LIVE(n) STR_NODE_LIVE(n)
496             #define I32A_NODE_LIVE(n) I32_NODE_LIVE(n) /* I32A keys are int32_t */
497             #define I16A_NODE_LIVE(n) I16_NODE_LIVE(n) /* I16A keys are int16_t */
498             #define IA_NODE_LIVE(n) II_NODE_LIVE(n) /* IA keys are int64_t */
499             #define SA_NODE_LIVE(n) STR_NODE_LIVE(n)
500              
501             /* ---- TTL-aware iteration helper ---- */
502             #define HM_TTL_SKIP_EXPIRED(self, i, now) \
503             (self->expires_at && self->expires_at[i] && (now) >= self->expires_at[i])
504              
505              
506             MODULE = Data::HashMap PACKAGE = Data::HashMap::I32
507             PROTOTYPES: DISABLE
508              
509             BOOT:
510 22           boot_xs_parse_keyword(0.40);
511 22           stash_i16 = gv_stashpvn("Data::HashMap::I16", 18, GV_ADD);
512 22           stash_i16a = gv_stashpvn("Data::HashMap::I16A", 19, GV_ADD);
513 22           stash_i16s = gv_stashpvn("Data::HashMap::I16S", 19, GV_ADD);
514 22           stash_i32 = gv_stashpvn("Data::HashMap::I32", 18, GV_ADD);
515 22           stash_i32a = gv_stashpvn("Data::HashMap::I32A", 19, GV_ADD);
516 22           stash_i32s = gv_stashpvn("Data::HashMap::I32S", 19, GV_ADD);
517 22           stash_ia = gv_stashpvn("Data::HashMap::IA", 17, GV_ADD);
518 22           stash_ii = gv_stashpvn("Data::HashMap::II", 17, GV_ADD);
519 22           stash_is = gv_stashpvn("Data::HashMap::IS", 17, GV_ADD);
520 22           stash_sa = gv_stashpvn("Data::HashMap::SA", 17, GV_ADD);
521 22           stash_si16 = gv_stashpvn("Data::HashMap::SI16", 19, GV_ADD);
522 22           stash_si32 = gv_stashpvn("Data::HashMap::SI32", 19, GV_ADD);
523 22           stash_si = gv_stashpvn("Data::HashMap::SI", 17, GV_ADD);
524 22           stash_ss = gv_stashpvn("Data::HashMap::SS", 17, GV_ADD);
525 22           REGISTER_KW(i16, put, "Data::HashMap::I16::put");
526 22           REGISTER_KW(i16, get, "Data::HashMap::I16::get");
527 22           REGISTER_KW(i16, remove, "Data::HashMap::I16::remove");
528 22           REGISTER_KW(i16, exists, "Data::HashMap::I16::exists");
529 22           REGISTER_KW(i16, incr, "Data::HashMap::I16::incr");
530 22           REGISTER_KW(i16, decr, "Data::HashMap::I16::decr");
531 22           REGISTER_KW(i16, incr_by, "Data::HashMap::I16::incr_by");
532 22           REGISTER_KW(i16, size, "Data::HashMap::I16::size");
533 22           REGISTER_KW(i16, keys, "Data::HashMap::I16::keys");
534 22           REGISTER_KW(i16, values, "Data::HashMap::I16::values");
535 22           REGISTER_KW(i16, items, "Data::HashMap::I16::items");
536 22           REGISTER_KW(i16, max_size, "Data::HashMap::I16::max_size");
537 22           REGISTER_KW(i16, ttl, "Data::HashMap::I16::ttl");
538 22           REGISTER_KW(i16, each, "Data::HashMap::I16::each");
539 22           REGISTER_KW(i16, iter_reset, "Data::HashMap::I16::iter_reset");
540 22           REGISTER_KW(i16, clear, "Data::HashMap::I16::clear");
541 22           REGISTER_KW(i16, to_hash, "Data::HashMap::I16::to_hash");
542 22           REGISTER_KW(i16, put_ttl, "Data::HashMap::I16::put_ttl");
543 22           REGISTER_KW(i16, get_or_set, "Data::HashMap::I16::get_or_set");
544 22           REGISTER_KW(i16s, put, "Data::HashMap::I16S::put");
545 22           REGISTER_KW(i16s, get, "Data::HashMap::I16S::get");
546 22           REGISTER_KW(i16s, remove, "Data::HashMap::I16S::remove");
547 22           REGISTER_KW(i16s, exists, "Data::HashMap::I16S::exists");
548 22           REGISTER_KW(i16s, size, "Data::HashMap::I16S::size");
549 22           REGISTER_KW(i16s, keys, "Data::HashMap::I16S::keys");
550 22           REGISTER_KW(i16s, values, "Data::HashMap::I16S::values");
551 22           REGISTER_KW(i16s, items, "Data::HashMap::I16S::items");
552 22           REGISTER_KW(i16s, max_size, "Data::HashMap::I16S::max_size");
553 22           REGISTER_KW(i16s, ttl, "Data::HashMap::I16S::ttl");
554 22           REGISTER_KW(i16s, each, "Data::HashMap::I16S::each");
555 22           REGISTER_KW(i16s, iter_reset, "Data::HashMap::I16S::iter_reset");
556 22           REGISTER_KW(i16s, clear, "Data::HashMap::I16S::clear");
557 22           REGISTER_KW(i16s, to_hash, "Data::HashMap::I16S::to_hash");
558 22           REGISTER_KW(i16s, put_ttl, "Data::HashMap::I16S::put_ttl");
559 22           REGISTER_KW(i16s, get_or_set, "Data::HashMap::I16S::get_or_set");
560 22           REGISTER_KW(i16s, get_direct, "Data::HashMap::I16S::get_direct");
561 22           REGISTER_KW(si16, put, "Data::HashMap::SI16::put");
562 22           REGISTER_KW(si16, get, "Data::HashMap::SI16::get");
563 22           REGISTER_KW(si16, remove, "Data::HashMap::SI16::remove");
564 22           REGISTER_KW(si16, exists, "Data::HashMap::SI16::exists");
565 22           REGISTER_KW(si16, incr, "Data::HashMap::SI16::incr");
566 22           REGISTER_KW(si16, decr, "Data::HashMap::SI16::decr");
567 22           REGISTER_KW(si16, incr_by, "Data::HashMap::SI16::incr_by");
568 22           REGISTER_KW(si16, size, "Data::HashMap::SI16::size");
569 22           REGISTER_KW(si16, keys, "Data::HashMap::SI16::keys");
570 22           REGISTER_KW(si16, values, "Data::HashMap::SI16::values");
571 22           REGISTER_KW(si16, items, "Data::HashMap::SI16::items");
572 22           REGISTER_KW(si16, max_size, "Data::HashMap::SI16::max_size");
573 22           REGISTER_KW(si16, ttl, "Data::HashMap::SI16::ttl");
574 22           REGISTER_KW(si16, each, "Data::HashMap::SI16::each");
575 22           REGISTER_KW(si16, iter_reset, "Data::HashMap::SI16::iter_reset");
576 22           REGISTER_KW(si16, clear, "Data::HashMap::SI16::clear");
577 22           REGISTER_KW(si16, to_hash, "Data::HashMap::SI16::to_hash");
578 22           REGISTER_KW(si16, put_ttl, "Data::HashMap::SI16::put_ttl");
579 22           REGISTER_KW(si16, get_or_set, "Data::HashMap::SI16::get_or_set");
580 22           REGISTER_KW(i32, put, "Data::HashMap::I32::put");
581 22           REGISTER_KW(i32, get, "Data::HashMap::I32::get");
582 22           REGISTER_KW(i32, remove, "Data::HashMap::I32::remove");
583 22           REGISTER_KW(i32, exists, "Data::HashMap::I32::exists");
584 22           REGISTER_KW(i32, incr, "Data::HashMap::I32::incr");
585 22           REGISTER_KW(i32, decr, "Data::HashMap::I32::decr");
586 22           REGISTER_KW(i32, incr_by, "Data::HashMap::I32::incr_by");
587 22           REGISTER_KW(i32, size, "Data::HashMap::I32::size");
588 22           REGISTER_KW(i32, keys, "Data::HashMap::I32::keys");
589 22           REGISTER_KW(i32, values, "Data::HashMap::I32::values");
590 22           REGISTER_KW(i32, items, "Data::HashMap::I32::items");
591 22           REGISTER_KW(i32, max_size, "Data::HashMap::I32::max_size");
592 22           REGISTER_KW(i32, ttl, "Data::HashMap::I32::ttl");
593 22           REGISTER_KW(i32, each, "Data::HashMap::I32::each");
594 22           REGISTER_KW(i32, iter_reset, "Data::HashMap::I32::iter_reset");
595 22           REGISTER_KW(i32, clear, "Data::HashMap::I32::clear");
596 22           REGISTER_KW(i32, to_hash, "Data::HashMap::I32::to_hash");
597 22           REGISTER_KW(i32, put_ttl, "Data::HashMap::I32::put_ttl");
598 22           REGISTER_KW(i32, get_or_set, "Data::HashMap::I32::get_or_set");
599 22           REGISTER_KW(ii, put, "Data::HashMap::II::put");
600 22           REGISTER_KW(ii, get, "Data::HashMap::II::get");
601 22           REGISTER_KW(ii, remove, "Data::HashMap::II::remove");
602 22           REGISTER_KW(ii, exists, "Data::HashMap::II::exists");
603 22           REGISTER_KW(ii, incr, "Data::HashMap::II::incr");
604 22           REGISTER_KW(ii, decr, "Data::HashMap::II::decr");
605 22           REGISTER_KW(ii, incr_by, "Data::HashMap::II::incr_by");
606 22           REGISTER_KW(ii, size, "Data::HashMap::II::size");
607 22           REGISTER_KW(ii, keys, "Data::HashMap::II::keys");
608 22           REGISTER_KW(ii, values, "Data::HashMap::II::values");
609 22           REGISTER_KW(ii, items, "Data::HashMap::II::items");
610 22           REGISTER_KW(ii, max_size, "Data::HashMap::II::max_size");
611 22           REGISTER_KW(ii, ttl, "Data::HashMap::II::ttl");
612 22           REGISTER_KW(ii, each, "Data::HashMap::II::each");
613 22           REGISTER_KW(ii, iter_reset, "Data::HashMap::II::iter_reset");
614 22           REGISTER_KW(ii, clear, "Data::HashMap::II::clear");
615 22           REGISTER_KW(ii, to_hash, "Data::HashMap::II::to_hash");
616 22           REGISTER_KW(ii, put_ttl, "Data::HashMap::II::put_ttl");
617 22           REGISTER_KW(ii, get_or_set, "Data::HashMap::II::get_or_set");
618 22           REGISTER_KW(is, put, "Data::HashMap::IS::put");
619 22           REGISTER_KW(is, get, "Data::HashMap::IS::get");
620 22           REGISTER_KW(is, remove, "Data::HashMap::IS::remove");
621 22           REGISTER_KW(is, exists, "Data::HashMap::IS::exists");
622 22           REGISTER_KW(is, size, "Data::HashMap::IS::size");
623 22           REGISTER_KW(is, keys, "Data::HashMap::IS::keys");
624 22           REGISTER_KW(is, values, "Data::HashMap::IS::values");
625 22           REGISTER_KW(is, items, "Data::HashMap::IS::items");
626 22           REGISTER_KW(is, max_size, "Data::HashMap::IS::max_size");
627 22           REGISTER_KW(is, ttl, "Data::HashMap::IS::ttl");
628 22           REGISTER_KW(is, each, "Data::HashMap::IS::each");
629 22           REGISTER_KW(is, iter_reset, "Data::HashMap::IS::iter_reset");
630 22           REGISTER_KW(is, clear, "Data::HashMap::IS::clear");
631 22           REGISTER_KW(is, to_hash, "Data::HashMap::IS::to_hash");
632 22           REGISTER_KW(is, put_ttl, "Data::HashMap::IS::put_ttl");
633 22           REGISTER_KW(is, get_or_set, "Data::HashMap::IS::get_or_set");
634 22           REGISTER_KW(is, get_direct, "Data::HashMap::IS::get_direct");
635 22           REGISTER_KW(si, put, "Data::HashMap::SI::put");
636 22           REGISTER_KW(si, get, "Data::HashMap::SI::get");
637 22           REGISTER_KW(si, remove, "Data::HashMap::SI::remove");
638 22           REGISTER_KW(si, exists, "Data::HashMap::SI::exists");
639 22           REGISTER_KW(si, incr, "Data::HashMap::SI::incr");
640 22           REGISTER_KW(si, decr, "Data::HashMap::SI::decr");
641 22           REGISTER_KW(si, incr_by, "Data::HashMap::SI::incr_by");
642 22           REGISTER_KW(si, size, "Data::HashMap::SI::size");
643 22           REGISTER_KW(si, keys, "Data::HashMap::SI::keys");
644 22           REGISTER_KW(si, values, "Data::HashMap::SI::values");
645 22           REGISTER_KW(si, items, "Data::HashMap::SI::items");
646 22           REGISTER_KW(si, max_size, "Data::HashMap::SI::max_size");
647 22           REGISTER_KW(si, ttl, "Data::HashMap::SI::ttl");
648 22           REGISTER_KW(si, each, "Data::HashMap::SI::each");
649 22           REGISTER_KW(si, iter_reset, "Data::HashMap::SI::iter_reset");
650 22           REGISTER_KW(si, clear, "Data::HashMap::SI::clear");
651 22           REGISTER_KW(si, to_hash, "Data::HashMap::SI::to_hash");
652 22           REGISTER_KW(si, put_ttl, "Data::HashMap::SI::put_ttl");
653 22           REGISTER_KW(si, get_or_set, "Data::HashMap::SI::get_or_set");
654 22           REGISTER_KW(ss, put, "Data::HashMap::SS::put");
655 22           REGISTER_KW(ss, get, "Data::HashMap::SS::get");
656 22           REGISTER_KW(ss, remove, "Data::HashMap::SS::remove");
657 22           REGISTER_KW(ss, exists, "Data::HashMap::SS::exists");
658 22           REGISTER_KW(ss, size, "Data::HashMap::SS::size");
659 22           REGISTER_KW(ss, keys, "Data::HashMap::SS::keys");
660 22           REGISTER_KW(ss, values, "Data::HashMap::SS::values");
661 22           REGISTER_KW(ss, items, "Data::HashMap::SS::items");
662 22           REGISTER_KW(ss, max_size, "Data::HashMap::SS::max_size");
663 22           REGISTER_KW(ss, ttl, "Data::HashMap::SS::ttl");
664 22           REGISTER_KW(ss, each, "Data::HashMap::SS::each");
665 22           REGISTER_KW(ss, iter_reset, "Data::HashMap::SS::iter_reset");
666 22           REGISTER_KW(ss, clear, "Data::HashMap::SS::clear");
667 22           REGISTER_KW(ss, to_hash, "Data::HashMap::SS::to_hash");
668 22           REGISTER_KW(ss, put_ttl, "Data::HashMap::SS::put_ttl");
669 22           REGISTER_KW(ss, get_or_set, "Data::HashMap::SS::get_or_set");
670 22           REGISTER_KW(ss, get_direct, "Data::HashMap::SS::get_direct");
671 22           REGISTER_KW(i32s, put, "Data::HashMap::I32S::put");
672 22           REGISTER_KW(i32s, get, "Data::HashMap::I32S::get");
673 22           REGISTER_KW(i32s, remove, "Data::HashMap::I32S::remove");
674 22           REGISTER_KW(i32s, exists, "Data::HashMap::I32S::exists");
675 22           REGISTER_KW(i32s, size, "Data::HashMap::I32S::size");
676 22           REGISTER_KW(i32s, keys, "Data::HashMap::I32S::keys");
677 22           REGISTER_KW(i32s, values, "Data::HashMap::I32S::values");
678 22           REGISTER_KW(i32s, items, "Data::HashMap::I32S::items");
679 22           REGISTER_KW(i32s, max_size, "Data::HashMap::I32S::max_size");
680 22           REGISTER_KW(i32s, ttl, "Data::HashMap::I32S::ttl");
681 22           REGISTER_KW(i32s, each, "Data::HashMap::I32S::each");
682 22           REGISTER_KW(i32s, iter_reset, "Data::HashMap::I32S::iter_reset");
683 22           REGISTER_KW(i32s, clear, "Data::HashMap::I32S::clear");
684 22           REGISTER_KW(i32s, to_hash, "Data::HashMap::I32S::to_hash");
685 22           REGISTER_KW(i32s, put_ttl, "Data::HashMap::I32S::put_ttl");
686 22           REGISTER_KW(i32s, get_or_set, "Data::HashMap::I32S::get_or_set");
687 22           REGISTER_KW(i32s, get_direct, "Data::HashMap::I32S::get_direct");
688 22           REGISTER_KW(si32, put, "Data::HashMap::SI32::put");
689 22           REGISTER_KW(si32, get, "Data::HashMap::SI32::get");
690 22           REGISTER_KW(si32, remove, "Data::HashMap::SI32::remove");
691 22           REGISTER_KW(si32, exists, "Data::HashMap::SI32::exists");
692 22           REGISTER_KW(si32, incr, "Data::HashMap::SI32::incr");
693 22           REGISTER_KW(si32, decr, "Data::HashMap::SI32::decr");
694 22           REGISTER_KW(si32, incr_by, "Data::HashMap::SI32::incr_by");
695 22           REGISTER_KW(si32, size, "Data::HashMap::SI32::size");
696 22           REGISTER_KW(si32, keys, "Data::HashMap::SI32::keys");
697 22           REGISTER_KW(si32, values, "Data::HashMap::SI32::values");
698 22           REGISTER_KW(si32, items, "Data::HashMap::SI32::items");
699 22           REGISTER_KW(si32, max_size, "Data::HashMap::SI32::max_size");
700 22           REGISTER_KW(si32, ttl, "Data::HashMap::SI32::ttl");
701 22           REGISTER_KW(si32, each, "Data::HashMap::SI32::each");
702 22           REGISTER_KW(si32, iter_reset, "Data::HashMap::SI32::iter_reset");
703 22           REGISTER_KW(si32, clear, "Data::HashMap::SI32::clear");
704 22           REGISTER_KW(si32, to_hash, "Data::HashMap::SI32::to_hash");
705 22           REGISTER_KW(si32, put_ttl, "Data::HashMap::SI32::put_ttl");
706 22           REGISTER_KW(si32, get_or_set, "Data::HashMap::SI32::get_or_set");
707 22           REGISTER_KW(i32a, put, "Data::HashMap::I32A::put");
708 22           REGISTER_KW(i32a, get, "Data::HashMap::I32A::get");
709 22           REGISTER_KW(i32a, remove, "Data::HashMap::I32A::remove");
710 22           REGISTER_KW(i32a, exists, "Data::HashMap::I32A::exists");
711 22           REGISTER_KW(i32a, size, "Data::HashMap::I32A::size");
712 22           REGISTER_KW(i32a, keys, "Data::HashMap::I32A::keys");
713 22           REGISTER_KW(i32a, values, "Data::HashMap::I32A::values");
714 22           REGISTER_KW(i32a, items, "Data::HashMap::I32A::items");
715 22           REGISTER_KW(i32a, max_size, "Data::HashMap::I32A::max_size");
716 22           REGISTER_KW(i32a, ttl, "Data::HashMap::I32A::ttl");
717 22           REGISTER_KW(i32a, each, "Data::HashMap::I32A::each");
718 22           REGISTER_KW(i32a, iter_reset, "Data::HashMap::I32A::iter_reset");
719 22           REGISTER_KW(i32a, clear, "Data::HashMap::I32A::clear");
720 22           REGISTER_KW(i32a, to_hash, "Data::HashMap::I32A::to_hash");
721 22           REGISTER_KW(i32a, put_ttl, "Data::HashMap::I32A::put_ttl");
722 22           REGISTER_KW(i32a, get_or_set, "Data::HashMap::I32A::get_or_set");
723 22           REGISTER_KW(i16a, put, "Data::HashMap::I16A::put");
724 22           REGISTER_KW(i16a, get, "Data::HashMap::I16A::get");
725 22           REGISTER_KW(i16a, remove, "Data::HashMap::I16A::remove");
726 22           REGISTER_KW(i16a, exists, "Data::HashMap::I16A::exists");
727 22           REGISTER_KW(i16a, size, "Data::HashMap::I16A::size");
728 22           REGISTER_KW(i16a, keys, "Data::HashMap::I16A::keys");
729 22           REGISTER_KW(i16a, values, "Data::HashMap::I16A::values");
730 22           REGISTER_KW(i16a, items, "Data::HashMap::I16A::items");
731 22           REGISTER_KW(i16a, max_size, "Data::HashMap::I16A::max_size");
732 22           REGISTER_KW(i16a, ttl, "Data::HashMap::I16A::ttl");
733 22           REGISTER_KW(i16a, each, "Data::HashMap::I16A::each");
734 22           REGISTER_KW(i16a, iter_reset, "Data::HashMap::I16A::iter_reset");
735 22           REGISTER_KW(i16a, clear, "Data::HashMap::I16A::clear");
736 22           REGISTER_KW(i16a, to_hash, "Data::HashMap::I16A::to_hash");
737 22           REGISTER_KW(i16a, put_ttl, "Data::HashMap::I16A::put_ttl");
738 22           REGISTER_KW(i16a, get_or_set, "Data::HashMap::I16A::get_or_set");
739 22           REGISTER_KW(ia, put, "Data::HashMap::IA::put");
740 22           REGISTER_KW(ia, get, "Data::HashMap::IA::get");
741 22           REGISTER_KW(ia, remove, "Data::HashMap::IA::remove");
742 22           REGISTER_KW(ia, exists, "Data::HashMap::IA::exists");
743 22           REGISTER_KW(ia, size, "Data::HashMap::IA::size");
744 22           REGISTER_KW(ia, keys, "Data::HashMap::IA::keys");
745 22           REGISTER_KW(ia, values, "Data::HashMap::IA::values");
746 22           REGISTER_KW(ia, items, "Data::HashMap::IA::items");
747 22           REGISTER_KW(ia, max_size, "Data::HashMap::IA::max_size");
748 22           REGISTER_KW(ia, ttl, "Data::HashMap::IA::ttl");
749 22           REGISTER_KW(ia, each, "Data::HashMap::IA::each");
750 22           REGISTER_KW(ia, iter_reset, "Data::HashMap::IA::iter_reset");
751 22           REGISTER_KW(ia, clear, "Data::HashMap::IA::clear");
752 22           REGISTER_KW(ia, to_hash, "Data::HashMap::IA::to_hash");
753 22           REGISTER_KW(ia, put_ttl, "Data::HashMap::IA::put_ttl");
754 22           REGISTER_KW(ia, get_or_set, "Data::HashMap::IA::get_or_set");
755 22           REGISTER_KW(sa, put, "Data::HashMap::SA::put");
756 22           REGISTER_KW(sa, get, "Data::HashMap::SA::get");
757 22           REGISTER_KW(sa, remove, "Data::HashMap::SA::remove");
758 22           REGISTER_KW(sa, exists, "Data::HashMap::SA::exists");
759 22           REGISTER_KW(sa, size, "Data::HashMap::SA::size");
760 22           REGISTER_KW(sa, keys, "Data::HashMap::SA::keys");
761 22           REGISTER_KW(sa, values, "Data::HashMap::SA::values");
762 22           REGISTER_KW(sa, items, "Data::HashMap::SA::items");
763 22           REGISTER_KW(sa, max_size, "Data::HashMap::SA::max_size");
764 22           REGISTER_KW(sa, ttl, "Data::HashMap::SA::ttl");
765 22           REGISTER_KW(sa, each, "Data::HashMap::SA::each");
766 22           REGISTER_KW(sa, iter_reset, "Data::HashMap::SA::iter_reset");
767 22           REGISTER_KW(sa, clear, "Data::HashMap::SA::clear");
768 22           REGISTER_KW(sa, to_hash, "Data::HashMap::SA::to_hash");
769 22           REGISTER_KW(sa, put_ttl, "Data::HashMap::SA::put_ttl");
770 22           REGISTER_KW(sa, get_or_set, "Data::HashMap::SA::get_or_set");
771              
772             SV*
773             new(char* class, ...)
774             CODE:
775 21 100         EXTRACT_NEW_ARGS(_max_size, _ttl);
    50          
776 21           HashMapI32* map = hashmap_i32_create(_max_size, _ttl);
777 21 50         if (!map) croak("Failed to create HashMap::I32");
778 21           RETVAL = sv_setref_pv(newSV(0), class, (void*)map);
779             OUTPUT:
780             RETVAL
781              
782             void
783             DESTROY(SV* self_sv)
784             CODE:
785 21 50         EXTRACT_MAP(HashMapI32, stash_i32, "Data::HashMap::I32", self_sv);
    50          
    50          
    50          
786 21           hashmap_i32_destroy(self);
787 21           sv_setiv(SvRV(self_sv), 0);
788              
789             bool
790             put(SV* self_sv, int32_t key, int32_t value)
791             CODE:
792 150225 50         EXTRACT_MAP(HashMapI32, stash_i32, "Data::HashMap::I32", self_sv);
    50          
    50          
    50          
793 150225           RETVAL = hashmap_i32_put(self, key, value, 0);
794             OUTPUT:
795             RETVAL
796              
797             SV*
798             get(SV* self_sv, int32_t key)
799             CODE:
800 50010 50         EXTRACT_MAP(HashMapI32, stash_i32, "Data::HashMap::I32", self_sv);
    50          
    50          
    50          
801             int32_t value;
802 50010 100         if (!hashmap_i32_get(self, key, &value)) XSRETURN_UNDEF;
803 50005           RETVAL = newSViv(value);
804             OUTPUT:
805             RETVAL
806              
807             bool
808             remove(SV* self_sv, int32_t key)
809             CODE:
810 150004 50         EXTRACT_MAP(HashMapI32, stash_i32, "Data::HashMap::I32", self_sv);
    50          
    50          
    50          
811 150004           RETVAL = hashmap_i32_remove(self, key);
812             OUTPUT:
813             RETVAL
814              
815             bool
816             exists(SV* self_sv, int32_t key)
817             CODE:
818 3 50         EXTRACT_MAP(HashMapI32, stash_i32, "Data::HashMap::I32", self_sv);
    50          
    50          
    50          
819 3           RETVAL = hashmap_i32_exists(self, key);
820             OUTPUT:
821             RETVAL
822              
823             SV*
824             incr(SV* self_sv, int32_t key)
825             CODE:
826 9 50         EXTRACT_MAP(HashMapI32, stash_i32, "Data::HashMap::I32", self_sv);
    50          
    50          
    50          
827             int32_t val;
828 9 100         if (!hashmap_i32_increment(self, key, &val))
829 2           croak("HashMap::I32: increment failed");
830 7           RETVAL = newSViv(val);
831             OUTPUT:
832             RETVAL
833              
834             SV*
835             decr(SV* self_sv, int32_t key)
836             CODE:
837 9 50         EXTRACT_MAP(HashMapI32, stash_i32, "Data::HashMap::I32", self_sv);
    50          
    50          
    50          
838             int32_t val;
839 9 100         if (!hashmap_i32_decrement(self, key, &val))
840 3           croak("HashMap::I32: decrement failed");
841 6           RETVAL = newSViv(val);
842             OUTPUT:
843             RETVAL
844              
845             SV*
846             incr_by(SV* self_sv, int32_t key, int32_t delta)
847             CODE:
848 9 50         EXTRACT_MAP(HashMapI32, stash_i32, "Data::HashMap::I32", self_sv);
    50          
    50          
    50          
849             int32_t val;
850 9 100         if (!hashmap_i32_increment_by(self, key, delta, &val))
851 2           croak("HashMap::I32: incr_by failed");
852 7           RETVAL = newSViv(val);
853             OUTPUT:
854             RETVAL
855              
856             size_t
857             size(SV* self_sv)
858             CODE:
859 6 50         EXTRACT_MAP(HashMapI32, stash_i32, "Data::HashMap::I32", self_sv);
    50          
    50          
    50          
860 6 50         RETVAL = self->size;
861             OUTPUT:
862             RETVAL
863              
864             size_t
865             max_size(SV* self_sv)
866             CODE:
867 0 0         EXTRACT_MAP(HashMapI32, stash_i32, "Data::HashMap::I32", self_sv);
    0          
    0          
    0          
868 0 0         RETVAL = self->max_size;
869             OUTPUT:
870             RETVAL
871              
872             UV
873             ttl(SV* self_sv)
874             CODE:
875 0 0         EXTRACT_MAP(HashMapI32, stash_i32, "Data::HashMap::I32", self_sv);
    0          
    0          
    0          
876 0 0         RETVAL = (UV)self->default_ttl;
877             OUTPUT:
878             RETVAL
879              
880             void
881             keys(SV* self_sv)
882             PPCODE:
883 2 50         EXTRACT_MAP(HashMapI32, stash_i32, "Data::HashMap::I32", self_sv);
    50          
    50          
    50          
884 2 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
885 2 50         EXTEND(SP, self->size);
886             size_t i;
887 34 100         for (i = 0; i < self->capacity; i++) {
888 32 100         if (I32_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now))
    50          
    50          
    0          
    0          
889 2 50         mXPUSHi(self->nodes[i].key);
890             }
891              
892             void
893             values(SV* self_sv)
894             PPCODE:
895 1 50         EXTRACT_MAP(HashMapI32, stash_i32, "Data::HashMap::I32", self_sv);
    50          
    50          
    50          
896 1 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
897 1 50         EXTEND(SP, self->size);
898             size_t i;
899 17 100         for (i = 0; i < self->capacity; i++) {
900 16 100         if (I32_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now))
    50          
    50          
    0          
    0          
901 2 50         mXPUSHi(self->nodes[i].value);
902             }
903              
904             void
905             items(SV* self_sv)
906             PPCODE:
907 1 50         EXTRACT_MAP(HashMapI32, stash_i32, "Data::HashMap::I32", self_sv);
    50          
    50          
    50          
908 1 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
909 1 50         EXTEND(SP, self->size * 2);
910             size_t i;
911 17 100         for (i = 0; i < self->capacity; i++) {
912 16 100         if (I32_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    50          
    50          
    0          
    0          
913 2 50         mXPUSHi(self->nodes[i].key);
914 2 50         mXPUSHi(self->nodes[i].value);
915             }
916             }
917              
918             void
919             each(SV* self_sv)
920             PPCODE:
921 14 50         EXTRACT_MAP(HashMapI32, stash_i32, "Data::HashMap::I32", self_sv);
    50          
    50          
    50          
922 14 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
923 71 100         while (self->iter_pos < self->capacity) {
924 67           size_t i = self->iter_pos++;
925 67 100         if (I32_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    50          
    50          
    0          
    0          
926 10 50         EXTEND(SP, 2);
927 10 50         mXPUSHi(self->nodes[i].key);
928 10 50         if (GIMME_V == G_SCALAR) XSRETURN(1);
929 10 50         mXPUSHi(self->nodes[i].value);
930 10           XSRETURN(2);
931             }
932             }
933 4           self->iter_pos = 0;
934 4           XSRETURN_EMPTY;
935              
936             void
937             iter_reset(SV* self_sv)
938             CODE:
939 1 50         EXTRACT_MAP(HashMapI32, stash_i32, "Data::HashMap::I32", self_sv);
    50          
    50          
    50          
940 1           self->iter_pos = 0;
941              
942             void
943             clear(SV* self_sv)
944             CODE:
945 3 50         EXTRACT_MAP(HashMapI32, stash_i32, "Data::HashMap::I32", self_sv);
    50          
    50          
    50          
946 3           hashmap_i32_clear(self);
947              
948             SV*
949             to_hash(SV* self_sv)
950             CODE:
951 1 50         EXTRACT_MAP(HashMapI32, stash_i32, "Data::HashMap::I32", self_sv);
    50          
    50          
    50          
952 1           HV* hv = newHV();
953 1 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
954             size_t i;
955 17 100         for (i = 0; i < self->capacity; i++) {
956 16 100         if (I32_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    50          
    50          
    0          
    0          
957 1           SV* val = newSViv(self->nodes[i].value);
958             char kbuf[24];
959 1           int klen = my_snprintf(kbuf, sizeof(kbuf), "%" IVdf, (IV)self->nodes[i].key);
960 1           (void)hv_store(hv, kbuf, klen, val, 0);
961             }
962             }
963 1           RETVAL = newRV_noinc((SV*)hv);
964             OUTPUT:
965             RETVAL
966              
967             bool
968             put_ttl(SV* self_sv, int32_t key, int32_t value, UV ttl)
969             CODE:
970 1 50         EXTRACT_MAP(HashMapI32, stash_i32, "Data::HashMap::I32", self_sv);
    50          
    50          
    50          
971 1           RETVAL = hashmap_i32_put(self, key, value, (uint32_t)ttl);
972             OUTPUT:
973             RETVAL
974              
975             SV*
976             get_or_set(SV* self_sv, int32_t key, int32_t default_value)
977             CODE:
978 3 50         EXTRACT_MAP(HashMapI32, stash_i32, "Data::HashMap::I32", self_sv);
    50          
    50          
    50          
979             bool was_found;
980 3           size_t idx = hashmap_i32_get_or_set(self, key, default_value, 0, &was_found);
981             (void)was_found;
982 3 100         if (idx >= self->capacity) XSRETURN_UNDEF;
983 2           RETVAL = newSViv(self->nodes[idx].value);
984             OUTPUT:
985             RETVAL
986              
987              
988              
989             MODULE = Data::HashMap PACKAGE = Data::HashMap::II
990             PROTOTYPES: DISABLE
991              
992             SV*
993             new(char* class, ...)
994             CODE:
995 74 100         EXTRACT_NEW_ARGS(_max_size, _ttl);
    100          
996 74           HashMapII* map = hashmap_ii_create(_max_size, _ttl);
997 74 50         if (!map) croak("Failed to create HashMap::II");
998 74           RETVAL = sv_setref_pv(newSV(0), class, (void*)map);
999             OUTPUT:
1000             RETVAL
1001              
1002             void
1003             DESTROY(SV* self_sv)
1004             CODE:
1005 74 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
1006 74           hashmap_ii_destroy(self);
1007 74           sv_setiv(SvRV(self_sv), 0);
1008              
1009             bool
1010             put(SV* self_sv, int64_t key, int64_t value)
1011             CODE:
1012 383157 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
1013 383157           RETVAL = hashmap_ii_put(self, key, value, 0);
1014             OUTPUT:
1015             RETVAL
1016              
1017             SV*
1018             get(SV* self_sv, int64_t key)
1019             CODE:
1020 100164 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
1021             int64_t value;
1022 100164 100         if (!hashmap_ii_get(self, key, &value)) XSRETURN_UNDEF;
1023 100138           RETVAL = newSViv(value);
1024             OUTPUT:
1025             RETVAL
1026              
1027             bool
1028             remove(SV* self_sv, int64_t key)
1029             CODE:
1030 280022 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
1031 280022           RETVAL = hashmap_ii_remove(self, key);
1032             OUTPUT:
1033             RETVAL
1034              
1035             bool
1036             exists(SV* self_sv, int64_t key)
1037             CODE:
1038 10 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
1039 10           RETVAL = hashmap_ii_exists(self, key);
1040             OUTPUT:
1041             RETVAL
1042              
1043             SV*
1044             incr(SV* self_sv, int64_t key)
1045             CODE:
1046 15014 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
1047             int64_t val;
1048 15014 100         if (!hashmap_ii_increment(self, key, &val))
1049 3           croak("HashMap::II: increment failed");
1050 15011           RETVAL = newSViv(val);
1051             OUTPUT:
1052             RETVAL
1053              
1054             SV*
1055             decr(SV* self_sv, int64_t key)
1056             CODE:
1057 5006 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
1058             int64_t val;
1059 5006 100         if (!hashmap_ii_decrement(self, key, &val))
1060 2           croak("HashMap::II: decrement failed");
1061 5004           RETVAL = newSViv(val);
1062             OUTPUT:
1063             RETVAL
1064              
1065             SV*
1066             incr_by(SV* self_sv, int64_t key, int64_t delta)
1067             CODE:
1068 8 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
1069             int64_t val;
1070 8 100         if (!hashmap_ii_increment_by(self, key, delta, &val))
1071 2           croak("HashMap::II: incr_by failed");
1072 6           RETVAL = newSViv(val);
1073             OUTPUT:
1074             RETVAL
1075              
1076             size_t
1077             size(SV* self_sv)
1078             CODE:
1079 33 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
1080 33 50         RETVAL = self->size;
1081             OUTPUT:
1082             RETVAL
1083              
1084             size_t
1085             max_size(SV* self_sv)
1086             CODE:
1087 4 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
1088 4 50         RETVAL = self->max_size;
1089             OUTPUT:
1090             RETVAL
1091              
1092             UV
1093             ttl(SV* self_sv)
1094             CODE:
1095 5 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
1096 5 50         RETVAL = (UV)self->default_ttl;
1097             OUTPUT:
1098             RETVAL
1099              
1100             void
1101             keys(SV* self_sv)
1102             PPCODE:
1103 9 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
1104 9 100         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
1105 9 50         EXTEND(SP, self->size);
1106             size_t i;
1107 649 100         for (i = 0; i < self->capacity; i++) {
1108 640 100         if (II_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now))
    100          
    100          
    50          
    100          
1109 221 50         mXPUSHi(self->nodes[i].key);
1110             }
1111              
1112             void
1113             values(SV* self_sv)
1114             PPCODE:
1115 5 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
1116 5 100         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
1117 5 50         EXTEND(SP, self->size);
1118             size_t i;
1119 565 100         for (i = 0; i < self->capacity; i++) {
1120 560 100         if (II_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now))
    100          
    100          
    50          
    50          
1121 203 50         mXPUSHi(self->nodes[i].value);
1122             }
1123              
1124             void
1125             items(SV* self_sv)
1126             PPCODE:
1127 5 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
1128 5 100         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
1129 5 50         EXTEND(SP, self->size * 2);
1130             size_t i;
1131 565 100         for (i = 0; i < self->capacity; i++) {
1132 560 100         if (II_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    100          
    100          
    50          
    50          
1133 203 50         mXPUSHi(self->nodes[i].key);
1134 203 50         mXPUSHi(self->nodes[i].value);
1135             }
1136             }
1137              
1138             void
1139             each(SV* self_sv)
1140             PPCODE:
1141 31 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
1142 31 100         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
1143 180 100         while (self->iter_pos < self->capacity) {
1144 174           size_t i = self->iter_pos++;
1145 174 100         if (II_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    100          
    100          
    50          
    100          
1146 25 50         EXTEND(SP, 2);
1147 25 50         mXPUSHi(self->nodes[i].key);
1148 25 100         if (GIMME_V == G_SCALAR) XSRETURN(1);
1149 24 50         mXPUSHi(self->nodes[i].value);
1150 24           XSRETURN(2);
1151             }
1152             }
1153 6           self->iter_pos = 0;
1154 6           XSRETURN_EMPTY;
1155              
1156             void
1157             iter_reset(SV* self_sv)
1158             CODE:
1159 1 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
1160 1           self->iter_pos = 0;
1161              
1162             void
1163             clear(SV* self_sv)
1164             CODE:
1165 8 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
1166 8           hashmap_ii_clear(self);
1167              
1168             SV*
1169             to_hash(SV* self_sv)
1170             CODE:
1171 4 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
1172 4           HV* hv = newHV();
1173 4 100         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
1174             size_t i;
1175 68 100         for (i = 0; i < self->capacity; i++) {
1176 64 100         if (II_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    50          
    100          
    100          
    50          
1177 3           SV* val = newSViv(self->nodes[i].value);
1178             char kbuf[24];
1179 3           int klen = my_snprintf(kbuf, sizeof(kbuf), "%" IVdf, (IV)self->nodes[i].key);
1180 3           (void)hv_store(hv, kbuf, klen, val, 0);
1181             }
1182             }
1183 4           RETVAL = newRV_noinc((SV*)hv);
1184             OUTPUT:
1185             RETVAL
1186              
1187             bool
1188             put_ttl(SV* self_sv, int64_t key, int64_t value, UV ttl)
1189             CODE:
1190 108 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
1191 108           RETVAL = hashmap_ii_put(self, key, value, (uint32_t)ttl);
1192             OUTPUT:
1193             RETVAL
1194              
1195             SV*
1196             get_or_set(SV* self_sv, int64_t key, int64_t default_value)
1197             CODE:
1198 15 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
1199             bool was_found;
1200 15           size_t idx = hashmap_ii_get_or_set(self, key, default_value, 0, &was_found);
1201             (void)was_found;
1202 15 50         if (idx >= self->capacity) XSRETURN_UNDEF;
1203 15           RETVAL = newSViv(self->nodes[idx].value);
1204             OUTPUT:
1205             RETVAL
1206              
1207              
1208              
1209             MODULE = Data::HashMap PACKAGE = Data::HashMap::IS
1210             PROTOTYPES: DISABLE
1211              
1212             SV*
1213             new(char* class, ...)
1214             CODE:
1215 33 100         EXTRACT_NEW_ARGS(_max_size, _ttl);
    100          
1216 33           HashMapIS* map = hashmap_is_create(_max_size, _ttl);
1217 33 50         if (!map) croak("Failed to create HashMap::IS");
1218 33           RETVAL = sv_setref_pv(newSV(0), class, (void*)map);
1219             OUTPUT:
1220             RETVAL
1221              
1222             void
1223             DESTROY(SV* self_sv)
1224             CODE:
1225 33 50         EXTRACT_MAP(HashMapIS, stash_is, "Data::HashMap::IS", self_sv);
    50          
    50          
    50          
1226 33           hashmap_is_destroy(self);
1227 33           sv_setiv(SvRV(self_sv), 0);
1228              
1229             bool
1230             put(SV* self_sv, int64_t key, SV* value)
1231             CODE:
1232 81023 50         EXTRACT_MAP(HashMapIS, stash_is, "Data::HashMap::IS", self_sv);
    50          
    50          
    50          
1233 81023 50         EXTRACT_STR_VAL(value);
1234 81023           RETVAL = hashmap_is_put(self, key, _vstr, (uint32_t)_vlen, _vutf8, 0);
1235             OUTPUT:
1236             RETVAL
1237              
1238             SV*
1239             get(SV* self_sv, int64_t key)
1240             CODE:
1241 50011 50         EXTRACT_MAP(HashMapIS, stash_is, "Data::HashMap::IS", self_sv);
    50          
    50          
    50          
1242             const char* val;
1243             uint32_t val_len;
1244             bool val_utf8;
1245 50011 100         if (!hashmap_is_get(self, key, &val, &val_len, &val_utf8))
1246 3           XSRETURN_UNDEF;
1247 50008           RETVAL = newSVpvn(val, val_len);
1248 50008 100         if (val_utf8) SvUTF8_on(RETVAL);
1249             OUTPUT:
1250             RETVAL
1251              
1252             SV*
1253             get_direct(SV* self_sv, int64_t key)
1254             CODE:
1255 5 50         EXTRACT_MAP(HashMapIS, stash_is, "Data::HashMap::IS", self_sv);
    50          
    50          
    50          
1256             const char* val;
1257             uint32_t val_len;
1258             bool val_utf8;
1259 5 100         if (!hashmap_is_get(self, key, &val, &val_len, &val_utf8))
1260 2           XSRETURN_UNDEF;
1261 3           RETVAL = hm_zerocopy_sv(aTHX_ val, val_len, val_utf8);
1262             OUTPUT:
1263             RETVAL
1264              
1265             bool
1266             remove(SV* self_sv, int64_t key)
1267             CODE:
1268 80106 50         EXTRACT_MAP(HashMapIS, stash_is, "Data::HashMap::IS", self_sv);
    50          
    50          
    50          
1269 80106           RETVAL = hashmap_is_remove(self, key);
1270             OUTPUT:
1271             RETVAL
1272              
1273             bool
1274             exists(SV* self_sv, int64_t key)
1275             CODE:
1276 3 50         EXTRACT_MAP(HashMapIS, stash_is, "Data::HashMap::IS", self_sv);
    50          
    50          
    50          
1277 3           RETVAL = hashmap_is_exists(self, key);
1278             OUTPUT:
1279             RETVAL
1280              
1281             size_t
1282             size(SV* self_sv)
1283             CODE:
1284 5 50         EXTRACT_MAP(HashMapIS, stash_is, "Data::HashMap::IS", self_sv);
    50          
    50          
    50          
1285 5 50         RETVAL = self->size;
1286             OUTPUT:
1287             RETVAL
1288              
1289             size_t
1290             max_size(SV* self_sv)
1291             CODE:
1292 0 0         EXTRACT_MAP(HashMapIS, stash_is, "Data::HashMap::IS", self_sv);
    0          
    0          
    0          
1293 0 0         RETVAL = self->max_size;
1294             OUTPUT:
1295             RETVAL
1296              
1297             UV
1298             ttl(SV* self_sv)
1299             CODE:
1300 0 0         EXTRACT_MAP(HashMapIS, stash_is, "Data::HashMap::IS", self_sv);
    0          
    0          
    0          
1301 0 0         RETVAL = (UV)self->default_ttl;
1302             OUTPUT:
1303             RETVAL
1304              
1305             void
1306             keys(SV* self_sv)
1307             PPCODE:
1308 4 50         EXTRACT_MAP(HashMapIS, stash_is, "Data::HashMap::IS", self_sv);
    50          
    50          
    50          
1309 4 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
1310 4 50         EXTEND(SP, self->size);
1311             size_t i;
1312 548 100         for (i = 0; i < self->capacity; i++) {
1313 544 100         if (IS_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now))
    100          
    50          
    0          
    0          
1314 200 50         mXPUSHi(self->nodes[i].key);
1315             }
1316              
1317             void
1318             values(SV* self_sv)
1319             PPCODE:
1320 3 50         EXTRACT_MAP(HashMapIS, stash_is, "Data::HashMap::IS", self_sv);
    50          
    50          
    50          
1321 3 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
1322 3 50         EXTEND(SP, self->size);
1323             size_t i;
1324 531 100         for (i = 0; i < self->capacity; i++) {
1325 528 100         if (IS_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    100          
    50          
    0          
    0          
1326 200 50         if (self->nodes[i].value) {
1327 200           SV* sv = newSVpvn(self->nodes[i].value,
1328             HM_UNPACK_LEN(self->nodes[i].val_len));
1329 200 50         if (HM_UNPACK_UTF8(self->nodes[i].val_len)) SvUTF8_on(sv);
1330 200 50         mXPUSHs(sv);
1331             } else {
1332 0 0         XPUSHs(&PL_sv_undef);
1333             }
1334             }
1335             }
1336              
1337             void
1338             items(SV* self_sv)
1339             PPCODE:
1340 1 50         EXTRACT_MAP(HashMapIS, stash_is, "Data::HashMap::IS", self_sv);
    50          
    50          
    50          
1341 1 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
1342 1 50         EXTEND(SP, self->size * 2);
1343             size_t i;
1344 17 100         for (i = 0; i < self->capacity; i++) {
1345 16 100         if (IS_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    50          
    50          
    0          
    0          
1346 2 50         mXPUSHi(self->nodes[i].key);
1347 2 50         if (self->nodes[i].value) {
1348 2           SV* sv = newSVpvn(self->nodes[i].value,
1349             HM_UNPACK_LEN(self->nodes[i].val_len));
1350 2 50         if (HM_UNPACK_UTF8(self->nodes[i].val_len)) SvUTF8_on(sv);
1351 2 50         mXPUSHs(sv);
1352             } else {
1353 0 0         XPUSHs(&PL_sv_undef);
1354             }
1355             }
1356             }
1357              
1358             void
1359             each(SV* self_sv)
1360             PPCODE:
1361 3 50         EXTRACT_MAP(HashMapIS, stash_is, "Data::HashMap::IS", self_sv);
    50          
    50          
    50          
1362 3 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
1363 17 100         while (self->iter_pos < self->capacity) {
1364 16           size_t i = self->iter_pos++;
1365 16 100         if (IS_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    50          
    50          
    0          
    0          
1366 2 50         EXTEND(SP, 2);
1367 2 50         mXPUSHi(self->nodes[i].key);
1368 2 50         if (GIMME_V == G_SCALAR) XSRETURN(1);
1369 2 50         if (self->nodes[i].value) {
1370 2           SV* vsv = newSVpvn(self->nodes[i].value,
1371             HM_UNPACK_LEN(self->nodes[i].val_len));
1372 2 50         if (HM_UNPACK_UTF8(self->nodes[i].val_len)) SvUTF8_on(vsv);
1373 2 50         mXPUSHs(vsv);
1374             } else {
1375 0 0         XPUSHs(&PL_sv_undef);
1376             }
1377 2           XSRETURN(2);
1378             }
1379             }
1380 1           self->iter_pos = 0;
1381 1           XSRETURN_EMPTY;
1382              
1383             void
1384             iter_reset(SV* self_sv)
1385             CODE:
1386 0 0         EXTRACT_MAP(HashMapIS, stash_is, "Data::HashMap::IS", self_sv);
    0          
    0          
    0          
1387 0           self->iter_pos = 0;
1388              
1389             void
1390             clear(SV* self_sv)
1391             CODE:
1392 2 50         EXTRACT_MAP(HashMapIS, stash_is, "Data::HashMap::IS", self_sv);
    50          
    50          
    50          
1393 2           hashmap_is_clear(self);
1394              
1395             SV*
1396             to_hash(SV* self_sv)
1397             CODE:
1398 3 50         EXTRACT_MAP(HashMapIS, stash_is, "Data::HashMap::IS", self_sv);
    50          
    50          
    50          
1399 3           HV* hv = newHV();
1400 3 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
1401             size_t i;
1402 531 100         for (i = 0; i < self->capacity; i++) {
1403 528 100         if (IS_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    100          
    50          
    0          
    0          
1404 199           uint32_t vlen = HM_UNPACK_LEN(self->nodes[i].val_len);
1405 199           bool vutf8 = HM_UNPACK_UTF8(self->nodes[i].val_len);
1406 398           SV* val = self->nodes[i].value
1407 199           ? newSVpvn(self->nodes[i].value, vlen)
1408 199 50         : newSV(0);
1409 199 50         if (self->nodes[i].value && vutf8) SvUTF8_on(val);
    50          
1410             char kbuf[24];
1411 199           int klen = my_snprintf(kbuf, sizeof(kbuf), "%" IVdf, (IV)self->nodes[i].key);
1412 199           (void)hv_store(hv, kbuf, klen, val, 0);
1413             }
1414             }
1415 3           RETVAL = newRV_noinc((SV*)hv);
1416             OUTPUT:
1417             RETVAL
1418              
1419             bool
1420             put_ttl(SV* self_sv, int64_t key, SV* value, UV ttl)
1421             CODE:
1422 0 0         EXTRACT_MAP(HashMapIS, stash_is, "Data::HashMap::IS", self_sv);
    0          
    0          
    0          
1423 0 0         EXTRACT_STR_VAL(value);
1424 0           RETVAL = hashmap_is_put(self, key, _vstr, (uint32_t)_vlen, _vutf8, (uint32_t)ttl);
1425             OUTPUT:
1426             RETVAL
1427              
1428             SV*
1429             get_or_set(SV* self_sv, int64_t key, SV* default_sv)
1430             CODE:
1431 9 50         EXTRACT_MAP(HashMapIS, stash_is, "Data::HashMap::IS", self_sv);
    50          
    50          
    50          
1432 9 50         EXTRACT_STR_VAL(default_sv);
1433             bool was_found;
1434 9           size_t idx = hashmap_is_get_or_set(self, key, _vstr, (uint32_t)_vlen, _vutf8, 0, &was_found);
1435             (void)was_found;
1436 9 50         if (idx >= self->capacity) XSRETURN_UNDEF;
1437 9 50         if (self->nodes[idx].value) {
1438 9           RETVAL = newSVpvn(self->nodes[idx].value, HM_UNPACK_LEN(self->nodes[idx].val_len));
1439 9 50         if (HM_UNPACK_UTF8(self->nodes[idx].val_len)) SvUTF8_on(RETVAL);
1440             } else {
1441 0           RETVAL = newSV(0);
1442             }
1443             OUTPUT:
1444             RETVAL
1445              
1446              
1447              
1448             MODULE = Data::HashMap PACKAGE = Data::HashMap::SI
1449             PROTOTYPES: DISABLE
1450              
1451             SV*
1452             new(char* class, ...)
1453             CODE:
1454 25 100         EXTRACT_NEW_ARGS(_max_size, _ttl);
    100          
1455 25           HashMapSI* map = hashmap_si_create(_max_size, _ttl);
1456 25 50         if (!map) croak("Failed to create HashMap::SI");
1457 25           RETVAL = sv_setref_pv(newSV(0), class, (void*)map);
1458             OUTPUT:
1459             RETVAL
1460              
1461             void
1462             DESTROY(SV* self_sv)
1463             CODE:
1464 25 50         EXTRACT_MAP(HashMapSI, stash_si, "Data::HashMap::SI", self_sv);
    50          
    50          
    50          
1465 25           hashmap_si_destroy(self);
1466 25           sv_setiv(SvRV(self_sv), 0);
1467              
1468             bool
1469             put(SV* self_sv, SV* key_sv, int64_t value)
1470             CODE:
1471 80226 50         EXTRACT_MAP(HashMapSI, stash_si, "Data::HashMap::SI", self_sv);
    50          
    50          
    50          
1472 80226 50         EXTRACT_STR_KEY(key_sv);
1473 80226           RETVAL = hashmap_si_put(self, _kstr, (uint32_t)_klen, _khash, _kutf8, value, 0);
1474             OUTPUT:
1475             RETVAL
1476              
1477             SV*
1478             get(SV* self_sv, SV* key_sv)
1479             CODE:
1480 50016 50         EXTRACT_MAP(HashMapSI, stash_si, "Data::HashMap::SI", self_sv);
    50          
    50          
    50          
1481 50016 50         EXTRACT_STR_KEY(key_sv);
1482             int64_t value;
1483 50016 100         if (!hashmap_si_get(self, _kstr, (uint32_t)_klen, _khash, _kutf8, &value))
1484 3           XSRETURN_UNDEF;
1485 50013           RETVAL = newSViv(value);
1486             OUTPUT:
1487             RETVAL
1488              
1489             bool
1490             remove(SV* self_sv, SV* key_sv)
1491             CODE:
1492 80006 50         EXTRACT_MAP(HashMapSI, stash_si, "Data::HashMap::SI", self_sv);
    50          
    50          
    50          
1493 80006 50         EXTRACT_STR_KEY(key_sv);
1494 80006           RETVAL = hashmap_si_remove(self, _kstr, (uint32_t)_klen, _khash, _kutf8);
1495             OUTPUT:
1496             RETVAL
1497              
1498             bool
1499             exists(SV* self_sv, SV* key_sv)
1500             CODE:
1501 2 50         EXTRACT_MAP(HashMapSI, stash_si, "Data::HashMap::SI", self_sv);
    50          
    50          
    50          
1502 2 50         EXTRACT_STR_KEY(key_sv);
1503 2           RETVAL = hashmap_si_exists(self, _kstr, (uint32_t)_klen, _khash, _kutf8);
1504             OUTPUT:
1505             RETVAL
1506              
1507             SV*
1508             incr(SV* self_sv, SV* key_sv)
1509             CODE:
1510 15015 50         EXTRACT_MAP(HashMapSI, stash_si, "Data::HashMap::SI", self_sv);
    50          
    50          
    50          
1511 15015 50         EXTRACT_STR_KEY(key_sv);
1512             int64_t val;
1513 15015 100         if (!hashmap_si_increment(self, _kstr, (uint32_t)_klen, _khash, _kutf8, &val))
1514 1           croak("HashMap::SI: increment failed");
1515 15014           RETVAL = newSViv(val);
1516             OUTPUT:
1517             RETVAL
1518              
1519             SV*
1520             decr(SV* self_sv, SV* key_sv)
1521             CODE:
1522 5006 50         EXTRACT_MAP(HashMapSI, stash_si, "Data::HashMap::SI", self_sv);
    50          
    50          
    50          
1523 5006 50         EXTRACT_STR_KEY(key_sv);
1524             int64_t val;
1525 5006 100         if (!hashmap_si_decrement(self, _kstr, (uint32_t)_klen, _khash, _kutf8, &val))
1526 2           croak("HashMap::SI: decrement failed");
1527 5004           RETVAL = newSViv(val);
1528             OUTPUT:
1529             RETVAL
1530              
1531             SV*
1532             incr_by(SV* self_sv, SV* key_sv, int64_t delta)
1533             CODE:
1534 6 50         EXTRACT_MAP(HashMapSI, stash_si, "Data::HashMap::SI", self_sv);
    50          
    50          
    50          
1535 6 50         EXTRACT_STR_KEY(key_sv);
1536             int64_t val;
1537 6 100         if (!hashmap_si_increment_by(self, _kstr, (uint32_t)_klen, _khash, _kutf8, delta, &val))
1538 2           croak("HashMap::SI: incr_by failed");
1539 4           RETVAL = newSViv(val);
1540             OUTPUT:
1541             RETVAL
1542              
1543             size_t
1544             size(SV* self_sv)
1545             CODE:
1546 5 50         EXTRACT_MAP(HashMapSI, stash_si, "Data::HashMap::SI", self_sv);
    50          
    50          
    50          
1547 5 50         RETVAL = self->size;
1548             OUTPUT:
1549             RETVAL
1550              
1551             size_t
1552             max_size(SV* self_sv)
1553             CODE:
1554 0 0         EXTRACT_MAP(HashMapSI, stash_si, "Data::HashMap::SI", self_sv);
    0          
    0          
    0          
1555 0 0         RETVAL = self->max_size;
1556             OUTPUT:
1557             RETVAL
1558              
1559             UV
1560             ttl(SV* self_sv)
1561             CODE:
1562 0 0         EXTRACT_MAP(HashMapSI, stash_si, "Data::HashMap::SI", self_sv);
    0          
    0          
    0          
1563 0 0         RETVAL = (UV)self->default_ttl;
1564             OUTPUT:
1565             RETVAL
1566              
1567             void
1568             keys(SV* self_sv)
1569             PPCODE:
1570 3 50         EXTRACT_MAP(HashMapSI, stash_si, "Data::HashMap::SI", self_sv);
    50          
    50          
    50          
1571 3 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
1572 3 50         EXTEND(SP, self->size);
1573             size_t i;
1574 51 100         for (i = 0; i < self->capacity; i++) {
1575 48 100         if (SI_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    100          
    50          
    0          
    0          
1576 7           uint32_t klen = HM_UNPACK_LEN(self->nodes[i].key_len);
1577 7           SV* sv = newSVpvn(self->nodes[i].key, klen);
1578 7 100         if (HM_UNPACK_UTF8(self->nodes[i].key_len)) SvUTF8_on(sv);
1579 7 50         mXPUSHs(sv);
1580             }
1581             }
1582              
1583             void
1584             values(SV* self_sv)
1585             PPCODE:
1586 1 50         EXTRACT_MAP(HashMapSI, stash_si, "Data::HashMap::SI", self_sv);
    50          
    50          
    50          
1587 1 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
1588 1 50         EXTEND(SP, self->size);
1589             size_t i;
1590 17 100         for (i = 0; i < self->capacity; i++) {
1591 16 100         if (SI_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now))
    50          
    50          
    0          
    0          
1592 2 50         mXPUSHi(self->nodes[i].value);
1593             }
1594              
1595             void
1596             items(SV* self_sv)
1597             PPCODE:
1598 2 50         EXTRACT_MAP(HashMapSI, stash_si, "Data::HashMap::SI", self_sv);
    50          
    50          
    50          
1599 2 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
1600 2 50         EXTEND(SP, self->size * 2);
1601             size_t i;
1602 34 100         for (i = 0; i < self->capacity; i++) {
1603 32 100         if (SI_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    100          
    50          
    0          
    0          
1604 7           uint32_t klen = HM_UNPACK_LEN(self->nodes[i].key_len);
1605 7           SV* sv = newSVpvn(self->nodes[i].key, klen);
1606 7 100         if (HM_UNPACK_UTF8(self->nodes[i].key_len)) SvUTF8_on(sv);
1607 7 50         mXPUSHs(sv);
1608 7 50         mXPUSHi(self->nodes[i].value);
1609             }
1610             }
1611              
1612             void
1613             each(SV* self_sv)
1614             PPCODE:
1615 4 50         EXTRACT_MAP(HashMapSI, stash_si, "Data::HashMap::SI", self_sv);
    50          
    50          
    50          
1616 4 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
1617 19 100         while (self->iter_pos < self->capacity) {
1618 18           size_t i = self->iter_pos++;
1619 18 100         if (SI_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    50          
    50          
    0          
    0          
1620 3 50         EXTEND(SP, 2);
1621             {
1622 3           uint32_t klen = HM_UNPACK_LEN(self->nodes[i].key_len);
1623 3           SV* ksv = newSVpvn(self->nodes[i].key, klen);
1624 3 50         if (HM_UNPACK_UTF8(self->nodes[i].key_len)) SvUTF8_on(ksv);
1625 3 50         mXPUSHs(ksv);
1626             }
1627 3 100         if (GIMME_V == G_SCALAR) XSRETURN(1);
1628 2 50         mXPUSHi(self->nodes[i].value);
1629 2           XSRETURN(2);
1630             }
1631             }
1632 1           self->iter_pos = 0;
1633 1           XSRETURN_EMPTY;
1634              
1635             void
1636             iter_reset(SV* self_sv)
1637             CODE:
1638 0 0         EXTRACT_MAP(HashMapSI, stash_si, "Data::HashMap::SI", self_sv);
    0          
    0          
    0          
1639 0           self->iter_pos = 0;
1640              
1641             void
1642             clear(SV* self_sv)
1643             CODE:
1644 2 50         EXTRACT_MAP(HashMapSI, stash_si, "Data::HashMap::SI", self_sv);
    50          
    50          
    50          
1645 2           hashmap_si_clear(self);
1646              
1647             SV*
1648             to_hash(SV* self_sv)
1649             CODE:
1650 1 50         EXTRACT_MAP(HashMapSI, stash_si, "Data::HashMap::SI", self_sv);
    50          
    50          
    50          
1651 1           HV* hv = newHV();
1652 1 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
1653             size_t i;
1654 17 100         for (i = 0; i < self->capacity; i++) {
1655 16 100         if (SI_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    50          
    50          
    0          
    0          
1656 1           uint32_t klen = HM_UNPACK_LEN(self->nodes[i].key_len);
1657 1           bool kutf8 = HM_UNPACK_UTF8(self->nodes[i].key_len);
1658 1           SV* val = newSViv(self->nodes[i].value);
1659 1 50         (void)hv_store(hv, self->nodes[i].key, kutf8 ? -(I32)klen : (I32)klen, val, 0);
1660             }
1661             }
1662 1           RETVAL = newRV_noinc((SV*)hv);
1663             OUTPUT:
1664             RETVAL
1665              
1666             bool
1667             put_ttl(SV* self_sv, SV* key_sv, int64_t value, UV ttl)
1668             CODE:
1669 0 0         EXTRACT_MAP(HashMapSI, stash_si, "Data::HashMap::SI", self_sv);
    0          
    0          
    0          
1670 0 0         EXTRACT_STR_KEY(key_sv);
1671 0           RETVAL = hashmap_si_put(self, _kstr, (uint32_t)_klen, _khash, _kutf8, value, (uint32_t)ttl);
1672             OUTPUT:
1673             RETVAL
1674              
1675             SV*
1676             get_or_set(SV* self_sv, SV* key_sv, int64_t default_value)
1677             CODE:
1678 8 50         EXTRACT_MAP(HashMapSI, stash_si, "Data::HashMap::SI", self_sv);
    50          
    50          
    50          
1679 8 50         EXTRACT_STR_KEY(key_sv);
1680             bool was_found;
1681 8           size_t idx = hashmap_si_get_or_set(self, _kstr, (uint32_t)_klen, _khash, _kutf8, default_value, 0, &was_found);
1682             (void)was_found;
1683 8 50         if (idx >= self->capacity) XSRETURN_UNDEF;
1684 8           RETVAL = newSViv(self->nodes[idx].value);
1685             OUTPUT:
1686             RETVAL
1687              
1688              
1689              
1690             MODULE = Data::HashMap PACKAGE = Data::HashMap::SS
1691             PROTOTYPES: DISABLE
1692              
1693             SV*
1694             new(char* class, ...)
1695             CODE:
1696 57 100         EXTRACT_NEW_ARGS(_max_size, _ttl);
    100          
1697 57           HashMapSS* map = hashmap_ss_create(_max_size, _ttl);
1698 57 50         if (!map) croak("Failed to create HashMap::SS");
1699 57           RETVAL = sv_setref_pv(newSV(0), class, (void*)map);
1700             OUTPUT:
1701             RETVAL
1702              
1703             void
1704             DESTROY(SV* self_sv)
1705             CODE:
1706 57 50         EXTRACT_MAP(HashMapSS, stash_ss, "Data::HashMap::SS", self_sv);
    50          
    50          
    50          
1707 57           hashmap_ss_destroy(self);
1708 57           sv_setiv(SvRV(self_sv), 0);
1709              
1710             bool
1711             put(SV* self_sv, SV* key_sv, SV* value)
1712             CODE:
1713 82317 50         EXTRACT_MAP(HashMapSS, stash_ss, "Data::HashMap::SS", self_sv);
    50          
    50          
    50          
1714 82317 50         EXTRACT_STR_KEY(key_sv);
1715 82317 50         EXTRACT_STR_VAL(value);
1716 82317           RETVAL = hashmap_ss_put(self, _kstr, (uint32_t)_klen, _khash, _kutf8,
1717             _vstr, (uint32_t)_vlen, _vutf8, 0);
1718             OUTPUT:
1719             RETVAL
1720              
1721             SV*
1722             get(SV* self_sv, SV* key_sv)
1723             CODE:
1724 50024 50         EXTRACT_MAP(HashMapSS, stash_ss, "Data::HashMap::SS", self_sv);
    50          
    50          
    50          
1725 50024 50         EXTRACT_STR_KEY(key_sv);
1726             const char* val;
1727             uint32_t val_len;
1728             bool val_utf8;
1729 50024 100         if (!hashmap_ss_get(self, _kstr, (uint32_t)_klen, _khash, _kutf8, &val, &val_len, &val_utf8))
1730 6           XSRETURN_UNDEF;
1731 50018           RETVAL = newSVpvn(val, val_len);
1732 50018 100         if (val_utf8) SvUTF8_on(RETVAL);
1733             OUTPUT:
1734             RETVAL
1735              
1736             SV*
1737             get_direct(SV* self_sv, SV* key_sv)
1738             CODE:
1739 5 50         EXTRACT_MAP(HashMapSS, stash_ss, "Data::HashMap::SS", self_sv);
    50          
    50          
    50          
1740 5 50         EXTRACT_STR_KEY(key_sv);
1741             const char* val;
1742             uint32_t val_len;
1743             bool val_utf8;
1744 5 100         if (!hashmap_ss_get(self, _kstr, (uint32_t)_klen, _khash, _kutf8, &val, &val_len, &val_utf8))
1745 1           XSRETURN_UNDEF;
1746 4           RETVAL = hm_zerocopy_sv(aTHX_ val, val_len, val_utf8);
1747             OUTPUT:
1748             RETVAL
1749              
1750             bool
1751             remove(SV* self_sv, SV* key_sv)
1752             CODE:
1753 80508 50         EXTRACT_MAP(HashMapSS, stash_ss, "Data::HashMap::SS", self_sv);
    50          
    50          
    50          
1754 80508 50         EXTRACT_STR_KEY(key_sv);
1755 80508           RETVAL = hashmap_ss_remove(self, _kstr, (uint32_t)_klen, _khash, _kutf8);
1756             OUTPUT:
1757             RETVAL
1758              
1759             bool
1760             exists(SV* self_sv, SV* key_sv)
1761             CODE:
1762 2 50         EXTRACT_MAP(HashMapSS, stash_ss, "Data::HashMap::SS", self_sv);
    50          
    50          
    50          
1763 2 50         EXTRACT_STR_KEY(key_sv);
1764 2           RETVAL = hashmap_ss_exists(self, _kstr, (uint32_t)_klen, _khash, _kutf8);
1765             OUTPUT:
1766             RETVAL
1767              
1768             size_t
1769             size(SV* self_sv)
1770             CODE:
1771 8 50         EXTRACT_MAP(HashMapSS, stash_ss, "Data::HashMap::SS", self_sv);
    50          
    50          
    50          
1772 8 50         RETVAL = self->size;
1773             OUTPUT:
1774             RETVAL
1775              
1776             size_t
1777             max_size(SV* self_sv)
1778             CODE:
1779 0 0         EXTRACT_MAP(HashMapSS, stash_ss, "Data::HashMap::SS", self_sv);
    0          
    0          
    0          
1780 0 0         RETVAL = self->max_size;
1781             OUTPUT:
1782             RETVAL
1783              
1784             UV
1785             ttl(SV* self_sv)
1786             CODE:
1787 0 0         EXTRACT_MAP(HashMapSS, stash_ss, "Data::HashMap::SS", self_sv);
    0          
    0          
    0          
1788 0 0         RETVAL = (UV)self->default_ttl;
1789             OUTPUT:
1790             RETVAL
1791              
1792             void
1793             keys(SV* self_sv)
1794             PPCODE:
1795 5 50         EXTRACT_MAP(HashMapSS, stash_ss, "Data::HashMap::SS", self_sv);
    50          
    50          
    50          
1796 5 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
1797 5 50         EXTEND(SP, self->size);
1798             size_t i;
1799 565 100         for (i = 0; i < self->capacity; i++) {
1800 560 100         if (SS_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    100          
    50          
    0          
    0          
1801 204           uint32_t klen = HM_UNPACK_LEN(self->nodes[i].key_len);
1802 204           SV* sv = newSVpvn(self->nodes[i].key, klen);
1803 204 100         if (HM_UNPACK_UTF8(self->nodes[i].key_len)) SvUTF8_on(sv);
1804 204 50         mXPUSHs(sv);
1805             }
1806             }
1807              
1808             void
1809             values(SV* self_sv)
1810             PPCODE:
1811 3 50         EXTRACT_MAP(HashMapSS, stash_ss, "Data::HashMap::SS", self_sv);
    50          
    50          
    50          
1812 3 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
1813 3 50         EXTEND(SP, self->size);
1814             size_t i;
1815 531 100         for (i = 0; i < self->capacity; i++) {
1816 528 100         if (SS_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    100          
    50          
    0          
    0          
1817 200 50         if (self->nodes[i].value) {
1818 200           SV* sv = newSVpvn(self->nodes[i].value,
1819             HM_UNPACK_LEN(self->nodes[i].val_len));
1820 200 50         if (HM_UNPACK_UTF8(self->nodes[i].val_len)) SvUTF8_on(sv);
1821 200 50         mXPUSHs(sv);
1822             } else {
1823 0 0         XPUSHs(&PL_sv_undef);
1824             }
1825             }
1826             }
1827              
1828             void
1829             items(SV* self_sv)
1830             PPCODE:
1831 1 50         EXTRACT_MAP(HashMapSS, stash_ss, "Data::HashMap::SS", self_sv);
    50          
    50          
    50          
1832 1 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
1833 1 50         EXTEND(SP, self->size * 2);
1834             size_t i;
1835 17 100         for (i = 0; i < self->capacity; i++) {
1836 16 100         if (SS_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    50          
    50          
    0          
    0          
1837 2           uint32_t klen = HM_UNPACK_LEN(self->nodes[i].key_len);
1838 2           SV* sv = newSVpvn(self->nodes[i].key, klen);
1839 2 50         if (HM_UNPACK_UTF8(self->nodes[i].key_len)) SvUTF8_on(sv);
1840 2 50         mXPUSHs(sv);
1841 2 50         if (self->nodes[i].value) {
1842 2           SV* vsv = newSVpvn(self->nodes[i].value,
1843             HM_UNPACK_LEN(self->nodes[i].val_len));
1844 2 50         if (HM_UNPACK_UTF8(self->nodes[i].val_len)) SvUTF8_on(vsv);
1845 2 50         mXPUSHs(vsv);
1846             } else {
1847 0 0         XPUSHs(&PL_sv_undef);
1848             }
1849             }
1850             }
1851              
1852             void
1853             each(SV* self_sv)
1854             PPCODE:
1855 47 50         EXTRACT_MAP(HashMapSS, stash_ss, "Data::HashMap::SS", self_sv);
    50          
    50          
    50          
1856 47 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
1857 93 100         while (self->iter_pos < self->capacity) {
1858 90           size_t i = self->iter_pos++;
1859 90 100         if (SS_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    50          
    50          
    0          
    0          
1860 44 50         EXTEND(SP, 2);
1861             {
1862 44           uint32_t klen = HM_UNPACK_LEN(self->nodes[i].key_len);
1863 44           SV* ksv = newSVpvn(self->nodes[i].key, klen);
1864 44 100         if (HM_UNPACK_UTF8(self->nodes[i].key_len)) SvUTF8_on(ksv);
1865 44 50         mXPUSHs(ksv);
1866             }
1867 44 100         if (GIMME_V == G_SCALAR) XSRETURN(1);
1868 43 50         if (self->nodes[i].value) {
1869 43           SV* vsv = newSVpvn(self->nodes[i].value,
1870             HM_UNPACK_LEN(self->nodes[i].val_len));
1871 43 100         if (HM_UNPACK_UTF8(self->nodes[i].val_len)) SvUTF8_on(vsv);
1872 43 50         mXPUSHs(vsv);
1873             } else {
1874 0 0         XPUSHs(&PL_sv_undef);
1875             }
1876 43           XSRETURN(2);
1877             }
1878             }
1879 3           self->iter_pos = 0;
1880 3           XSRETURN_EMPTY;
1881              
1882             void
1883             iter_reset(SV* self_sv)
1884             CODE:
1885 0 0         EXTRACT_MAP(HashMapSS, stash_ss, "Data::HashMap::SS", self_sv);
    0          
    0          
    0          
1886 0           self->iter_pos = 0;
1887              
1888             void
1889             clear(SV* self_sv)
1890             CODE:
1891 9 50         EXTRACT_MAP(HashMapSS, stash_ss, "Data::HashMap::SS", self_sv);
    50          
    50          
    50          
1892 9           hashmap_ss_clear(self);
1893              
1894             SV*
1895             to_hash(SV* self_sv)
1896             CODE:
1897 6 50         EXTRACT_MAP(HashMapSS, stash_ss, "Data::HashMap::SS", self_sv);
    50          
    50          
    50          
1898 6           HV* hv = newHV();
1899 6 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
1900             size_t i;
1901 614 100         for (i = 0; i < self->capacity; i++) {
1902 608 100         if (SS_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    100          
    50          
    0          
    0          
1903 241           uint32_t klen = HM_UNPACK_LEN(self->nodes[i].key_len);
1904 241           bool kutf8 = HM_UNPACK_UTF8(self->nodes[i].key_len);
1905 241           uint32_t vlen = HM_UNPACK_LEN(self->nodes[i].val_len);
1906 241           bool vutf8 = HM_UNPACK_UTF8(self->nodes[i].val_len);
1907 482           SV* val = self->nodes[i].value
1908 241           ? newSVpvn(self->nodes[i].value, vlen)
1909 241 50         : newSV(0);
1910 241 50         if (self->nodes[i].value && vutf8) SvUTF8_on(val);
    100          
1911 241 100         (void)hv_store(hv, self->nodes[i].key, kutf8 ? -(I32)klen : (I32)klen, val, 0);
1912             }
1913             }
1914 6           RETVAL = newRV_noinc((SV*)hv);
1915             OUTPUT:
1916             RETVAL
1917              
1918             bool
1919             put_ttl(SV* self_sv, SV* key_sv, SV* value, UV ttl)
1920             CODE:
1921 102 50         EXTRACT_MAP(HashMapSS, stash_ss, "Data::HashMap::SS", self_sv);
    50          
    50          
    50          
1922 102 50         EXTRACT_STR_KEY(key_sv);
1923 102 50         EXTRACT_STR_VAL(value);
1924 102           RETVAL = hashmap_ss_put(self, _kstr, (uint32_t)_klen, _khash, _kutf8,
1925             _vstr, (uint32_t)_vlen, _vutf8, (uint32_t)ttl);
1926             OUTPUT:
1927             RETVAL
1928              
1929             SV*
1930             get_or_set(SV* self_sv, SV* key_sv, SV* default_sv)
1931             CODE:
1932 9 50         EXTRACT_MAP(HashMapSS, stash_ss, "Data::HashMap::SS", self_sv);
    50          
    50          
    50          
1933 9 50         EXTRACT_STR_KEY(key_sv);
1934 9 50         EXTRACT_STR_VAL(default_sv);
1935             bool was_found;
1936 9           size_t idx = hashmap_ss_get_or_set(self, _kstr, (uint32_t)_klen, _khash, _kutf8,
1937             _vstr, (uint32_t)_vlen, _vutf8, 0, &was_found);
1938             (void)was_found;
1939 9 50         if (idx >= self->capacity) XSRETURN_UNDEF;
1940 9 50         if (self->nodes[idx].value) {
1941 9           RETVAL = newSVpvn(self->nodes[idx].value, HM_UNPACK_LEN(self->nodes[idx].val_len));
1942 9 50         if (HM_UNPACK_UTF8(self->nodes[idx].val_len)) SvUTF8_on(RETVAL);
1943             } else {
1944 0           RETVAL = newSV(0);
1945             }
1946             OUTPUT:
1947             RETVAL
1948              
1949              
1950              
1951             MODULE = Data::HashMap PACKAGE = Data::HashMap::I32S
1952             PROTOTYPES: DISABLE
1953              
1954             SV*
1955             new(char* class, ...)
1956             CODE:
1957 13 100         EXTRACT_NEW_ARGS(_max_size, _ttl);
    50          
1958 13           HashMapI32S* map = hashmap_i32s_create(_max_size, _ttl);
1959 13 50         if (!map) croak("Failed to create HashMap::I32S");
1960 13           RETVAL = sv_setref_pv(newSV(0), class, (void*)map);
1961             OUTPUT:
1962             RETVAL
1963              
1964             void
1965             DESTROY(SV* self_sv)
1966             CODE:
1967 13 50         EXTRACT_MAP(HashMapI32S, stash_i32s, "Data::HashMap::I32S", self_sv);
    50          
    50          
    50          
1968 13           hashmap_i32s_destroy(self);
1969 13           sv_setiv(SvRV(self_sv), 0);
1970              
1971             bool
1972             put(SV* self_sv, int32_t key, SV* value)
1973             CODE:
1974 80416 50         EXTRACT_MAP(HashMapI32S, stash_i32s, "Data::HashMap::I32S", self_sv);
    50          
    50          
    50          
1975 80416 50         EXTRACT_STR_VAL(value);
1976 80416           RETVAL = hashmap_i32s_put(self, key, _vstr, (uint32_t)_vlen, _vutf8, 0);
1977             OUTPUT:
1978             RETVAL
1979              
1980             SV*
1981             get(SV* self_sv, int32_t key)
1982             CODE:
1983 50010 50         EXTRACT_MAP(HashMapI32S, stash_i32s, "Data::HashMap::I32S", self_sv);
    50          
    50          
    50          
1984             const char* val;
1985             uint32_t val_len;
1986             bool val_utf8;
1987 50010 100         if (!hashmap_i32s_get(self, key, &val, &val_len, &val_utf8))
1988 3           XSRETURN_UNDEF;
1989 50007           RETVAL = newSVpvn(val, val_len);
1990 50007 100         if (val_utf8) SvUTF8_on(RETVAL);
1991             OUTPUT:
1992             RETVAL
1993              
1994             SV*
1995             get_direct(SV* self_sv, int32_t key)
1996             CODE:
1997 1 50         EXTRACT_MAP(HashMapI32S, stash_i32s, "Data::HashMap::I32S", self_sv);
    50          
    50          
    50          
1998             const char* val;
1999             uint32_t val_len;
2000             bool val_utf8;
2001 1 50         if (!hashmap_i32s_get(self, key, &val, &val_len, &val_utf8))
2002 0           XSRETURN_UNDEF;
2003 1           RETVAL = hm_zerocopy_sv(aTHX_ val, val_len, val_utf8);
2004             OUTPUT:
2005             RETVAL
2006              
2007             bool
2008             remove(SV* self_sv, int32_t key)
2009             CODE:
2010 80006 50         EXTRACT_MAP(HashMapI32S, stash_i32s, "Data::HashMap::I32S", self_sv);
    50          
    50          
    50          
2011 80006           RETVAL = hashmap_i32s_remove(self, key);
2012             OUTPUT:
2013             RETVAL
2014              
2015             bool
2016             exists(SV* self_sv, int32_t key)
2017             CODE:
2018 3 50         EXTRACT_MAP(HashMapI32S, stash_i32s, "Data::HashMap::I32S", self_sv);
    50          
    50          
    50          
2019 3           RETVAL = hashmap_i32s_exists(self, key);
2020             OUTPUT:
2021             RETVAL
2022              
2023             size_t
2024             size(SV* self_sv)
2025             CODE:
2026 6 50         EXTRACT_MAP(HashMapI32S, stash_i32s, "Data::HashMap::I32S", self_sv);
    50          
    50          
    50          
2027 6 50         RETVAL = self->size;
2028             OUTPUT:
2029             RETVAL
2030              
2031             size_t
2032             max_size(SV* self_sv)
2033             CODE:
2034 0 0         EXTRACT_MAP(HashMapI32S, stash_i32s, "Data::HashMap::I32S", self_sv);
    0          
    0          
    0          
2035 0 0         RETVAL = self->max_size;
2036             OUTPUT:
2037             RETVAL
2038              
2039             UV
2040             ttl(SV* self_sv)
2041             CODE:
2042 0 0         EXTRACT_MAP(HashMapI32S, stash_i32s, "Data::HashMap::I32S", self_sv);
    0          
    0          
    0          
2043 0 0         RETVAL = (UV)self->default_ttl;
2044             OUTPUT:
2045             RETVAL
2046              
2047             void
2048             keys(SV* self_sv)
2049             PPCODE:
2050 2 50         EXTRACT_MAP(HashMapI32S, stash_i32s, "Data::HashMap::I32S", self_sv);
    50          
    50          
    50          
2051 2 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
2052 2 50         EXTEND(SP, self->size);
2053             size_t i;
2054 34 100         for (i = 0; i < self->capacity; i++) {
2055 32 100         if (I32S_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now))
    50          
    50          
    0          
    0          
2056 2 50         mXPUSHi(self->nodes[i].key);
2057             }
2058              
2059             void
2060             values(SV* self_sv)
2061             PPCODE:
2062 1 50         EXTRACT_MAP(HashMapI32S, stash_i32s, "Data::HashMap::I32S", self_sv);
    50          
    50          
    50          
2063 1 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
2064 1 50         EXTEND(SP, self->size);
2065             size_t i;
2066 17 100         for (i = 0; i < self->capacity; i++) {
2067 16 100         if (I32S_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    50          
    50          
    0          
    0          
2068 2 50         if (self->nodes[i].value) {
2069 2           SV* sv = newSVpvn(self->nodes[i].value,
2070             HM_UNPACK_LEN(self->nodes[i].val_len));
2071 2 50         if (HM_UNPACK_UTF8(self->nodes[i].val_len)) SvUTF8_on(sv);
2072 2 50         mXPUSHs(sv);
2073             } else {
2074 0 0         XPUSHs(&PL_sv_undef);
2075             }
2076             }
2077             }
2078              
2079             void
2080             items(SV* self_sv)
2081             PPCODE:
2082 1 50         EXTRACT_MAP(HashMapI32S, stash_i32s, "Data::HashMap::I32S", self_sv);
    50          
    50          
    50          
2083 1 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
2084 1 50         EXTEND(SP, self->size * 2);
2085             size_t i;
2086 17 100         for (i = 0; i < self->capacity; i++) {
2087 16 100         if (I32S_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    50          
    50          
    0          
    0          
2088 2 50         mXPUSHi(self->nodes[i].key);
2089 2 50         if (self->nodes[i].value) {
2090 2           SV* sv = newSVpvn(self->nodes[i].value,
2091             HM_UNPACK_LEN(self->nodes[i].val_len));
2092 2 50         if (HM_UNPACK_UTF8(self->nodes[i].val_len)) SvUTF8_on(sv);
2093 2 50         mXPUSHs(sv);
2094             } else {
2095 0 0         XPUSHs(&PL_sv_undef);
2096             }
2097             }
2098             }
2099              
2100             void
2101             each(SV* self_sv)
2102             PPCODE:
2103 3 50         EXTRACT_MAP(HashMapI32S, stash_i32s, "Data::HashMap::I32S", self_sv);
    50          
    50          
    50          
2104 3 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
2105 17 100         while (self->iter_pos < self->capacity) {
2106 16           size_t i = self->iter_pos++;
2107 16 100         if (I32S_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    50          
    50          
    0          
    0          
2108 2 50         EXTEND(SP, 2);
2109 2 50         mXPUSHi(self->nodes[i].key);
2110 2 50         if (GIMME_V == G_SCALAR) XSRETURN(1);
2111 2 50         if (self->nodes[i].value) {
2112 2           SV* vsv = newSVpvn(self->nodes[i].value,
2113             HM_UNPACK_LEN(self->nodes[i].val_len));
2114 2 50         if (HM_UNPACK_UTF8(self->nodes[i].val_len)) SvUTF8_on(vsv);
2115 2 50         mXPUSHs(vsv);
2116             } else {
2117 0 0         XPUSHs(&PL_sv_undef);
2118             }
2119 2           XSRETURN(2);
2120             }
2121             }
2122 1           self->iter_pos = 0;
2123 1           XSRETURN_EMPTY;
2124              
2125             void
2126             iter_reset(SV* self_sv)
2127             CODE:
2128 0 0         EXTRACT_MAP(HashMapI32S, stash_i32s, "Data::HashMap::I32S", self_sv);
    0          
    0          
    0          
2129 0           self->iter_pos = 0;
2130              
2131             void
2132             clear(SV* self_sv)
2133             CODE:
2134 3 50         EXTRACT_MAP(HashMapI32S, stash_i32s, "Data::HashMap::I32S", self_sv);
    50          
    50          
    50          
2135 3           hashmap_i32s_clear(self);
2136              
2137             SV*
2138             to_hash(SV* self_sv)
2139             CODE:
2140 1 50         EXTRACT_MAP(HashMapI32S, stash_i32s, "Data::HashMap::I32S", self_sv);
    50          
    50          
    50          
2141 1           HV* hv = newHV();
2142 1 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
2143             size_t i;
2144 17 100         for (i = 0; i < self->capacity; i++) {
2145 16 100         if (I32S_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    50          
    50          
    0          
    0          
2146 1           uint32_t vlen = HM_UNPACK_LEN(self->nodes[i].val_len);
2147 1           bool vutf8 = HM_UNPACK_UTF8(self->nodes[i].val_len);
2148 2           SV* val = self->nodes[i].value
2149 1           ? newSVpvn(self->nodes[i].value, vlen)
2150 1 50         : newSV(0);
2151 1 50         if (self->nodes[i].value && vutf8) SvUTF8_on(val);
    50          
2152             char kbuf[24];
2153 1           int klen = my_snprintf(kbuf, sizeof(kbuf), "%" IVdf, (IV)self->nodes[i].key);
2154 1           (void)hv_store(hv, kbuf, klen, val, 0);
2155             }
2156             }
2157 1           RETVAL = newRV_noinc((SV*)hv);
2158             OUTPUT:
2159             RETVAL
2160              
2161             bool
2162             put_ttl(SV* self_sv, int32_t key, SV* value, UV ttl)
2163             CODE:
2164 0 0         EXTRACT_MAP(HashMapI32S, stash_i32s, "Data::HashMap::I32S", self_sv);
    0          
    0          
    0          
2165 0 0         EXTRACT_STR_VAL(value);
2166 0           RETVAL = hashmap_i32s_put(self, key, _vstr, (uint32_t)_vlen, _vutf8, (uint32_t)ttl);
2167             OUTPUT:
2168             RETVAL
2169              
2170             SV*
2171             get_or_set(SV* self_sv, int32_t key, SV* default_sv)
2172             CODE:
2173 0 0         EXTRACT_MAP(HashMapI32S, stash_i32s, "Data::HashMap::I32S", self_sv);
    0          
    0          
    0          
2174 0 0         EXTRACT_STR_VAL(default_sv);
2175             bool was_found;
2176 0           size_t idx = hashmap_i32s_get_or_set(self, key, _vstr, (uint32_t)_vlen, _vutf8, 0, &was_found);
2177             (void)was_found;
2178 0 0         if (idx >= self->capacity) XSRETURN_UNDEF;
2179 0 0         if (self->nodes[idx].value) {
2180 0           RETVAL = newSVpvn(self->nodes[idx].value, HM_UNPACK_LEN(self->nodes[idx].val_len));
2181 0 0         if (HM_UNPACK_UTF8(self->nodes[idx].val_len)) SvUTF8_on(RETVAL);
2182             } else {
2183 0           RETVAL = newSV(0);
2184             }
2185             OUTPUT:
2186             RETVAL
2187              
2188              
2189              
2190             MODULE = Data::HashMap PACKAGE = Data::HashMap::SI32
2191             PROTOTYPES: DISABLE
2192              
2193             SV*
2194             new(char* class, ...)
2195             CODE:
2196 15 100         EXTRACT_NEW_ARGS(_max_size, _ttl);
    50          
2197 15           HashMapSI32* map = hashmap_si32_create(_max_size, _ttl);
2198 15 50         if (!map) croak("Failed to create HashMap::SI32");
2199 15           RETVAL = sv_setref_pv(newSV(0), class, (void*)map);
2200             OUTPUT:
2201             RETVAL
2202              
2203             void
2204             DESTROY(SV* self_sv)
2205             CODE:
2206 15 50         EXTRACT_MAP(HashMapSI32, stash_si32, "Data::HashMap::SI32", self_sv);
    50          
    50          
    50          
2207 15           hashmap_si32_destroy(self);
2208 15           sv_setiv(SvRV(self_sv), 0);
2209              
2210             bool
2211             put(SV* self_sv, SV* key_sv, int32_t value)
2212             CODE:
2213 80219 50         EXTRACT_MAP(HashMapSI32, stash_si32, "Data::HashMap::SI32", self_sv);
    50          
    50          
    50          
2214 80219 50         EXTRACT_STR_KEY(key_sv);
2215 80219           RETVAL = hashmap_si32_put(self, _kstr, (uint32_t)_klen, _khash, _kutf8, value, 0);
2216             OUTPUT:
2217             RETVAL
2218              
2219             SV*
2220             get(SV* self_sv, SV* key_sv)
2221             CODE:
2222 50010 50         EXTRACT_MAP(HashMapSI32, stash_si32, "Data::HashMap::SI32", self_sv);
    50          
    50          
    50          
2223 50010 50         EXTRACT_STR_KEY(key_sv);
2224             int32_t value;
2225 50010 100         if (!hashmap_si32_get(self, _kstr, (uint32_t)_klen, _khash, _kutf8, &value))
2226 3           XSRETURN_UNDEF;
2227 50007           RETVAL = newSViv(value);
2228             OUTPUT:
2229             RETVAL
2230              
2231             bool
2232             remove(SV* self_sv, SV* key_sv)
2233             CODE:
2234 80005 50         EXTRACT_MAP(HashMapSI32, stash_si32, "Data::HashMap::SI32", self_sv);
    50          
    50          
    50          
2235 80005 50         EXTRACT_STR_KEY(key_sv);
2236 80005           RETVAL = hashmap_si32_remove(self, _kstr, (uint32_t)_klen, _khash, _kutf8);
2237             OUTPUT:
2238             RETVAL
2239              
2240             bool
2241             exists(SV* self_sv, SV* key_sv)
2242             CODE:
2243 2 50         EXTRACT_MAP(HashMapSI32, stash_si32, "Data::HashMap::SI32", self_sv);
    50          
    50          
    50          
2244 2 50         EXTRACT_STR_KEY(key_sv);
2245 2           RETVAL = hashmap_si32_exists(self, _kstr, (uint32_t)_klen, _khash, _kutf8);
2246             OUTPUT:
2247             RETVAL
2248              
2249             SV*
2250             incr(SV* self_sv, SV* key_sv)
2251             CODE:
2252 12 50         EXTRACT_MAP(HashMapSI32, stash_si32, "Data::HashMap::SI32", self_sv);
    50          
    50          
    50          
2253 12 50         EXTRACT_STR_KEY(key_sv);
2254             int32_t val;
2255 12 100         if (!hashmap_si32_increment(self, _kstr, (uint32_t)_klen, _khash, _kutf8, &val))
2256 1           croak("HashMap::SI32: increment failed");
2257 11           RETVAL = newSViv(val);
2258             OUTPUT:
2259             RETVAL
2260              
2261             SV*
2262             decr(SV* self_sv, SV* key_sv)
2263             CODE:
2264 3 50         EXTRACT_MAP(HashMapSI32, stash_si32, "Data::HashMap::SI32", self_sv);
    50          
    50          
    50          
2265 3 50         EXTRACT_STR_KEY(key_sv);
2266             int32_t val;
2267 3 100         if (!hashmap_si32_decrement(self, _kstr, (uint32_t)_klen, _khash, _kutf8, &val))
2268 1           croak("HashMap::SI32: decrement failed");
2269 2           RETVAL = newSViv(val);
2270             OUTPUT:
2271             RETVAL
2272              
2273             SV*
2274             incr_by(SV* self_sv, SV* key_sv, int32_t delta)
2275             CODE:
2276 6 50         EXTRACT_MAP(HashMapSI32, stash_si32, "Data::HashMap::SI32", self_sv);
    50          
    50          
    50          
2277 6 50         EXTRACT_STR_KEY(key_sv);
2278             int32_t val;
2279 6 100         if (!hashmap_si32_increment_by(self, _kstr, (uint32_t)_klen, _khash, _kutf8, delta, &val))
2280 2           croak("HashMap::SI32: incr_by failed");
2281 4           RETVAL = newSViv(val);
2282             OUTPUT:
2283             RETVAL
2284              
2285             size_t
2286             size(SV* self_sv)
2287             CODE:
2288 5 50         EXTRACT_MAP(HashMapSI32, stash_si32, "Data::HashMap::SI32", self_sv);
    50          
    50          
    50          
2289 5 50         RETVAL = self->size;
2290             OUTPUT:
2291             RETVAL
2292              
2293             size_t
2294             max_size(SV* self_sv)
2295             CODE:
2296 0 0         EXTRACT_MAP(HashMapSI32, stash_si32, "Data::HashMap::SI32", self_sv);
    0          
    0          
    0          
2297 0 0         RETVAL = self->max_size;
2298             OUTPUT:
2299             RETVAL
2300              
2301             UV
2302             ttl(SV* self_sv)
2303             CODE:
2304 0 0         EXTRACT_MAP(HashMapSI32, stash_si32, "Data::HashMap::SI32", self_sv);
    0          
    0          
    0          
2305 0 0         RETVAL = (UV)self->default_ttl;
2306             OUTPUT:
2307             RETVAL
2308              
2309             void
2310             keys(SV* self_sv)
2311             PPCODE:
2312 3 50         EXTRACT_MAP(HashMapSI32, stash_si32, "Data::HashMap::SI32", self_sv);
    50          
    50          
    50          
2313 3 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
2314 3 50         EXTEND(SP, self->size);
2315             size_t i;
2316 51 100         for (i = 0; i < self->capacity; i++) {
2317 48 100         if (SI32_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    100          
    50          
    0          
    0          
2318 7           uint32_t klen = HM_UNPACK_LEN(self->nodes[i].key_len);
2319 7           SV* sv = newSVpvn(self->nodes[i].key, klen);
2320 7 100         if (HM_UNPACK_UTF8(self->nodes[i].key_len)) SvUTF8_on(sv);
2321 7 50         mXPUSHs(sv);
2322             }
2323             }
2324              
2325             void
2326             values(SV* self_sv)
2327             PPCODE:
2328 1 50         EXTRACT_MAP(HashMapSI32, stash_si32, "Data::HashMap::SI32", self_sv);
    50          
    50          
    50          
2329 1 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
2330 1 50         EXTEND(SP, self->size);
2331             size_t i;
2332 17 100         for (i = 0; i < self->capacity; i++) {
2333 16 100         if (SI32_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now))
    50          
    50          
    0          
    0          
2334 2 50         mXPUSHi(self->nodes[i].value);
2335             }
2336              
2337             void
2338             items(SV* self_sv)
2339             PPCODE:
2340 2 50         EXTRACT_MAP(HashMapSI32, stash_si32, "Data::HashMap::SI32", self_sv);
    50          
    50          
    50          
2341 2 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
2342 2 50         EXTEND(SP, self->size * 2);
2343             size_t i;
2344 34 100         for (i = 0; i < self->capacity; i++) {
2345 32 100         if (SI32_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    100          
    50          
    0          
    0          
2346 7           uint32_t klen = HM_UNPACK_LEN(self->nodes[i].key_len);
2347 7           SV* sv = newSVpvn(self->nodes[i].key, klen);
2348 7 100         if (HM_UNPACK_UTF8(self->nodes[i].key_len)) SvUTF8_on(sv);
2349 7 50         mXPUSHs(sv);
2350 7 50         mXPUSHi(self->nodes[i].value);
2351             }
2352             }
2353              
2354             void
2355             each(SV* self_sv)
2356             PPCODE:
2357 3 50         EXTRACT_MAP(HashMapSI32, stash_si32, "Data::HashMap::SI32", self_sv);
    50          
    50          
    50          
2358 3 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
2359 17 100         while (self->iter_pos < self->capacity) {
2360 16           size_t i = self->iter_pos++;
2361 16 100         if (SI32_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    50          
    50          
    0          
    0          
2362 2 50         EXTEND(SP, 2);
2363             {
2364 2           uint32_t klen = HM_UNPACK_LEN(self->nodes[i].key_len);
2365 2           SV* ksv = newSVpvn(self->nodes[i].key, klen);
2366 2 50         if (HM_UNPACK_UTF8(self->nodes[i].key_len)) SvUTF8_on(ksv);
2367 2 50         mXPUSHs(ksv);
2368             }
2369 2 50         if (GIMME_V == G_SCALAR) XSRETURN(1);
2370 2 50         mXPUSHi(self->nodes[i].value);
2371 2           XSRETURN(2);
2372             }
2373             }
2374 1           self->iter_pos = 0;
2375 1           XSRETURN_EMPTY;
2376              
2377             void
2378             iter_reset(SV* self_sv)
2379             CODE:
2380 0 0         EXTRACT_MAP(HashMapSI32, stash_si32, "Data::HashMap::SI32", self_sv);
    0          
    0          
    0          
2381 0           self->iter_pos = 0;
2382              
2383             void
2384             clear(SV* self_sv)
2385             CODE:
2386 2 50         EXTRACT_MAP(HashMapSI32, stash_si32, "Data::HashMap::SI32", self_sv);
    50          
    50          
    50          
2387 2           hashmap_si32_clear(self);
2388              
2389             SV*
2390             to_hash(SV* self_sv)
2391             CODE:
2392 1 50         EXTRACT_MAP(HashMapSI32, stash_si32, "Data::HashMap::SI32", self_sv);
    50          
    50          
    50          
2393 1           HV* hv = newHV();
2394 1 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
2395             size_t i;
2396 17 100         for (i = 0; i < self->capacity; i++) {
2397 16 100         if (SI32_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    50          
    50          
    0          
    0          
2398 1           uint32_t klen = HM_UNPACK_LEN(self->nodes[i].key_len);
2399 1           bool kutf8 = HM_UNPACK_UTF8(self->nodes[i].key_len);
2400 1           SV* val = newSViv(self->nodes[i].value);
2401 1 50         (void)hv_store(hv, self->nodes[i].key, kutf8 ? -(I32)klen : (I32)klen, val, 0);
2402             }
2403             }
2404 1           RETVAL = newRV_noinc((SV*)hv);
2405             OUTPUT:
2406             RETVAL
2407              
2408             bool
2409             put_ttl(SV* self_sv, SV* key_sv, int32_t value, UV ttl)
2410             CODE:
2411 1 50         EXTRACT_MAP(HashMapSI32, stash_si32, "Data::HashMap::SI32", self_sv);
    50          
    50          
    50          
2412 1 50         EXTRACT_STR_KEY(key_sv);
2413 1           RETVAL = hashmap_si32_put(self, _kstr, (uint32_t)_klen, _khash, _kutf8, value, (uint32_t)ttl);
2414             OUTPUT:
2415             RETVAL
2416              
2417             SV*
2418             get_or_set(SV* self_sv, SV* key_sv, int32_t default_value)
2419             CODE:
2420 1 50         EXTRACT_MAP(HashMapSI32, stash_si32, "Data::HashMap::SI32", self_sv);
    50          
    50          
    50          
2421 1 50         EXTRACT_STR_KEY(key_sv);
2422             bool was_found;
2423 1           size_t idx = hashmap_si32_get_or_set(self, _kstr, (uint32_t)_klen, _khash, _kutf8, default_value, 0, &was_found);
2424             (void)was_found;
2425 1 50         if (idx >= self->capacity) XSRETURN_UNDEF;
2426 1           RETVAL = newSViv(self->nodes[idx].value);
2427             OUTPUT:
2428             RETVAL
2429              
2430              
2431              
2432             MODULE = Data::HashMap PACKAGE = Data::HashMap::I16
2433             PROTOTYPES: DISABLE
2434              
2435             SV*
2436             new(char* class, ...)
2437             CODE:
2438 19 100         EXTRACT_NEW_ARGS(_max_size, _ttl);
    100          
2439 19           HashMapI16* map = hashmap_i16_create(_max_size, _ttl);
2440 19 50         if (!map) croak("Failed to create HashMap::I16");
2441 19           RETVAL = sv_setref_pv(newSV(0), class, (void*)map);
2442             OUTPUT:
2443             RETVAL
2444              
2445             void
2446             DESTROY(SV* self_sv)
2447             CODE:
2448 19 50         EXTRACT_MAP(HashMapI16, stash_i16, "Data::HashMap::I16", self_sv);
    50          
    50          
    50          
2449 19           hashmap_i16_destroy(self);
2450 19           sv_setiv(SvRV(self_sv), 0);
2451              
2452             bool
2453             put(SV* self_sv, int16_t key, int16_t value)
2454             CODE:
2455 81227 50         EXTRACT_MAP(HashMapI16, stash_i16, "Data::HashMap::I16", self_sv);
    50          
    50          
    50          
2456 81227           RETVAL = hashmap_i16_put(self, key, value, 0);
2457             OUTPUT:
2458             RETVAL
2459              
2460             SV*
2461             get(SV* self_sv, int16_t key)
2462             CODE:
2463 30013 50         EXTRACT_MAP(HashMapI16, stash_i16, "Data::HashMap::I16", self_sv);
    50          
    50          
    50          
2464             int16_t value;
2465 30013 100         if (!hashmap_i16_get(self, key, &value)) XSRETURN_UNDEF;
2466 30007           RETVAL = newSViv(value);
2467             OUTPUT:
2468             RETVAL
2469              
2470             bool
2471             remove(SV* self_sv, int16_t key)
2472             CODE:
2473 80007 50         EXTRACT_MAP(HashMapI16, stash_i16, "Data::HashMap::I16", self_sv);
    50          
    50          
    50          
2474 80007           RETVAL = hashmap_i16_remove(self, key);
2475             OUTPUT:
2476             RETVAL
2477              
2478             bool
2479             exists(SV* self_sv, int16_t key)
2480             CODE:
2481 4 50         EXTRACT_MAP(HashMapI16, stash_i16, "Data::HashMap::I16", self_sv);
    50          
    50          
    50          
2482 4           RETVAL = hashmap_i16_exists(self, key);
2483             OUTPUT:
2484             RETVAL
2485              
2486             SV*
2487             incr(SV* self_sv, int16_t key)
2488             CODE:
2489 12 50         EXTRACT_MAP(HashMapI16, stash_i16, "Data::HashMap::I16", self_sv);
    50          
    50          
    50          
2490             int16_t val;
2491 12 100         if (!hashmap_i16_increment(self, key, &val))
2492 3           croak("HashMap::I16: increment failed");
2493 9           RETVAL = newSViv(val);
2494             OUTPUT:
2495             RETVAL
2496              
2497             SV*
2498             decr(SV* self_sv, int16_t key)
2499             CODE:
2500 6 50         EXTRACT_MAP(HashMapI16, stash_i16, "Data::HashMap::I16", self_sv);
    50          
    50          
    50          
2501             int16_t val;
2502 6 100         if (!hashmap_i16_decrement(self, key, &val))
2503 2           croak("HashMap::I16: decrement failed");
2504 4           RETVAL = newSViv(val);
2505             OUTPUT:
2506             RETVAL
2507              
2508             SV*
2509             incr_by(SV* self_sv, int16_t key, int16_t delta)
2510             CODE:
2511 8 50         EXTRACT_MAP(HashMapI16, stash_i16, "Data::HashMap::I16", self_sv);
    50          
    50          
    50          
2512             int16_t val;
2513 8 100         if (!hashmap_i16_increment_by(self, key, delta, &val))
2514 2           croak("HashMap::I16: incr_by failed");
2515 6           RETVAL = newSViv(val);
2516             OUTPUT:
2517             RETVAL
2518              
2519             size_t
2520             size(SV* self_sv)
2521             CODE:
2522 8 50         EXTRACT_MAP(HashMapI16, stash_i16, "Data::HashMap::I16", self_sv);
    50          
    50          
    50          
2523 8 50         RETVAL = self->size;
2524             OUTPUT:
2525             RETVAL
2526              
2527             size_t
2528             max_size(SV* self_sv)
2529             CODE:
2530 0 0         EXTRACT_MAP(HashMapI16, stash_i16, "Data::HashMap::I16", self_sv);
    0          
    0          
    0          
2531 0 0         RETVAL = self->max_size;
2532             OUTPUT:
2533             RETVAL
2534              
2535             UV
2536             ttl(SV* self_sv)
2537             CODE:
2538 0 0         EXTRACT_MAP(HashMapI16, stash_i16, "Data::HashMap::I16", self_sv);
    0          
    0          
    0          
2539 0 0         RETVAL = (UV)self->default_ttl;
2540             OUTPUT:
2541             RETVAL
2542              
2543             void
2544             keys(SV* self_sv)
2545             PPCODE:
2546 3 50         EXTRACT_MAP(HashMapI16, stash_i16, "Data::HashMap::I16", self_sv);
    50          
    50          
    50          
2547 3 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
2548 3 50         EXTEND(SP, self->size);
2549             size_t i;
2550 51 100         for (i = 0; i < self->capacity; i++) {
2551 48 100         if (I16_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now))
    50          
    50          
    0          
    0          
2552 4 50         mXPUSHi(self->nodes[i].key);
2553             }
2554              
2555             void
2556             values(SV* self_sv)
2557             PPCODE:
2558 2 50         EXTRACT_MAP(HashMapI16, stash_i16, "Data::HashMap::I16", self_sv);
    50          
    50          
    50          
2559 2 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
2560 2 50         EXTEND(SP, self->size);
2561             size_t i;
2562 34 100         for (i = 0; i < self->capacity; i++) {
2563 32 100         if (I16_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now))
    50          
    50          
    0          
    0          
2564 4 50         mXPUSHi(self->nodes[i].value);
2565             }
2566              
2567             void
2568             items(SV* self_sv)
2569             PPCODE:
2570 1 50         EXTRACT_MAP(HashMapI16, stash_i16, "Data::HashMap::I16", self_sv);
    50          
    50          
    50          
2571 1 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
2572 1 50         EXTEND(SP, self->size * 2);
2573             size_t i;
2574 17 100         for (i = 0; i < self->capacity; i++) {
2575 16 100         if (I16_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    50          
    50          
    0          
    0          
2576 2 50         mXPUSHi(self->nodes[i].key);
2577 2 50         mXPUSHi(self->nodes[i].value);
2578             }
2579             }
2580              
2581             void
2582             each(SV* self_sv)
2583             PPCODE:
2584 3 50         EXTRACT_MAP(HashMapI16, stash_i16, "Data::HashMap::I16", self_sv);
    50          
    50          
    50          
2585 3 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
2586 17 100         while (self->iter_pos < self->capacity) {
2587 16           size_t i = self->iter_pos++;
2588 16 100         if (I16_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    50          
    50          
    0          
    0          
2589 2 50         EXTEND(SP, 2);
2590 2 50         mXPUSHi(self->nodes[i].key);
2591 2 50         if (GIMME_V == G_SCALAR) XSRETURN(1);
2592 2 50         mXPUSHi(self->nodes[i].value);
2593 2           XSRETURN(2);
2594             }
2595             }
2596 1           self->iter_pos = 0;
2597 1           XSRETURN_EMPTY;
2598              
2599             void
2600             iter_reset(SV* self_sv)
2601             CODE:
2602 0 0         EXTRACT_MAP(HashMapI16, stash_i16, "Data::HashMap::I16", self_sv);
    0          
    0          
    0          
2603 0           self->iter_pos = 0;
2604              
2605             void
2606             clear(SV* self_sv)
2607             CODE:
2608 3 50         EXTRACT_MAP(HashMapI16, stash_i16, "Data::HashMap::I16", self_sv);
    50          
    50          
    50          
2609 3           hashmap_i16_clear(self);
2610              
2611             SV*
2612             to_hash(SV* self_sv)
2613             CODE:
2614 3 50         EXTRACT_MAP(HashMapI16, stash_i16, "Data::HashMap::I16", self_sv);
    50          
    50          
    50          
2615 3           HV* hv = newHV();
2616 3 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
2617             size_t i;
2618 531 100         for (i = 0; i < self->capacity; i++) {
2619 528 100         if (I16_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    100          
    50          
    0          
    0          
2620 199           SV* val = newSViv(self->nodes[i].value);
2621             char kbuf[24];
2622 199           int klen = my_snprintf(kbuf, sizeof(kbuf), "%" IVdf, (IV)self->nodes[i].key);
2623 199           (void)hv_store(hv, kbuf, klen, val, 0);
2624             }
2625             }
2626 3           RETVAL = newRV_noinc((SV*)hv);
2627             OUTPUT:
2628             RETVAL
2629              
2630             bool
2631             put_ttl(SV* self_sv, int16_t key, int16_t value, UV ttl)
2632             CODE:
2633 0 0         EXTRACT_MAP(HashMapI16, stash_i16, "Data::HashMap::I16", self_sv);
    0          
    0          
    0          
2634 0           RETVAL = hashmap_i16_put(self, key, value, (uint32_t)ttl);
2635             OUTPUT:
2636             RETVAL
2637              
2638             SV*
2639             get_or_set(SV* self_sv, int16_t key, int16_t default_value)
2640             CODE:
2641 3 50         EXTRACT_MAP(HashMapI16, stash_i16, "Data::HashMap::I16", self_sv);
    50          
    50          
    50          
2642             bool was_found;
2643 3           size_t idx = hashmap_i16_get_or_set(self, key, default_value, 0, &was_found);
2644             (void)was_found;
2645 3 100         if (idx >= self->capacity) XSRETURN_UNDEF;
2646 2           RETVAL = newSViv(self->nodes[idx].value);
2647             OUTPUT:
2648             RETVAL
2649              
2650              
2651              
2652             MODULE = Data::HashMap PACKAGE = Data::HashMap::I16S
2653             PROTOTYPES: DISABLE
2654              
2655             SV*
2656             new(char* class, ...)
2657             CODE:
2658 14 100         EXTRACT_NEW_ARGS(_max_size, _ttl);
    50          
2659 14           HashMapI16S* map = hashmap_i16s_create(_max_size, _ttl);
2660 14 50         if (!map) croak("Failed to create HashMap::I16S");
2661 14           RETVAL = sv_setref_pv(newSV(0), class, (void*)map);
2662             OUTPUT:
2663             RETVAL
2664              
2665             void
2666             DESTROY(SV* self_sv)
2667             CODE:
2668 14 50         EXTRACT_MAP(HashMapI16S, stash_i16s, "Data::HashMap::I16S", self_sv);
    50          
    50          
    50          
2669 14           hashmap_i16s_destroy(self);
2670 14           sv_setiv(SvRV(self_sv), 0);
2671              
2672             bool
2673             put(SV* self_sv, int16_t key, SV* value)
2674             CODE:
2675 60315 50         EXTRACT_MAP(HashMapI16S, stash_i16s, "Data::HashMap::I16S", self_sv);
    50          
    50          
    50          
2676 60315 50         EXTRACT_STR_VAL(value);
2677 60315           RETVAL = hashmap_i16s_put(self, key, _vstr, (uint32_t)_vlen, _vutf8, 0);
2678             OUTPUT:
2679             RETVAL
2680              
2681             SV*
2682             get(SV* self_sv, int16_t key)
2683             CODE:
2684 30009 50         EXTRACT_MAP(HashMapI16S, stash_i16s, "Data::HashMap::I16S", self_sv);
    50          
    50          
    50          
2685             const char* val;
2686             uint32_t val_len;
2687             bool val_utf8;
2688 30009 100         if (!hashmap_i16s_get(self, key, &val, &val_len, &val_utf8))
2689 3           XSRETURN_UNDEF;
2690 30006           RETVAL = newSVpvn(val, val_len);
2691 30006 100         if (val_utf8) SvUTF8_on(RETVAL);
2692             OUTPUT:
2693             RETVAL
2694              
2695             SV*
2696             get_direct(SV* self_sv, int16_t key)
2697             CODE:
2698 2 50         EXTRACT_MAP(HashMapI16S, stash_i16s, "Data::HashMap::I16S", self_sv);
    50          
    50          
    50          
2699             const char* val;
2700             uint32_t val_len;
2701             bool val_utf8;
2702 2 100         if (!hashmap_i16s_get(self, key, &val, &val_len, &val_utf8))
2703 1           XSRETURN_UNDEF;
2704 1           RETVAL = hm_zerocopy_sv(aTHX_ val, val_len, val_utf8);
2705             OUTPUT:
2706             RETVAL
2707              
2708             bool
2709             remove(SV* self_sv, int16_t key)
2710             CODE:
2711 60006 50         EXTRACT_MAP(HashMapI16S, stash_i16s, "Data::HashMap::I16S", self_sv);
    50          
    50          
    50          
2712 60006           RETVAL = hashmap_i16s_remove(self, key);
2713             OUTPUT:
2714             RETVAL
2715              
2716             bool
2717             exists(SV* self_sv, int16_t key)
2718             CODE:
2719 4 50         EXTRACT_MAP(HashMapI16S, stash_i16s, "Data::HashMap::I16S", self_sv);
    50          
    50          
    50          
2720 4           RETVAL = hashmap_i16s_exists(self, key);
2721             OUTPUT:
2722             RETVAL
2723              
2724             size_t
2725             size(SV* self_sv)
2726             CODE:
2727 8 50         EXTRACT_MAP(HashMapI16S, stash_i16s, "Data::HashMap::I16S", self_sv);
    50          
    50          
    50          
2728 8 50         RETVAL = self->size;
2729             OUTPUT:
2730             RETVAL
2731              
2732             size_t
2733             max_size(SV* self_sv)
2734             CODE:
2735 0 0         EXTRACT_MAP(HashMapI16S, stash_i16s, "Data::HashMap::I16S", self_sv);
    0          
    0          
    0          
2736 0 0         RETVAL = self->max_size;
2737             OUTPUT:
2738             RETVAL
2739              
2740             UV
2741             ttl(SV* self_sv)
2742             CODE:
2743 0 0         EXTRACT_MAP(HashMapI16S, stash_i16s, "Data::HashMap::I16S", self_sv);
    0          
    0          
    0          
2744 0 0         RETVAL = (UV)self->default_ttl;
2745             OUTPUT:
2746             RETVAL
2747              
2748             void
2749             keys(SV* self_sv)
2750             PPCODE:
2751 2 50         EXTRACT_MAP(HashMapI16S, stash_i16s, "Data::HashMap::I16S", self_sv);
    50          
    50          
    50          
2752 2 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
2753 2 50         EXTEND(SP, self->size);
2754             size_t i;
2755 34 100         for (i = 0; i < self->capacity; i++) {
2756 32 100         if (I16S_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now))
    50          
    50          
    0          
    0          
2757 2 50         mXPUSHi(self->nodes[i].key);
2758             }
2759              
2760             void
2761             values(SV* self_sv)
2762             PPCODE:
2763 1 50         EXTRACT_MAP(HashMapI16S, stash_i16s, "Data::HashMap::I16S", self_sv);
    50          
    50          
    50          
2764 1 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
2765 1 50         EXTEND(SP, self->size);
2766             size_t i;
2767 17 100         for (i = 0; i < self->capacity; i++) {
2768 16 100         if (I16S_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    50          
    50          
    0          
    0          
2769 2 50         if (self->nodes[i].value) {
2770 2           SV* sv = newSVpvn(self->nodes[i].value,
2771             HM_UNPACK_LEN(self->nodes[i].val_len));
2772 2 50         if (HM_UNPACK_UTF8(self->nodes[i].val_len)) SvUTF8_on(sv);
2773 2 50         mXPUSHs(sv);
2774             } else {
2775 0 0         XPUSHs(&PL_sv_undef);
2776             }
2777             }
2778             }
2779              
2780             void
2781             items(SV* self_sv)
2782             PPCODE:
2783 1 50         EXTRACT_MAP(HashMapI16S, stash_i16s, "Data::HashMap::I16S", self_sv);
    50          
    50          
    50          
2784 1 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
2785 1 50         EXTEND(SP, self->size * 2);
2786             size_t i;
2787 17 100         for (i = 0; i < self->capacity; i++) {
2788 16 100         if (I16S_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    50          
    50          
    0          
    0          
2789 2 50         mXPUSHi(self->nodes[i].key);
2790 2 50         if (self->nodes[i].value) {
2791 2           SV* sv = newSVpvn(self->nodes[i].value,
2792             HM_UNPACK_LEN(self->nodes[i].val_len));
2793 2 50         if (HM_UNPACK_UTF8(self->nodes[i].val_len)) SvUTF8_on(sv);
2794 2 50         mXPUSHs(sv);
2795             } else {
2796 0 0         XPUSHs(&PL_sv_undef);
2797             }
2798             }
2799             }
2800              
2801             void
2802             each(SV* self_sv)
2803             PPCODE:
2804 3 50         EXTRACT_MAP(HashMapI16S, stash_i16s, "Data::HashMap::I16S", self_sv);
    50          
    50          
    50          
2805 3 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
2806 17 100         while (self->iter_pos < self->capacity) {
2807 16           size_t i = self->iter_pos++;
2808 16 100         if (I16S_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    50          
    50          
    0          
    0          
2809 2 50         EXTEND(SP, 2);
2810 2 50         mXPUSHi(self->nodes[i].key);
2811 2 50         if (GIMME_V == G_SCALAR) XSRETURN(1);
2812 2 50         if (self->nodes[i].value) {
2813 2           SV* vsv = newSVpvn(self->nodes[i].value,
2814             HM_UNPACK_LEN(self->nodes[i].val_len));
2815 2 50         if (HM_UNPACK_UTF8(self->nodes[i].val_len)) SvUTF8_on(vsv);
2816 2 50         mXPUSHs(vsv);
2817             } else {
2818 0 0         XPUSHs(&PL_sv_undef);
2819             }
2820 2           XSRETURN(2);
2821             }
2822             }
2823 1           self->iter_pos = 0;
2824 1           XSRETURN_EMPTY;
2825              
2826             void
2827             iter_reset(SV* self_sv)
2828             CODE:
2829 0 0         EXTRACT_MAP(HashMapI16S, stash_i16s, "Data::HashMap::I16S", self_sv);
    0          
    0          
    0          
2830 0           self->iter_pos = 0;
2831              
2832             void
2833             clear(SV* self_sv)
2834             CODE:
2835 3 50         EXTRACT_MAP(HashMapI16S, stash_i16s, "Data::HashMap::I16S", self_sv);
    50          
    50          
    50          
2836 3           hashmap_i16s_clear(self);
2837              
2838             SV*
2839             to_hash(SV* self_sv)
2840             CODE:
2841 0 0         EXTRACT_MAP(HashMapI16S, stash_i16s, "Data::HashMap::I16S", self_sv);
    0          
    0          
    0          
2842 0           HV* hv = newHV();
2843 0 0         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
2844             size_t i;
2845 0 0         for (i = 0; i < self->capacity; i++) {
2846 0 0         if (I16S_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    0          
    0          
    0          
    0          
2847 0           uint32_t vlen = HM_UNPACK_LEN(self->nodes[i].val_len);
2848 0           bool vutf8 = HM_UNPACK_UTF8(self->nodes[i].val_len);
2849 0           SV* val = self->nodes[i].value
2850 0           ? newSVpvn(self->nodes[i].value, vlen)
2851 0 0         : newSV(0);
2852 0 0         if (self->nodes[i].value && vutf8) SvUTF8_on(val);
    0          
2853             char kbuf[24];
2854 0           int klen = my_snprintf(kbuf, sizeof(kbuf), "%" IVdf, (IV)self->nodes[i].key);
2855 0           (void)hv_store(hv, kbuf, klen, val, 0);
2856             }
2857             }
2858 0           RETVAL = newRV_noinc((SV*)hv);
2859             OUTPUT:
2860             RETVAL
2861              
2862             bool
2863             put_ttl(SV* self_sv, int16_t key, SV* value, UV ttl)
2864             CODE:
2865 0 0         EXTRACT_MAP(HashMapI16S, stash_i16s, "Data::HashMap::I16S", self_sv);
    0          
    0          
    0          
2866 0 0         EXTRACT_STR_VAL(value);
2867 0           RETVAL = hashmap_i16s_put(self, key, _vstr, (uint32_t)_vlen, _vutf8, (uint32_t)ttl);
2868             OUTPUT:
2869             RETVAL
2870              
2871             SV*
2872             get_or_set(SV* self_sv, int16_t key, SV* default_sv)
2873             CODE:
2874 1 50         EXTRACT_MAP(HashMapI16S, stash_i16s, "Data::HashMap::I16S", self_sv);
    50          
    50          
    50          
2875 1 50         EXTRACT_STR_VAL(default_sv);
2876             bool was_found;
2877 1           size_t idx = hashmap_i16s_get_or_set(self, key, _vstr, (uint32_t)_vlen, _vutf8, 0, &was_found);
2878             (void)was_found;
2879 1 50         if (idx >= self->capacity) XSRETURN_UNDEF;
2880 1 50         if (self->nodes[idx].value) {
2881 1           RETVAL = newSVpvn(self->nodes[idx].value, HM_UNPACK_LEN(self->nodes[idx].val_len));
2882 1 50         if (HM_UNPACK_UTF8(self->nodes[idx].val_len)) SvUTF8_on(RETVAL);
2883             } else {
2884 0           RETVAL = newSV(0);
2885             }
2886             OUTPUT:
2887             RETVAL
2888              
2889              
2890              
2891             MODULE = Data::HashMap PACKAGE = Data::HashMap::SI16
2892             PROTOTYPES: DISABLE
2893              
2894             SV*
2895             new(char* class, ...)
2896             CODE:
2897 14 100         EXTRACT_NEW_ARGS(_max_size, _ttl);
    100          
2898 14           HashMapSI16* map = hashmap_si16_create(_max_size, _ttl);
2899 14 50         if (!map) croak("Failed to create HashMap::SI16");
2900 14           RETVAL = sv_setref_pv(newSV(0), class, (void*)map);
2901             OUTPUT:
2902             RETVAL
2903              
2904             void
2905             DESTROY(SV* self_sv)
2906             CODE:
2907 14 50         EXTRACT_MAP(HashMapSI16, stash_si16, "Data::HashMap::SI16", self_sv);
    50          
    50          
    50          
2908 14           hashmap_si16_destroy(self);
2909 14           sv_setiv(SvRV(self_sv), 0);
2910              
2911             bool
2912             put(SV* self_sv, SV* key_sv, int16_t value)
2913             CODE:
2914 80119 50         EXTRACT_MAP(HashMapSI16, stash_si16, "Data::HashMap::SI16", self_sv);
    50          
    50          
    50          
2915 80119 50         EXTRACT_STR_KEY(key_sv);
2916 80119           RETVAL = hashmap_si16_put(self, _kstr, (uint32_t)_klen, _khash, _kutf8, value, 0);
2917             OUTPUT:
2918             RETVAL
2919              
2920             SV*
2921             get(SV* self_sv, SV* key_sv)
2922             CODE:
2923 50010 50         EXTRACT_MAP(HashMapSI16, stash_si16, "Data::HashMap::SI16", self_sv);
    50          
    50          
    50          
2924 50010 50         EXTRACT_STR_KEY(key_sv);
2925             int16_t value;
2926 50010 100         if (!hashmap_si16_get(self, _kstr, (uint32_t)_klen, _khash, _kutf8, &value))
2927 4           XSRETURN_UNDEF;
2928 50006           RETVAL = newSViv(value);
2929             OUTPUT:
2930             RETVAL
2931              
2932             bool
2933             remove(SV* self_sv, SV* key_sv)
2934             CODE:
2935 80005 50         EXTRACT_MAP(HashMapSI16, stash_si16, "Data::HashMap::SI16", self_sv);
    50          
    50          
    50          
2936 80005 50         EXTRACT_STR_KEY(key_sv);
2937 80005           RETVAL = hashmap_si16_remove(self, _kstr, (uint32_t)_klen, _khash, _kutf8);
2938             OUTPUT:
2939             RETVAL
2940              
2941             bool
2942             exists(SV* self_sv, SV* key_sv)
2943             CODE:
2944 4 50         EXTRACT_MAP(HashMapSI16, stash_si16, "Data::HashMap::SI16", self_sv);
    50          
    50          
    50          
2945 4 50         EXTRACT_STR_KEY(key_sv);
2946 4           RETVAL = hashmap_si16_exists(self, _kstr, (uint32_t)_klen, _khash, _kutf8);
2947             OUTPUT:
2948             RETVAL
2949              
2950             SV*
2951             incr(SV* self_sv, SV* key_sv)
2952             CODE:
2953 10 50         EXTRACT_MAP(HashMapSI16, stash_si16, "Data::HashMap::SI16", self_sv);
    50          
    50          
    50          
2954 10 50         EXTRACT_STR_KEY(key_sv);
2955             int16_t val;
2956 10 100         if (!hashmap_si16_increment(self, _kstr, (uint32_t)_klen, _khash, _kutf8, &val))
2957 1           croak("HashMap::SI16: increment failed");
2958 9           RETVAL = newSViv(val);
2959             OUTPUT:
2960             RETVAL
2961              
2962             SV*
2963             decr(SV* self_sv, SV* key_sv)
2964             CODE:
2965 5 50         EXTRACT_MAP(HashMapSI16, stash_si16, "Data::HashMap::SI16", self_sv);
    50          
    50          
    50          
2966 5 50         EXTRACT_STR_KEY(key_sv);
2967             int16_t val;
2968 5 100         if (!hashmap_si16_decrement(self, _kstr, (uint32_t)_klen, _khash, _kutf8, &val))
2969 1           croak("HashMap::SI16: decrement failed");
2970 4           RETVAL = newSViv(val);
2971             OUTPUT:
2972             RETVAL
2973              
2974             SV*
2975             incr_by(SV* self_sv, SV* key_sv, int16_t delta)
2976             CODE:
2977 6 50         EXTRACT_MAP(HashMapSI16, stash_si16, "Data::HashMap::SI16", self_sv);
    50          
    50          
    50          
2978 6 50         EXTRACT_STR_KEY(key_sv);
2979             int16_t val;
2980 6 100         if (!hashmap_si16_increment_by(self, _kstr, (uint32_t)_klen, _khash, _kutf8, delta, &val))
2981 2           croak("HashMap::SI16: incr_by failed");
2982 4           RETVAL = newSViv(val);
2983             OUTPUT:
2984             RETVAL
2985              
2986             size_t
2987             size(SV* self_sv)
2988             CODE:
2989 6 50         EXTRACT_MAP(HashMapSI16, stash_si16, "Data::HashMap::SI16", self_sv);
    50          
    50          
    50          
2990 6 50         RETVAL = self->size;
2991             OUTPUT:
2992             RETVAL
2993              
2994             size_t
2995             max_size(SV* self_sv)
2996             CODE:
2997 0 0         EXTRACT_MAP(HashMapSI16, stash_si16, "Data::HashMap::SI16", self_sv);
    0          
    0          
    0          
2998 0 0         RETVAL = self->max_size;
2999             OUTPUT:
3000             RETVAL
3001              
3002             UV
3003             ttl(SV* self_sv)
3004             CODE:
3005 0 0         EXTRACT_MAP(HashMapSI16, stash_si16, "Data::HashMap::SI16", self_sv);
    0          
    0          
    0          
3006 0 0         RETVAL = (UV)self->default_ttl;
3007             OUTPUT:
3008             RETVAL
3009              
3010             void
3011             keys(SV* self_sv)
3012             PPCODE:
3013 2 50         EXTRACT_MAP(HashMapSI16, stash_si16, "Data::HashMap::SI16", self_sv);
    50          
    50          
    50          
3014 2 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
3015 2 50         EXTEND(SP, self->size);
3016             size_t i;
3017 34 100         for (i = 0; i < self->capacity; i++) {
3018 32 100         if (SI16_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    50          
    50          
    0          
    0          
3019 2           uint32_t klen = HM_UNPACK_LEN(self->nodes[i].key_len);
3020 2           SV* sv = newSVpvn(self->nodes[i].key, klen);
3021 2 50         if (HM_UNPACK_UTF8(self->nodes[i].key_len)) SvUTF8_on(sv);
3022 2 50         mXPUSHs(sv);
3023             }
3024             }
3025              
3026             void
3027             values(SV* self_sv)
3028             PPCODE:
3029 1 50         EXTRACT_MAP(HashMapSI16, stash_si16, "Data::HashMap::SI16", self_sv);
    50          
    50          
    50          
3030 1 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
3031 1 50         EXTEND(SP, self->size);
3032             size_t i;
3033 17 100         for (i = 0; i < self->capacity; i++) {
3034 16 100         if (SI16_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now))
    50          
    50          
    0          
    0          
3035 2 50         mXPUSHi(self->nodes[i].value);
3036             }
3037              
3038             void
3039             items(SV* self_sv)
3040             PPCODE:
3041 1 50         EXTRACT_MAP(HashMapSI16, stash_si16, "Data::HashMap::SI16", self_sv);
    50          
    50          
    50          
3042 1 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
3043 1 50         EXTEND(SP, self->size * 2);
3044             size_t i;
3045 17 100         for (i = 0; i < self->capacity; i++) {
3046 16 100         if (SI16_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    50          
    50          
    0          
    0          
3047 2           uint32_t klen = HM_UNPACK_LEN(self->nodes[i].key_len);
3048 2           SV* sv = newSVpvn(self->nodes[i].key, klen);
3049 2 50         if (HM_UNPACK_UTF8(self->nodes[i].key_len)) SvUTF8_on(sv);
3050 2 50         mXPUSHs(sv);
3051 2 50         mXPUSHi(self->nodes[i].value);
3052             }
3053             }
3054              
3055             void
3056             each(SV* self_sv)
3057             PPCODE:
3058 3 50         EXTRACT_MAP(HashMapSI16, stash_si16, "Data::HashMap::SI16", self_sv);
    50          
    50          
    50          
3059 3 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
3060 17 100         while (self->iter_pos < self->capacity) {
3061 16           size_t i = self->iter_pos++;
3062 16 100         if (SI16_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    50          
    50          
    0          
    0          
3063 2 50         EXTEND(SP, 2);
3064             {
3065 2           uint32_t klen = HM_UNPACK_LEN(self->nodes[i].key_len);
3066 2           SV* ksv = newSVpvn(self->nodes[i].key, klen);
3067 2 50         if (HM_UNPACK_UTF8(self->nodes[i].key_len)) SvUTF8_on(ksv);
3068 2 50         mXPUSHs(ksv);
3069             }
3070 2 50         if (GIMME_V == G_SCALAR) XSRETURN(1);
3071 2 50         mXPUSHi(self->nodes[i].value);
3072 2           XSRETURN(2);
3073             }
3074             }
3075 1           self->iter_pos = 0;
3076 1           XSRETURN_EMPTY;
3077              
3078             void
3079             iter_reset(SV* self_sv)
3080             CODE:
3081 0 0         EXTRACT_MAP(HashMapSI16, stash_si16, "Data::HashMap::SI16", self_sv);
    0          
    0          
    0          
3082 0           self->iter_pos = 0;
3083              
3084             void
3085             clear(SV* self_sv)
3086             CODE:
3087 2 50         EXTRACT_MAP(HashMapSI16, stash_si16, "Data::HashMap::SI16", self_sv);
    50          
    50          
    50          
3088 2           hashmap_si16_clear(self);
3089              
3090             SV*
3091             to_hash(SV* self_sv)
3092             CODE:
3093 1 50         EXTRACT_MAP(HashMapSI16, stash_si16, "Data::HashMap::SI16", self_sv);
    50          
    50          
    50          
3094 1           HV* hv = newHV();
3095 1 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
3096             size_t i;
3097 17 100         for (i = 0; i < self->capacity; i++) {
3098 16 100         if (SI16_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    50          
    50          
    0          
    0          
3099 1           uint32_t klen = HM_UNPACK_LEN(self->nodes[i].key_len);
3100 1           bool kutf8 = HM_UNPACK_UTF8(self->nodes[i].key_len);
3101 1           SV* val = newSViv(self->nodes[i].value);
3102 1 50         (void)hv_store(hv, self->nodes[i].key, kutf8 ? -(I32)klen : (I32)klen, val, 0);
3103             }
3104             }
3105 1           RETVAL = newRV_noinc((SV*)hv);
3106             OUTPUT:
3107             RETVAL
3108              
3109             bool
3110             put_ttl(SV* self_sv, SV* key_sv, int16_t value, UV ttl)
3111             CODE:
3112 1 50         EXTRACT_MAP(HashMapSI16, stash_si16, "Data::HashMap::SI16", self_sv);
    50          
    50          
    50          
3113 1 50         EXTRACT_STR_KEY(key_sv);
3114 1           RETVAL = hashmap_si16_put(self, _kstr, (uint32_t)_klen, _khash, _kutf8, value, (uint32_t)ttl);
3115             OUTPUT:
3116             RETVAL
3117              
3118             SV*
3119             get_or_set(SV* self_sv, SV* key_sv, int16_t default_value)
3120             CODE:
3121 0 0         EXTRACT_MAP(HashMapSI16, stash_si16, "Data::HashMap::SI16", self_sv);
    0          
    0          
    0          
3122 0 0         EXTRACT_STR_KEY(key_sv);
3123             bool was_found;
3124 0           size_t idx = hashmap_si16_get_or_set(self, _kstr, (uint32_t)_klen, _khash, _kutf8, default_value, 0, &was_found);
3125             (void)was_found;
3126 0 0         if (idx >= self->capacity) XSRETURN_UNDEF;
3127 0           RETVAL = newSViv(self->nodes[idx].value);
3128             OUTPUT:
3129             RETVAL
3130              
3131              
3132              
3133             MODULE = Data::HashMap PACKAGE = Data::HashMap::I32A
3134             PROTOTYPES: DISABLE
3135              
3136             SV*
3137             new(char* class, ...)
3138             CODE:
3139 15 100         EXTRACT_NEW_ARGS(_max_size, _ttl);
    100          
3140 15           HashMapI32A* map = hashmap_i32a_create(_max_size, _ttl);
3141 15 50         if (!map) croak("Failed to create HashMap::I32A");
3142 15           map->free_value_fn = hm_sv_free;
3143 15           RETVAL = sv_setref_pv(newSV(0), class, (void*)map);
3144             OUTPUT:
3145             RETVAL
3146              
3147             void
3148             DESTROY(SV* self_sv)
3149             CODE:
3150 15 50         EXTRACT_MAP(HashMapI32A, stash_i32a, "Data::HashMap::I32A", self_sv);
    50          
    50          
    50          
3151 15           hashmap_i32a_destroy(self);
3152 15           sv_setiv(SvRV(self_sv), 0);
3153              
3154             bool
3155             put(SV* self_sv, int32_t key, SV* value)
3156             CODE:
3157 50127 50         EXTRACT_MAP(HashMapI32A, stash_i32a, "Data::HashMap::I32A", self_sv);
    50          
    50          
    50          
3158 50127           SvREFCNT_inc(value);
3159 50127           RETVAL = hashmap_i32a_put(self, key, (void*)value, 0);
3160 50127 100         if (!RETVAL) SvREFCNT_dec(value);
3161             OUTPUT:
3162             RETVAL
3163              
3164             SV*
3165             get(SV* self_sv, int32_t key)
3166             CODE:
3167 50016 50         EXTRACT_MAP(HashMapI32A, stash_i32a, "Data::HashMap::I32A", self_sv);
    50          
    50          
    50          
3168             void* val;
3169 50016 100         if (!hashmap_i32a_get(self, key, &val)) XSRETURN_UNDEF;
3170 50012           RETVAL = SvREFCNT_inc((SV*)val);
3171             OUTPUT:
3172             RETVAL
3173              
3174             bool
3175             remove(SV* self_sv, int32_t key)
3176             CODE:
3177 50005 50         EXTRACT_MAP(HashMapI32A, stash_i32a, "Data::HashMap::I32A", self_sv);
    50          
    50          
    50          
3178 50005           RETVAL = hashmap_i32a_remove(self, key);
3179             OUTPUT:
3180             RETVAL
3181              
3182             bool
3183             exists(SV* self_sv, int32_t key)
3184             CODE:
3185 3 50         EXTRACT_MAP(HashMapI32A, stash_i32a, "Data::HashMap::I32A", self_sv);
    50          
    50          
    50          
3186 3           RETVAL = hashmap_i32a_exists(self, key);
3187             OUTPUT:
3188             RETVAL
3189              
3190             size_t
3191             size(SV* self_sv)
3192             CODE:
3193 9 50         EXTRACT_MAP(HashMapI32A, stash_i32a, "Data::HashMap::I32A", self_sv);
    50          
    50          
    50          
3194 9 50         RETVAL = self->size;
3195             OUTPUT:
3196             RETVAL
3197              
3198             size_t
3199             max_size(SV* self_sv)
3200             CODE:
3201 0 0         EXTRACT_MAP(HashMapI32A, stash_i32a, "Data::HashMap::I32A", self_sv);
    0          
    0          
    0          
3202 0 0         RETVAL = self->max_size;
3203             OUTPUT:
3204             RETVAL
3205              
3206             UV
3207             ttl(SV* self_sv)
3208             CODE:
3209 0 0         EXTRACT_MAP(HashMapI32A, stash_i32a, "Data::HashMap::I32A", self_sv);
    0          
    0          
    0          
3210 0 0         RETVAL = (UV)self->default_ttl;
3211             OUTPUT:
3212             RETVAL
3213              
3214             void
3215             keys(SV* self_sv)
3216             PPCODE:
3217 1 50         EXTRACT_MAP(HashMapI32A, stash_i32a, "Data::HashMap::I32A", self_sv);
    50          
    50          
    50          
3218 1 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
3219 1 50         EXTEND(SP, self->size);
3220             size_t i;
3221 17 100         for (i = 0; i < self->capacity; i++) {
3222 16 100         if (I32A_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now))
    50          
    50          
    0          
    0          
3223 2 50         mXPUSHi(self->nodes[i].key);
3224             }
3225              
3226             void
3227             values(SV* self_sv)
3228             PPCODE:
3229 1 50         EXTRACT_MAP(HashMapI32A, stash_i32a, "Data::HashMap::I32A", self_sv);
    50          
    50          
    50          
3230 1 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
3231 1 50         EXTEND(SP, self->size);
3232             size_t i;
3233 17 100         for (i = 0; i < self->capacity; i++) {
3234 16 100         if (I32A_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    50          
    50          
    0          
    0          
3235 2 50         SV* sv = self->nodes[i].value ? SvREFCNT_inc((SV*)self->nodes[i].value) : &PL_sv_undef;
3236 2 50         mXPUSHs(sv);
3237             }
3238             }
3239              
3240             void
3241             items(SV* self_sv)
3242             PPCODE:
3243 1 50         EXTRACT_MAP(HashMapI32A, stash_i32a, "Data::HashMap::I32A", self_sv);
    50          
    50          
    50          
3244 1 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
3245 1 50         EXTEND(SP, self->size * 2);
3246             size_t i;
3247 17 100         for (i = 0; i < self->capacity; i++) {
3248 16 100         if (I32A_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    50          
    50          
    0          
    0          
3249 2 50         mXPUSHi(self->nodes[i].key);
3250 2 50         SV* sv = self->nodes[i].value ? SvREFCNT_inc((SV*)self->nodes[i].value) : &PL_sv_undef;
3251 2 50         mXPUSHs(sv);
3252             }
3253             }
3254              
3255             void
3256             each(SV* self_sv)
3257             PPCODE:
3258 6 50         EXTRACT_MAP(HashMapI32A, stash_i32a, "Data::HashMap::I32A", self_sv);
    50          
    50          
    50          
3259 6 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
3260 34 100         while (self->iter_pos < self->capacity) {
3261 32           size_t i = self->iter_pos++;
3262 32 100         if (I32A_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    50          
    50          
    0          
    0          
3263 4 50         EXTEND(SP, 2);
3264 4 50         mXPUSHi(self->nodes[i].key);
3265 4 50         if (GIMME_V == G_SCALAR) XSRETURN(1);
3266 4 50         SV* sv = self->nodes[i].value ? SvREFCNT_inc((SV*)self->nodes[i].value) : &PL_sv_undef;
3267 4 50         mXPUSHs(sv);
3268 4           XSRETURN(2);
3269             }
3270             }
3271 2           self->iter_pos = 0;
3272 2           XSRETURN_EMPTY;
3273              
3274             void
3275             iter_reset(SV* self_sv)
3276             CODE:
3277 0 0         EXTRACT_MAP(HashMapI32A, stash_i32a, "Data::HashMap::I32A", self_sv);
    0          
    0          
    0          
3278 0           self->iter_pos = 0;
3279              
3280             void
3281             clear(SV* self_sv)
3282             CODE:
3283 3 50         EXTRACT_MAP(HashMapI32A, stash_i32a, "Data::HashMap::I32A", self_sv);
    50          
    50          
    50          
3284 3           hashmap_i32a_clear(self);
3285              
3286             SV*
3287             to_hash(SV* self_sv)
3288             CODE:
3289 1 50         EXTRACT_MAP(HashMapI32A, stash_i32a, "Data::HashMap::I32A", self_sv);
    50          
    50          
    50          
3290 1           HV* hv = newHV();
3291 1 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
3292             size_t i;
3293 17 100         for (i = 0; i < self->capacity; i++) {
3294 16 100         if (I32A_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    50          
    50          
    0          
    0          
3295 1 50         SV* val = self->nodes[i].value ? SvREFCNT_inc((SV*)self->nodes[i].value) : &PL_sv_undef;
3296             char kbuf[24];
3297 1           int klen = my_snprintf(kbuf, sizeof(kbuf), "%" IVdf, (IV)self->nodes[i].key);
3298 1           (void)hv_store(hv, kbuf, klen, val, 0);
3299             }
3300             }
3301 1           RETVAL = newRV_noinc((SV*)hv);
3302             OUTPUT:
3303             RETVAL
3304              
3305             bool
3306             put_ttl(SV* self_sv, int32_t key, SV* value, UV ttl)
3307             CODE:
3308 0 0         EXTRACT_MAP(HashMapI32A, stash_i32a, "Data::HashMap::I32A", self_sv);
    0          
    0          
    0          
3309 0           SvREFCNT_inc(value);
3310 0           RETVAL = hashmap_i32a_put(self, key, (void*)value, (uint32_t)ttl);
3311 0 0         if (!RETVAL) SvREFCNT_dec(value);
3312             OUTPUT:
3313             RETVAL
3314              
3315             SV*
3316             get_or_set(SV* self_sv, int32_t key, SV* default_value)
3317             CODE:
3318 2 50         EXTRACT_MAP(HashMapI32A, stash_i32a, "Data::HashMap::I32A", self_sv);
    50          
    50          
    50          
3319             bool was_found;
3320 2           SvREFCNT_inc(default_value);
3321 2           size_t idx = hashmap_i32a_get_or_set(self, key, (void*)default_value, 0, &was_found);
3322 2 50         if (idx >= self->capacity) {
3323 0           SvREFCNT_dec(default_value);
3324 0           XSRETURN_UNDEF;
3325             }
3326 2 50         if (was_found) SvREFCNT_dec(default_value);
3327 2           RETVAL = SvREFCNT_inc((SV*)self->nodes[idx].value);
3328             OUTPUT:
3329             RETVAL
3330              
3331              
3332              
3333             MODULE = Data::HashMap PACKAGE = Data::HashMap::I16A
3334             PROTOTYPES: DISABLE
3335              
3336             SV*
3337             new(char* class, ...)
3338             CODE:
3339 15 100         EXTRACT_NEW_ARGS(_max_size, _ttl);
    100          
3340 15           HashMapI16A* map = hashmap_i16a_create(_max_size, _ttl);
3341 15 50         if (!map) croak("Failed to create HashMap::I16A");
3342 15           map->free_value_fn = hm_sv_free;
3343 15           RETVAL = sv_setref_pv(newSV(0), class, (void*)map);
3344             OUTPUT:
3345             RETVAL
3346              
3347             void
3348             DESTROY(SV* self_sv)
3349             CODE:
3350 15 50         EXTRACT_MAP(HashMapI16A, stash_i16a, "Data::HashMap::I16A", self_sv);
    50          
    50          
    50          
3351 15           hashmap_i16a_destroy(self);
3352 15           sv_setiv(SvRV(self_sv), 0);
3353              
3354             bool
3355             put(SV* self_sv, int16_t key, SV* value)
3356             CODE:
3357 30067 50         EXTRACT_MAP(HashMapI16A, stash_i16a, "Data::HashMap::I16A", self_sv);
    50          
    50          
    50          
3358 30067           SvREFCNT_inc(value);
3359 30067           RETVAL = hashmap_i16a_put(self, key, (void*)value, 0);
3360 30067 100         if (!RETVAL) SvREFCNT_dec(value);
3361             OUTPUT:
3362             RETVAL
3363              
3364             SV*
3365             get(SV* self_sv, int16_t key)
3366             CODE:
3367 30016 50         EXTRACT_MAP(HashMapI16A, stash_i16a, "Data::HashMap::I16A", self_sv);
    50          
    50          
    50          
3368             void* val;
3369 30016 100         if (!hashmap_i16a_get(self, key, &val)) XSRETURN_UNDEF;
3370 30012           RETVAL = SvREFCNT_inc((SV*)val);
3371             OUTPUT:
3372             RETVAL
3373              
3374             bool
3375             remove(SV* self_sv, int16_t key)
3376             CODE:
3377 30005 50         EXTRACT_MAP(HashMapI16A, stash_i16a, "Data::HashMap::I16A", self_sv);
    50          
    50          
    50          
3378 30005           RETVAL = hashmap_i16a_remove(self, key);
3379             OUTPUT:
3380             RETVAL
3381              
3382             bool
3383             exists(SV* self_sv, int16_t key)
3384             CODE:
3385 3 50         EXTRACT_MAP(HashMapI16A, stash_i16a, "Data::HashMap::I16A", self_sv);
    50          
    50          
    50          
3386 3           RETVAL = hashmap_i16a_exists(self, key);
3387             OUTPUT:
3388             RETVAL
3389              
3390             size_t
3391             size(SV* self_sv)
3392             CODE:
3393 9 50         EXTRACT_MAP(HashMapI16A, stash_i16a, "Data::HashMap::I16A", self_sv);
    50          
    50          
    50          
3394 9 50         RETVAL = self->size;
3395             OUTPUT:
3396             RETVAL
3397              
3398             size_t
3399             max_size(SV* self_sv)
3400             CODE:
3401 0 0         EXTRACT_MAP(HashMapI16A, stash_i16a, "Data::HashMap::I16A", self_sv);
    0          
    0          
    0          
3402 0 0         RETVAL = self->max_size;
3403             OUTPUT:
3404             RETVAL
3405              
3406             UV
3407             ttl(SV* self_sv)
3408             CODE:
3409 0 0         EXTRACT_MAP(HashMapI16A, stash_i16a, "Data::HashMap::I16A", self_sv);
    0          
    0          
    0          
3410 0 0         RETVAL = (UV)self->default_ttl;
3411             OUTPUT:
3412             RETVAL
3413              
3414             void
3415             keys(SV* self_sv)
3416             PPCODE:
3417 1 50         EXTRACT_MAP(HashMapI16A, stash_i16a, "Data::HashMap::I16A", self_sv);
    50          
    50          
    50          
3418 1 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
3419 1 50         EXTEND(SP, self->size);
3420             size_t i;
3421 17 100         for (i = 0; i < self->capacity; i++) {
3422 16 100         if (I16A_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now))
    50          
    50          
    0          
    0          
3423 2 50         mXPUSHi(self->nodes[i].key);
3424             }
3425              
3426             void
3427             values(SV* self_sv)
3428             PPCODE:
3429 1 50         EXTRACT_MAP(HashMapI16A, stash_i16a, "Data::HashMap::I16A", self_sv);
    50          
    50          
    50          
3430 1 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
3431 1 50         EXTEND(SP, self->size);
3432             size_t i;
3433 17 100         for (i = 0; i < self->capacity; i++) {
3434 16 100         if (I16A_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    50          
    50          
    0          
    0          
3435 2 50         SV* sv = self->nodes[i].value ? SvREFCNT_inc((SV*)self->nodes[i].value) : &PL_sv_undef;
3436 2 50         mXPUSHs(sv);
3437             }
3438             }
3439              
3440             void
3441             items(SV* self_sv)
3442             PPCODE:
3443 1 50         EXTRACT_MAP(HashMapI16A, stash_i16a, "Data::HashMap::I16A", self_sv);
    50          
    50          
    50          
3444 1 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
3445 1 50         EXTEND(SP, self->size * 2);
3446             size_t i;
3447 17 100         for (i = 0; i < self->capacity; i++) {
3448 16 100         if (I16A_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    50          
    50          
    0          
    0          
3449 2 50         mXPUSHi(self->nodes[i].key);
3450 2 50         SV* sv = self->nodes[i].value ? SvREFCNT_inc((SV*)self->nodes[i].value) : &PL_sv_undef;
3451 2 50         mXPUSHs(sv);
3452             }
3453             }
3454              
3455             void
3456             each(SV* self_sv)
3457             PPCODE:
3458 6 50         EXTRACT_MAP(HashMapI16A, stash_i16a, "Data::HashMap::I16A", self_sv);
    50          
    50          
    50          
3459 6 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
3460 34 100         while (self->iter_pos < self->capacity) {
3461 32           size_t i = self->iter_pos++;
3462 32 100         if (I16A_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    50          
    50          
    0          
    0          
3463 4 50         EXTEND(SP, 2);
3464 4 50         mXPUSHi(self->nodes[i].key);
3465 4 50         if (GIMME_V == G_SCALAR) XSRETURN(1);
3466 4 50         SV* sv = self->nodes[i].value ? SvREFCNT_inc((SV*)self->nodes[i].value) : &PL_sv_undef;
3467 4 50         mXPUSHs(sv);
3468 4           XSRETURN(2);
3469             }
3470             }
3471 2           self->iter_pos = 0;
3472 2           XSRETURN_EMPTY;
3473              
3474             void
3475             iter_reset(SV* self_sv)
3476             CODE:
3477 0 0         EXTRACT_MAP(HashMapI16A, stash_i16a, "Data::HashMap::I16A", self_sv);
    0          
    0          
    0          
3478 0           self->iter_pos = 0;
3479              
3480             void
3481             clear(SV* self_sv)
3482             CODE:
3483 3 50         EXTRACT_MAP(HashMapI16A, stash_i16a, "Data::HashMap::I16A", self_sv);
    50          
    50          
    50          
3484 3           hashmap_i16a_clear(self);
3485              
3486             SV*
3487             to_hash(SV* self_sv)
3488             CODE:
3489 0 0         EXTRACT_MAP(HashMapI16A, stash_i16a, "Data::HashMap::I16A", self_sv);
    0          
    0          
    0          
3490 0           HV* hv = newHV();
3491 0 0         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
3492             size_t i;
3493 0 0         for (i = 0; i < self->capacity; i++) {
3494 0 0         if (I16A_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    0          
    0          
    0          
    0          
3495 0 0         SV* val = self->nodes[i].value ? SvREFCNT_inc((SV*)self->nodes[i].value) : &PL_sv_undef;
3496             char kbuf[24];
3497 0           int klen = my_snprintf(kbuf, sizeof(kbuf), "%" IVdf, (IV)self->nodes[i].key);
3498 0           (void)hv_store(hv, kbuf, klen, val, 0);
3499             }
3500             }
3501 0           RETVAL = newRV_noinc((SV*)hv);
3502             OUTPUT:
3503             RETVAL
3504              
3505             bool
3506             put_ttl(SV* self_sv, int16_t key, SV* value, UV ttl)
3507             CODE:
3508 0 0         EXTRACT_MAP(HashMapI16A, stash_i16a, "Data::HashMap::I16A", self_sv);
    0          
    0          
    0          
3509 0           SvREFCNT_inc(value);
3510 0           RETVAL = hashmap_i16a_put(self, key, (void*)value, (uint32_t)ttl);
3511 0 0         if (!RETVAL) SvREFCNT_dec(value);
3512             OUTPUT:
3513             RETVAL
3514              
3515             SV*
3516             get_or_set(SV* self_sv, int16_t key, SV* default_value)
3517             CODE:
3518 2 50         EXTRACT_MAP(HashMapI16A, stash_i16a, "Data::HashMap::I16A", self_sv);
    50          
    50          
    50          
3519             bool was_found;
3520 2           SvREFCNT_inc(default_value);
3521 2           size_t idx = hashmap_i16a_get_or_set(self, key, (void*)default_value, 0, &was_found);
3522 2 50         if (idx >= self->capacity) {
3523 0           SvREFCNT_dec(default_value);
3524 0           XSRETURN_UNDEF;
3525             }
3526 2 50         if (was_found) SvREFCNT_dec(default_value);
3527 2           RETVAL = SvREFCNT_inc((SV*)self->nodes[idx].value);
3528             OUTPUT:
3529             RETVAL
3530              
3531              
3532              
3533             MODULE = Data::HashMap PACKAGE = Data::HashMap::IA
3534             PROTOTYPES: DISABLE
3535              
3536             SV*
3537             new(char* class, ...)
3538             CODE:
3539 47 100         EXTRACT_NEW_ARGS(_max_size, _ttl);
    100          
3540 47           HashMapIA* map = hashmap_ia_create(_max_size, _ttl);
3541 47 50         if (!map) croak("Failed to create HashMap::IA");
3542 47           map->free_value_fn = hm_sv_free;
3543 47           RETVAL = sv_setref_pv(newSV(0), class, (void*)map);
3544             OUTPUT:
3545             RETVAL
3546              
3547             void
3548             DESTROY(SV* self_sv)
3549             CODE:
3550 47 50         EXTRACT_MAP(HashMapIA, stash_ia, "Data::HashMap::IA", self_sv);
    50          
    50          
    50          
3551 47           hashmap_ia_destroy(self);
3552 47           sv_setiv(SvRV(self_sv), 0);
3553              
3554             bool
3555             put(SV* self_sv, int64_t key, SV* value)
3556             CODE:
3557 81917 50         EXTRACT_MAP(HashMapIA, stash_ia, "Data::HashMap::IA", self_sv);
    50          
    50          
    50          
3558 81917           SvREFCNT_inc(value);
3559 81917           RETVAL = hashmap_ia_put(self, key, (void*)value, 0);
3560 81917 100         if (!RETVAL) SvREFCNT_dec(value);
3561             OUTPUT:
3562             RETVAL
3563              
3564             SV*
3565             get(SV* self_sv, int64_t key)
3566             CODE:
3567 50023 50         EXTRACT_MAP(HashMapIA, stash_ia, "Data::HashMap::IA", self_sv);
    50          
    50          
    50          
3568             void* val;
3569 50023 100         if (!hashmap_ia_get(self, key, &val)) XSRETURN_UNDEF;
3570 50016           RETVAL = SvREFCNT_inc((SV*)val);
3571             OUTPUT:
3572             RETVAL
3573              
3574             bool
3575             remove(SV* self_sv, int64_t key)
3576             CODE:
3577 80505 50         EXTRACT_MAP(HashMapIA, stash_ia, "Data::HashMap::IA", self_sv);
    50          
    50          
    50          
3578 80505           RETVAL = hashmap_ia_remove(self, key);
3579             OUTPUT:
3580             RETVAL
3581              
3582             bool
3583             exists(SV* self_sv, int64_t key)
3584             CODE:
3585 4 50         EXTRACT_MAP(HashMapIA, stash_ia, "Data::HashMap::IA", self_sv);
    50          
    50          
    50          
3586 4           RETVAL = hashmap_ia_exists(self, key);
3587             OUTPUT:
3588             RETVAL
3589              
3590             size_t
3591             size(SV* self_sv)
3592             CODE:
3593 11 50         EXTRACT_MAP(HashMapIA, stash_ia, "Data::HashMap::IA", self_sv);
    50          
    50          
    50          
3594 11 50         RETVAL = self->size;
3595             OUTPUT:
3596             RETVAL
3597              
3598             size_t
3599             max_size(SV* self_sv)
3600             CODE:
3601 0 0         EXTRACT_MAP(HashMapIA, stash_ia, "Data::HashMap::IA", self_sv);
    0          
    0          
    0          
3602 0 0         RETVAL = self->max_size;
3603             OUTPUT:
3604             RETVAL
3605              
3606             UV
3607             ttl(SV* self_sv)
3608             CODE:
3609 0 0         EXTRACT_MAP(HashMapIA, stash_ia, "Data::HashMap::IA", self_sv);
    0          
    0          
    0          
3610 0 0         RETVAL = (UV)self->default_ttl;
3611             OUTPUT:
3612             RETVAL
3613              
3614             void
3615             keys(SV* self_sv)
3616             PPCODE:
3617 5 50         EXTRACT_MAP(HashMapIA, stash_ia, "Data::HashMap::IA", self_sv);
    50          
    50          
    50          
3618 5 100         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
3619 5 50         EXTEND(SP, self->size);
3620             size_t i;
3621 309 100         for (i = 0; i < self->capacity; i++) {
3622 304 100         if (IA_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now))
    100          
    100          
    50          
    50          
3623 100 50         mXPUSHi(self->nodes[i].key);
3624             }
3625              
3626             void
3627             values(SV* self_sv)
3628             PPCODE:
3629 3 50         EXTRACT_MAP(HashMapIA, stash_ia, "Data::HashMap::IA", self_sv);
    50          
    50          
    50          
3630 3 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
3631 3 50         EXTEND(SP, self->size);
3632             size_t i;
3633 275 100         for (i = 0; i < self->capacity; i++) {
3634 272 100         if (IA_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    100          
    50          
    0          
    0          
3635 100 50         SV* sv = self->nodes[i].value ? SvREFCNT_inc((SV*)self->nodes[i].value) : &PL_sv_undef;
3636 100 50         mXPUSHs(sv);
3637             }
3638             }
3639              
3640             void
3641             items(SV* self_sv)
3642             PPCODE:
3643 1 50         EXTRACT_MAP(HashMapIA, stash_ia, "Data::HashMap::IA", self_sv);
    50          
    50          
    50          
3644 1 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
3645 1 50         EXTEND(SP, self->size * 2);
3646             size_t i;
3647 17 100         for (i = 0; i < self->capacity; i++) {
3648 16 100         if (IA_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    50          
    50          
    0          
    0          
3649 2 50         mXPUSHi(self->nodes[i].key);
3650 2 50         SV* sv = self->nodes[i].value ? SvREFCNT_inc((SV*)self->nodes[i].value) : &PL_sv_undef;
3651 2 50         mXPUSHs(sv);
3652             }
3653             }
3654              
3655             void
3656             each(SV* self_sv)
3657             PPCODE:
3658 48 50         EXTRACT_MAP(HashMapIA, stash_ia, "Data::HashMap::IA", self_sv);
    50          
    50          
    50          
3659 48 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
3660 100 100         while (self->iter_pos < self->capacity) {
3661 96           size_t i = self->iter_pos++;
3662 96 100         if (IA_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    50          
    50          
    0          
    0          
3663 44 50         EXTEND(SP, 2);
3664 44 50         mXPUSHi(self->nodes[i].key);
3665 44 50         if (GIMME_V == G_SCALAR) XSRETURN(1);
3666 44 50         SV* sv = self->nodes[i].value ? SvREFCNT_inc((SV*)self->nodes[i].value) : &PL_sv_undef;
3667 44 50         mXPUSHs(sv);
3668 44           XSRETURN(2);
3669             }
3670             }
3671 4           self->iter_pos = 0;
3672 4           XSRETURN_EMPTY;
3673              
3674             void
3675             iter_reset(SV* self_sv)
3676             CODE:
3677 0 0         EXTRACT_MAP(HashMapIA, stash_ia, "Data::HashMap::IA", self_sv);
    0          
    0          
    0          
3678 0           self->iter_pos = 0;
3679              
3680             void
3681             clear(SV* self_sv)
3682             CODE:
3683 7 50         EXTRACT_MAP(HashMapIA, stash_ia, "Data::HashMap::IA", self_sv);
    50          
    50          
    50          
3684 7           hashmap_ia_clear(self);
3685              
3686             SV*
3687             to_hash(SV* self_sv)
3688             CODE:
3689 3 50         EXTRACT_MAP(HashMapIA, stash_ia, "Data::HashMap::IA", self_sv);
    50          
    50          
    50          
3690 3           HV* hv = newHV();
3691 3 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
3692             size_t i;
3693 83 100         for (i = 0; i < self->capacity; i++) {
3694 80 100         if (IA_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    50          
    50          
    0          
    0          
3695 41 50         SV* val = self->nodes[i].value ? SvREFCNT_inc((SV*)self->nodes[i].value) : &PL_sv_undef;
3696             char kbuf[24];
3697 41           int klen = my_snprintf(kbuf, sizeof(kbuf), "%" IVdf, (IV)self->nodes[i].key);
3698 41           (void)hv_store(hv, kbuf, klen, val, 0);
3699             }
3700             }
3701 3           RETVAL = newRV_noinc((SV*)hv);
3702             OUTPUT:
3703             RETVAL
3704              
3705             bool
3706             put_ttl(SV* self_sv, int64_t key, SV* value, UV ttl)
3707             CODE:
3708 101 50         EXTRACT_MAP(HashMapIA, stash_ia, "Data::HashMap::IA", self_sv);
    50          
    50          
    50          
3709 101           SvREFCNT_inc(value);
3710 101           RETVAL = hashmap_ia_put(self, key, (void*)value, (uint32_t)ttl);
3711 101 50         if (!RETVAL) SvREFCNT_dec(value);
3712             OUTPUT:
3713             RETVAL
3714              
3715             SV*
3716             get_or_set(SV* self_sv, int64_t key, SV* default_value)
3717             CODE:
3718 4 50         EXTRACT_MAP(HashMapIA, stash_ia, "Data::HashMap::IA", self_sv);
    50          
    50          
    50          
3719             bool was_found;
3720 4           SvREFCNT_inc(default_value);
3721 4           size_t idx = hashmap_ia_get_or_set(self, key, (void*)default_value, 0, &was_found);
3722 4 50         if (idx >= self->capacity) {
3723 0           SvREFCNT_dec(default_value);
3724 0           XSRETURN_UNDEF;
3725             }
3726 4 100         if (was_found) SvREFCNT_dec(default_value);
3727 4           RETVAL = SvREFCNT_inc((SV*)self->nodes[idx].value);
3728             OUTPUT:
3729             RETVAL
3730              
3731              
3732              
3733             MODULE = Data::HashMap PACKAGE = Data::HashMap::SA
3734             PROTOTYPES: DISABLE
3735              
3736             SV*
3737             new(char* class, ...)
3738             CODE:
3739 44 100         EXTRACT_NEW_ARGS(_max_size, _ttl);
    100          
3740 44           HashMapSA* map = hashmap_sa_create(_max_size, _ttl);
3741 44 50         if (!map) croak("Failed to create HashMap::SA");
3742 44           map->free_value_fn = hm_sv_free;
3743 44           RETVAL = sv_setref_pv(newSV(0), class, (void*)map);
3744             OUTPUT:
3745             RETVAL
3746              
3747             void
3748             DESTROY(SV* self_sv)
3749             CODE:
3750 44 50         EXTRACT_MAP(HashMapSA, stash_sa, "Data::HashMap::SA", self_sv);
    50          
    50          
    50          
3751 44           hashmap_sa_destroy(self);
3752 44           sv_setiv(SvRV(self_sv), 0);
3753              
3754             bool
3755             put(SV* self_sv, SV* key_sv, SV* value)
3756             CODE:
3757 81579 50         EXTRACT_MAP(HashMapSA, stash_sa, "Data::HashMap::SA", self_sv);
    50          
    50          
    50          
3758 81579 50         EXTRACT_STR_KEY(key_sv);
3759 81579           SvREFCNT_inc(value);
3760 81579           RETVAL = hashmap_sa_put(self, _kstr, (uint32_t)_klen, _khash, _kutf8, (void*)value, 0);
3761 81579 50         if (!RETVAL) SvREFCNT_dec(value);
3762             OUTPUT:
3763             RETVAL
3764              
3765             SV*
3766             get(SV* self_sv, SV* key_sv)
3767             CODE:
3768 50024 50         EXTRACT_MAP(HashMapSA, stash_sa, "Data::HashMap::SA", self_sv);
    50          
    50          
    50          
3769 50024 50         EXTRACT_STR_KEY(key_sv);
3770             void* val;
3771 50024 100         if (!hashmap_sa_get(self, _kstr, (uint32_t)_klen, _khash, _kutf8, &val))
3772 5           XSRETURN_UNDEF;
3773 50019           RETVAL = SvREFCNT_inc((SV*)val);
3774             OUTPUT:
3775             RETVAL
3776              
3777             bool
3778             remove(SV* self_sv, SV* key_sv)
3779             CODE:
3780 80505 50         EXTRACT_MAP(HashMapSA, stash_sa, "Data::HashMap::SA", self_sv);
    50          
    50          
    50          
3781 80505 50         EXTRACT_STR_KEY(key_sv);
3782 80505           RETVAL = hashmap_sa_remove(self, _kstr, (uint32_t)_klen, _khash, _kutf8);
3783             OUTPUT:
3784             RETVAL
3785              
3786             bool
3787             exists(SV* self_sv, SV* key_sv)
3788             CODE:
3789 5 50         EXTRACT_MAP(HashMapSA, stash_sa, "Data::HashMap::SA", self_sv);
    50          
    50          
    50          
3790 5 50         EXTRACT_STR_KEY(key_sv);
3791 5           RETVAL = hashmap_sa_exists(self, _kstr, (uint32_t)_klen, _khash, _kutf8);
3792             OUTPUT:
3793             RETVAL
3794              
3795             size_t
3796             size(SV* self_sv)
3797             CODE:
3798 12 50         EXTRACT_MAP(HashMapSA, stash_sa, "Data::HashMap::SA", self_sv);
    50          
    50          
    50          
3799 12 50         RETVAL = self->size;
3800             OUTPUT:
3801             RETVAL
3802              
3803             size_t
3804             max_size(SV* self_sv)
3805             CODE:
3806 0 0         EXTRACT_MAP(HashMapSA, stash_sa, "Data::HashMap::SA", self_sv);
    0          
    0          
    0          
3807 0 0         RETVAL = self->max_size;
3808             OUTPUT:
3809             RETVAL
3810              
3811             UV
3812             ttl(SV* self_sv)
3813             CODE:
3814 0 0         EXTRACT_MAP(HashMapSA, stash_sa, "Data::HashMap::SA", self_sv);
    0          
    0          
    0          
3815 0 0         RETVAL = (UV)self->default_ttl;
3816             OUTPUT:
3817             RETVAL
3818              
3819             void
3820             keys(SV* self_sv)
3821             PPCODE:
3822 5 50         EXTRACT_MAP(HashMapSA, stash_sa, "Data::HashMap::SA", self_sv);
    50          
    50          
    50          
3823 5 100         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
3824 5 50         EXTEND(SP, self->size);
3825             size_t i;
3826 309 100         for (i = 0; i < self->capacity; i++) {
3827 304 100         if (SA_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    100          
    100          
    50          
    50          
3828 100           uint32_t klen = HM_UNPACK_LEN(self->nodes[i].key_len);
3829 100           SV* sv = newSVpvn(self->nodes[i].key, klen);
3830 100 50         if (HM_UNPACK_UTF8(self->nodes[i].key_len)) SvUTF8_on(sv);
3831 100 50         mXPUSHs(sv);
3832             }
3833             }
3834              
3835             void
3836             values(SV* self_sv)
3837             PPCODE:
3838 3 50         EXTRACT_MAP(HashMapSA, stash_sa, "Data::HashMap::SA", self_sv);
    50          
    50          
    50          
3839 3 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
3840 3 50         EXTEND(SP, self->size);
3841             size_t i;
3842 275 100         for (i = 0; i < self->capacity; i++) {
3843 272 100         if (SA_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    100          
    50          
    0          
    0          
3844 100 50         SV* sv = self->nodes[i].value ? SvREFCNT_inc((SV*)self->nodes[i].value) : &PL_sv_undef;
3845 100 50         mXPUSHs(sv);
3846             }
3847             }
3848              
3849             void
3850             items(SV* self_sv)
3851             PPCODE:
3852 1 50         EXTRACT_MAP(HashMapSA, stash_sa, "Data::HashMap::SA", self_sv);
    50          
    50          
    50          
3853 1 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
3854 1 50         EXTEND(SP, self->size * 2);
3855             size_t i;
3856 17 100         for (i = 0; i < self->capacity; i++) {
3857 16 100         if (SA_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    50          
    50          
    0          
    0          
3858 2           uint32_t klen = HM_UNPACK_LEN(self->nodes[i].key_len);
3859 2           SV* ksv = newSVpvn(self->nodes[i].key, klen);
3860 2 50         if (HM_UNPACK_UTF8(self->nodes[i].key_len)) SvUTF8_on(ksv);
3861 2 50         mXPUSHs(ksv);
3862 2 50         SV* vsv = self->nodes[i].value ? SvREFCNT_inc((SV*)self->nodes[i].value) : &PL_sv_undef;
3863 2 50         mXPUSHs(vsv);
3864             }
3865             }
3866              
3867             void
3868             each(SV* self_sv)
3869             PPCODE:
3870 48 50         EXTRACT_MAP(HashMapSA, stash_sa, "Data::HashMap::SA", self_sv);
    50          
    50          
    50          
3871 48 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
3872 100 100         while (self->iter_pos < self->capacity) {
3873 96           size_t i = self->iter_pos++;
3874 96 100         if (SA_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    50          
    50          
    0          
    0          
3875 44 50         EXTEND(SP, 2);
3876             {
3877 44           uint32_t klen = HM_UNPACK_LEN(self->nodes[i].key_len);
3878 44           SV* ksv = newSVpvn(self->nodes[i].key, klen);
3879 44 50         if (HM_UNPACK_UTF8(self->nodes[i].key_len)) SvUTF8_on(ksv);
3880 44 50         mXPUSHs(ksv);
3881             }
3882 44 50         if (GIMME_V == G_SCALAR) XSRETURN(1);
3883 44 50         SV* vsv = self->nodes[i].value ? SvREFCNT_inc((SV*)self->nodes[i].value) : &PL_sv_undef;
3884 44 50         mXPUSHs(vsv);
3885 44           XSRETURN(2);
3886             }
3887             }
3888 4           self->iter_pos = 0;
3889 4           XSRETURN_EMPTY;
3890              
3891             void
3892             iter_reset(SV* self_sv)
3893             CODE:
3894 0 0         EXTRACT_MAP(HashMapSA, stash_sa, "Data::HashMap::SA", self_sv);
    0          
    0          
    0          
3895 0           self->iter_pos = 0;
3896              
3897             void
3898             clear(SV* self_sv)
3899             CODE:
3900 3 50         EXTRACT_MAP(HashMapSA, stash_sa, "Data::HashMap::SA", self_sv);
    50          
    50          
    50          
3901 3           hashmap_sa_clear(self);
3902              
3903             SV*
3904             to_hash(SV* self_sv)
3905             CODE:
3906 1 50         EXTRACT_MAP(HashMapSA, stash_sa, "Data::HashMap::SA", self_sv);
    50          
    50          
    50          
3907 1           HV* hv = newHV();
3908 1 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
3909             size_t i;
3910 17 100         for (i = 0; i < self->capacity; i++) {
3911 16 100         if (SA_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    50          
    50          
    0          
    0          
3912 1           uint32_t klen = HM_UNPACK_LEN(self->nodes[i].key_len);
3913 1           bool kutf8 = HM_UNPACK_UTF8(self->nodes[i].key_len);
3914 1 50         SV* val = self->nodes[i].value ? SvREFCNT_inc((SV*)self->nodes[i].value) : &PL_sv_undef;
3915 1 50         (void)hv_store(hv, self->nodes[i].key, kutf8 ? -(I32)klen : (I32)klen, val, 0);
3916             }
3917             }
3918 1           RETVAL = newRV_noinc((SV*)hv);
3919             OUTPUT:
3920             RETVAL
3921              
3922             bool
3923             put_ttl(SV* self_sv, SV* key_sv, SV* value, UV ttl)
3924             CODE:
3925 1 50         EXTRACT_MAP(HashMapSA, stash_sa, "Data::HashMap::SA", self_sv);
    50          
    50          
    50          
3926 1 50         EXTRACT_STR_KEY(key_sv);
3927 1           SvREFCNT_inc(value);
3928 1           RETVAL = hashmap_sa_put(self, _kstr, (uint32_t)_klen, _khash, _kutf8, (void*)value, (uint32_t)ttl);
3929 1 50         if (!RETVAL) SvREFCNT_dec(value);
3930             OUTPUT:
3931             RETVAL
3932              
3933             SV*
3934             get_or_set(SV* self_sv, SV* key_sv, SV* default_value)
3935             CODE:
3936 4 50         EXTRACT_MAP(HashMapSA, stash_sa, "Data::HashMap::SA", self_sv);
    50          
    50          
    50          
3937 4 50         EXTRACT_STR_KEY(key_sv);
3938             bool was_found;
3939 4           SvREFCNT_inc(default_value);
3940 4           size_t idx = hashmap_sa_get_or_set(self, _kstr, (uint32_t)_klen, _khash, _kutf8, (void*)default_value, 0, &was_found);
3941 4 50         if (idx >= self->capacity) {
3942 0           SvREFCNT_dec(default_value);
3943 0           XSRETURN_UNDEF;
3944             }
3945 4 100         if (was_found) SvREFCNT_dec(default_value);
3946 4           RETVAL = SvREFCNT_inc((SV*)self->nodes[idx].value);
3947             OUTPUT:
3948             RETVAL
3949