File Coverage

xs/i32.xsi
Criterion Covered Total %
statement 169 242 69.8
branch 219 628 34.8
condition n/a
subroutine n/a
pod n/a
total 388 870 44.6


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