Line data Source code
1 : /* Copyright 2017 noseglasses <shinynoseglasses@gmail.com>
2 : *
3 : * This program is free software: you can redistribute it and/or modify
4 : * it under the terms of the GNU Lesser General Public License as published by
5 : * the Free Software Foundation, either version 3 of the License, or
6 : * (at your option) any later version.
7 : *
8 : * This program is distributed in the hope that it will be useful,
9 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 : * GNU Lesser General Public License for more details.
12 : *
13 : * You should have received a copy of the GNU Lesser General Public License
14 : * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 : */
16 :
17 : #include "detail/ppg_event_buffer_detail.h"
18 : #include "detail/ppg_context_detail.h"
19 : #include "detail/ppg_global_detail.h"
20 : #include "detail/ppg_malloc_detail.h"
21 : #include "ppg_debug.h"
22 : #include "ppg_settings.h"
23 :
24 : #include <stdlib.h>
25 : #include <string.h>
26 : #include <assert.h>
27 :
28 : #define PPG_EB ppg_context->event_buffer
29 :
30 2904 : PPG_Count ppg_event_buffer_size(void)
31 : {
32 2904 : return PPG_EB.size;
33 : }
34 :
35 50 : void ppg_event_buffer_resize(PPG_Event_Buffer *event_buffer,
36 : PPG_Count new_size)
37 : {
38 50 : PPG_ASSERT(event_buffer);
39 :
40 50 : if(new_size <= event_buffer->max_size) { return; }
41 :
42 50 : PPG_Event_Queue_Entry *new_events
43 50 : = (PPG_Event_Queue_Entry*)PPG_MALLOC(sizeof(PPG_Event_Queue_Entry)*new_size);
44 :
45 50 : event_buffer->max_size = new_size;
46 :
47 50 : if(event_buffer->events && (event_buffer->size > 0)) {
48 0 : memcpy(new_events, event_buffer->events,
49 0 : sizeof(PPG_Event_Queue_Entry)*event_buffer->size);
50 : }
51 :
52 50 : event_buffer->events = new_events;
53 : }
54 :
55 : // Reurns an in place version of the event
56 : //
57 780 : PPG_Event * ppg_event_buffer_store_event(PPG_Event *event)
58 : {
59 : #if PPG_HAVE_ASSERTIONS
60 780 : if(PPG_EB.start > PPG_EB.end) {
61 0 : PPG_Count n_events = PPG_MAX_EVENTS + PPG_EB.end - PPG_EB.start;
62 0 : PPG_ASSERT(n_events < PPG_MAX_EVENTS - 1); // At least one left!
63 : }
64 : else {
65 780 : PPG_Count n_events = PPG_EB.end - PPG_EB.start;
66 780 : PPG_ASSERT(n_events < PPG_MAX_EVENTS - 1); // At least one left!
67 : }
68 : #endif
69 :
70 780 : PPG_Event_Buffer_Index_Type new_pos = PPG_EB.end;
71 :
72 780 : if(PPG_EB.end == PPG_MAX_EVENTS - 1) {
73 0 : PPG_EB.end = 0;
74 : }
75 : else {
76 780 : ++PPG_EB.end;
77 : }
78 :
79 1560 : PPG_EB.events[new_pos] = (PPG_Event_Queue_Entry) {
80 780 : .event = *event,
81 : .consumer = NULL,
82 : .token_state = (PPG_Token_State) {
83 : .state = 0,
84 : .changed = false
85 : }
86 : };
87 :
88 780 : ++PPG_EB.size;
89 :
90 780 : PPG_LOG("Storing event at %u\n", PPG_EB.end);
91 780 : PPG_LOG(" start: %u, cur: %u, end: %u, size: %u\n",
92 : PPG_EB.start, PPG_EB.cur, PPG_EB.end, PPG_EB.size);
93 :
94 780 : return &PPG_EB.events[new_pos].event;
95 : }
96 :
97 321 : void ppg_event_buffer_reset(PPG_Event_Buffer *eb)
98 : {
99 321 : eb->start = 0;
100 321 : eb->end = 0;
101 321 : eb->cur = 0;
102 :
103 321 : eb->size = 0;
104 :
105 321 : PPG_LOG("Event queue reset\n");
106 321 : PPG_LOG(" start: %u, cur: %u, end: %u, size: %u\n",
107 : eb->start, eb->cur, eb->end, eb->size);
108 321 : }
109 :
110 41 : void ppg_event_buffer_init(PPG_Event_Buffer *eb)
111 : {
112 41 : ppg_event_buffer_reset(eb);
113 :
114 41 : eb->max_size = 0;
115 41 : eb->events = NULL;
116 :
117 41 : ppg_event_buffer_resize(eb, PPG_MAX_EVENTS);
118 41 : }
119 :
120 :
121 9 : void ppg_event_buffer_restore(PPG_Event_Buffer *eb)
122 : {
123 9 : PPG_Count safed_size = eb->max_size;
124 :
125 9 : eb->events = NULL;
126 9 : eb->max_size = 0; // This forces resize
127 :
128 9 : ppg_event_buffer_resize(eb, safed_size);
129 9 : }
130 :
131 41 : void ppg_event_buffer_free(PPG_Event_Buffer *event_buffer)
132 : {
133 41 : if(!event_buffer->events) { return; }
134 :
135 41 : free(event_buffer->events);
136 :
137 41 : event_buffer->events = NULL;
138 : }
139 :
140 1452 : bool ppg_event_buffer_events_left(void)
141 : {
142 : // PPG_LOG("ppg_event_buffer_events_left: %u, cur: %u, end: %u, size: %u\n",
143 : // PPG_EB.start, PPG_EB.cur, PPG_EB.end, PPG_EB.size);
144 1452 : return (PPG_EB.cur != PPG_EB.end);
145 : }
146 :
147 713 : void ppg_event_buffer_advance(void)
148 : {
149 713 : if(PPG_EB.size == 0) { return; }
150 :
151 713 : if(PPG_EB.cur == PPG_MAX_EVENTS - 1) {
152 0 : PPG_EB.cur = 0;
153 : }
154 : else {
155 713 : ++PPG_EB.cur;
156 : }
157 :
158 : #if PPG_HAVE_ASSERTIONS
159 713 : ppg_check_event_buffer_validity();
160 : #endif
161 :
162 713 : PPG_LOG("Event queue advanced\n");
163 713 : PPG_LOG(" start: %u, cur: %u, end: %u, size: %u\n",
164 : PPG_EB.start, PPG_EB.cur, PPG_EB.end, PPG_EB.size);
165 : }
166 :
167 : #if PPG_HAVE_ASSERTIONS
168 811 : void ppg_check_event_buffer_validity(void)
169 : {
170 811 : if(PPG_EB.end > PPG_EB.start) {
171 811 : PPG_ASSERT(PPG_EB.cur >= PPG_EB.start);
172 811 : PPG_ASSERT(PPG_EB.cur <= PPG_EB.end);
173 : }
174 0 : else if(PPG_EB.end == PPG_EB.start) {
175 0 : PPG_ASSERT(PPG_EB.size == 0);
176 0 : PPG_ASSERT(PPG_EB.end == PPG_EB.cur);
177 : }
178 : else {
179 0 : PPG_ASSERT( !( (PPG_EB.cur > PPG_EB.end)
180 : && (PPG_EB.cur < PPG_EB.start)));
181 : }
182 811 : }
183 : #endif
184 :
185 97 : static void ppg_even_buffer_recompute_size(void)
186 : {
187 97 : if(PPG_EB.end > PPG_EB.start) {
188 :
189 0 : PPG_EB.size = PPG_EB.end - PPG_EB.start;
190 : }
191 97 : else if(PPG_EB.end == PPG_EB.start) {
192 97 : PPG_EB.size = 0;
193 : }
194 : else {
195 :
196 0 : PPG_EB.size = PPG_MAX_EVENTS + PPG_EB.end - PPG_EB.start;
197 : }
198 97 : }
199 :
200 437 : static void ppg_flush_non_considered_events(PPG_Event_Queue_Entry *eqe,
201 : void *user_data)
202 : {
203 : PPG_UNUSED(user_data);
204 :
205 437 : if(!(eqe->event.flags & PPG_Event_Considered)) {
206 :
207 : // Events that were not considered and are
208 : // not control tags such as those used for
209 : // abort input events are flushed
210 : //
211 16 : ppg_context->event_processor(&eqe->event, NULL);
212 : }
213 437 : }
214 :
215 102 : void ppg_event_buffer_truncate_at_front(void)
216 : {
217 102 : if(PPG_EB.cur == PPG_EB.end) {
218 5 : ppg_event_buffer_reset(&PPG_EB);
219 : }
220 : else {
221 :
222 97 : ppg_event_buffer_advance();
223 :
224 : // Any events that were not
225 : // considered by the last match, e.g. intermixed deactivations
226 : // of currently unrelated inputs are flushed.
227 :
228 : // Temporarily reset the end of the event buffer to
229 : // simplify flushing
230 : //
231 97 : PPG_Count old_end = PPG_EB.end;
232 97 : PPG_EB.end = PPG_EB.cur;
233 :
234 97 : ppg_event_buffer_iterate2(
235 : (PPG_Event_Processor_Visitor)ppg_flush_non_considered_events,
236 : NULL);
237 :
238 97 : PPG_EB.end = old_end; // Revert the original end
239 :
240 97 : PPG_EB.start = PPG_EB.cur; // Truncate the front of the queue
241 :
242 97 : ppg_even_buffer_recompute_size();
243 :
244 : }
245 : // PPG_LOG("Event queue truncated at front\n");
246 : // PPG_LOG(" start: %u, cur: %u, end: %u, size: %u\n",
247 : // PPG_EB.start, PPG_EB.cur, PPG_EB.end, PPG_EB.size);
248 :
249 102 : }
250 :
251 : // This method does not erase events but just changes
252 : // the input position
253 : //
254 28 : void ppg_event_buffer_remove_first_event(void)
255 : {
256 28 : if(PPG_EB.size == 0) { return; }
257 :
258 28 : if(PPG_EB.start < PPG_MAX_EVENTS - 1) {
259 28 : ++PPG_EB.start;
260 : }
261 : else {
262 0 : PPG_EB.start = 0;
263 : }
264 :
265 28 : --PPG_EB.size;
266 :
267 : // PPG_LOG("Event queue removed first event\n");
268 : // PPG_LOG(" start: %u, cur: %u, end: %u, size: %u\n",
269 : // PPG_EB.start, PPG_EB.cur, PPG_EB.end, PPG_EB.size);
270 :
271 : }
272 :
273 42 : void ppg_even_buffer_flush_and_remove_first_event(bool on_success)
274 : {
275 : PPG_UNUSED(on_success);
276 :
277 : // PPG_LOG("Flushing and removing first event\n");
278 :
279 42 : ppg_context->event_processor(&PPG_EB.events[PPG_EB.start].event, NULL);
280 :
281 42 : if(PPG_EB.size > 1) {
282 28 : ppg_event_buffer_remove_first_event();
283 : }
284 : else {
285 14 : ppg_event_buffer_reset(&PPG_EB);
286 : }
287 42 : }
288 :
289 102 : void ppg_event_buffer_on_match_success(void)
290 : {
291 102 : PPG_LOG("Prp. evt bffr on suc.\n");
292 :
293 102 : ppg_active_tokens_update();
294 :
295 : // Even though the pattern matches, it is possible that not
296 : // all events were considered as there might have been a
297 : // a tree furcation traverse involved. This might leave events
298 : // after the current event that might be part of
299 : // a future match.
300 : //
301 : // Thus, we remove all events up to the current one and leave the
302 : // rest.
303 : //
304 102 : ppg_event_buffer_truncate_at_front();
305 102 : }
306 :
307 673 : void ppg_event_buffer_iterate2(
308 : PPG_Event_Processor_Visitor visitor,
309 : void *user_data)
310 : {
311 673 : if(ppg_event_buffer_size() == 0) { return; }
312 :
313 438 : if(PPG_EB.size == 0) { return; }
314 :
315 438 : if(PPG_EB.start > PPG_EB.end) {
316 :
317 0 : for(PPG_Count i = PPG_EB.start; i < PPG_MAX_EVENTS; ++i) {
318 :
319 0 : visitor(&PPG_EB.events[i], user_data);
320 : }
321 0 : for(PPG_Count i = 0; i < PPG_EB.end; ++i) {
322 :
323 0 : visitor(&PPG_EB.events[i], user_data);
324 : }
325 : }
326 : else {
327 1629 : for(PPG_Count i = PPG_EB.start; i < PPG_EB.end; ++i) {
328 :
329 1191 : visitor(&PPG_EB.events[i], user_data);
330 : }
331 : }
332 : }
|