split the working code out from the XS file
[poe-xs-queue-array.git] / Array.xs
1 #include "EXTERN.h"
2 #include "perl.h"
3 #include "XSUB.h"
4 #include <string.h> /* for memmove() mostly */
5 #include <errno.h> /* errno values */
6 #include "queue.h"
7
8 /* this typedef lets the standard T_PTROBJ typemap handle the
9 conversion between perl class and C type and back again */
10 typedef poe_queue *POE__XS__Queue__Array;
11
12 /* This gives us our new method and correct destruction */
13 #define pq_new(class) pq_create()
14 #define pq_DESTROY(pq) pq_delete(pq)
15
16 MODULE = POE::XS::Queue::Array  PACKAGE = POE::XS::Queue::Array PREFIX = pq_
17
18 PROTOTYPES: DISABLE
19
20 POE::XS::Queue::Array
21 pq_new(class)
22
23 void
24 pq_DESTROY(pq)
25         POE::XS::Queue::Array pq
26
27 int
28 pq_enqueue(pq, priority, payload)
29      POE::XS::Queue::Array pq
30      double priority
31      SV *payload
32      
33 void
34 pq_dequeue_next(pq)
35         POE::XS::Queue::Array pq
36       PREINIT:
37         pq_priority_t priority;
38         pq_id_t id;
39         SV *payload;
40       PPCODE:
41         if (pq_dequeue_next(pq, &priority, &id, &payload)) {
42           EXTEND(SP, 3);
43           PUSHs(sv_2mortal(newSVnv(priority)));
44           PUSHs(sv_2mortal(newSViv(id)));
45           PUSHs(sv_2mortal(payload));
46         }
47
48 SV *
49 pq_get_next_priority(pq)
50         POE::XS::Queue::Array pq
51       PREINIT:
52         pq_priority_t priority;
53       CODE:
54         if (pq_get_next_priority(pq, &priority)) {
55           RETVAL = newSVnv(priority); /* XS will mortalize this for us */
56         }
57         else {
58           RETVAL = &PL_sv_undef;
59         }
60       OUTPUT:
61         RETVAL
62
63 int
64 pq_get_item_count(pq)
65         POE::XS::Queue::Array pq
66
67 void
68 pq_remove_item(pq, id, filter)
69         POE::XS::Queue::Array pq
70         int id
71         SV *filter
72       PREINIT:
73         pq_entry removed;
74       PPCODE:
75         if (pq_remove_item(pq, id, filter, &removed)) {
76           EXTEND(SP, 3);
77           PUSHs(sv_2mortal(newSVnv(removed.priority)));
78           PUSHs(sv_2mortal(newSViv(removed.id)));
79           PUSHs(sv_2mortal(removed.payload));
80         }
81
82 void
83 pq_remove_items(pq, filter, ...)
84         POE::XS::Queue::Array pq
85         SV *filter
86       PREINIT:
87         int max_count;
88         pq_entry *removed_entries = NULL;
89         int removed_count;
90         int i;
91       PPCODE:
92         if (items > 2)
93           max_count = SvIV(ST(2));
94         else
95           max_count = pq_get_item_count(pq);
96         removed_count = pq_remove_items(pq, filter, max_count, 
97                                         &removed_entries);
98         if (removed_count) {
99           EXTEND(SP, removed_count);
100           for (i = 0; i < removed_count; ++i) {
101             pq_entry *entry = removed_entries + i;
102             AV *av = newAV();
103             SV *rv;
104             av_extend(av, 2);
105             av_store(av, 0, newSVnv(entry->priority));
106             av_store(av, 1, newSViv(entry->id));
107             av_store(av, 2, entry->payload);
108             rv = newRV_noinc((SV *)av);
109             PUSHs(sv_2mortal(rv));
110           }
111         }
112         if (removed_entries)
113           free(removed_entries);
114
115 void
116 pq_adjust_priority(pq, id, filter, delta)
117         POE::XS::Queue::Array pq
118         int id
119         SV *filter
120         double delta
121       PREINIT:
122         pq_priority_t new_priority;
123       PPCODE:
124         if (pq_adjust_priority(pq, id, filter, delta, &new_priority)) {
125           EXTEND(SP, 1);
126           PUSHs(sv_2mortal(newSVnv(new_priority)));
127         }
128
129 void
130 pq_set_priority(pq, id, filter, new_priority)
131         POE::XS::Queue::Array pq
132         int id
133         SV *filter
134         double new_priority
135       PPCODE:
136         if (pq_set_priority(pq, id, filter, new_priority)) {
137           EXTEND(SP, 1);
138           PUSHs(sv_2mortal(newSVnv(new_priority)));
139         }
140
141 void
142 pq_peek_items(pq, filter, ...)
143         POE::XS::Queue::Array pq
144         SV *filter
145       PREINIT:
146         pq_entry *ret_items;
147         int count, i;
148         int max_count;
149       PPCODE:
150         if (items == 3)
151           max_count = SvIV(ST(2));
152         else
153           max_count = pq_get_item_count(pq);
154         count = pq_peek_items(pq, filter, max_count, &ret_items);
155         if (count) {
156           EXTEND(SP, count);
157           for (i = 0; i < count; ++i) {
158             pq_entry *entry = ret_items + i;
159             AV *av = newAV();
160             SV *rv;
161             av_extend(av, 2);
162             av_store(av, 0, newSVnv(entry->priority));
163             av_store(av, 1, newSViv(entry->id));
164             av_store(av, 2, newSVsv(entry->payload));
165             rv = newRV_noinc((SV *)av);
166             PUSHs(sv_2mortal(rv));
167           }
168           free(ret_items);
169         }
170
171 void
172 pq_dump(pq)
173         POE::XS::Queue::Array pq