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