File Coverage

xs/ii.xsi
Criterion Covered Total %
statement 246 252 97.6
branch 387 622 62.2
condition n/a
subroutine n/a
pod n/a
total 633 874 72.4


line stmt bran cond sub pod time code
1             MODULE = Data::HashMap PACKAGE = Data::HashMap::II
2             PROTOTYPES: DISABLE
3              
4             SV*
5             new(char* class, ...)
6             CODE:
7 118 100         EXTRACT_NEW_ARGS(_max_size, _ttl, _lru_skip);
    100          
    100          
8 118           HashMapII* map = hashmap_ii_create(_max_size, _ttl, _lru_skip);
9 118 50         if (!map) croak("Failed to create HashMap::II");
10 118           RETVAL = sv_setref_pv(newSV(0), class, (void*)map);
11             OUTPUT:
12             RETVAL
13              
14             void
15             DESTROY(SV* self_sv)
16             CODE:
17 127 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
18 127           hashmap_ii_destroy(self);
19 127           sv_setiv(SvRV(self_sv), 0);
20              
21             bool
22             put(SV* self_sv, int64_t key, int64_t value)
23             CODE:
24 384733 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
25 384733           RETVAL = hashmap_ii_put(self, key, value, 0);
26             OUTPUT:
27             RETVAL
28              
29             SV*
30             get(SV* self_sv, int64_t key)
31             CODE:
32 100192 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
33             int64_t value;
34 100192 100         if (!hashmap_ii_get(self, key, &value)) XSRETURN_UNDEF;
35 100162           RETVAL = newSViv(value);
36             OUTPUT:
37             RETVAL
38              
39             bool
40             remove(SV* self_sv, int64_t key)
41             CODE:
42 280022 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
43 280022           RETVAL = hashmap_ii_remove(self, key);
44             OUTPUT:
45             RETVAL
46              
47             SV*
48             take(SV* self_sv, int64_t key)
49             CODE:
50 3 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
51             int64_t value;
52 3 100         if (!hashmap_ii_take(self, key, &value)) XSRETURN_UNDEF;
53 1           RETVAL = newSViv(value);
54             OUTPUT:
55             RETVAL
56              
57             bool
58             exists(SV* self_sv, int64_t key)
59             CODE:
60 10 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
61 10           RETVAL = hashmap_ii_exists(self, key);
62             OUTPUT:
63             RETVAL
64              
65             SV*
66             incr(SV* self_sv, int64_t key)
67             CODE:
68 15014 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
69             int64_t val;
70 15014 100         if (!hashmap_ii_increment(self, key, &val))
71 3           croak("HashMap::II: increment failed");
72 15011           RETVAL = newSViv(val);
73             OUTPUT:
74             RETVAL
75              
76             SV*
77             decr(SV* self_sv, int64_t key)
78             CODE:
79 5006 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
80             int64_t val;
81 5006 100         if (!hashmap_ii_decrement(self, key, &val))
82 2           croak("HashMap::II: decrement failed");
83 5004           RETVAL = newSViv(val);
84             OUTPUT:
85             RETVAL
86              
87             SV*
88             incr_by(SV* self_sv, int64_t key, int64_t delta)
89             CODE:
90 8 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
91             int64_t val;
92 8 100         if (!hashmap_ii_increment_by(self, key, delta, &val))
93 2           croak("HashMap::II: incr_by failed");
94 6           RETVAL = newSViv(val);
95             OUTPUT:
96             RETVAL
97              
98             size_t
99             size(SV* self_sv)
100             CODE:
101 55 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
102 55 50         RETVAL = self->size;
103             OUTPUT:
104             RETVAL
105              
106             size_t
107             max_size(SV* self_sv)
108             CODE:
109 7 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
110 7 50         RETVAL = self->max_size;
111             OUTPUT:
112             RETVAL
113              
114             UV
115             ttl(SV* self_sv)
116             CODE:
117 5 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
118 5 50         RETVAL = (UV)self->default_ttl;
119             OUTPUT:
120             RETVAL
121              
122             UV
123             lru_skip(SV* self_sv)
124             CODE:
125 4 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
126 4 50         RETVAL = (UV)self->lru_skip;
127             OUTPUT:
128             RETVAL
129              
130             void
131             keys(SV* self_sv)
132             PPCODE:
133 9 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
134 9 100         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
135 9 50         EXTEND(SP, self->size);
136             size_t i;
137 649 100         for (i = 0; i < self->capacity; i++) {
138 640 100         if (II_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now))
    100          
    100          
    50          
    100          
139 221 50         mXPUSHi(self->nodes[i].key);
140             }
141              
142             void
143             values(SV* self_sv)
144             PPCODE:
145 5 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
146 5 100         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
147 5 50         EXTEND(SP, self->size);
148             size_t i;
149 565 100         for (i = 0; i < self->capacity; i++) {
150 560 100         if (II_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now))
    100          
    100          
    50          
    50          
151 203 50         mXPUSHi(self->nodes[i].value);
152             }
153              
154             void
155             items(SV* self_sv)
156             PPCODE:
157 5 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
158 5 100         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
159 5 50         EXTEND(SP, self->size * 2);
160             size_t i;
161 565 100         for (i = 0; i < self->capacity; i++) {
162 560 100         if (II_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    100          
    100          
    50          
    50          
163 203 50         mXPUSHi(self->nodes[i].key);
164 203 50         mXPUSHi(self->nodes[i].value);
165             }
166             }
167              
168             void
169             each(SV* self_sv)
170             PPCODE:
171 31 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
172 31 100         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
173 180 100         while (self->iter_pos < self->capacity) {
174 174           size_t i = self->iter_pos++;
175 174 100         if (II_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    100          
    100          
    50          
    100          
176 25 50         EXTEND(SP, 2);
177 25 50         mXPUSHi(self->nodes[i].key);
178 25 100         if (GIMME_V == G_SCALAR) XSRETURN(1);
179 24 50         mXPUSHi(self->nodes[i].value);
180 24           XSRETURN(2);
181             }
182             }
183 6           self->iter_pos = 0;
184 6           XSRETURN_EMPTY;
185              
186             void
187             iter_reset(SV* self_sv)
188             CODE:
189 1 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
190 1           self->iter_pos = 0;
191              
192             void
193             drain(SV* self_sv, UV count)
194             PPCODE:
195 5 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
196 5 100         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
197 5           UV n = 0;
198 5 50         EXTEND(SP, (count < self->size ? count : self->size) * 2);
199 59 100         while (self->iter_pos < self->capacity && n < count) {
    100          
200 54           size_t i = self->iter_pos++;
201 54 100         if (II_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    50          
    100          
    50          
    100          
202 14 50         mXPUSHi(self->nodes[i].key);
203 14 50         mXPUSHi(self->nodes[i].value);
204 14 100         if (HM_UNLIKELY(self->lru_prev)) hashmap_ii_lru_unlink(self, (uint32_t)i);
205 14           hashmap_ii_tombstone_at(self, i);
206 14           n++;
207             }
208             }
209 5 100         if (self->iter_pos >= self->capacity) self->iter_pos = 0;
210 5 100         if (self->tombstones > self->capacity / 4 ||
211 4 100         (self->size > 0 && self->tombstones > self->size))
    50          
212 1           hashmap_ii_compact(self);
213              
214             void
215             pop(SV* self_sv)
216             PPCODE:
217 7 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
218 7 100         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
219 7 100         if (self->lru_prev) {
220 5 100         while (self->lru_tail != HM_LRU_NONE) {
221 4           uint32_t idx = self->lru_tail;
222 4 100         if (HM_UNLIKELY(self->expires_at && self->expires_at[idx]) && now > self->expires_at[idx]) {
    50          
    100          
223 2           hashmap_ii_expire_at(self, idx, true); continue;
224             }
225 2 50         EXTEND(SP, 2);
226 2 50         mXPUSHi(self->nodes[idx].key);
227 2 50         mXPUSHi(self->nodes[idx].value);
228 2           hashmap_ii_lru_unlink(self, idx);
229 2           hashmap_ii_tombstone_at(self, idx);
230 2 50         if (self->tombstones > self->capacity / 4 ||
231 2 100         (self->size > 0 && self->tombstones > self->size))
    50          
232 0           hashmap_ii_compact(self);
233 2           XSRETURN(2);
234             }
235 1           XSRETURN_EMPTY;
236             } else {
237 31 100         while (self->iter_pos < self->capacity) {
238 30           size_t i = self->iter_pos++;
239 30 100         if (II_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    50          
    50          
    0          
    0          
240 3 50         EXTEND(SP, 2);
241 3 50         mXPUSHi(self->nodes[i].key);
242 3 50         mXPUSHi(self->nodes[i].value);
243 3           hashmap_ii_tombstone_at(self, i);
244 3 50         if (self->tombstones > self->capacity / 4 ||
245 3 100         (self->size > 0 && self->tombstones > self->size))
    100          
246 1           hashmap_ii_compact(self);
247 3           XSRETURN(2);
248             }
249             }
250 1           self->iter_pos = 0;
251 1           XSRETURN_EMPTY;
252             }
253              
254             void
255             shift(SV* self_sv)
256             PPCODE:
257 7 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
258 7 100         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
259 7 100         if (self->lru_prev) {
260 3 100         while (self->lru_head != HM_LRU_NONE) {
261 2           uint32_t idx = self->lru_head;
262 2 100         if (HM_UNLIKELY(self->expires_at && self->expires_at[idx]) && now > self->expires_at[idx]) {
    50          
    50          
263 0           hashmap_ii_expire_at(self, idx, true); continue;
264             }
265 2 50         EXTEND(SP, 2);
266 2 50         mXPUSHi(self->nodes[idx].key);
267 2 50         mXPUSHi(self->nodes[idx].value);
268 2           hashmap_ii_lru_unlink(self, idx);
269 2           hashmap_ii_tombstone_at(self, idx);
270 2 50         if (self->tombstones > self->capacity / 4 ||
271 2 50         (self->size > 0 && self->tombstones > self->size))
    50          
272 0           hashmap_ii_compact(self);
273 2           XSRETURN(2);
274             }
275 1           XSRETURN_EMPTY;
276             } else {
277 4 100         if (self->iter_pos == 0) self->iter_pos = self->capacity;
278 20 100         while (self->iter_pos > 0) {
279 19           size_t i = --self->iter_pos;
280 19 100         if (II_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    50          
    50          
    0          
    0          
281 3 50         EXTEND(SP, 2);
282 3 50         mXPUSHi(self->nodes[i].key);
283 3 50         mXPUSHi(self->nodes[i].value);
284 3           hashmap_ii_tombstone_at(self, i);
285 3 50         if (self->tombstones > self->capacity / 4 ||
286 3 100         (self->size > 0 && self->tombstones > self->size))
    100          
287 1           hashmap_ii_compact(self);
288 3           XSRETURN(2);
289             }
290             }
291 1           XSRETURN_EMPTY;
292             }
293              
294              
295             void
296             clear(SV* self_sv)
297             CODE:
298 8 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
299 8           hashmap_ii_clear(self);
300              
301             void
302             reserve(SV* self_sv, UV count)
303             CODE:
304 1 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
305 1 50         if (!hashmap_ii_reserve(self, (size_t)count))
306 0           croak("Failed to reserve capacity");
307              
308             void
309             purge(SV* self_sv)
310             CODE:
311 1 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
312 1           hashmap_ii_purge(self);
313              
314             SV*
315             freeze(SV* self_sv)
316             CODE:
317 5 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
318 5 100         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
319 5           SV* buf = newSV(22 + self->size * 32);
320 5           SvPOK_on(buf);
321 5           SvCUR_set(buf, 0);
322             /* Header: magic(4) + version(1) + variant_id(1) + count(4) + max_size(4) + ttl(4) + lru_skip(4) */
323 5           sv_catpvn(buf, "DHMP", 4);
324 5           { uint8_t ver = 1; sv_catpvn(buf, (const char*)&ver, 1); }
325 5           { uint8_t vid = 1; sv_catpvn(buf, (const char*)&vid, 1); }
326 5           STRLEN cnt_offset = SvCUR(buf);
327 5           { uint32_t cnt = 0; sv_catpvn(buf, (const char*)&cnt, 4); }
328 5           UV n_written = 0;
329 5           { uint32_t ms = (uint32_t)self->max_size; sv_catpvn(buf, (const char*)&ms, 4); }
330 5           { uint32_t dt = self->default_ttl; sv_catpvn(buf, (const char*)&dt, 4); }
331 5           { uint32_t ls = self->lru_skip; sv_catpvn(buf, (const char*)&ls, 4); }
332             { size_t i;
333 437 100         for (i = 0; i < self->capacity; i++) {
334 432 100         if (II_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    50          
    100          
    100          
    100          
335 154           sv_catpvn(buf, (const char*)&self->nodes[i].key, 8);
336 154           sv_catpvn(buf, (const char*)&self->nodes[i].value, 8);
337             /* TTL: remaining seconds (0 = none) */
338 154           { uint32_t rem = 0;
339 154 100         if (self->expires_at && self->expires_at[i] && self->expires_at[i] >= now) {
    100          
    50          
340 2           rem = self->expires_at[i] - now;
341 2 50         if (!rem) rem = 1;
342             }
343 154           sv_catpvn(buf, (const char*)&rem, 4);
344             }
345 154           n_written++;
346             }
347             }
348             }
349 5           { uint32_t actual = (uint32_t)n_written;
350 5           memcpy(SvPVX(buf) + cnt_offset, &actual, 4); }
351 5           RETVAL = buf;
352             OUTPUT:
353             RETVAL
354              
355             SV*
356             thaw(char* class, SV* data)
357             CODE:
358             STRLEN dlen;
359 8           const uint8_t* p = (const uint8_t*)SvPV(data, dlen);
360 8           const uint8_t* end = p + dlen;
361 8 100         if (dlen < 22 || memcmp(p, "DHMP", 4) != 0) croak("Invalid freeze data");
    50          
362 7           p += 4;
363 7 50         uint8_t ver = *p++; if (ver != 1) croak("Unsupported freeze version %d", ver);
364 7 100         uint8_t vid = *p++; if (vid != 1) croak("Variant mismatch: expected 1, got %d", vid);
365 6           uint32_t cnt; memcpy(&cnt, p, 4); p += 4;
366 6           uint32_t ms; memcpy(&ms, p, 4); p += 4;
367 6           uint32_t dt; memcpy(&dt, p, 4); p += 4;
368 6           uint32_t ls; memcpy(&ls, p, 4); p += 4;
369 6           HashMapII* map = hashmap_ii_create((size_t)ms, dt, ls);
370 6 50         if (!map) croak("Failed to create map for thaw");
371 6 50         if (cnt > 0) hashmap_ii_reserve(map, (size_t)cnt);
372             { uint32_t j;
373 161 100         for (j = 0; j < cnt; j++) {
374 156 100         if (p + 20 > end) { hashmap_ii_destroy(map); croak("Truncated freeze data"); }
375 155           int64_t key; memcpy(&key, p, 8); p += 8;
376 155           int64_t val; memcpy(&val, p, 8); p += 8;
377 155           uint32_t ttl; memcpy(&ttl, p, 4); p += 4;
378 155           hashmap_ii_put(map, key, val, ttl);
379 155 100         if (ttl == 0 && map->expires_at) hashmap_ii_persist(map, key);
    100          
380             }
381             }
382 5 50         if (p > end) croak("Truncated freeze data");
383 5           RETVAL = sv_setref_pv(newSV(0), class, (void*)map);
384             OUTPUT:
385             RETVAL
386              
387              
388             UV
389             capacity(SV* self_sv)
390             CODE:
391 2 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
392 2 50         RETVAL = (UV)self->capacity;
393             OUTPUT:
394             RETVAL
395              
396             bool
397             persist(SV* self_sv, int64_t key)
398             CODE:
399 3 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
400 3           RETVAL = hashmap_ii_persist(self, key);
401             OUTPUT:
402             RETVAL
403              
404             SV*
405             swap(SV* self_sv, int64_t key, int64_t new_val)
406             CODE:
407 2 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
408             int64_t old;
409 2 100         if (!hashmap_ii_swap(self, key, new_val, &old)) XSRETURN_UNDEF;
410 1           RETVAL = newSViv(old);
411             OUTPUT:
412             RETVAL
413              
414             bool
415             cas(SV* self_sv, int64_t key, int64_t expected, int64_t new_val)
416             CODE:
417 3 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
418 3           RETVAL = hashmap_ii_cas(self, key, expected, new_val);
419             OUTPUT:
420             RETVAL
421              
422              
423             SV*
424             clone(SV* self_sv)
425             CODE:
426 4 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
427 4           HashMapII* clone = hashmap_ii_clone(self);
428 4 50         if (!clone) croak("Failed to clone");
429 4 50         RETVAL = sv_setref_pv(newSV(0), HvNAME(SvSTASH(SvRV(self_sv))), (void*)clone);
    50          
    50          
    0          
    50          
    50          
430             OUTPUT:
431             RETVAL
432              
433             void
434             from_hash(SV* self_sv, SV* href)
435             CODE:
436 2 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
437 2 50         if (!SvROK(href) || SvTYPE(SvRV(href)) != SVt_PVHV)
    50          
438 0           croak("from_hash requires a hashref");
439 2           HV* hv = (HV*)SvRV(href);
440 2 50         hashmap_ii_reserve(self, (size_t)HvUSEDKEYS(hv));
441 2           hv_iterinit(hv);
442             HE* he;
443 55 100         while ((he = hv_iternext(hv))) {
444 53           SV* ksv = hv_iterkeysv(he);
445 53           int64_t key = (int64_t)SvIV(ksv);
446 53           SV* val = HeVAL(he);
447 53           hashmap_ii_put(self, key, (int64_t)SvIV(val), 0);
448             }
449              
450             void
451             merge(SV* self_sv, SV* other_sv)
452             CODE:
453 4 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
454 4 50         if (!SvROK(other_sv) || !SvOBJECT(SvRV(other_sv)) || SvSTASH(SvRV(other_sv)) != stash_ii)
    50          
    50          
455 0           croak("Expected a Data::HashMap::II object");
456 4           HashMapII* other = INT2PTR(HashMapII*, SvIV(SvRV(other_sv)));
457 4           hashmap_ii_reserve(self, self->size + other->size);
458 4 50         uint32_t now = other->expires_at ? (uint32_t)time(NULL) : 0;
459             size_t i;
460 68 100         for (i = 0; i < other->capacity; i++) {
461 64 100         if (II_NODE_LIVE(other->nodes[i]) && !HM_TTL_SKIP_EXPIRED(other, i, now))
    50          
    50          
    0          
    0          
462 7           hashmap_ii_put(self, other->nodes[i].key, other->nodes[i].value, 0);
463             }
464              
465              
466             SV*
467             to_hash(SV* self_sv)
468             CODE:
469 5 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
470 5           HV* hv = newHV();
471 5 100         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
472             size_t i;
473 197 100         for (i = 0; i < self->capacity; i++) {
474 192 100         if (II_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    50          
    100          
    100          
    50          
475 53           SV* val = newSViv(self->nodes[i].value);
476             char kbuf[24];
477 53           int klen = my_snprintf(kbuf, sizeof(kbuf), "%" IVdf, (IV)self->nodes[i].key);
478 53           (void)hv_store(hv, kbuf, klen, val, 0);
479             }
480             }
481 5           RETVAL = newRV_noinc((SV*)hv);
482             OUTPUT:
483             RETVAL
484              
485             bool
486             put_ttl(SV* self_sv, int64_t key, int64_t value, UV ttl)
487             CODE:
488 108 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
489 108           RETVAL = hashmap_ii_put(self, key, value, (uint32_t)ttl);
490             OUTPUT:
491             RETVAL
492              
493             SV*
494             get_or_set(SV* self_sv, int64_t key, int64_t default_value)
495             CODE:
496 15 50         EXTRACT_MAP(HashMapII, stash_ii, "Data::HashMap::II", self_sv);
    50          
    50          
    50          
497             bool was_found;
498 15           size_t idx = hashmap_ii_get_or_set(self, key, default_value, 0, &was_found);
499             (void)was_found;
500 15 50         if (idx >= self->capacity) XSRETURN_UNDEF;
501 15           RETVAL = newSViv(self->nodes[idx].value);
502             OUTPUT:
503             RETVAL
504              
505              
506