File Coverage

Tree-Interval-Fast.xs
Criterion Covered Total %
statement 42 46 91.3
branch 27 76 35.5
condition n/a
subroutine n/a
pod n/a
total 69 122 56.5


line stmt bran cond sub pod time code
1             #ifdef __cplusplus
2             extern "C" {
3             #endif
4              
5             /*
6             From http://blogs.perl.org/users/nick_wellnhofer/2015/03/writing-xs-like-a-pro---perl-no-get-context-and-static-functions.html
7             The perlxs man page recommends to define the PERL_NO_GET_CONTEXT macro before including EXTERN.h, perl.h, and XSUB.h.
8             If this macro is defined, it is assumed that the interpreter context is passed as a parameter to every function.
9             If it's undefined, the context will typically be fetched from thread-local storage when calling the Perl API, which
10             incurs a performance overhead.
11            
12             WARNING:
13            
14             setting this macro involves additional changes to the XS code. For example, if the XS file has static functions that
15             call into the Perl API, you'll get somewhat cryptic error messages like the following:
16              
17             /usr/lib/i386-linux-gnu/perl/5.20/CORE/perl.h:155:16: error: ‘my_perl’ undeclared (first use in this function)
18             # define aTHX my_perl
19              
20             See http://perldoc.perl.org/perlguts.html#How-do-I-use-all-this-in-extensions? for ways in which to avoid these
21             errors when using the macro.
22              
23             One way is to begin each static function that invoke the perl API with the dTHX macro to fetch context. This is
24             used in the following static functions.
25             Another more efficient approach is to prepend pTHX_ to the argument list in the declaration of each static
26             function and aTHX_ when each of these functions are invoked. This is used directly in the AVL tree library
27             source code.
28             */
29             #define PERL_NO_GET_CONTEXT
30            
31             #ifdef ENABLE_DEBUG
32             #define TRACEME(x) do { \
33             if (SvTRUE(perl_get_sv("Tree::Interval::Fast::ENABLE_DEBUG", TRUE))) \
34             { PerlIO_stdoutf (x); PerlIO_stdoutf ("\n"); } \
35             } while (0)
36             #else
37             #define TRACEME(x)
38             #endif
39            
40             #include "EXTERN.h"
41             #include "perl.h"
42             #include "XSUB.h"
43            
44             #include "ppport.h"
45            
46             #include "interval.h"
47             #include "interval_list.h"
48             #include "interval_tree.h"
49              
50             #ifdef __cplusplus
51             }
52             #endif
53              
54             typedef interval_t* Tree__Interval__Fast__Interval;
55             typedef itree_t* Tree__Interval__Fast;
56              
57             /* C-level callbacks required by the interval tree library */
58              
59 90           static SV* svclone(SV* p) {
60             dTHX; /* fetch context */
61              
62 90           return SvREFCNT_inc(p);
63             }
64              
65 90           void svdestroy(SV* p) {
66             dTHX; /* fetch context */
67              
68 90           SvREFCNT_dec(p);
69 90           }
70              
71             /*====================================================================
72             * XS SECTION
73             *====================================================================*/
74              
75             MODULE = Tree::Interval::Fast PACKAGE = Tree::Interval::Fast::Interval
76              
77             Tree::Interval::Fast::Interval
78             new(packname, low, high, data)
79             char* packname
80             float low
81             float high
82             SV* data
83             PROTOTYPE: $$$
84             CODE:
85 24           RETVAL = interval_new(low, high, data, svclone, svdestroy);
86             OUTPUT:
87             RETVAL
88              
89             Tree::Interval::Fast::Interval
90             copy(interval)
91             Tree::Interval::Fast::Interval interval
92             PROTOTYPE: $
93             CODE:
94 3           RETVAL = interval_copy(interval);
95             OUTPUT:
96             RETVAL
97              
98             int
99             overlap(i1, i2)
100             Tree::Interval::Fast::Interval i1
101             Tree::Interval::Fast::Interval i2
102             PROTOTYPE: $$
103             CODE:
104 12           RETVAL = interval_overlap(i1, i2);
105             OUTPUT:
106             RETVAL
107              
108             int
109             equal(i1, i2)
110             Tree::Interval::Fast::Interval i1
111             Tree::Interval::Fast::Interval i2
112             PROTOTYPE: $$
113             CODE:
114 12           RETVAL = interval_equal(i1, i2);
115             OUTPUT:
116             RETVAL
117              
118             float
119             low(interval)
120             Tree::Interval::Fast::Interval interval
121             PROTOTYPE: $
122             CODE:
123 13           RETVAL = interval->low;
124             OUTPUT:
125             RETVAL
126              
127             float
128             high(interval)
129             Tree::Interval::Fast::Interval interval
130             PROTOTYPE: $
131             CODE:
132 13           RETVAL = interval->high;
133             OUTPUT:
134             RETVAL
135              
136             SV*
137             data(interval)
138             Tree::Interval::Fast::Interval interval
139             PROTOTYPE: $
140             CODE:
141 11           RETVAL = newSVsv(interval->data);
142             OUTPUT:
143             RETVAL
144              
145             void
146             DESTROY(interval)
147             Tree::Interval::Fast::Interval interval
148             PROTOTYPE: $
149             CODE:
150 37           interval_delete(interval);
151            
152             MODULE = Tree::Interval::Fast PACKAGE = Tree::Interval::Fast
153              
154             Tree::Interval::Fast
155             new( class )
156             char* class
157             PROTOTYPE: $
158             CODE:
159              
160 9 50         TRACEME("Allocating interval tree");
    50          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    50          
    0          
    50          
161 9           RETVAL = itree_new(svclone, svdestroy);
162              
163 9 50         if(RETVAL == NULL) {
164 0           warn("Unable to allocate interval tree");
165 0           XSRETURN_UNDEF;
166             }
167              
168             OUTPUT:
169             RETVAL
170              
171             Tree::Interval::Fast::Interval
172             find( tree, low, high )
173             Tree::Interval::Fast tree
174             int low
175             int high
176             PROTOTYPE: $$$
177             PREINIT:
178             interval_t *i, *result;
179            
180             CODE:
181 7           i = interval_new( low, high, &PL_sv_undef, svclone, svdestroy);
182              
183 7           result = itree_find( tree, i );
184 7           interval_delete(i);
185              
186 7 100         if(result == NULL)
187 3           XSRETURN_UNDEF;
188              
189             /*
190             * Return a copy of the result as this belongs to the tree
191             *
192             * WARNING
193             *
194             * Invoking interval_copy on the result generates segfault.
195             * Couldn't figure out why so far.
196             *
197             */
198 4           RETVAL = interval_new( result->low, result->high, result->data, svclone, svdestroy);
199              
200             OUTPUT:
201             RETVAL
202              
203             SV*
204             findall( tree, low, high )
205             Tree::Interval::Fast tree
206             int low
207             int high
208             PROTOTYPE: $$$
209             PREINIT:
210             AV* av_ref;
211             interval_t *i;
212             const interval_t *item;
213             ilist_t* results;
214             ilisttrav_t* trav;
215            
216             CODE:
217 4           i = interval_new ( low, high, &PL_sv_undef, svclone, svdestroy );
218              
219 4           results = itree_findall ( tree, i );
220 4           interval_delete ( i );
221              
222             /* empty results set, return undef */
223 4 50         if ( results == NULL || !ilist_size ( results ) ) {
    100          
224 1           ilist_delete ( results );
225 1           XSRETURN_UNDEF;
226             }
227              
228             /* return a reference to an array of intervals */
229 3           av_ref = (AV*) sv_2mortal( (SV*) newAV() );
230              
231 3           trav = ilisttrav_new( results );
232 3 50         if ( trav == NULL ) {
233 0           ilist_delete ( results );
234 0           croak("Cannot traverse results set");
235             }
236              
237 9 100         for(item = ilisttrav_first(trav); item!=NULL; item=ilisttrav_next(trav)) {
238 6           SV* ref = newSV(0);
239 6           sv_setref_pv( ref, "Tree::Interval::Fast::Interval", (void*)interval_new(item->low, item->high, item->data, svclone, svdestroy) );
240 6           av_push(av_ref, ref);
241             }
242              
243 3           RETVAL = newRV( (SV*) av_ref );
244 3           ilist_delete ( results );
245              
246             OUTPUT:
247             RETVAL
248              
249              
250             int
251             insert( tree, interval )
252             Tree::Interval::Fast tree
253             Tree::Interval::Fast::Interval interval
254             PROTOTYPE: $$
255             CODE:
256 42           RETVAL = itree_insert( tree, interval );
257              
258             OUTPUT:
259             RETVAL
260              
261             int
262             remove( tree, interval )
263             Tree::Interval::Fast tree
264             Tree::Interval::Fast::Interval interval
265             PROTOTYPE: $$
266             CODE:
267 18           RETVAL = itree_remove( tree, interval );
268              
269             OUTPUT:
270             RETVAL
271            
272             int
273             size( tree )
274             Tree::Interval::Fast tree
275             PROTOTYPE: $
276             CODE:
277 22           RETVAL = itree_size( tree );
278              
279             OUTPUT:
280             RETVAL
281              
282             void
283             DESTROY( tree )
284             Tree::Interval::Fast tree
285             PROTOTYPE: $
286             CODE:
287 9 50         TRACEME("Deleting interval tree");
    50          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    50          
    0          
    50          
288 9           itree_delete( tree );