File Coverage

xs/i16.xsi
Criterion Covered Total %
statement 105 242 43.3
branch 169 628 26.9
condition n/a
subroutine n/a
pod n/a
total 274 870 31.4


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