LCOV - code coverage report
Current view: top level - src - ppg_cluster.c (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 111 116 95.7 %
Date: 2018-01-08 Functions: 12 12 100.0 %

          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             : }

Generated by: LCOV version 1.10