Comprehensive regression tests for Perl_refcounted_he_fetch().
[p5sagit/p5-mst-13.2.git] / ext / XS / APItest / APItest.xs
CommitLineData
6a93a7e5 1#define PERL_IN_XS_APITEST
3e61d65a 2#include "EXTERN.h"
3#include "perl.h"
4#include "XSUB.h"
5
85ce96a1 6
7/* for my_cxt tests */
8
9#define MY_CXT_KEY "XS::APItest::_guts" XS_VERSION
10
11typedef struct {
12 int i;
13 SV *sv;
14} my_cxt_t;
15
16START_MY_CXT
17
18/* indirect functions to test the [pa]MY_CXT macros */
f16dd614 19
85ce96a1 20int
21my_cxt_getint_p(pMY_CXT)
22{
23 return MY_CXT.i;
24}
f16dd614 25
85ce96a1 26void
27my_cxt_setint_p(pMY_CXT_ int i)
28{
29 MY_CXT.i = i;
30}
f16dd614 31
32SV*
33my_cxt_getsv_interp()
34{
35#ifdef PERL_IMPLICIT_CONTEXT
36 dTHX;
37 dMY_CXT_INTERP(my_perl);
38#else
39 dMY_CXT;
40#endif
41 return MY_CXT.sv;
42}
43
85ce96a1 44void
45my_cxt_setsv_p(SV* sv _pMY_CXT)
46{
47 MY_CXT.sv = sv;
48}
49
50
9b5c3821 51/* from exception.c */
52int exception(int);
0314122a 53
2dc92170 54/* A routine to test hv_delayfree_ent
55 (which itself is tested by testing on hv_free_ent */
56
57typedef void (freeent_function)(pTHX_ HV *, register HE *);
58
59void
60test_freeent(freeent_function *f) {
61 dTHX;
62 dSP;
63 HV *test_hash = newHV();
64 HE *victim;
65 SV *test_scalar;
66 U32 results[4];
67 int i;
68
8afd2d2e 69#ifdef PURIFY
70 victim = (HE*)safemalloc(sizeof(HE));
71#else
2dc92170 72 /* Storing then deleting something should ensure that a hash entry is
73 available. */
74 hv_store(test_hash, "", 0, &PL_sv_yes, 0);
75 hv_delete(test_hash, "", 0, 0);
76
77 /* We need to "inline" new_he here as it's static, and the functions we
78 test expect to be able to call del_HE on the HE */
6a93a7e5 79 if (!PL_body_roots[HE_SVSLOT])
2dc92170 80 croak("PL_he_root is 0");
6a93a7e5 81 victim = PL_body_roots[HE_SVSLOT];
82 PL_body_roots[HE_SVSLOT] = HeNEXT(victim);
8afd2d2e 83#endif
2dc92170 84
85 victim->hent_hek = Perl_share_hek(aTHX_ "", 0, 0);
86
87 test_scalar = newSV(0);
88 SvREFCNT_inc(test_scalar);
de616631 89 HeVAL(victim) = test_scalar;
2dc92170 90
91 /* Need this little game else we free the temps on the return stack. */
92 results[0] = SvREFCNT(test_scalar);
93 SAVETMPS;
94 results[1] = SvREFCNT(test_scalar);
95 f(aTHX_ test_hash, victim);
96 results[2] = SvREFCNT(test_scalar);
97 FREETMPS;
98 results[3] = SvREFCNT(test_scalar);
99
100 i = 0;
101 do {
102 mPUSHu(results[i]);
103 } while (++i < sizeof(results)/sizeof(results[0]));
104
105 /* Goodbye to our extra reference. */
106 SvREFCNT_dec(test_scalar);
107}
108
0314122a 109MODULE = XS::APItest:Hash PACKAGE = XS::APItest::Hash
110
028f8eaa 111#define UTF8KLEN(sv, len) (SvUTF8(sv) ? -(I32)len : (I32)len)
112
0314122a 113bool
114exists(hash, key_sv)
115 PREINIT:
116 STRLEN len;
117 const char *key;
118 INPUT:
119 HV *hash
120 SV *key_sv
121 CODE:
122 key = SvPV(key_sv, len);
028f8eaa 123 RETVAL = hv_exists(hash, key, UTF8KLEN(key_sv, len));
0314122a 124 OUTPUT:
125 RETVAL
126
b60cf05a 127SV *
128delete(hash, key_sv)
129 PREINIT:
130 STRLEN len;
131 const char *key;
132 INPUT:
133 HV *hash
134 SV *key_sv
135 CODE:
136 key = SvPV(key_sv, len);
137 /* It's already mortal, so need to increase reference count. */
028f8eaa 138 RETVAL = SvREFCNT_inc(hv_delete(hash, key, UTF8KLEN(key_sv, len), 0));
b60cf05a 139 OUTPUT:
140 RETVAL
141
142SV *
858117f8 143store_ent(hash, key, value)
144 PREINIT:
145 SV *copy;
146 HE *result;
147 INPUT:
148 HV *hash
149 SV *key
150 SV *value
151 CODE:
152 copy = newSV(0);
153 result = hv_store_ent(hash, key, copy, 0);
154 SvSetMagicSV(copy, value);
155 if (!result) {
156 SvREFCNT_dec(copy);
157 XSRETURN_EMPTY;
158 }
159 /* It's about to become mortal, so need to increase reference count.
160 */
161 RETVAL = SvREFCNT_inc(HeVAL(result));
162 OUTPUT:
163 RETVAL
164
165
166SV *
b60cf05a 167store(hash, key_sv, value)
168 PREINIT:
169 STRLEN len;
170 const char *key;
171 SV *copy;
172 SV **result;
173 INPUT:
174 HV *hash
175 SV *key_sv
176 SV *value
177 CODE:
178 key = SvPV(key_sv, len);
179 copy = newSV(0);
028f8eaa 180 result = hv_store(hash, key, UTF8KLEN(key_sv, len), copy, 0);
858117f8 181 SvSetMagicSV(copy, value);
b60cf05a 182 if (!result) {
183 SvREFCNT_dec(copy);
184 XSRETURN_EMPTY;
185 }
186 /* It's about to become mortal, so need to increase reference count.
187 */
188 RETVAL = SvREFCNT_inc(*result);
189 OUTPUT:
190 RETVAL
191
192
193SV *
194fetch(hash, key_sv)
195 PREINIT:
196 STRLEN len;
197 const char *key;
198 SV **result;
199 INPUT:
200 HV *hash
201 SV *key_sv
202 CODE:
203 key = SvPV(key_sv, len);
028f8eaa 204 result = hv_fetch(hash, key, UTF8KLEN(key_sv, len), 0);
b60cf05a 205 if (!result) {
206 XSRETURN_EMPTY;
207 }
208 /* Force mg_get */
209 RETVAL = newSVsv(*result);
210 OUTPUT:
211 RETVAL
2dc92170 212
439efdfe 213void
2dc92170 214test_hv_free_ent()
215 PPCODE:
216 test_freeent(&Perl_hv_free_ent);
217 XSRETURN(4);
218
439efdfe 219void
2dc92170 220test_hv_delayfree_ent()
221 PPCODE:
222 test_freeent(&Perl_hv_delayfree_ent);
223 XSRETURN(4);
35ab5632 224
225SV *
226test_share_unshare_pvn(input)
227 PREINIT:
228 SV *output;
229 STRLEN len;
230 U32 hash;
231 char *pvx;
232 char *p;
233 INPUT:
234 SV *input
235 CODE:
236 pvx = SvPV(input, len);
237 PERL_HASH(hash, pvx, len);
238 p = sharepvn(pvx, len, hash);
239 RETVAL = newSVpvn(p, len);
240 unsharepvn(p, len, hash);
241 OUTPUT:
242 RETVAL
d8c5b3c5 243
244bool
245refcounted_he_exists(key, level=0)
246 SV *key
247 IV level
248 CODE:
249 if (level) {
250 croak("level must be zero, not %"IVdf, level);
251 }
252 RETVAL = (Perl_refcounted_he_fetch(aTHX_ PL_curcop->cop_hints_hash,
253 key, NULL, 0, 0, 0)
254 != &PL_sv_placeholder);
255 OUTPUT:
256 RETVAL
257
258
259SV *
260refcounted_he_fetch(key, level=0)
261 SV *key
262 IV level
263 CODE:
264 if (level) {
265 croak("level must be zero, not %"IVdf, level);
266 }
267 RETVAL = Perl_refcounted_he_fetch(aTHX_ PL_curcop->cop_hints_hash, key,
268 NULL, 0, 0, 0);
269 SvREFCNT_inc(RETVAL);
270 OUTPUT:
271 RETVAL
272
35ab5632 273
0314122a 274=pod
275
276sub TIEHASH { bless {}, $_[0] }
277sub STORE { $_[0]->{$_[1]} = $_[2] }
278sub FETCH { $_[0]->{$_[1]} }
279sub FIRSTKEY { my $a = scalar keys %{$_[0]}; each %{$_[0]} }
280sub NEXTKEY { each %{$_[0]} }
281sub EXISTS { exists $_[0]->{$_[1]} }
282sub DELETE { delete $_[0]->{$_[1]} }
283sub CLEAR { %{$_[0]} = () }
284
285=cut
286
3e61d65a 287MODULE = XS::APItest PACKAGE = XS::APItest
288
289PROTOTYPES: DISABLE
290
85ce96a1 291BOOT:
292{
293 MY_CXT_INIT;
294 MY_CXT.i = 99;
295 MY_CXT.sv = newSVpv("initial",0);
296}
297
298void
299CLONE(...)
300 CODE:
301 MY_CXT_CLONE;
302 MY_CXT.sv = newSVpv("initial_clone",0);
303
3e61d65a 304void
305print_double(val)
306 double val
307 CODE:
308 printf("%5.3f\n",val);
309
310int
311have_long_double()
312 CODE:
313#ifdef HAS_LONG_DOUBLE
314 RETVAL = 1;
315#else
316 RETVAL = 0;
317#endif
cabb36f0 318 OUTPUT:
319 RETVAL
3e61d65a 320
321void
322print_long_double()
323 CODE:
324#ifdef HAS_LONG_DOUBLE
fc0bf671 325# if defined(PERL_PRIfldbl) && (LONG_DOUBLESIZE > DOUBLESIZE)
3e61d65a 326 long double val = 7.0;
327 printf("%5.3" PERL_PRIfldbl "\n",val);
328# else
329 double val = 7.0;
330 printf("%5.3f\n",val);
331# endif
332#endif
333
334void
3e61d65a 335print_int(val)
336 int val
337 CODE:
338 printf("%d\n",val);
339
340void
341print_long(val)
342 long val
343 CODE:
344 printf("%ld\n",val);
345
346void
347print_float(val)
348 float val
349 CODE:
350 printf("%5.3f\n",val);
9d911683 351
352void
353print_flush()
354 CODE:
355 fflush(stdout);
d4b90eee 356
357void
358mpushp()
359 PPCODE:
360 EXTEND(SP, 3);
361 mPUSHp("one", 3);
362 mPUSHp("two", 3);
363 mPUSHp("three", 5);
364 XSRETURN(3);
365
366void
367mpushn()
368 PPCODE:
369 EXTEND(SP, 3);
370 mPUSHn(0.5);
371 mPUSHn(-0.25);
372 mPUSHn(0.125);
373 XSRETURN(3);
374
375void
376mpushi()
377 PPCODE:
378 EXTEND(SP, 3);
d75b63cf 379 mPUSHi(-1);
380 mPUSHi(2);
381 mPUSHi(-3);
d4b90eee 382 XSRETURN(3);
383
384void
385mpushu()
386 PPCODE:
387 EXTEND(SP, 3);
d75b63cf 388 mPUSHu(1);
389 mPUSHu(2);
390 mPUSHu(3);
d4b90eee 391 XSRETURN(3);
392
393void
394mxpushp()
395 PPCODE:
396 mXPUSHp("one", 3);
397 mXPUSHp("two", 3);
398 mXPUSHp("three", 5);
399 XSRETURN(3);
400
401void
402mxpushn()
403 PPCODE:
404 mXPUSHn(0.5);
405 mXPUSHn(-0.25);
406 mXPUSHn(0.125);
407 XSRETURN(3);
408
409void
410mxpushi()
411 PPCODE:
d75b63cf 412 mXPUSHi(-1);
413 mXPUSHi(2);
414 mXPUSHi(-3);
d4b90eee 415 XSRETURN(3);
416
417void
418mxpushu()
419 PPCODE:
d75b63cf 420 mXPUSHu(1);
421 mXPUSHu(2);
422 mXPUSHu(3);
d4b90eee 423 XSRETURN(3);
d1f347d7 424
425
426void
427call_sv(sv, flags, ...)
428 SV* sv
429 I32 flags
430 PREINIT:
431 I32 i;
432 PPCODE:
433 for (i=0; i<items-2; i++)
434 ST(i) = ST(i+2); /* pop first two args */
435 PUSHMARK(SP);
436 SP += items - 2;
437 PUTBACK;
438 i = call_sv(sv, flags);
439 SPAGAIN;
440 EXTEND(SP, 1);
441 PUSHs(sv_2mortal(newSViv(i)));
442
443void
444call_pv(subname, flags, ...)
445 char* subname
446 I32 flags
447 PREINIT:
448 I32 i;
449 PPCODE:
450 for (i=0; i<items-2; i++)
451 ST(i) = ST(i+2); /* pop first two args */
452 PUSHMARK(SP);
453 SP += items - 2;
454 PUTBACK;
455 i = call_pv(subname, flags);
456 SPAGAIN;
457 EXTEND(SP, 1);
458 PUSHs(sv_2mortal(newSViv(i)));
459
460void
461call_method(methname, flags, ...)
462 char* methname
463 I32 flags
464 PREINIT:
465 I32 i;
466 PPCODE:
467 for (i=0; i<items-2; i++)
468 ST(i) = ST(i+2); /* pop first two args */
469 PUSHMARK(SP);
470 SP += items - 2;
471 PUTBACK;
472 i = call_method(methname, flags);
473 SPAGAIN;
474 EXTEND(SP, 1);
475 PUSHs(sv_2mortal(newSViv(i)));
476
477void
478eval_sv(sv, flags)
479 SV* sv
480 I32 flags
481 PREINIT:
482 I32 i;
483 PPCODE:
484 PUTBACK;
485 i = eval_sv(sv, flags);
486 SPAGAIN;
487 EXTEND(SP, 1);
488 PUSHs(sv_2mortal(newSViv(i)));
489
b8e65a9b 490void
d1f347d7 491eval_pv(p, croak_on_error)
492 const char* p
493 I32 croak_on_error
d1f347d7 494 PPCODE:
495 PUTBACK;
496 EXTEND(SP, 1);
497 PUSHs(eval_pv(p, croak_on_error));
498
499void
500require_pv(pv)
501 const char* pv
d1f347d7 502 PPCODE:
503 PUTBACK;
504 require_pv(pv);
505
0ca3a874 506int
507exception(throw_e)
508 int throw_e
509 OUTPUT:
510 RETVAL
d1f347d7 511
ef469b03 512void
7e7a3dfc 513mycroak(sv)
514 SV* sv
ef469b03 515 CODE:
7e7a3dfc 516 if (SvOK(sv)) {
517 Perl_croak(aTHX_ "%s", SvPV_nolen(sv));
518 }
519 else {
520 Perl_croak(aTHX_ NULL);
521 }
5d2b1485 522
523SV*
524strtab()
525 CODE:
526 RETVAL = newRV_inc((SV*)PL_strtab);
527 OUTPUT:
528 RETVAL
85ce96a1 529
530int
531my_cxt_getint()
532 CODE:
533 dMY_CXT;
534 RETVAL = my_cxt_getint_p(aMY_CXT);
535 OUTPUT:
536 RETVAL
537
538void
539my_cxt_setint(i)
540 int i;
541 CODE:
542 dMY_CXT;
543 my_cxt_setint_p(aMY_CXT_ i);
544
545void
546my_cxt_getsv()
547 PPCODE:
85ce96a1 548 EXTEND(SP, 1);
f16dd614 549 ST(0) = my_cxt_getsv_interp();
85ce96a1 550 XSRETURN(1);
551
552void
553my_cxt_setsv(sv)
554 SV *sv;
555 CODE:
556 dMY_CXT;
557 SvREFCNT_dec(MY_CXT.sv);
558 my_cxt_setsv_p(sv _aMY_CXT);
559 SvREFCNT_inc(sv);