If you only have a small number of possible tuple values it would make sense to write some sort of hashing function which could turn them into integer indexes for quick searching.
If there are < 32 values you could do something with bitmasks:
unsigned int hash(char *value){...}
typedef struct _tuple {
unsigned int bitvalues;
void * data
} tuple;
tuple a,b,c,d;
a.bitvalues = hash("one");
a.bitvalues |= hash("four");
//a.data = something;
unsigned int event = 0;
//foreach value in event;
event |= hash(string_val);
// foreach tuple
if(x->bitvalues & test == test)
{
//matches
}
If there are too many values to do a bitmask solution you could have an array of linked lists. Go through each item in the event. If the item matches key_one, walk through the tuples with that first key and check the event for the second key:
typedef struct _tuple {
unsigned int key_one;
unsigned int key_two;
_tuple *next;
void * data;
} tuple;
tuple a,b,c,d;
a.key_one = hash("one");
a.key_two = hash("four");
tuple * list = malloc(/*big enough for all hash indexes*/
memset(/*clear list*/);
//foreach touple item
if(list[item->key_one])
put item on the end of the list;
else
list[item->key_one] = item;
//foreach event
//foreach key
if(item_ptr = list[key])
while(item_ptr.next)
if(!item_ptr.key_two || /*item has key_two*/)
//match
item_ptr = item_ptr.next;
This code is in no way tested and probably has many small errors but you should get the idea. (one error that was corrected was the test condition for tuple match)
If event processing speed is of utmost importance it would make sense to iterate through all of your constructed tuples, count the number of occurrences and go through possibly re-ordering the key one/key two of each tuple so the most unique value is listed first.