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 "ppg_cluster.h"
18 : #include "ppg_debug.h"
19 : #include "detail/ppg_context_detail.h"
20 : #include "detail/ppg_aggregate_detail.h"
21 : #include "detail/ppg_pattern_detail.h"
22 : #include "detail/ppg_token_detail.h"
23 : #include "detail/ppg_token_precedence_detail.h"
24 : #include "detail/ppg_malloc_detail.h"
25 :
26 : #include <string.h>
27 :
28 : typedef struct {
29 : PPG_Aggregate aggregate;
30 : PPG_Bitfield member_active_lasting;
31 : PPG_Count n_lasting;
32 : } PPG_Cluster;
33 :
34 196 : static bool ppg_cluster_match_event(
35 : PPG_Cluster *cluster,
36 : PPG_Event *event,
37 : bool modify_only_if_consuming)
38 : {
39 196 : bool input_part_of_cluster = false;
40 :
41 196 : PPG_ASSERT(cluster->aggregate.n_members != 0);
42 :
43 : /* Check it the input is part of the current cluster
44 : */
45 620 : for(PPG_Count i = 0; i < cluster->aggregate.n_members; ++i) {
46 :
47 502 : if(cluster->aggregate.inputs[i] == event->input) {
48 :
49 172 : input_part_of_cluster = true;
50 :
51 172 : if(event->flags & PPG_Event_Active) {
52 94 : if(!ppg_bitfield_get_bit(&cluster->aggregate.member_active, i)) {
53 94 : ppg_bitfield_set_bit(&cluster->aggregate.member_active, i, true);
54 94 : ++cluster->aggregate.n_inputs_active;
55 : }
56 :
57 94 : if(!ppg_bitfield_get_bit(&cluster->member_active_lasting, i)) {
58 84 : ppg_bitfield_set_bit(&cluster->member_active_lasting, i, true);
59 84 : ++cluster->n_lasting;
60 : }
61 : }
62 : else {
63 :
64 78 : if(cluster->aggregate.super.misc.flags & PPG_Cluster_Flags_Disallow_Input_Deactivation) {
65 0 : if(!modify_only_if_consuming) {
66 0 : cluster->aggregate.super.misc.state = PPG_Token_Invalid;
67 : }
68 0 : return false;
69 : }
70 :
71 : /* Note: If input deactivation is allowed, we do not care for
72 : * released inputs here. Every cluster member must be
73 : * pressed only once
74 : */
75 78 : if(ppg_bitfield_get_bit(&cluster->aggregate.member_active, i)) {
76 :
77 70 : ppg_bitfield_set_bit(&cluster->aggregate.member_active, i, false);
78 70 : --cluster->aggregate.n_inputs_active;
79 : }
80 : else {
81 8 : return false;
82 : }
83 :
84 70 : break;
85 : }
86 : }
87 : }
88 :
89 : #if PPG_HAVE_LOGGING
90 752 : for(PPG_Count i = 0; i < cluster->aggregate.n_members; ++i) {
91 564 : PPG_LOG("%d: 0x%d = %d\n",
92 : i,
93 : cluster->aggregate.inputs[i],
94 : ppg_bitfield_get_bit(&cluster->aggregate.member_active, i)
95 : );
96 : }
97 188 : PPG_LOG("Lasting\n");
98 752 : for(PPG_Count i = 0; i < cluster->aggregate.n_members; ++i) {
99 564 : PPG_LOG("%d: 0x%d = %d\n",
100 : i,
101 : cluster->aggregate.inputs[i],
102 : ppg_bitfield_get_bit(&cluster->member_active_lasting, i)
103 : );
104 : }
105 : #endif
106 :
107 188 : if(!input_part_of_cluster) {
108 24 : if(event->flags & PPG_Event_Active) {
109 :
110 22 : if(!modify_only_if_consuming) {
111 22 : cluster->aggregate.super.misc.state = PPG_Token_Invalid;
112 : }
113 : }
114 :
115 : // Clusters ignore unmatching deactivation events
116 :
117 24 : return false;
118 : }
119 :
120 164 : cluster->aggregate.super.misc.state = PPG_Token_Activation_In_Progress;
121 :
122 164 : if( (cluster->aggregate.n_inputs_active == 0)
123 26 : && (cluster->aggregate.super.misc.flags & PPG_Aggregate_All_Active)
124 : ) {
125 :
126 36 : if(cluster->aggregate.super.misc.flags & PPG_Aggregate_All_Active) {
127 :
128 18 : if(cluster->aggregate.super.misc.flags & PPG_Token_Flags_Pedantic) {
129 : /* Cluster matches
130 : */
131 0 : cluster->aggregate.super.misc.state = PPG_Token_Matches;
132 : }
133 : else {
134 18 : cluster->aggregate.super.misc.state = PPG_Token_Finalized;
135 : }
136 : }
137 : }
138 146 : else if(cluster->n_lasting == cluster->aggregate.n_members) {
139 :
140 54 : cluster->aggregate.super.misc.flags |= PPG_Aggregate_All_Active;
141 :
142 : /* Cluster matches
143 : */
144 54 : cluster->aggregate.super.misc.state = PPG_Token_Matches;
145 : // PPG_LOG("O");
146 : }
147 : else {
148 92 : if(cluster->aggregate.super.misc.flags & PPG_Aggregate_All_Active) {
149 0 : cluster->aggregate.super.misc.state = PPG_Token_Deactivation_In_Progress;
150 : }
151 : }
152 :
153 164 : return true;
154 : }
155 :
156 126 : static PPG_Count ppg_cluster_token_precedence(PPG_Token__ *token)
157 : {
158 : PPG_UNUSED(token);
159 126 : return PPG_Token_Precedence_Cluster;
160 : }
161 :
162 12 : static size_t ppg_cluster_dynamic_member_size(PPG_Token *token)
163 : {
164 12 : return sizeof(PPG_Cluster)
165 12 : + ppg_aggregate_dynamic_member_size((PPG_Aggregate *)token)
166 24 : + ppg_bitfield_get_num_cells(&((PPG_Cluster *)token)->member_active_lasting)
167 12 : *sizeof(PPG_Bitfield_Storage_Type);
168 : }
169 :
170 12 : static char *ppg_cluster_placement_clone(PPG_Token__ *token, char *buffer)
171 : {
172 12 : PPG_Cluster *cluster = (PPG_Cluster *)token;
173 :
174 12 : *((PPG_Cluster *)buffer) = *cluster;
175 :
176 12 : PPG_Cluster *clone = (PPG_Cluster *)buffer;
177 12 : PPG_Token__ *clone_token = (PPG_Token__ *)buffer;
178 :
179 : // printf("Replacing children pointer %p with %p\n", clone->children, (PPG_Token__ **)(buffer + sizeof(PPG_Cluster)));
180 :
181 12 : clone_token->children = (PPG_Token__ **)(buffer + sizeof(PPG_Cluster));
182 :
183 12 : buffer = ppg_aggregate_copy_dynamic_members(token, clone_token, buffer + sizeof(PPG_Cluster));
184 :
185 12 : size_t n_bytes = ppg_bitfield_get_num_cells(&cluster->member_active_lasting)
186 : *sizeof(PPG_Bitfield_Storage_Type);
187 :
188 12 : memcpy(buffer, (void*)cluster->member_active_lasting.bitarray, n_bytes);
189 :
190 12 : clone->member_active_lasting.bitarray = (PPG_Bitfield_Storage_Type *)buffer;
191 :
192 12 : return buffer + n_bytes;
193 : }
194 :
195 12 : static void ppg_cluster_addresses_to_relative( PPG_Token__ *token,
196 : void *begin_of_buffer
197 : )
198 : {
199 12 : ppg_aggregate_addresses_to_relative(token, begin_of_buffer);
200 :
201 12 : PPG_Cluster *cluster = (PPG_Cluster *)token;
202 :
203 12 : cluster->member_active_lasting.bitarray = (PPG_Bitfield_Storage_Type *)
204 12 : ((char*)cluster->member_active_lasting.bitarray
205 12 : - (char*)begin_of_buffer);
206 12 : }
207 :
208 6 : static void ppg_cluster_addresses_to_absolute( PPG_Token__ *token,
209 : void *begin_of_buffer
210 : )
211 : {
212 6 : ppg_aggregate_addresses_to_absolute(token, begin_of_buffer);
213 :
214 6 : PPG_Cluster *cluster = (PPG_Cluster *)token;
215 :
216 6 : cluster->member_active_lasting.bitarray = (PPG_Bitfield_Storage_Type *)
217 : ((char*)begin_of_buffer
218 6 : + (size_t)cluster->member_active_lasting.bitarray);
219 6 : }
220 :
221 : #if PPG_PRINT_SELF_ENABLED
222 182 : static void ppg_cluster_print_self(PPG_Cluster *c, PPG_Count indent, bool recurse)
223 : {
224 182 : PPG_I PPG_LOG("<*** clstr (0x%" PRIXPTR ") ***>\n", (uintptr_t)c);
225 182 : ppg_token_print_self_start((PPG_Token__*)c, indent);
226 182 : PPG_I PPG_LOG("\tn mbr: %d\n", c->aggregate.n_members);
227 182 : PPG_I PPG_LOG("\tn I actv: %d\n", c->aggregate.n_inputs_active);
228 182 : PPG_I PPG_LOG("\tn I lastg.: %d\n", c->n_lasting);
229 :
230 728 : for(PPG_Count i = 0; i < c->aggregate.n_members; ++i) {
231 546 : PPG_LOG("\t\tI: 0x%d, actv: %d\n",
232 : c->aggregate.inputs[i],
233 : ppg_bitfield_get_bit(&c->aggregate.member_active, i));
234 : }
235 :
236 728 : for(PPG_Count i = 0; i < c->aggregate.n_members; ++i) {
237 546 : PPG_LOG("\t\tI: 0x%d, lasting actv: %d\n",
238 : c->aggregate.inputs[i],
239 : ppg_bitfield_get_bit(&c->member_active_lasting, i));
240 : }
241 :
242 182 : ppg_token_print_self_end((PPG_Token__*)c, indent, recurse);
243 182 : }
244 : #endif
245 :
246 18 : static PPG_Cluster *ppg_cluster_destroy(PPG_Cluster *cluster) {
247 :
248 18 : ppg_bitfield_destroy(&cluster->member_active_lasting);
249 :
250 18 : ppg_aggregate_destroy(&cluster->aggregate);
251 :
252 18 : return cluster;
253 : }
254 :
255 46 : static void ppg_cluster_reset(PPG_Cluster *cluster)
256 : {
257 46 : ppg_aggregate_reset(&cluster->aggregate);
258 :
259 184 : for(PPG_Count i = 0; i < cluster->aggregate.n_members; ++i) {
260 138 : ppg_bitfield_set_bit(&cluster->member_active_lasting,
261 : i,
262 : false);
263 : }
264 :
265 46 : cluster->n_lasting = 0;
266 46 : }
267 :
268 : PPG_Token_Vtable ppg_cluster_vtable =
269 : {
270 : .match_event
271 : = (PPG_Token_Match_Event_Fun) ppg_cluster_match_event,
272 : .reset
273 : = (PPG_Token_Reset_Fun) ppg_cluster_reset,
274 : .destroy
275 : = (PPG_Token_Destroy_Fun) ppg_cluster_destroy,
276 : .equals
277 : = (PPG_Token_Equals_Fun) ppg_aggregates_equal,
278 : .token_precedence
279 : = (PPG_Token_Precedence_Fun)ppg_cluster_token_precedence,
280 : .dynamic_size
281 : = (PPG_Token_Dynamic_Size_Requirement_Fun)ppg_cluster_dynamic_member_size,
282 : .placement_clone
283 : = (PPG_Token_Placement_Clone_Fun)ppg_cluster_placement_clone,
284 : .register_ptrs_for_compression
285 : = (PPG_Token_Register_Pointers_For_Compression)ppg_token_register_pointers_for_compression,
286 : .addresses_to_relative
287 : = (PPG_Token_Addresses_To_Relative)ppg_cluster_addresses_to_relative,
288 : .addresses_to_absolute
289 : = (PPG_Token_Addresses_To_Absolute)ppg_cluster_addresses_to_absolute
290 : #if PPG_PRINT_SELF_ENABLED
291 : ,
292 : .print_self
293 : = (PPG_Token_Print_Self_Fun) ppg_cluster_print_self
294 : #endif
295 :
296 : #if PPG_HAVE_DEBUGGING
297 : ,
298 : .check_initialized
299 : = (PPG_Token_Check_Initialized_Fun)ppg_aggregate_check_initialized
300 : #endif
301 : };
302 :
303 18 : PPG_Cluster *ppg_cluster_alloc(void) {
304 18 : return (PPG_Cluster*)PPG_MALLOC(sizeof(PPG_Cluster));
305 : }
306 :
307 18 : PPG_Token ppg_cluster_create(
308 : PPG_Count n_inputs,
309 : PPG_Input_Id inputs[])
310 : {
311 18 : PPG_Cluster *cluster = ppg_cluster_alloc();
312 :
313 18 : ppg_aggregate_new(cluster);
314 :
315 18 : cluster->aggregate.super.vtable = &ppg_cluster_vtable;
316 :
317 18 : ppg_bitfield_init(&cluster->member_active_lasting);
318 18 : ppg_bitfield_resize(&cluster->member_active_lasting,
319 : n_inputs,
320 : false /*drop old bits*/);
321 :
322 18 : cluster->n_lasting = 0;
323 :
324 18 : return ppg_global_initialize_aggregate(&cluster->aggregate, n_inputs, inputs);
325 : }
326 :
327 18 : PPG_Token ppg_cluster(
328 : PPG_Layer layer,
329 : PPG_Action action,
330 : PPG_Count n_inputs,
331 : PPG_Input_Id inputs[])
332 : {
333 : // PPG_LOG("Adding cluster\n");
334 :
335 18 : PPG_Token__ *token =
336 18 : (PPG_Token__ *)ppg_cluster_create(n_inputs, inputs);
337 :
338 18 : token->action = action;
339 :
340 18 : PPG_Token__ *tokens[1] = { token };
341 :
342 18 : PPG_Token__ *leaf_token
343 18 : = ppg_pattern_from_list(NULL, layer, 1, tokens);
344 :
345 18 : return leaf_token;
346 : }
|