File Coverage

xs/i32.xsi
Criterion Covered Total %
statement 173 252 68.6
branch 218 622 35.0
condition n/a
subroutine n/a
pod n/a
total 391 874 44.7


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         if (self->tombstones > self->capacity / 4 ||
210 1 50         (self->size > 0 && self->tombstones > self->size))
    50          
211 1           hashmap_i32_compact(self);
212              
213             void
214             pop(SV* self_sv)
215             PPCODE:
216 1 50         EXTRACT_MAP(HashMapI32, stash_i32, "Data::HashMap::I32", self_sv);
    50          
    50          
    50          
217 1 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
218 1 50         if (self->lru_prev) {
219 0 0         while (self->lru_tail != HM_LRU_NONE) {
220 0           uint32_t idx = self->lru_tail;
221 0 0         if (HM_UNLIKELY(self->expires_at && self->expires_at[idx]) && now > self->expires_at[idx]) {
    0          
    0          
222 0           hashmap_i32_expire_at(self, idx, true); continue;
223             }
224 0 0         EXTEND(SP, 2);
225 0 0         mXPUSHi(self->nodes[idx].key);
226 0 0         mXPUSHi(self->nodes[idx].value);
227 0           hashmap_i32_lru_unlink(self, idx);
228 0           hashmap_i32_tombstone_at(self, idx);
229 0 0         if (self->tombstones > self->capacity / 4 ||
230 0 0         (self->size > 0 && self->tombstones > self->size))
    0          
231 0           hashmap_i32_compact(self);
232 0           XSRETURN(2);
233             }
234 0           XSRETURN_EMPTY;
235             } else {
236 13 50         while (self->iter_pos < self->capacity) {
237 13           size_t i = self->iter_pos++;
238 13 100         if (I32_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    50          
    50          
    0          
    0          
239 1 50         EXTEND(SP, 2);
240 1 50         mXPUSHi(self->nodes[i].key);
241 1 50         mXPUSHi(self->nodes[i].value);
242 1           hashmap_i32_tombstone_at(self, i);
243 1 50         if (self->tombstones > self->capacity / 4 ||
244 1 50         (self->size > 0 && self->tombstones > self->size))
    50          
245 0           hashmap_i32_compact(self);
246 1           XSRETURN(2);
247             }
248             }
249 0           self->iter_pos = 0;
250 0           XSRETURN_EMPTY;
251             }
252              
253             void
254             shift(SV* self_sv)
255             PPCODE:
256 1 50         EXTRACT_MAP(HashMapI32, stash_i32, "Data::HashMap::I32", self_sv);
    50          
    50          
    50          
257 1 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
258 1 50         if (self->lru_prev) {
259 0 0         while (self->lru_head != HM_LRU_NONE) {
260 0           uint32_t idx = self->lru_head;
261 0 0         if (HM_UNLIKELY(self->expires_at && self->expires_at[idx]) && now > self->expires_at[idx]) {
    0          
    0          
262 0           hashmap_i32_expire_at(self, idx, true); continue;
263             }
264 0 0         EXTEND(SP, 2);
265 0 0         mXPUSHi(self->nodes[idx].key);
266 0 0         mXPUSHi(self->nodes[idx].value);
267 0           hashmap_i32_lru_unlink(self, idx);
268 0           hashmap_i32_tombstone_at(self, idx);
269 0 0         if (self->tombstones > self->capacity / 4 ||
270 0 0         (self->size > 0 && self->tombstones > self->size))
    0          
271 0           hashmap_i32_compact(self);
272 0           XSRETURN(2);
273             }
274 0           XSRETURN_EMPTY;
275             } else {
276 1 50         if (self->iter_pos == 0) self->iter_pos = self->capacity;
277 2 50         while (self->iter_pos > 0) {
278 2           size_t i = --self->iter_pos;
279 2 100         if (I32_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    50          
    50          
    0          
    0          
280 1 50         EXTEND(SP, 2);
281 1 50         mXPUSHi(self->nodes[i].key);
282 1 50         mXPUSHi(self->nodes[i].value);
283 1           hashmap_i32_tombstone_at(self, i);
284 1 50         if (self->tombstones > self->capacity / 4 ||
285 1 50         (self->size > 0 && self->tombstones > self->size))
    50          
286 0           hashmap_i32_compact(self);
287 1           XSRETURN(2);
288             }
289             }
290 0           XSRETURN_EMPTY;
291             }
292              
293              
294             void
295             clear(SV* self_sv)
296             CODE:
297 3 50         EXTRACT_MAP(HashMapI32, stash_i32, "Data::HashMap::I32", self_sv);
    50          
    50          
    50          
298 3           hashmap_i32_clear(self);
299              
300             void
301             reserve(SV* self_sv, UV count)
302             CODE:
303 0 0         EXTRACT_MAP(HashMapI32, stash_i32, "Data::HashMap::I32", self_sv);
    0          
    0          
    0          
304 0 0         if (!hashmap_i32_reserve(self, (size_t)count))
305 0           croak("Failed to reserve capacity");
306              
307             void
308             purge(SV* self_sv)
309             CODE:
310 0 0         EXTRACT_MAP(HashMapI32, stash_i32, "Data::HashMap::I32", self_sv);
    0          
    0          
    0          
311 0           hashmap_i32_purge(self);
312              
313             SV*
314             freeze(SV* self_sv)
315             CODE:
316 1 50         EXTRACT_MAP(HashMapI32, stash_i32, "Data::HashMap::I32", self_sv);
    50          
    50          
    50          
317 1 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
318 1           SV* buf = newSV(22 + self->size * 32);
319 1           SvPOK_on(buf);
320 1           SvCUR_set(buf, 0);
321             /* Header: magic(4) + version(1) + variant_id(1) + count(4) + max_size(4) + ttl(4) + lru_skip(4) */
322 1           sv_catpvn(buf, "DHMP", 4);
323 1           { uint8_t ver = 1; sv_catpvn(buf, (const char*)&ver, 1); }
324 1           { uint8_t vid = 0; sv_catpvn(buf, (const char*)&vid, 1); }
325 1           STRLEN cnt_offset = SvCUR(buf);
326 1           { uint32_t cnt = 0; sv_catpvn(buf, (const char*)&cnt, 4); }
327 1           UV n_written = 0;
328 1           { uint32_t ms = (uint32_t)self->max_size; sv_catpvn(buf, (const char*)&ms, 4); }
329 1           { uint32_t dt = self->default_ttl; sv_catpvn(buf, (const char*)&dt, 4); }
330 1           { uint32_t ls = self->lru_skip; sv_catpvn(buf, (const char*)&ls, 4); }
331             { size_t i;
332 17 100         for (i = 0; i < self->capacity; i++) {
333 16 100         if (I32_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    50          
    50          
    0          
    0          
334 10           sv_catpvn(buf, (const char*)&self->nodes[i].key, 4);
335 10           sv_catpvn(buf, (const char*)&self->nodes[i].value, 4);
336             /* TTL: remaining seconds (0 = none) */
337 10           { uint32_t rem = 0;
338 10 50         if (self->expires_at && self->expires_at[i] && self->expires_at[i] >= now) {
    0          
    0          
339 0           rem = self->expires_at[i] - now;
340 0 0         if (!rem) rem = 1;
341             }
342 10           sv_catpvn(buf, (const char*)&rem, 4);
343             }
344 10           n_written++;
345             }
346             }
347             }
348 1           { uint32_t actual = (uint32_t)n_written;
349 1           memcpy(SvPVX(buf) + cnt_offset, &actual, 4); }
350 1           RETVAL = buf;
351             OUTPUT:
352             RETVAL
353              
354             SV*
355             thaw(char* class, SV* data)
356             CODE:
357             STRLEN dlen;
358 1           const uint8_t* p = (const uint8_t*)SvPV(data, dlen);
359 1           const uint8_t* end = p + dlen;
360 1 50         if (dlen < 22 || memcmp(p, "DHMP", 4) != 0) croak("Invalid freeze data");
    50          
361 1           p += 4;
362 1 50         uint8_t ver = *p++; if (ver != 1) croak("Unsupported freeze version %d", ver);
363 1 50         uint8_t vid = *p++; if (vid != 0) croak("Variant mismatch: expected 0, got %d", vid);
364 1           uint32_t cnt; memcpy(&cnt, p, 4); p += 4;
365 1           uint32_t ms; memcpy(&ms, p, 4); p += 4;
366 1           uint32_t dt; memcpy(&dt, p, 4); p += 4;
367 1           uint32_t ls; memcpy(&ls, p, 4); p += 4;
368 1           HashMapI32* map = hashmap_i32_create((size_t)ms, dt, ls);
369 1 50         if (!map) croak("Failed to create map for thaw");
370 1 50         if (cnt > 0) hashmap_i32_reserve(map, (size_t)cnt);
371             { uint32_t j;
372 11 100         for (j = 0; j < cnt; j++) {
373 10 50         if (p + 12 > end) { hashmap_i32_destroy(map); croak("Truncated freeze data"); }
374 10           int32_t key; memcpy(&key, p, 4); p += 4;
375 10           int32_t val; memcpy(&val, p, 4); p += 4;
376 10           uint32_t ttl; memcpy(&ttl, p, 4); p += 4;
377 10           hashmap_i32_put(map, key, val, ttl);
378 10 50         if (ttl == 0 && map->expires_at) hashmap_i32_persist(map, key);
    50          
379             }
380             }
381 1 50         if (p > end) croak("Truncated freeze data");
382 1           RETVAL = sv_setref_pv(newSV(0), class, (void*)map);
383             OUTPUT:
384             RETVAL
385              
386              
387             UV
388             capacity(SV* self_sv)
389             CODE:
390 0 0         EXTRACT_MAP(HashMapI32, stash_i32, "Data::HashMap::I32", self_sv);
    0          
    0          
    0          
391 0 0         RETVAL = (UV)self->capacity;
392             OUTPUT:
393             RETVAL
394              
395             bool
396             persist(SV* self_sv, int32_t key)
397             CODE:
398 0 0         EXTRACT_MAP(HashMapI32, stash_i32, "Data::HashMap::I32", self_sv);
    0          
    0          
    0          
399 0           RETVAL = hashmap_i32_persist(self, key);
400             OUTPUT:
401             RETVAL
402              
403             SV*
404             swap(SV* self_sv, int32_t key, int32_t new_val)
405             CODE:
406 0 0         EXTRACT_MAP(HashMapI32, stash_i32, "Data::HashMap::I32", self_sv);
    0          
    0          
    0          
407             int32_t old;
408 0 0         if (!hashmap_i32_swap(self, key, new_val, &old)) XSRETURN_UNDEF;
409 0           RETVAL = newSViv(old);
410             OUTPUT:
411             RETVAL
412              
413             bool
414             cas(SV* self_sv, int32_t key, int32_t expected, int32_t new_val)
415             CODE:
416 0 0         EXTRACT_MAP(HashMapI32, stash_i32, "Data::HashMap::I32", self_sv);
    0          
    0          
    0          
417 0           RETVAL = hashmap_i32_cas(self, key, expected, new_val);
418             OUTPUT:
419             RETVAL
420              
421              
422             SV*
423             clone(SV* self_sv)
424             CODE:
425 0 0         EXTRACT_MAP(HashMapI32, stash_i32, "Data::HashMap::I32", self_sv);
    0          
    0          
    0          
426 0           HashMapI32* clone = hashmap_i32_clone(self);
427 0 0         if (!clone) croak("Failed to clone");
428 0 0         RETVAL = sv_setref_pv(newSV(0), HvNAME(SvSTASH(SvRV(self_sv))), (void*)clone);
    0          
    0          
    0          
    0          
    0          
429             OUTPUT:
430             RETVAL
431              
432             void
433             from_hash(SV* self_sv, SV* href)
434             CODE:
435 0 0         EXTRACT_MAP(HashMapI32, stash_i32, "Data::HashMap::I32", self_sv);
    0          
    0          
    0          
436 0 0         if (!SvROK(href) || SvTYPE(SvRV(href)) != SVt_PVHV)
    0          
437 0           croak("from_hash requires a hashref");
438 0           HV* hv = (HV*)SvRV(href);
439 0 0         hashmap_i32_reserve(self, (size_t)HvUSEDKEYS(hv));
440 0           hv_iterinit(hv);
441             HE* he;
442 0 0         while ((he = hv_iternext(hv))) {
443 0           SV* ksv = hv_iterkeysv(he);
444 0           int32_t key = (int32_t)SvIV(ksv);
445 0           SV* val = HeVAL(he);
446 0           hashmap_i32_put(self, key, (int32_t)SvIV(val), 0);
447             }
448              
449             void
450             merge(SV* self_sv, SV* other_sv)
451             CODE:
452 0 0         EXTRACT_MAP(HashMapI32, stash_i32, "Data::HashMap::I32", self_sv);
    0          
    0          
    0          
453 0 0         if (!SvROK(other_sv) || !SvOBJECT(SvRV(other_sv)) || SvSTASH(SvRV(other_sv)) != stash_i32)
    0          
    0          
454 0           croak("Expected a Data::HashMap::I32 object");
455 0           HashMapI32* other = INT2PTR(HashMapI32*, SvIV(SvRV(other_sv)));
456 0           hashmap_i32_reserve(self, self->size + other->size);
457 0 0         uint32_t now = other->expires_at ? (uint32_t)time(NULL) : 0;
458             size_t i;
459 0 0         for (i = 0; i < other->capacity; i++) {
460 0 0         if (I32_NODE_LIVE(other->nodes[i]) && !HM_TTL_SKIP_EXPIRED(other, i, now))
    0          
    0          
    0          
    0          
461 0           hashmap_i32_put(self, other->nodes[i].key, other->nodes[i].value, 0);
462             }
463              
464              
465             SV*
466             to_hash(SV* self_sv)
467             CODE:
468 1 50         EXTRACT_MAP(HashMapI32, stash_i32, "Data::HashMap::I32", self_sv);
    50          
    50          
    50          
469 1           HV* hv = newHV();
470 1 50         uint32_t now = self->expires_at ? (uint32_t)time(NULL) : 0;
471             size_t i;
472 17 100         for (i = 0; i < self->capacity; i++) {
473 16 100         if (I32_NODE_LIVE(self->nodes[i]) && !HM_TTL_SKIP_EXPIRED(self, i, now)) {
    50          
    50          
    0          
    0          
474 1           SV* val = newSViv(self->nodes[i].value);
475             char kbuf[24];
476 1           int klen = my_snprintf(kbuf, sizeof(kbuf), "%" IVdf, (IV)self->nodes[i].key);
477 1           (void)hv_store(hv, kbuf, klen, val, 0);
478             }
479             }
480 1           RETVAL = newRV_noinc((SV*)hv);
481             OUTPUT:
482             RETVAL
483              
484             bool
485             put_ttl(SV* self_sv, int32_t key, int32_t value, UV ttl)
486             CODE:
487 1 50         EXTRACT_MAP(HashMapI32, stash_i32, "Data::HashMap::I32", self_sv);
    50          
    50          
    50          
488 1           RETVAL = hashmap_i32_put(self, key, value, (uint32_t)ttl);
489             OUTPUT:
490             RETVAL
491              
492             SV*
493             get_or_set(SV* self_sv, int32_t key, int32_t default_value)
494             CODE:
495 3 50         EXTRACT_MAP(HashMapI32, stash_i32, "Data::HashMap::I32", self_sv);
    50          
    50          
    50          
496             bool was_found;
497 3           size_t idx = hashmap_i32_get_or_set(self, key, default_value, 0, &was_found);
498             (void)was_found;
499 3 100         if (idx >= self->capacity) XSRETURN_UNDEF;
500 2           RETVAL = newSViv(self->nodes[idx].value);
501             OUTPUT:
502             RETVAL
503              
504              
505