File Coverage

lib/Data/LnArray/XS.xs
Criterion Covered Total %
statement 349 354 98.5
branch 150 188 79.7
condition n/a
subroutine n/a
pod n/a
total 499 542 92.0


line stmt bran cond sub pod time code
1             #define PERL_NO_GET_CONTEXT // we'll define thread context if necessary (faster)
2             #include "EXTERN.h" // globals/constant import locations
3             #include "perl.h" // Perl symbols, structures and constants definition
4             #include "XSUB.h" // xsubpp functions and macros
5             #include // rand()
6             #include
7              
8 56           static SV * new (SV * class, AV * array) {
9             dTHX;
10 56 100         if (SvTYPE(class) != SVt_PV) {
11 12 50         char * name = HvNAME(SvSTASH(SvRV(class)));
    50          
    50          
    0          
    50          
    50          
12 12           class = newSVpv(name, strlen(name));
13             }
14 56           return sv_bless(newRV_noinc((SV*)array), gv_stashsv(class, 0));
15             }
16              
17 14           static AV * reverse (AV * current) {
18             dTHX;
19 14           AV * array = newAV();
20 14           int len = av_len(current), i = 0;
21 42 100         for (i = 0; i <= len; i++) {
22 28           av_unshift(array, 1);
23 28           av_store(array, 0, newSVsv(*av_fetch(current, i, 0)));
24             }
25 14           return array;
26             }
27              
28 2           static SV * reduce (AV * array, SV * red, SV * cb) {
29             dTHX;
30 2           int len = av_len(array), i = 0;
31 10 100         for (i = 0; i <= len; i++) {
32 8           dSP;
33 8           SV * val = *av_fetch(array, i, 0);
34 8 50         PUSHMARK(SP);
35 8 50         XPUSHs(red);
36 8 50         XPUSHs(val);
37 8           PUTBACK;
38 8           call_sv(cb, G_SCALAR);
39 8           SPAGAIN;
40 8           red = POPs;
41 8           PUTBACK;
42             }
43 2           return red;
44             }
45              
46 18           static int mmin (int first, int second) {
47 18 100         if (first > second) {
48 1           return second;
49             }
50 17           return first;
51             }
52              
53 5           static int mmax (int first, int second) {
54 5 50         if (first < second) {
55 0           return second;
56             }
57 5           return first;
58             }
59              
60             MODULE = Data::LnArray::XS PACKAGE = Data::LnArray::XS
61             PROTOTYPES: ENABLE
62              
63             SV *
64             arr(...)
65             CODE:
66 1           AV * array = av_make(items, MARK+1);
67 1           RETVAL = new(newSVpv("Data::LnArray::XS", 17), array);
68             OUTPUT:
69             RETVAL
70              
71             SV *
72             new(...)
73             CODE:
74 43           AV * array = av_make(items, MARK+1);
75 43           SV * class = av_shift(array);
76 43           RETVAL = new(class, array);
77             OUTPUT:
78             RETVAL
79              
80             SV *
81             get(self, index)
82             SV * self
83             SV * index
84             CODE:
85 2           RETVAL = newSVsv(*av_fetch((AV*)SvRV(self), SvIV(index), 0));
86             OUTPUT:
87             RETVAL
88              
89             SV *
90             set(self, index, value)
91             SV * self
92             SV * index
93             SV * value
94             CODE:
95 1           av_store((AV*)SvRV(self), SvIV(index), newSVsv(value));
96 1           RETVAL = newSVsv(self);
97             OUTPUT:
98             RETVAL
99              
100             SV *
101             length(self)
102             SV * self
103             CODE:
104 12           RETVAL = newSViv(av_len((AV*)SvRV(self)) + 1);
105             OUTPUT:
106             RETVAL
107              
108             SV *
109             from (...)
110             CODE:
111 5           int i = 0;
112 5           SV * self = ST(0);
113 5           SV * from = ST(1);
114 5           AV * array = newAV();
115 5 100         if (SvTYPE(SvRV(from)) == SVt_PVHV) {
116 2 100         if (!hv_exists((HV*)SvRV(from), "length", 6)) {
117 1           croak("currently cannot handle");
118             }
119 1           int len = SvIV(*hv_fetch((HV*)SvRV(from), "length", 6, 0));
120 6 100         for (i = 0; i < len; i++) {
121 5           av_push(array, newSViv(i));
122             }
123 3 100         } else if ( SvTYPE(SvRV(from)) != SVt_PVAV ) {
124             STRLEN retlen;
125 1           char * str = SvPV(from, retlen);
126 4 100         for (i = 0; i < retlen; i++) {
127 3           SV *sv = newSVpvn(str, 1);
128 3           av_push(array, sv);
129 3           str += 1;
130             }
131             } else {
132 2           array = (AV*)SvRV(from);
133             }
134            
135 4 100         if (items > 2) {
136 2           SV * cb = ST(2);
137 10 100         for (i = 0; i <= av_len(array); i++) {
138 8           dSP;
139 8           GvSV(PL_defgv) = *av_fetch(array, i, 0);
140 8 50         PUSHMARK(SP);
141 8           call_sv(cb, G_SCALAR);
142 8           SPAGAIN;
143 8           SV * ret = POPs;
144 8           PUTBACK;
145 8           av_store(array, i, newSVsv(ret));
146             }
147             }
148              
149 4           RETVAL = newSVsv(new(self, array));
150             OUTPUT:
151             RETVAL
152              
153             void
154             retrieve(self)
155             SV * self
156             CODE:
157 6           int i = 0;
158 6           AV * array = (AV*)SvRV(self);
159 6           int len = av_len(array);
160 29 100         for (i = 0; i <= len; i++) {
161 23           ST(i) = newSVsv(*av_fetch(array, i, 0));
162             }
163 6           XSRETURN(i);
164              
165             SV *
166             isArray(self, ...)
167             SV * self
168             CODE:
169 0           SV * array = ST(1);
170 0 0         if ( !SvROK(array) || SvTYPE(SvRV(array)) != SVt_PVAV ) {
    0          
171 0           RETVAL = newRV_inc((SV*)newSViv(0));
172             } else {
173 0           RETVAL = newRV_inc((SV*)newSViv(1));
174             }
175             OUTPUT:
176             RETVAL
177              
178             SV *
179             of(...)
180             CODE:
181 1           AV * array = av_make(items, MARK+1);
182 1           SV * class = av_shift(array);
183 1           RETVAL = new(class, array);
184             OUTPUT:
185             RETVAL
186              
187             SV *
188             copyWithin(self, target, start, ...)
189             SV * self
190             SV * target
191             SV * start
192             CODE:
193 4           int length = av_len((AV*)SvRV(self)) + 1;
194            
195 4           int itarget = SvIV(target);
196 4           int to = itarget < 0
197 1           ? mmax( length + itarget, 0)
198 4 100         : mmin( itarget, length);
199              
200 4           int istart = SvIV(start);
201 4           int from = istart < 0
202 1           ? mmax( length + istart, 0)
203 4 100         : mmin( istart, length);
204              
205 4 50         int iend = items == 4 ? SvIV(ST(3)) : length - 1;
206 4           int final = iend < 0
207 1           ? mmax( length + iend, 0)
208 4 100         : mmin( iend, length);
209              
210              
211 4           int count = mmin(final - from, length - to);
212              
213 4           int direction = 1;
214              
215 4 100         if ( from < to && to < ( from + count ) ) {
    50          
216 1           direction = - 1;
217 1           from += count - 1;
218 1           to += count - 1;
219             }
220              
221 4           AV * array = (AV*)SvRV(self);
222              
223 9 100         while ( count > 0 ) {
224 5           av_store(array, to, newSVsv(*av_fetch(array, from, 0)));
225 5           from += direction;
226 5           to += direction;
227 5           count--;
228             }
229              
230 4           RETVAL = newSVsv(self);
231             OUTPUT:
232             RETVAL
233              
234             SV *
235             fill(self, target, start, ...)
236             SV * self
237             SV * target
238             SV * start
239             CODE:
240 3           int length = av_len((AV*)SvRV(self)) + 1;
241            
242 3           int istart = SvIV(start);
243 3           int from = istart < 0
244 1           ? mmax( length + istart, 0)
245 3 100         : mmin( istart, length);
246              
247 3 100         int iend = items == 4 ? SvIV(ST(3)) : length - 1;
248 3           int final = iend < 0
249 1           ? mmax( length + iend, 0)
250 3 100         : mmin( iend, length);
251              
252 3           AV * array = (AV*)SvRV(self);
253            
254 7 100         while (from <= final) {
255 4           av_store(array, from, newSVsv(target));
256 4           from++;
257             }
258              
259 3           RETVAL = newSVsv(self);
260             OUTPUT:
261             RETVAL
262              
263             SV *
264             pop(self)
265             SV * self
266             CODE:
267 1           RETVAL = av_pop((AV*)SvRV(self));
268             OUTPUT:
269             RETVAL
270              
271             SV *
272             push(self, value)
273             SV * self
274             SV * value
275             CODE:
276 1           av_push((AV*)SvRV(self), newSVsv(value));
277 1           RETVAL = newSVsv(self);
278             OUTPUT:
279             RETVAL
280              
281             SV *
282             reverse(self)
283             SV * self
284             CODE:
285 1           AV * current = (AV*)SvRV(self);
286 1           AV * array = reverse(current);
287 1           RETVAL = newSVsv(new(self, array));
288             OUTPUT:
289             RETVAL
290              
291             SV *
292             shift(self)
293             SV * self
294             CODE:
295 1           RETVAL = av_shift((AV*)SvRV(self));
296             OUTPUT:
297             RETVAL
298              
299             SV *
300             sort(self, cb)
301             SV * self
302             SV * cb
303             CODE:
304 2           AV * array = (AV*)SvRV(self);
305 2           AV * new_array = newAV();
306 2           int len = av_len(array), i = 0, j = 0;
307 2           GV * aa = gv_fetchpv("a", GV_ADD, SVt_PV);
308 2           GV * bb = gv_fetchpv("b", GV_ADD, SVt_PV);
309 2           SAVESPTR(GvSV(aa));
310 2           SAVESPTR(GvSV(bb));
311 10 100         for (i = 0; i <= len; i++) {
312 8           av_push(new_array, newSVsv(*av_fetch(array, i, 0)));
313             }
314 10 100         for (i = 0; i <= len; i++) {
315 32 100         for (j = 0; j < len; j++) {
316 24           dSP;
317 24           SV * a = GvSV(aa) = newSVsv(*av_fetch(new_array, j, 0));
318 24           SV * b = GvSV(bb) = newSVsv(*av_fetch(new_array, j + 1, 0));
319 24 50         PUSHMARK(SP);
320 24           call_sv(cb, 3);
321 24           double ret = SvNV(ST(2));
322 24 100         if (ret > 0) {
323 6           av_store(new_array, j, newSVsv(b));
324 6           av_store(new_array, j + 1, newSVsv(a));
325             }
326 24           PUTBACK;
327             }
328             }
329            
330 2           RETVAL = newSVsv(new(self, new_array));
331             OUTPUT:
332             RETVAL
333              
334             SV *
335             unshift(self, ...)
336             SV * self
337             CODE:
338 1           AV * array = (AV*)SvRV(self);
339 1           int i = 1;
340 2 100         for (i = 1; i < items; i++) {
341 1           av_unshift(array, 1);
342 1           av_store(array, 0, newSVsv(ST(i)));
343             }
344 1           RETVAL = newSVsv(self);
345             OUTPUT:
346             RETVAL
347              
348             SV *
349             concat(self, array)
350             SV * self
351             AV * array
352             CODE:
353 1           int len = av_len(array), i = 0;
354 5 100         for (i = 0; i <= len; i++) {
355 4           av_push((AV*)SvRV(self), newSVsv(*av_fetch(array, i, 0)));
356             }
357 1           RETVAL = newSVsv(self);
358             OUTPUT:
359             RETVAL
360              
361             SV *
362             filter(self, cb)
363             SV * self
364             SV * cb
365             CODE:
366 1           AV * array = (AV*)SvRV(self);
367 1           AV * new_array = newAV();
368 1           int len = av_len(array), i = 0;
369 5 100         for (i = 0; i <= len; i++) {
370 4           dSP;
371 4           SV * val = *av_fetch(array, i, 0);
372 4 50         PUSHMARK(SP);
373 4 50         XPUSHs(val);
374 4           PUTBACK;
375 4           call_sv(cb, G_SCALAR);
376 4 100         if (SvTRUEx(*PL_stack_sp)) {
377 3           av_push(new_array, newSVsv(val));
378             }
379             }
380 1           RETVAL = newSVsv(new(self, new_array));
381             OUTPUT:
382             RETVAL
383              
384             SV *
385             includes(self, find)
386             SV * self
387             SV * find
388             CODE:
389 2           AV * array = (AV*)SvRV(self);
390 2           int len = av_len(array), i = 0;
391 2           RETVAL = newRV_inc((SV*)newSViv(0));
392 10 100         for (i = 0; i <= len; i++) {
393 9           SV * val = *av_fetch(array, i, 0);
394 9 100         if ( SvTYPE(val) == SVt_PV ) {
395             STRLEN r1, r2;
396 5           char * v1 = SvPV(val, r1);
397 5           char * v2 = SvPV(find, r2);
398 5 100         if ( strcmp(v1, v2) == 0 ) {
399 1           RETVAL = newRV_inc((SV*)newSViv(1));
400 1           break;
401             }
402             }
403             }
404             OUTPUT:
405             RETVAL
406              
407             SV *
408             indexOf(self, find)
409             SV * self
410             SV * find
411             CODE:
412 3           AV * array = (AV*)SvRV(self);
413 3           int len = av_len(array), i = 0;
414 3           RETVAL = (SV*)newSViv(-1);
415 9 100         for (i = 0; i <= len; i++) {
416 8           SV * val = *av_fetch(array, i, 0);
417 8 50         if ( SvTYPE(val) == SVt_PV ) {
418             STRLEN r1, r2;
419 8           char * v1 = SvPV(val, r1);
420 8           char * v2 = SvPV(find, r2);
421 8 100         if ( strcmp(v1, v2) == 0 ) {
422 2           RETVAL = (SV*)newSViv(i);
423 2           break;
424             }
425             }
426             }
427             OUTPUT:
428             RETVAL
429              
430             SV *
431             join(self, join)
432             SV * self
433             SV * join
434             CODE:
435 2           AV * array = (AV*)SvRV(self);
436 2           int len = av_len(array), i = 0;
437             STRLEN retlen;
438 2           char * joiner = SvPV(join, retlen);
439 2           RETVAL = newSVpv("", 0);
440 10 100         for (i = 0; i <= len; i++) {
441 8 100         if (i > 0) {
442 6           sv_catpv(RETVAL, joiner);
443             }
444 8           sv_catpv(RETVAL, SvPV(*av_fetch(array, i, 0), retlen));
445             }
446             OUTPUT:
447             RETVAL
448              
449              
450             SV *
451             lastIndexOf(self, find)
452             SV * self
453             SV * find
454             CODE:
455 1           AV * array = (AV*)SvRV(self);
456 1           int len = av_len(array), i = 0;
457 1           RETVAL = (SV*)newSViv(-1);
458 6 100         for (i = 0; i <= len; i++) {
459 5           SV * val = *av_fetch(array, i, 0);
460 5 50         if ( SvTYPE(val) == SVt_PV ) {
461             STRLEN r1, r2;
462 5           char * v1 = SvPV(val, r1);
463 5           char * v2 = SvPV(find, r2);
464 5 100         if ( strcmp(v1, v2) == 0 ) {
465 2           RETVAL = (SV*)newSViv(i);
466             }
467             }
468             }
469             OUTPUT:
470             RETVAL
471              
472             SV *
473             slice(self, start, end)
474             SV * self
475             SV * start
476             SV * end
477             CODE:
478 1           AV * array = (AV*)SvRV(self);
479 1           AV * new_array = newAV();
480 1           int from = SvIV(start);
481 1           int to = mmin(SvIV(end), av_len(array));
482 3 100         for (from = from; from <= to; from++) {
483 2           av_push(new_array, newSVsv(*av_fetch(array, from, 0)));
484             }
485 1           RETVAL = newSVsv(new(self, new_array));
486             OUTPUT:
487             RETVAL
488              
489             SV *
490             toString(self, join)
491             SV * self
492             SV * join
493             CODE:
494 1           AV * array = (AV*)SvRV(self);
495 1           int len = av_len(array), i = 0;
496             STRLEN retlen;
497 1           char * joiner = SvPV(join, retlen);
498 1           RETVAL = newSVpv("", 0);
499 5 100         for (i = 0; i <= len; i++) {
500 4 100         if (i > 0) {
501 3           sv_catpv(RETVAL, joiner);
502             }
503 4           sv_catpv(RETVAL, SvPV(*av_fetch(array, i, 0), retlen));
504             }
505             OUTPUT:
506             RETVAL
507              
508              
509             void
510             entries(self)
511             SV * self
512             CODE:
513 1           int i = 0;
514 1           AV * array = (AV*)SvRV(self);
515 1           int len = av_len(array);
516 1           int st = 0;
517 5 100         for (i = 0; i <= len; i++) {
518 4           ST(st) = newSViv(i);
519 4           st++;
520 4           ST(st) = newSVsv(*av_fetch(array, i, 0));
521 4           st++;
522             }
523 1           XSRETURN(i);
524              
525             SV *
526             every(self, cb)
527             SV * self
528             SV * cb
529             CODE:
530 2           AV * array = (AV*)SvRV(self);
531 2           int len = av_len(array), i = 0;
532 2           RETVAL = newRV_inc((SV*)newSViv(1));
533 7 100         for (i = 0; i <= len; i++) {
534 6           dSP;
535 6           SV * val = *av_fetch(array, i, 0);
536 6 50         PUSHMARK(SP);
537 6 50         XPUSHs(val);
538 6           PUTBACK;
539 6           call_sv(cb, G_SCALAR);
540 6 100         if (!SvTRUEx(*PL_stack_sp)) {
541 1           PUTBACK;
542 1           RETVAL = newRV_inc((SV*)newSViv(0));
543 1           break;
544             }
545             }
546             OUTPUT:
547             RETVAL
548              
549             SV *
550             find(self, cb)
551             SV * self
552             SV * cb
553             CODE:
554 2           AV * array = (AV*)SvRV(self);
555 2           int len = av_len(array), i = 0;
556 2           RETVAL = (SV*) 0;
557 6 100         for (i = 0; i <= len; i++) {
558 5           SV * val = *av_fetch(array, i, 0);
559 5 50         PUSHMARK(SP);
560 5 50         XPUSHs(val);
561 5           PUTBACK;
562 5           call_sv(cb, G_SCALAR);
563 5 100         if (SvTRUEx(*PL_stack_sp)) {
564 1           RETVAL = newSVsv(val);
565 1           break;
566             }
567             }
568             OUTPUT:
569             RETVAL
570              
571             SV *
572             findIndex(self, cb)
573             SV * self
574             SV * cb
575             CODE:
576 2           AV * array = (AV*)SvRV(self);
577 2           int len = av_len(array), i = 0;
578 2           RETVAL = (SV*) 0;
579 6 100         for (i = 0; i <= len; i++) {
580 5           SV * val = *av_fetch(array, i, 0);
581 5 50         PUSHMARK(SP);
582 5 50         XPUSHs(val);
583 5           PUTBACK;
584 5           call_sv(cb, G_SCALAR);
585 5 100         if (SvTRUEx(*PL_stack_sp)) {
586 1           RETVAL = newSViv(i);
587 1           break;
588             }
589             }
590             OUTPUT:
591             RETVAL
592              
593             SV *
594             forEach(self, cb)
595             SV * self
596             SV * cb
597             CODE:
598 1           AV * array = (AV*)SvRV(self);
599 1           int len = av_len(array), i = 0, j = 0;
600 1           AV * into = newAV();
601 5 100         for (i = 0; i <= len; i++) {
602 4           dSP;
603 4           GvSV(PL_defgv) = *av_fetch(array, i, 0);
604 4 50         PUSHMARK(SP);
605 4           int p = call_sv(cb, 3);
606 4           SPAGAIN;
607 4 50         if (SvTRUEx(*PL_stack_sp)) {
608 4           AV * temp = newAV();
609 12 100         for (j = 0; j < p; j++) {
610 8           av_push(temp, newSVsv(POPs));
611             }
612 4           temp = reverse(temp);
613 12 100         for (j = 0; j < p; j++) {
614 8           av_push(into, *av_fetch(temp, j, 0));
615             }
616             }
617 4           PUTBACK;
618             }
619 1           len = av_len(into);
620 9 100         for (i = 0; i <= len; i++) {
621 8           ST(i) = newSVsv(*av_fetch(into, i, 0));
622             }
623 1           XSRETURN(i);
624              
625             SV *
626             keys(self)
627             SV * self
628             CODE:
629 1           int i = 0;
630 1           AV * array = (AV*)SvRV(self);
631 1           int len = av_len(array);
632 5 100         for (i = 0; i <= len; i++) {
633 4           ST(i) = newSViv(i);
634             }
635 1           XSRETURN(i);
636             OUTPUT:
637             RETVAL
638              
639             SV *
640             map(self, cb)
641             SV * self
642             SV * cb
643             CODE:
644 2           AV * array = (AV*)SvRV(self);
645 2           AV * new_array = newAV();
646 2           int len = av_len(array), i = 0, j = 0;
647 2           int offset = 0;
648 10 100         for (i = 0; i <= len; i++) {
649 8           dSP;
650 8           SV * val = *av_fetch(array, i, 0);
651 8 50         PUSHMARK(SP);
652 8 50         XPUSHs(val);
653 8           PUTBACK;
654 8           int p = call_sv(cb, 3);
655 8           SPAGAIN;
656 8 50         if (SvTRUEx(*PL_stack_sp)) {
657 8           AV * temp = newAV();
658 20 100         for (j = 0; j < p; j++) {
659 12           av_push(temp, newSVsv(POPs));
660             }
661 8           temp = reverse(temp);
662 20 100         for (j = 0; j < p; j++) {
663 12           av_push(new_array, *av_fetch(temp, j, 0));
664             }
665             }
666 8           PUTBACK;
667              
668             }
669 2           RETVAL = newSVsv(new(self, new_array));
670             OUTPUT:
671             RETVAL
672              
673             SV *
674             reduce(self, cb, ...)
675             SV * self
676             SV * cb
677             CODE:
678 1 50         SV * red = items > 2 ? ST(3) : newSV(0);
679 1           AV * array = (AV*)SvRV(self);
680 1           RETVAL = newSVsv(reduce(array, red, cb));
681             OUTPUT:
682             RETVAL
683              
684             SV *
685             reduceRight(self, cb, ...)
686             SV * self
687             SV * cb
688             CODE:
689 1 50         SV * red = items > 2 ? ST(3) : newSV(0);
690 1           AV * array = reverse((AV*)SvRV(self));
691 1           RETVAL = newSVsv(reduce(array, red, cb));
692             OUTPUT:
693             RETVAL
694              
695             SV *
696             some(self, cb)
697             SV * self
698             SV * cb
699             CODE:
700 2           AV * array = (AV*)SvRV(self);
701 2           int len = av_len(array), i = 0;
702 2           RETVAL = newRV_inc((SV*)newSViv(0));
703 6 100         for (i = 0; i <= len; i++) {
704 5           dSP;
705 5           SV * val = *av_fetch(array, i, 0);
706 5 50         PUSHMARK(SP);
707 5 50         XPUSHs(val);
708 5           PUTBACK;
709 5           call_sv(cb, G_SCALAR);
710 5 100         if (SvTRUEx(*PL_stack_sp)) {
711 1           PUTBACK;
712 1           RETVAL = newRV_inc((SV*)newSViv(1));
713 1           break;
714             }
715             }
716             OUTPUT:
717             RETVAL
718              
719             void
720             values(self)
721             SV * self
722             CODE:
723 1           int i = 0;
724 1           AV * array = (AV*)SvRV(self);
725 1           int len = av_len(array);
726 5 100         for (i = 0; i <= len; i++) {
727 4           ST(i) = newSVsv(*av_fetch(array, i, 0));
728             }
729 1           XSRETURN(i);