durable_rules 0.31.1

Sign up to get free protection for your applications and to get access to all the features.
data/src/rules/net.h ADDED
@@ -0,0 +1,141 @@
1
+
2
+ #include "rete.h"
3
+ #ifdef _WIN32
4
+ #include "../../deps/hiredis_win/hiredis.h"
5
+ #include "../../deps/hiredis_win/sds.h"
6
+ #else
7
+ #include "../../deps/hiredis/hiredis.h"
8
+ #include "../../deps/hiredis/sds.h"
9
+ #endif
10
+
11
+ #define HASH_LENGTH 40
12
+ #define MAX_MESSAGE_BATCH 64
13
+
14
+ #define ACTION_ASSERT_FACT 1
15
+ #define ACTION_ASSERT_EVENT 2
16
+ #define ACTION_RETRACT_FACT 3
17
+ #define ACTION_RETRACT_EVENT 4
18
+ #define ACTION_ADD_FACT 5
19
+ #define ACTION_ADD_EVENT 6
20
+ #define ACTION_REMOVE_FACT 7
21
+ #define ACTION_REMOVE_EVENT 8
22
+
23
+ typedef char functionHash[HASH_LENGTH + 1];
24
+
25
+ typedef struct binding {
26
+ redisContext *reContext;
27
+ functionHash evalMessageHash;
28
+ functionHash addMessageHash;
29
+ functionHash peekActionHash;
30
+ functionHash removeActionHash;
31
+ functionHash partitionHash;
32
+ functionHash timersHash;
33
+ char *sessionHashset;
34
+ char *factsHashset;
35
+ char *eventsHashset;
36
+ char *timersSortedset;
37
+ } binding;
38
+
39
+ typedef struct bindingsList {
40
+ binding *bindings;
41
+ unsigned int bindingsLength;
42
+ unsigned int lastBinding;
43
+ unsigned int lastTimersBinding;
44
+ } bindingsList;
45
+
46
+ unsigned int getBindingIndex(ruleset *tree,
47
+ unsigned int sidHash,
48
+ unsigned int *bindingIndex);
49
+
50
+ unsigned int formatEvalMessage(void *rulesBinding,
51
+ char *sid,
52
+ char *mid,
53
+ char *message,
54
+ jsonProperty *allProperties,
55
+ unsigned int propertiesLength,
56
+ unsigned char actionType,
57
+ char **keys,
58
+ unsigned int keysLength,
59
+ char **command);
60
+
61
+ unsigned int formatStoreMessage(void *rulesBinding,
62
+ char *sid,
63
+ char *message,
64
+ jsonProperty *allProperties,
65
+ unsigned int propertiesLength,
66
+ unsigned char storeFact,
67
+ char **keys,
68
+ unsigned int keysLength,
69
+ char **command);
70
+
71
+ unsigned int formatStoreSession(void *rulesBinding,
72
+ char *sid,
73
+ char *state,
74
+ unsigned char tryExists,
75
+ char **command);
76
+
77
+ unsigned int formatStoreSessionFact(void *rulesBinding,
78
+ char *sid,
79
+ char *message,
80
+ unsigned char tryExists,
81
+ char **command);
82
+
83
+ unsigned int formatRemoveTimer(void *rulesBinding,
84
+ char *timer,
85
+ char **command);
86
+
87
+ unsigned int formatRemoveAction(void *rulesBinding,
88
+ char *sid,
89
+ char **command);
90
+
91
+ unsigned int formatRemoveMessage(void *rulesBinding,
92
+ char *sid,
93
+ char *mid,
94
+ unsigned char removeFact,
95
+ char **command);
96
+
97
+ unsigned int formatPeekAction(void *rulesBinding,
98
+ char *sid,
99
+ char **command);
100
+
101
+ unsigned int executeBatch(void *rulesBinding,
102
+ char **commands,
103
+ unsigned int commandCount);
104
+
105
+ unsigned int executeBatchWithReply(void *rulesBinding,
106
+ unsigned int expectedReplies,
107
+ char **commands,
108
+ unsigned int commandCount,
109
+ redisReply **lastReply);
110
+
111
+ unsigned int startNonBlockingBatch(void *rulesBinding,
112
+ char **commands,
113
+ unsigned int commandCount,
114
+ unsigned int *replyCount);
115
+
116
+ unsigned int completeNonBlockingBatch(void *rulesBinding,
117
+ unsigned int replyCount);
118
+
119
+ unsigned int removeMessage(void *rulesBinding,
120
+ char *sid,
121
+ char *mid);
122
+
123
+ unsigned int peekAction(ruleset *tree,
124
+ void **bindingContext,
125
+ redisReply **reply);
126
+
127
+ unsigned int peekTimers(ruleset *tree,
128
+ void **bindingContext,
129
+ redisReply **reply);
130
+
131
+ unsigned int registerTimer(void *rulesBinding,
132
+ unsigned int duration,
133
+ char *timer);
134
+
135
+ unsigned int deleteBindingsList(ruleset *tree);
136
+
137
+ unsigned int getSession(void *rulesBinding,
138
+ char *sid,
139
+ char **state);
140
+
141
+
data/src/rules/rete.c ADDED
@@ -0,0 +1,1726 @@
1
+
2
+ #include <stdio.h>
3
+ #include <stdlib.h>
4
+ #include <time.h>
5
+ #include <string.h>
6
+ #include "rules.h"
7
+ #include "net.h"
8
+ #include "json.h"
9
+
10
+ #define HASH_ALL 193486302 // all
11
+ #define HASH_ANY 193486381 // any
12
+ #define HASH_PRI 193502832 // pri
13
+ #define HASH_COUNT 255678574 // count
14
+ #define HASH_SPAN 2090731639 // span
15
+ #define HASH_CAP 193488121 // cap
16
+ #define HASH_BY 5863264 // by
17
+ #define HASH_LT 193419881 // $lt
18
+ #define HASH_LTE 2087888878 // $lte
19
+ #define HASH_GT 193419716 // $gt
20
+ #define HASH_GTE 2087883433 // $gte
21
+ #define HASH_EQ 193419647 // $eq
22
+ #define HASH_NEQ 2087890573 // $neq
23
+ #define HASH_EX 193419654 // $ex
24
+ #define HASH_NEX 2087890580 // $nex
25
+ #define HASH_OR 193419978 // $or
26
+ #define HASH_AND 2087876700 // $and
27
+ #define HASH_S 5861212 // $s
28
+ #define HASH_NAME 2090536006 // name
29
+ #define HASH_ADD 2087876370 // $add
30
+ #define HASH_SUB 2087896531 // $sub
31
+ #define HASH_MUL 2087890007 // $mul
32
+ #define HASH_DIV 2087879820 // $div
33
+ #define HASH_L 5861205 // $l
34
+ #define HASH_R 5861211 //$r
35
+
36
+ typedef struct path {
37
+ unsigned char operator;
38
+ struct path **parents;
39
+ unsigned int parentsLength;
40
+ unsigned short count;
41
+ expression *expressions;
42
+ unsigned int expressionsLength;
43
+ } path;
44
+
45
+ typedef struct any {
46
+ struct all **nodes;
47
+ unsigned int nodesLength;
48
+ } any;
49
+
50
+ typedef struct all {
51
+ unsigned short count;
52
+ unsigned int *expressions;
53
+ unsigned short expressionsLength;
54
+ } all;
55
+
56
+ static unsigned int validateAlgebra(char *rule);
57
+
58
+ static unsigned int createBeta(ruleset *tree,
59
+ char *rule,
60
+ unsigned char operator,
61
+ unsigned int nextOffset,
62
+ path *nextPath,
63
+ path **outPath);
64
+
65
+ static unsigned int storeString(ruleset *tree,
66
+ char *newString,
67
+ unsigned int *stringOffset,
68
+ unsigned int length) {
69
+
70
+ unsigned int newStringLength = length + 1;
71
+ if (!tree->stringPool) {
72
+ tree->stringPool = malloc(newStringLength * sizeof(char));
73
+ if (!tree->stringPool) {
74
+ return ERR_OUT_OF_MEMORY;
75
+ }
76
+
77
+ *stringOffset = 0;
78
+ tree->stringPoolLength = newStringLength;
79
+ } else {
80
+ tree->stringPool = realloc(tree->stringPool, (tree->stringPoolLength + newStringLength) * sizeof(char));
81
+ if (!tree->stringPool) {
82
+ return ERR_OUT_OF_MEMORY;
83
+ }
84
+
85
+ *stringOffset = tree->stringPoolLength;
86
+ tree->stringPoolLength = tree->stringPoolLength + newStringLength;
87
+ }
88
+
89
+ strncpy(tree->stringPool + *stringOffset, newString, length);
90
+ tree->stringPool[tree->stringPoolLength - 1] = '\0';
91
+ return RULES_OK;
92
+ }
93
+
94
+ static unsigned int storeExpression(ruleset *tree,
95
+ expression **newExpression,
96
+ unsigned int *expressionOffset) {
97
+
98
+ if (!tree->expressionPool) {
99
+ tree->expressionPool = malloc(sizeof(expression));
100
+ if (!tree->expressionPool) {
101
+ return ERR_OUT_OF_MEMORY;
102
+ }
103
+
104
+ *expressionOffset = 0;
105
+ *newExpression = &tree->expressionPool[0];
106
+ tree->expressionOffset = 1;
107
+ } else {
108
+ tree->expressionPool = realloc(tree->expressionPool, (tree->expressionOffset + 1) * sizeof(expression));
109
+ if (!tree->expressionPool) {
110
+ return ERR_OUT_OF_MEMORY;
111
+ }
112
+
113
+ *expressionOffset = tree->expressionOffset;
114
+ *newExpression = &tree->expressionPool[tree->expressionOffset];
115
+ tree->expressionOffset = tree->expressionOffset + 1;
116
+ }
117
+
118
+ return RULES_OK;
119
+ }
120
+
121
+ static unsigned int storeIdiom(ruleset *tree,
122
+ idiom **newIdiom,
123
+ unsigned int *idiomOffset) {
124
+
125
+ if (!tree->idiomPool) {
126
+ tree->idiomPool = malloc(sizeof(idiom));
127
+ if (!tree->idiomPool) {
128
+ return ERR_OUT_OF_MEMORY;
129
+ }
130
+
131
+ *idiomOffset = 0;
132
+ *newIdiom = &tree->idiomPool[0];
133
+ tree->idiomOffset = 1;
134
+ } else {
135
+ tree->idiomPool = realloc(tree->idiomPool, (tree->idiomOffset + 1) * sizeof(idiom));
136
+ if (!tree->idiomPool) {
137
+ return ERR_OUT_OF_MEMORY;
138
+ }
139
+
140
+ *idiomOffset = tree->idiomOffset;
141
+ *newIdiom = &tree->idiomPool[tree->idiomOffset];
142
+ tree->idiomOffset = tree->idiomOffset + 1;
143
+ }
144
+
145
+ return RULES_OK;
146
+ }
147
+
148
+ static unsigned int appendTerm(expression *expr, unsigned int nodeOffset) {
149
+ if (expr->termsLength == 0) {
150
+ expr->termsLength = 1;
151
+ expr->t.termsPointer = malloc(sizeof(unsigned int));
152
+ if (!expr->t.termsPointer) {
153
+ return ERR_OUT_OF_MEMORY;
154
+ }
155
+
156
+ expr->t.termsPointer[0] = nodeOffset;
157
+ }
158
+ else {
159
+ expr->termsLength = expr->termsLength + 1;
160
+ expr->t.termsPointer = realloc(expr->t.termsPointer, expr->termsLength * sizeof(unsigned int));
161
+ if (!expr->t.termsPointer) {
162
+ return ERR_OUT_OF_MEMORY;
163
+ }
164
+
165
+ expr->t.termsPointer[expr->termsLength - 1] = nodeOffset;
166
+ }
167
+
168
+ return RULES_OK;
169
+ }
170
+
171
+ static unsigned int storeJoin(ruleset *tree,
172
+ join **newJoin,
173
+ unsigned int *joinOffset) {
174
+
175
+ if (!tree->joinPool) {
176
+ tree->joinPool = malloc(sizeof(join));
177
+ if (!tree->joinPool) {
178
+ return ERR_OUT_OF_MEMORY;
179
+ }
180
+
181
+ *joinOffset = 0;
182
+ *newJoin = &tree->joinPool[0];
183
+ tree->joinOffset = 1;
184
+ } else {
185
+ tree->joinPool = realloc(tree->joinPool, (tree->joinOffset + 1) * sizeof(join));
186
+ if (!tree->joinPool) {
187
+ return ERR_OUT_OF_MEMORY;
188
+ }
189
+
190
+ *joinOffset = tree->joinOffset;
191
+ *newJoin = &tree->joinPool[tree->joinOffset];
192
+ tree->joinOffset = tree->joinOffset + 1;
193
+ }
194
+
195
+ return RULES_OK;
196
+ }
197
+
198
+ static unsigned int storeNode(ruleset *tree,
199
+ node **newNode,
200
+ unsigned int *nodeOffset) {
201
+
202
+ if (!tree->nodePool) {
203
+ tree->nodePool = malloc(sizeof(node));
204
+ if (!tree->nodePool) {
205
+ return ERR_OUT_OF_MEMORY;
206
+ }
207
+
208
+ *nodeOffset = 0;
209
+ *newNode = &tree->nodePool[0];
210
+ tree->nodeOffset = 1;
211
+ } else {
212
+ tree->nodePool = realloc(tree->nodePool, (tree->nodeOffset + 1) * sizeof(node));
213
+ if (!tree->nodePool) {
214
+ return ERR_OUT_OF_MEMORY;
215
+ }
216
+
217
+ *nodeOffset = tree->nodeOffset;
218
+ *newNode = &tree->nodePool[tree->nodeOffset];
219
+ tree->nodeOffset = tree->nodeOffset + 1;
220
+ }
221
+
222
+ return RULES_OK;
223
+ }
224
+
225
+ static unsigned int storeAlpha(ruleset *tree,
226
+ node **newNode,
227
+ unsigned int *nodeOffset) {
228
+
229
+ unsigned int result = storeNode(tree, newNode, nodeOffset);
230
+ if (result != RULES_OK) {
231
+ return result;
232
+ }
233
+
234
+ (*newNode)->value.a.nextListOffset = 0;
235
+ (*newNode)->value.a.betaListOffset = 0;
236
+ (*newNode)->value.a.nextOffset = 0;
237
+ return RULES_OK;
238
+ }
239
+
240
+ static unsigned int allocateNext(ruleset *tree,
241
+ unsigned int length,
242
+ unsigned int *offset) {
243
+
244
+ if (!tree->nextPool) {
245
+ tree->nextPool = malloc((length + 1) * sizeof(unsigned int));
246
+ if (!tree->nextPool) {
247
+ return ERR_OUT_OF_MEMORY;
248
+ }
249
+
250
+ memset(tree->nextPool, 0, (length + 1) * sizeof(unsigned int));
251
+ *offset = 1;
252
+ tree->nextOffset = length + 1;
253
+ } else {
254
+ tree->nextPool = realloc(tree->nextPool, (tree->nextOffset + length) * sizeof(unsigned int));
255
+ if (!tree->nextPool) {
256
+ return ERR_OUT_OF_MEMORY;
257
+ }
258
+
259
+ memset(&tree->nextPool[tree->nextOffset], 0, length * sizeof(unsigned int));
260
+ *offset = tree->nextOffset;
261
+ tree->nextOffset = tree->nextOffset + length;
262
+ }
263
+
264
+ return RULES_OK;
265
+ }
266
+
267
+
268
+ static unsigned int ensureNextHashset(ruleset *tree, node *newNode) {
269
+ if (!newNode->value.a.nextOffset) {
270
+ return allocateNext(tree, NEXT_BUCKET_LENGTH, &newNode->value.a.nextOffset);
271
+ }
272
+
273
+ return RULES_OK;
274
+ }
275
+
276
+ static unsigned int ensureNextList(ruleset *tree, node *newNode) {
277
+ if (!newNode->value.a.nextListOffset) {
278
+ return allocateNext(tree, NEXT_LIST_LENGTH, &newNode->value.a.nextListOffset);
279
+ }
280
+
281
+ return RULES_OK;
282
+ }
283
+
284
+ static unsigned int ensureBetaList(ruleset *tree, node *newNode) {
285
+ if (!newNode->value.a.betaListOffset) {
286
+ return allocateNext(tree, BETA_LIST_LENGTH, &newNode->value.a.betaListOffset);
287
+ }
288
+
289
+ return RULES_OK;
290
+ }
291
+
292
+ static void copyValue(ruleset *tree,
293
+ jsonValue *right,
294
+ char *first,
295
+ char *last,
296
+ unsigned int idiomOffset,
297
+ reference *ref,
298
+ unsigned char type) {
299
+ right->type = type;
300
+ unsigned int leftLength;
301
+ char temp;
302
+ switch(type) {
303
+ case JSON_EVENT_PROPERTY:
304
+ case JSON_STATE_PROPERTY:
305
+ right->value.property.hash = ref->hash;
306
+ right->value.property.nameOffset = ref->nameOffset;
307
+ right->value.property.idOffset = ref->idOffset;
308
+ break;
309
+ case JSON_STATE_IDIOM:
310
+ case JSON_EVENT_IDIOM:
311
+ right->value.idiomOffset = idiomOffset;
312
+ break;
313
+ case JSON_STRING:
314
+ leftLength = last - first;
315
+ storeString(tree, first, &right->value.stringOffset, leftLength);
316
+ break;
317
+ case JSON_INT:
318
+ temp = last[1];
319
+ last[1] = '\0';
320
+ right->value.i = atol(first);
321
+ last[1] = temp;
322
+ break;
323
+ case JSON_DOUBLE:
324
+ temp = last[1];
325
+ last[1] = '\0';
326
+ right->value.d = atof(first);
327
+ last[1] = temp;
328
+ break;
329
+ case JSON_BOOL:
330
+ leftLength = last - first + 1;
331
+ unsigned char leftb = 1;
332
+ if (leftLength == 5 && strncmp("false", first, 5) == 0) {
333
+ leftb = 0;
334
+ }
335
+ right->value.b = leftb;
336
+ break;
337
+ }
338
+ }
339
+
340
+ static unsigned char compareValue(ruleset *tree,
341
+ jsonValue *right,
342
+ char *first,
343
+ char *last,
344
+ reference *ref,
345
+ unsigned char type) {
346
+
347
+ if (right->type != type) {
348
+ return 0;
349
+ }
350
+
351
+ unsigned int leftLength;
352
+ char temp;
353
+ switch(type) {
354
+ case JSON_EVENT_PROPERTY:
355
+ case JSON_STATE_PROPERTY:
356
+ if (right->value.property.hash == ref->hash &&
357
+ right->value.property.nameOffset == ref->nameOffset &&
358
+ right->value.property.idOffset == ref->idOffset)
359
+ return 1;
360
+
361
+ return 0;
362
+ case JSON_STATE_IDIOM:
363
+ case JSON_EVENT_IDIOM:
364
+ return 0;
365
+ case JSON_STRING:
366
+ leftLength = last - first;
367
+ char *rightString = &tree->stringPool[right->value.stringOffset];
368
+ unsigned int rightLength = strlen(rightString);
369
+ return (leftLength == rightLength ? !strncmp(rightString, first, rightLength): 0);
370
+ case JSON_INT:
371
+ temp = last[1];
372
+ last[1] = '\0';
373
+ long lefti = atol(first);
374
+ last[1] = temp;
375
+ return (right->value.i == lefti);
376
+ case JSON_DOUBLE:
377
+ temp = last[1];
378
+ last[1] = '\0';
379
+ double leftd = atof(first);
380
+ last[1] = temp;
381
+ return (right->value.d == leftd);
382
+ case JSON_BOOL:
383
+ leftLength = last - first + 1;
384
+ unsigned char leftb = 1;
385
+ if (leftLength == 5 && strncmp("false", first, 5) == 0) {
386
+ leftb = 0;
387
+ }
388
+ return (right->value.b == leftb);
389
+ }
390
+
391
+ return 0;
392
+ }
393
+
394
+ static unsigned int validateSetting(unsigned int settingHash, char *rule, unsigned char targetType) {
395
+ char *first;
396
+ char *last;
397
+ unsigned int hash;
398
+ unsigned char type;
399
+ unsigned int result = readNextName(rule, &first, &last, &hash);
400
+ while (result == PARSE_OK) {
401
+ if (hash == settingHash) {
402
+ result = readNextValue(last, &first, &last, &type);
403
+ if (type != targetType) {
404
+ return ERR_UNEXPECTED_TYPE;
405
+ }
406
+
407
+ return PARSE_OK;
408
+ }
409
+
410
+ result = readNextName(last, &first, &last, &hash);
411
+ }
412
+
413
+ return ERR_SETTING_NOT_FOUND;
414
+ }
415
+
416
+ static unsigned int validateReference(char *rule, unsigned char *referenceType) {
417
+ char *first;
418
+ char *last;
419
+ unsigned char type;
420
+ unsigned int hash;
421
+ unsigned int result;
422
+
423
+ result = readNextName(rule, &first, &last, &hash);
424
+ if (result != PARSE_OK) {
425
+ return result;
426
+ }
427
+
428
+ if (hash != HASH_S) {
429
+ *referenceType = JSON_EVENT_PROPERTY;
430
+ result = readNextString(last, &first, &last, &hash);
431
+ if (result != PARSE_OK) {
432
+ return result;
433
+ }
434
+ } else {
435
+ *referenceType = JSON_STATE_PROPERTY;
436
+ if (readNextString(last, &first, &last, &hash) != PARSE_OK) {
437
+ result = readNextValue(last, &first, &last, &type);
438
+ if (result != PARSE_OK) {
439
+ return result;
440
+ }
441
+
442
+ unsigned int result = readNextName(first, &first, &last, &hash);
443
+ while (result == PARSE_OK) {
444
+ switch (hash) {
445
+ case HASH_NAME:
446
+ result = readNextString(last, &first, &last, &hash);
447
+ break;
448
+ case HASH_ID:
449
+ result = readNextValue(last, &first, &last, &type);
450
+ break;
451
+ default:
452
+ result = readNextValue(last, &first, &last, &type);
453
+ break;
454
+ }
455
+
456
+ if (result != PARSE_OK) {
457
+ return result;
458
+ }
459
+ result = readNextName(last, &first, &last, &hash);
460
+ }
461
+ }
462
+ }
463
+
464
+ return PARSE_OK;
465
+ }
466
+
467
+ static unsigned int validateIdiom(char *rule, unsigned char *idiomType) {
468
+ char *first;
469
+ char *last;
470
+ unsigned char type;
471
+ unsigned int hash;
472
+ unsigned int result;
473
+
474
+ result = readNextName(rule, &first, &last, &hash);
475
+ if (result != PARSE_OK) {
476
+ return result;
477
+ }
478
+
479
+ if (hash != HASH_ADD && hash != HASH_SUB &&
480
+ hash != HASH_MUL && hash != HASH_DIV) {
481
+ return validateReference(rule, idiomType);
482
+ } else {
483
+ result = readNextValue(last, &first, &last, &type);
484
+ if (result != PARSE_OK) {
485
+ return result;
486
+ }
487
+
488
+ *idiomType = 0;
489
+ result = readNextName(first, &first, &last, &hash);
490
+ while (result == PARSE_OK) {
491
+ unsigned char newIdiomType = 0;
492
+ result = readNextValue(last, &first, &last, &type);
493
+ if (result != PARSE_OK) {
494
+ return result;
495
+ }
496
+
497
+ if (type == JSON_OBJECT) {
498
+ result = validateIdiom(first, &newIdiomType);
499
+ if (result != PARSE_OK) {
500
+ return result;
501
+ }
502
+ }
503
+
504
+ if (newIdiomType == JSON_EVENT_PROPERTY || newIdiomType == JSON_EVENT_IDIOM) {
505
+ if (*idiomType == JSON_STATE_PROPERTY || *idiomType == JSON_STATE_IDIOM) {
506
+ return ERR_UNEXPECTED_TYPE;
507
+ }
508
+
509
+ *idiomType = JSON_EVENT_IDIOM;
510
+ }
511
+
512
+ if (newIdiomType == JSON_STATE_PROPERTY || newIdiomType == JSON_STATE_IDIOM) {
513
+ if (*idiomType == JSON_EVENT_PROPERTY || *idiomType == JSON_EVENT_IDIOM) {
514
+ return ERR_UNEXPECTED_TYPE;
515
+ }
516
+
517
+ *idiomType = JSON_STATE_IDIOM;
518
+ }
519
+
520
+ if (hash != HASH_L && hash != HASH_R) {
521
+ return ERR_UNEXPECTED_NAME;
522
+ }
523
+
524
+ result = readNextName(last, &first, &last, &hash);
525
+ }
526
+ }
527
+
528
+ return PARSE_OK;
529
+ }
530
+
531
+
532
+ static unsigned int validateExpression(char *rule) {
533
+ char *first;
534
+ char *last;
535
+ unsigned char type;
536
+ unsigned char operator = OP_NOP;
537
+ unsigned int hash;
538
+ unsigned int result = readNextName(rule, &first, &last, &hash);
539
+ if (result != PARSE_OK) {
540
+ return result;
541
+ }
542
+
543
+ switch (hash) {
544
+ case HASH_EQ:
545
+ operator = OP_EQ;
546
+ break;
547
+ case HASH_NEQ:
548
+ operator = OP_NEQ;
549
+ break;
550
+ case HASH_GT:
551
+ operator = OP_GT;
552
+ break;
553
+ case HASH_GTE:
554
+ operator = OP_GTE;
555
+ break;
556
+ case HASH_EX:
557
+ operator = OP_EX;
558
+ break;
559
+ case HASH_NEX:
560
+ operator = OP_NEX;
561
+ break;
562
+ case HASH_LT:
563
+ operator = OP_LT;
564
+ break;
565
+ case HASH_LTE:
566
+ operator = OP_LTE;
567
+ break;
568
+ case HASH_AND:
569
+ case HASH_OR:
570
+ result = readNextValue(last, &first, &last, &type);
571
+ if (type != JSON_ARRAY) {
572
+ return ERR_UNEXPECTED_TYPE;
573
+ }
574
+
575
+ result = readNextArrayValue(first, &first, &last, &type);
576
+ while (result == PARSE_OK) {
577
+ result = validateExpression(first);
578
+ if (result != PARSE_OK) {
579
+ return result;
580
+ }
581
+
582
+ result = readNextArrayValue(last, &first, &last, &type);
583
+ }
584
+
585
+ return (result == PARSE_END ? RULES_OK: result);
586
+ }
587
+
588
+ if (operator == OP_NOP) {
589
+ operator = OP_EQ;
590
+ first = rule;
591
+ } else {
592
+ result = readNextValue(last, &first, &last, &type);
593
+ if (result != PARSE_OK) {
594
+ return result;
595
+ }
596
+ if (type != JSON_OBJECT) {
597
+ return ERR_UNEXPECTED_TYPE;
598
+ }
599
+ }
600
+
601
+ result = readNextName(first, &first, &last, &hash);
602
+ if (result != PARSE_OK) {
603
+ return result;
604
+ }
605
+
606
+ // Validating expression rValue
607
+ result = readNextValue(last, &first, &last, &type);
608
+ if (result != PARSE_OK) {
609
+ return result;
610
+ }
611
+
612
+ if (type == JSON_ARRAY) {
613
+ return ERR_UNEXPECTED_TYPE;
614
+ }
615
+
616
+ if (type == JSON_OBJECT) {
617
+ unsigned char idiomType = 0;
618
+ result = validateIdiom(first, &idiomType);
619
+ if (result != PARSE_OK) {
620
+ return result;
621
+ }
622
+ }
623
+
624
+ return PARSE_OK;
625
+ }
626
+
627
+ static unsigned int validateAlgebra(char *rule) {
628
+ char *first;
629
+ char *last;
630
+ char *lastArrayValue;
631
+ unsigned int hash;
632
+ unsigned char type;
633
+ unsigned char reenter = 0;
634
+ unsigned int result = readNextArrayValue(rule, &first, &lastArrayValue, &type);
635
+ while (result == PARSE_OK) {
636
+ result = readNextName(first, &first, &last, &hash);
637
+ unsigned int nameLength = last - first;
638
+ if (nameLength >= 4) {
639
+ if (!strncmp("$all", last - 4, 4)) {
640
+ nameLength = nameLength - 4;
641
+ reenter = 1;
642
+ } else if (!strncmp("$any", last - 4, 4)) {
643
+ nameLength = nameLength - 4;
644
+ reenter = 1;
645
+ } else if (!strncmp("$not", last - 4, 4)) {
646
+ nameLength = nameLength - 4;
647
+ }
648
+
649
+ if (nameLength == 0) {
650
+ return ERR_RULE_WITHOUT_QUALIFIER;
651
+ }
652
+ }
653
+
654
+ result = readNextValue(last, &first, &last, &type);
655
+ if (result != PARSE_OK) {
656
+ return result;
657
+ }
658
+
659
+ if (!reenter) {
660
+ result = validateExpression(first);
661
+ }
662
+ else {
663
+ result = validateAlgebra(first);
664
+ reenter = 0;
665
+ }
666
+
667
+ if (result != PARSE_OK) {
668
+ return result;
669
+ }
670
+
671
+ result = readNextArrayValue(lastArrayValue, &first, &lastArrayValue, &type);
672
+ }
673
+
674
+ return (result == PARSE_END ? PARSE_OK: result);
675
+ }
676
+
677
+ static unsigned int validateRuleset(char *rules) {
678
+ char *first;
679
+ char *last;
680
+ char *firstName;
681
+ char *lastName;
682
+ char *lastRuleValue;
683
+ unsigned char type;
684
+ unsigned int hash;
685
+ unsigned int result;
686
+ result = readNextName(rules, &firstName, &lastName, &hash);
687
+ while (result == PARSE_OK) {
688
+ result = readNextValue(lastName, &first, &lastRuleValue, &type);
689
+ if (result != PARSE_OK) {
690
+ return result;
691
+ }
692
+ if (type != JSON_OBJECT) {
693
+ return ERR_UNEXPECTED_TYPE;
694
+ }
695
+
696
+ unsigned int countResult = validateSetting(HASH_COUNT, first, JSON_INT);
697
+ if (countResult != PARSE_OK && countResult != ERR_SETTING_NOT_FOUND) {
698
+ return countResult;
699
+ }
700
+
701
+ unsigned int spanResult = validateSetting(HASH_SPAN, first, JSON_INT);
702
+ if (spanResult != PARSE_OK && spanResult != ERR_SETTING_NOT_FOUND) {
703
+ return spanResult;
704
+ }
705
+
706
+ unsigned int capResult = validateSetting(HASH_CAP, first, JSON_INT);
707
+ if (capResult != PARSE_OK && capResult != ERR_SETTING_NOT_FOUND) {
708
+ return capResult;
709
+ }
710
+
711
+ if ((spanResult == PARSE_OK && (countResult == PARSE_OK || capResult == PARSE_OK)) ||
712
+ (countResult == PARSE_OK && capResult == PARSE_OK)) {
713
+ return ERR_UNEXPECTED_NAME;
714
+ }
715
+
716
+ result = validateSetting(HASH_BY, first, JSON_STRING);
717
+ if (result != PARSE_OK && result != ERR_SETTING_NOT_FOUND) {
718
+ return result;
719
+ }
720
+
721
+ result = validateSetting(HASH_PRI, first, JSON_INT);
722
+ if (result != PARSE_OK && result != ERR_SETTING_NOT_FOUND) {
723
+ return result;
724
+ }
725
+
726
+ result = readNextName(first, &first, &last, &hash);
727
+ while (result == PARSE_OK) {
728
+ result = readNextValue(last, &first, &last, &type);
729
+ if (result != PARSE_OK) {
730
+ return result;
731
+ }
732
+
733
+ if (hash == HASH_ALL || hash == HASH_ANY) {
734
+ result = validateAlgebra(first);
735
+ if (result != RULES_OK && result != PARSE_END) {
736
+ return result;
737
+ }
738
+ } else if (hash != HASH_COUNT && hash != HASH_PRI && hash != HASH_SPAN && hash != HASH_CAP && hash != HASH_BY) {
739
+ return ERR_UNEXPECTED_NAME;
740
+ }
741
+
742
+ result = readNextName(last, &first, &last, &hash);
743
+ }
744
+
745
+ result = readNextName(lastRuleValue, &firstName, &lastName, &hash);
746
+ }
747
+
748
+ return (result == PARSE_END ? PARSE_OK: result);
749
+ }
750
+
751
+ static unsigned int linkAlpha(ruleset *tree,
752
+ unsigned int parentOffset,
753
+ unsigned int nextOffset) {
754
+ unsigned int result;
755
+ unsigned int entry;
756
+ node *parentAlpha = &tree->nodePool[parentOffset];
757
+ node *nextNode = &tree->nodePool[nextOffset];
758
+ if (nextNode->type != NODE_ALPHA) {
759
+ result = ensureBetaList(tree, parentAlpha);
760
+ if (result != RULES_OK) {
761
+ return result;
762
+ }
763
+
764
+ unsigned int *parentBetaList = &tree->nextPool[parentAlpha->value.a.betaListOffset];
765
+ for (entry = 0; parentBetaList[entry] != 0; ++entry) {
766
+ if (entry == BETA_LIST_LENGTH) {
767
+ return ERR_RULE_BETA_LIMIT_EXCEEDED;
768
+ }
769
+ }
770
+
771
+ parentBetaList[entry] = nextOffset;
772
+ }
773
+ else if (nextNode->value.a.operator == OP_NEX) {
774
+ result = ensureNextList(tree, parentAlpha);
775
+ if (result != RULES_OK) {
776
+ return result;
777
+ }
778
+
779
+ unsigned int *parentNextList = &tree->nextPool[parentAlpha->value.a.nextListOffset];
780
+ unsigned int entry;
781
+ for (entry = 0; parentNextList[entry] != 0; ++entry) {
782
+ if (entry == NEXT_LIST_LENGTH) {
783
+ return ERR_RULE_EXISTS_LIMIT_EXCEEDED;
784
+ }
785
+ }
786
+
787
+ parentNextList[entry] = nextOffset;
788
+ }
789
+ else {
790
+ result = ensureNextHashset(tree, parentAlpha);
791
+ if (result != RULES_OK) {
792
+ return result;
793
+ }
794
+
795
+ unsigned int *parentNext = &tree->nextPool[parentAlpha->value.a.nextOffset];
796
+ unsigned int hash = nextNode->value.a.hash;
797
+ for (entry = hash & HASH_MASK; parentNext[entry] != 0; entry = (entry + 1) % NEXT_BUCKET_LENGTH) {
798
+ if ((entry + 1) % NEXT_BUCKET_LENGTH == (hash & HASH_MASK)) {
799
+ return ERR_RULE_LIMIT_EXCEEDED;
800
+ }
801
+ }
802
+
803
+ parentNext[entry] = nextOffset;
804
+ }
805
+
806
+ return RULES_OK;
807
+ }
808
+
809
+ static unsigned char readReference(ruleset *tree, char *rule, reference *ref) {
810
+ char *first;
811
+ char *last;
812
+ unsigned char type;
813
+ unsigned int hash;
814
+ unsigned char returnType = JSON_EVENT_PROPERTY;
815
+
816
+ ref->idOffset = 0;
817
+ readNextName(rule, &first, &last, &hash);
818
+ if (hash != HASH_S) {
819
+ storeString(tree, first, &ref->idOffset, last - first);
820
+ readNextString(last, &first, &last, &hash);
821
+ ref->hash = hash;
822
+ storeString(tree, first, &ref->nameOffset, last - first);
823
+ } else {
824
+ returnType = JSON_STATE_PROPERTY;
825
+ if (readNextString(last, &first, &last, &hash) == PARSE_OK) {
826
+ ref->hash = hash;
827
+ storeString(tree, first, &ref->nameOffset, last - first);
828
+ }
829
+ else {
830
+ readNextValue(last, &first, &last, &type);
831
+ unsigned int result = readNextName(first, &first, &last, &hash);
832
+ while (result == PARSE_OK) {
833
+ switch (hash) {
834
+ case HASH_NAME:
835
+ readNextString(last, &first, &last, &hash);
836
+ ref->hash = hash;
837
+ storeString(tree, first, &ref->nameOffset, last - first);
838
+ break;
839
+ case HASH_ID:
840
+ readNextValue(last, &first, &last, &type);
841
+ if (type == JSON_STRING) {
842
+ storeString(tree, first, &ref->idOffset, last - first);
843
+ } else{
844
+ storeString(tree, first, &ref->idOffset, last - first + 1);
845
+ }
846
+
847
+ break;
848
+ default:
849
+ readNextValue(last, &first, &last, &type);
850
+ break;
851
+ }
852
+
853
+ result = readNextName(last, &first, &last, &hash);
854
+ }
855
+ }
856
+ }
857
+
858
+ return returnType;
859
+ }
860
+
861
+ static unsigned int readIdiom(ruleset *tree, char *rule, unsigned char *idiomType, unsigned int *idiomOffset, reference *ref) {
862
+ char *first;
863
+ char *last;
864
+ unsigned char type = 0;
865
+ unsigned char operator = OP_NOP;
866
+ unsigned int hash;
867
+ unsigned int result;
868
+
869
+ readNextName(rule, &first, &last, &hash);
870
+ switch (hash) {
871
+ case HASH_ADD:
872
+ operator = OP_ADD;
873
+ break;
874
+ case HASH_SUB:
875
+ operator = OP_SUB;
876
+ break;
877
+ case HASH_MUL:
878
+ operator = OP_MUL;
879
+ break;
880
+ case HASH_DIV:
881
+ operator = OP_DIV;
882
+ break;
883
+ }
884
+
885
+ if (operator == OP_NOP) {
886
+ *idiomType = readReference(tree, rule, ref);
887
+ } else {
888
+ idiom *newIdiom = NULL;
889
+ result = storeIdiom(tree, &newIdiom, idiomOffset);
890
+ if (result != RULES_OK) {
891
+ return result;
892
+ }
893
+
894
+ *idiomType = JSON_STATE_IDIOM;
895
+ newIdiom->operator = operator;
896
+ readNextValue(last, &first, &last, &type);
897
+ result = readNextName(first, &first, &last, &hash);
898
+ while (result == PARSE_OK) {
899
+ unsigned int newIdiomOffset = 0;
900
+ reference newRef;
901
+ readNextValue(last, &first, &last, &type);
902
+ if (type == JSON_OBJECT) {
903
+ result = readIdiom(tree, first, &type, &newIdiomOffset, &newRef);
904
+ if (result != RULES_OK) {
905
+ return result;
906
+ }
907
+ }
908
+
909
+ if (type == JSON_EVENT_PROPERTY || type == JSON_EVENT_IDIOM) {
910
+ *idiomType = JSON_EVENT_IDIOM;
911
+ }
912
+
913
+ // newIdiom address might have changed after readIdiom
914
+ newIdiom = &tree->idiomPool[*idiomOffset];
915
+ switch (hash) {
916
+ case HASH_L:
917
+ copyValue(tree, &newIdiom->left, first, last, newIdiomOffset, &newRef, type);
918
+ break;
919
+ case HASH_R:
920
+ copyValue(tree, &newIdiom->right, first, last, newIdiomOffset, &newRef, type);
921
+ break;
922
+ }
923
+
924
+ result = readNextName(last, &first, &last, &hash);
925
+ }
926
+ }
927
+
928
+ return RULES_OK;
929
+ }
930
+
931
+ static unsigned int findAlpha(ruleset *tree,
932
+ unsigned int parentOffset,
933
+ unsigned char operator,
934
+ char *rule,
935
+ expression *expr,
936
+ unsigned int *resultOffset) {
937
+ char *first;
938
+ char *last;
939
+ char *firstName;
940
+ char *lastName;
941
+ unsigned char type;
942
+ unsigned int entry;
943
+ unsigned int hash;
944
+ unsigned int idiomOffset;
945
+ unsigned int result;
946
+ reference ref;
947
+
948
+ readNextName(rule, &firstName, &lastName, &hash);
949
+ readNextValue(lastName, &first, &last, &type);
950
+ if (type == JSON_OBJECT) {
951
+ result = readIdiom(tree, first, &type, &idiomOffset, &ref);
952
+ if (result != RULES_OK) {
953
+ return result;
954
+ }
955
+ }
956
+
957
+ node *parent = &tree->nodePool[parentOffset];
958
+ unsigned int *parentNext;
959
+ if (parent->value.a.nextOffset) {
960
+ parentNext = &tree->nextPool[parent->value.a.nextOffset];
961
+ for (entry = hash & HASH_MASK; parentNext[entry] != 0; entry = (entry + 1) % NEXT_BUCKET_LENGTH) {
962
+ node *currentNode = &tree->nodePool[parentNext[entry]];
963
+ if (currentNode->value.a.hash == hash &&
964
+ currentNode->value.a.operator == operator) {
965
+ if (compareValue(tree, &currentNode->value.a.right, first, last, &ref, type)) {
966
+ *resultOffset = parentNext[entry];
967
+ return RULES_OK;
968
+ }
969
+ }
970
+ }
971
+ }
972
+
973
+ if (parent->value.a.nextListOffset) {
974
+ parentNext = &tree->nextPool[parent->value.a.nextListOffset];
975
+ for (entry = 0; parentNext[entry] != 0; ++entry) {
976
+ node *currentNode = &tree->nodePool[parentNext[entry]];
977
+ if (currentNode->value.a.hash == hash&&
978
+ currentNode->value.a.operator == operator) {
979
+ if (compareValue(tree, &currentNode->value.a.right, first, last, &ref, type)) {
980
+ *resultOffset = parentNext[entry];
981
+ return RULES_OK;
982
+ }
983
+ }
984
+ }
985
+ }
986
+
987
+ unsigned int stringOffset;
988
+ result = storeString(tree, firstName, &stringOffset, lastName - firstName);
989
+ if (result != RULES_OK) {
990
+ return result;
991
+ }
992
+
993
+ node *newAlpha;
994
+ result = storeAlpha(tree, &newAlpha, resultOffset);
995
+ if (result != RULES_OK) {
996
+ return result;
997
+ }
998
+
999
+ newAlpha->nameOffset = stringOffset;
1000
+ newAlpha->type = NODE_ALPHA;
1001
+ newAlpha->value.a.hash = hash;
1002
+ newAlpha->value.a.operator = operator;
1003
+ copyValue(tree, &newAlpha->value.a.right, first, last, idiomOffset, &ref, type);
1004
+ if (type == JSON_EVENT_PROPERTY || type == JSON_EVENT_IDIOM) {
1005
+ result = appendTerm(expr, *resultOffset);
1006
+ if (result != RULES_OK) {
1007
+ return result;
1008
+ }
1009
+ }
1010
+
1011
+ return linkAlpha(tree, parentOffset, *resultOffset);
1012
+ }
1013
+
1014
+ static void getSymbolSetting(unsigned int settingHash, char *rule, unsigned int *symbolHash) {
1015
+ char *first;
1016
+ char *last;
1017
+ unsigned int hash;
1018
+ unsigned char type;
1019
+ unsigned int result = readNextName(rule, &first, &last, &hash);
1020
+ while (result == PARSE_OK) {
1021
+ if (hash == settingHash) {
1022
+ readNextString(last, &first, &last, symbolHash);
1023
+ break;
1024
+ } else {
1025
+ readNextValue(last, &first, &last, &type);
1026
+ result = readNextName(last, &first, &last, &hash);
1027
+ }
1028
+ }
1029
+ }
1030
+
1031
+ static void getSetting(unsigned int settingHash, char *rule, unsigned short *value) {
1032
+ char *first;
1033
+ char *last;
1034
+ char temp;
1035
+ unsigned int hash;
1036
+ unsigned char type;
1037
+ unsigned int result = readNextName(rule, &first, &last, &hash);
1038
+ while (result == PARSE_OK) {
1039
+ readNextValue(last, &first, &last, &type);
1040
+ if (hash == settingHash) {
1041
+ temp = first[last - first + 1];
1042
+ first[last - first + 1] = '\0';
1043
+ *value = atoi(first);
1044
+ first[last - first + 1] = temp;
1045
+ break;
1046
+ }
1047
+ result = readNextName(last, &first, &last, &hash);
1048
+ }
1049
+ }
1050
+
1051
+ static unsigned int createAlpha(ruleset *tree,
1052
+ char *rule,
1053
+ expression *expr,
1054
+ unsigned int nextOffset,
1055
+ unsigned int *newOffset) {
1056
+ char *first;
1057
+ char *last;
1058
+ unsigned char type;
1059
+ unsigned char operator = OP_NOP;
1060
+ unsigned int hash;
1061
+ unsigned int result;
1062
+ unsigned int parentOffset = *newOffset;
1063
+ readNextName(rule, &first, &last, &hash);
1064
+ switch (hash) {
1065
+ case HASH_EQ:
1066
+ operator = OP_EQ;
1067
+ break;
1068
+ case HASH_NEQ:
1069
+ operator = OP_NEQ;
1070
+ break;
1071
+ case HASH_GT:
1072
+ operator = OP_GT;
1073
+ break;
1074
+ case HASH_GTE:
1075
+ operator = OP_GTE;
1076
+ break;
1077
+ case HASH_EX:
1078
+ operator = OP_EX;
1079
+ break;
1080
+ case HASH_NEX:
1081
+ operator = OP_NEX;
1082
+ break;
1083
+ case HASH_LT:
1084
+ operator = OP_LT;
1085
+ break;
1086
+ case HASH_LTE:
1087
+ operator = OP_LTE;
1088
+ break;
1089
+ case HASH_AND:
1090
+ result = appendTerm(expr, tree->andNodeOffset);
1091
+ if (result != RULES_OK) {
1092
+ return result;
1093
+ }
1094
+
1095
+ readNextValue(last, &first, &last, &type);
1096
+ unsigned int previousOffset = 0;
1097
+ unsigned int resultOffset = parentOffset;
1098
+ result = readNextArrayValue(first, &first, &last, &type);
1099
+ while (result == PARSE_OK) {
1100
+ createAlpha(tree, first, expr, 0, &resultOffset);
1101
+ previousOffset = resultOffset;
1102
+ result = readNextArrayValue(last, &first, &last, &type);
1103
+ }
1104
+
1105
+ result = appendTerm(expr, tree->endNodeOffset);
1106
+ if (result != RULES_OK) {
1107
+ return result;
1108
+ }
1109
+ return linkAlpha(tree, previousOffset, nextOffset);
1110
+ case HASH_OR:
1111
+ result = appendTerm(expr, tree->orNodeOffset);
1112
+ if (result != RULES_OK) {
1113
+ return result;
1114
+ }
1115
+
1116
+ readNextValue(last, &first, &last, &type);
1117
+ result = readNextArrayValue(first, &first, &last, &type);
1118
+ while (result == PARSE_OK) {
1119
+ unsigned int single_offset = parentOffset;
1120
+ createAlpha(tree, first, expr, nextOffset, &single_offset);
1121
+ result = readNextArrayValue(last, &first, &last, &type);
1122
+ }
1123
+
1124
+ result = appendTerm(expr, tree->endNodeOffset);
1125
+ if (result != RULES_OK) {
1126
+ return result;
1127
+ }
1128
+ return RULES_OK;
1129
+ }
1130
+
1131
+ if (operator == OP_NOP) {
1132
+ operator = OP_EQ;
1133
+ first = rule;
1134
+ } else {
1135
+ readNextValue(last, &first, &last, &type);
1136
+ }
1137
+
1138
+ if (nextOffset == 0) {
1139
+ return findAlpha(tree, parentOffset, operator, first, expr, newOffset);
1140
+ } else {
1141
+ unsigned int result = findAlpha(tree, parentOffset, operator, first, expr, newOffset);
1142
+ if (result != RULES_OK) {
1143
+ return result;
1144
+ }
1145
+
1146
+ return linkAlpha(tree, *newOffset, nextOffset);
1147
+ }
1148
+ }
1149
+
1150
+ static unsigned int createBetaConnector(ruleset *tree,
1151
+ char *rule,
1152
+ path *betaPath,
1153
+ unsigned int nextOffset) {
1154
+ char *first;
1155
+ char *last;
1156
+ char *lastArrayValue;
1157
+ unsigned int hash;
1158
+ unsigned char type;
1159
+ unsigned int result = readNextArrayValue(rule, &first, &lastArrayValue, &type);
1160
+ while (result == PARSE_OK) {
1161
+ readNextName(first, &first, &last, &hash);
1162
+ unsigned int nameLength = last - first;
1163
+ unsigned char operator = OP_NOP;
1164
+ if (nameLength >= 4) {
1165
+ if (!strncmp("$all", last - 4, 4)) {
1166
+ operator = OP_ALL;
1167
+ } else if (!strncmp("$any", last - 4, 4)) {
1168
+ operator = OP_ANY;
1169
+ } else if (!strncmp("$not", last - 4, 4)) {
1170
+ operator = OP_NOT;
1171
+ }
1172
+
1173
+ if (operator == OP_ALL || operator == OP_ANY || operator == OP_NOT) {
1174
+ nameLength = nameLength - 4;
1175
+ hash = djbHash(first, nameLength);
1176
+ }
1177
+ }
1178
+
1179
+ unsigned int stringOffset;
1180
+ result = storeString(tree, first, &stringOffset, nameLength);
1181
+ if (result != RULES_OK) {
1182
+ return result;
1183
+ }
1184
+
1185
+ node *connector;
1186
+ unsigned int connectorOffset;
1187
+ result = storeNode(tree, &connector, &connectorOffset);
1188
+ if (result != RULES_OK) {
1189
+ return result;
1190
+ }
1191
+
1192
+ expression *expr;
1193
+ connector->nameOffset = stringOffset;
1194
+ connector->type = NODE_BETA_CONNECTOR;
1195
+ connector->value.b.nextOffset = nextOffset;
1196
+ connector->value.b.not = (operator == OP_NOT) ? 1 : 0;
1197
+ connector->value.b.hash = hash;
1198
+ if (betaPath->expressionsLength == 0) {
1199
+ betaPath->expressionsLength = 1;
1200
+ betaPath->expressions = malloc(sizeof(expression));
1201
+ if (!betaPath->expressions) {
1202
+ return ERR_OUT_OF_MEMORY;
1203
+ }
1204
+
1205
+ expr = betaPath->expressions;
1206
+ }
1207
+ else {
1208
+ betaPath->expressionsLength = betaPath->expressionsLength + 1;
1209
+ betaPath->expressions = realloc(betaPath->expressions, betaPath->expressionsLength * sizeof(expression));
1210
+ if (!betaPath->expressions) {
1211
+ return ERR_OUT_OF_MEMORY;
1212
+ }
1213
+
1214
+ expr = &betaPath->expressions[betaPath->expressionsLength - 1];
1215
+ }
1216
+
1217
+ expr->nameOffset = stringOffset;
1218
+ expr->aliasOffset = stringOffset;
1219
+ expr->not = (operator == OP_NOT) ? 1 : 0;
1220
+ expr->termsLength = 0;
1221
+ expr->t.termsPointer = NULL;
1222
+ if (operator == OP_NOP || operator == OP_NOT) {
1223
+ unsigned int resultOffset = NODE_M_OFFSET;
1224
+ readNextValue(last, &first, &last, &type);
1225
+ result = createAlpha(tree, first, expr, connectorOffset, &resultOffset);
1226
+ }
1227
+ else {
1228
+ readNextValue(last, &first, &last, &type);
1229
+ result = createBeta(tree, first, operator, connectorOffset, betaPath, NULL);
1230
+ }
1231
+
1232
+ if (result != RULES_OK) {
1233
+ return result;
1234
+ }
1235
+
1236
+ result = readNextArrayValue(lastArrayValue, &first, &lastArrayValue, &type);
1237
+ }
1238
+
1239
+ return (result == PARSE_END ? RULES_OK: result);
1240
+ }
1241
+
1242
+ static unsigned int createBeta(ruleset *tree,
1243
+ char *rule,
1244
+ unsigned char operator,
1245
+ unsigned int nextOffset,
1246
+ path *nextPath,
1247
+ path **outPath) {
1248
+
1249
+ path *betaPath = malloc(sizeof(path));
1250
+ if (!betaPath) {
1251
+ return ERR_OUT_OF_MEMORY;
1252
+ }
1253
+
1254
+ betaPath->operator = operator;
1255
+ betaPath->expressionsLength = 0;
1256
+ betaPath->expressions = NULL;
1257
+ betaPath->parents = NULL;
1258
+ betaPath->parentsLength = 0;
1259
+
1260
+ if (nextPath) {
1261
+ if (nextPath->parentsLength == 0) {
1262
+ nextPath->parentsLength = nextPath->expressionsLength;
1263
+ nextPath->parents = calloc(nextPath->expressionsLength, sizeof(path*));
1264
+ if (!nextPath->parents) {
1265
+ return ERR_OUT_OF_MEMORY;
1266
+ }
1267
+
1268
+ nextPath->parents[nextPath->expressionsLength - 1] = betaPath;
1269
+ } else {
1270
+ int lengthDiff = nextPath->expressionsLength - nextPath->parentsLength;
1271
+ nextPath->parents = realloc(nextPath->parents, sizeof(path*) * nextPath->expressionsLength);
1272
+ if (!nextPath->parents) {
1273
+ return ERR_OUT_OF_MEMORY;
1274
+ }
1275
+
1276
+ for (int i = 0; i < lengthDiff -1; ++i) {
1277
+ nextPath->parents[nextPath->parentsLength + i] = NULL;
1278
+ }
1279
+
1280
+ nextPath->parentsLength = nextPath->expressionsLength;
1281
+ nextPath->parents[nextPath->parentsLength - 1] = betaPath;
1282
+ }
1283
+ }
1284
+
1285
+ if (outPath) {
1286
+ *outPath = betaPath;
1287
+ }
1288
+
1289
+ return createBetaConnector(tree, rule, betaPath, nextOffset);
1290
+ }
1291
+
1292
+ static unsigned int add(any *right, any *left, any **result) {
1293
+ right->nodes = realloc(right->nodes, (right->nodesLength + left->nodesLength) * sizeof(all*));
1294
+ if (!right->nodes) {
1295
+ return ERR_OUT_OF_MEMORY;
1296
+ }
1297
+ for (unsigned int i = 0; i < left->nodesLength; ++i) {
1298
+ right->nodes[right->nodesLength + i] = left->nodes[i];
1299
+ }
1300
+ right->nodesLength = right->nodesLength + left->nodesLength;
1301
+ free(left->nodes);
1302
+ free(left);
1303
+ *result = right;
1304
+ return RULES_OK;
1305
+ }
1306
+
1307
+ static unsigned int multiply(ruleset *tree, any *right, any *left, any **result) {
1308
+ any *product = malloc(sizeof(any));
1309
+ product->nodesLength = right->nodesLength * left->nodesLength;
1310
+ product->nodes = malloc(sizeof(all*) * product->nodesLength);
1311
+
1312
+ for (unsigned int i = 0; i < left->nodesLength; ++i) {
1313
+ all *leftAll = left->nodes[i];
1314
+ for (unsigned int ii = 0; ii < right->nodesLength; ++ii) {
1315
+ all *rightAll = right->nodes[ii];
1316
+ all *newAll = malloc(sizeof(all));
1317
+ if (!newAll) {
1318
+ return ERR_OUT_OF_MEMORY;
1319
+ }
1320
+
1321
+ newAll->count = (leftAll->count > rightAll->count ? leftAll->count: rightAll->count);
1322
+ newAll->expressions = malloc((rightAll->expressionsLength + leftAll->expressionsLength) * sizeof(unsigned int));
1323
+ if (!newAll->expressions) {
1324
+ return ERR_OUT_OF_MEMORY;
1325
+ }
1326
+
1327
+ for (unsigned int iii = 0; iii < rightAll->expressionsLength; ++iii) {
1328
+ newAll->expressions[iii] = rightAll->expressions[iii];
1329
+ }
1330
+
1331
+ for (unsigned int iii = 0; iii < leftAll->expressionsLength; ++iii) {
1332
+ newAll->expressions[rightAll->expressionsLength + iii] = leftAll->expressions[iii];
1333
+ }
1334
+
1335
+ newAll->expressionsLength = rightAll->expressionsLength + leftAll->expressionsLength;
1336
+ product->nodes[i + ii * left->nodesLength] = newAll;
1337
+ }
1338
+
1339
+ free(leftAll->expressions);
1340
+ free(leftAll);
1341
+ }
1342
+
1343
+ for (unsigned int i = 0; i < right->nodesLength; ++i) {
1344
+ all *rightAll = right->nodes[i];
1345
+ free(rightAll->expressions);
1346
+ free(rightAll);
1347
+ }
1348
+
1349
+ free(right->nodes);
1350
+ free(right);
1351
+ free(left->nodes);
1352
+ free(left);
1353
+ *result = product;
1354
+ return RULES_OK;
1355
+ }
1356
+
1357
+ static unsigned int createSingleQuery(ruleset *tree,
1358
+ char *name,
1359
+ expression *expr,
1360
+ any **resultAny) {
1361
+ any *newAny = malloc(sizeof(any));
1362
+ if (!newAny) {
1363
+ return ERR_OUT_OF_MEMORY;
1364
+ }
1365
+
1366
+ newAny->nodesLength = 1;
1367
+ newAny->nodes = malloc(sizeof(all*));
1368
+ if (!newAny->nodes) {
1369
+ return ERR_OUT_OF_MEMORY;
1370
+ }
1371
+
1372
+ newAny->nodes[0] = malloc(sizeof(all));
1373
+ if (!newAny->nodes[0]) {
1374
+ return ERR_OUT_OF_MEMORY;
1375
+ }
1376
+
1377
+ newAny->nodes[0]->expressionsLength = 1;
1378
+ newAny->nodes[0]->expressions = malloc(sizeof(unsigned int));
1379
+ if (!newAny->nodes[0]->expressions) {
1380
+ return ERR_OUT_OF_MEMORY;
1381
+ }
1382
+
1383
+ expression *newExpression;
1384
+ unsigned int result = storeExpression(tree, &newExpression, newAny->nodes[0]->expressions);
1385
+ if (result != RULES_OK) {
1386
+ return result;
1387
+ }
1388
+
1389
+ result = storeString(tree, name, &newExpression->nameOffset, strlen(name));
1390
+ if (result != RULES_OK) {
1391
+ return result;
1392
+ }
1393
+
1394
+ newExpression->aliasOffset = expr->aliasOffset;
1395
+ newExpression->termsLength = expr->termsLength;
1396
+ newExpression->not = expr->not;
1397
+ if (expr->termsLength) {
1398
+ result = allocateNext(tree, expr->termsLength, &newExpression->t.termsOffset);
1399
+ if (result != RULES_OK) {
1400
+ return result;
1401
+ }
1402
+
1403
+ for (unsigned short i = 0; i < expr->termsLength; ++i) {
1404
+ tree->nextPool[newExpression->t.termsOffset + i] = expr->t.termsPointer[i];
1405
+ }
1406
+
1407
+ free(expr->t.termsPointer);
1408
+ }
1409
+
1410
+ *resultAny = newAny;
1411
+ return RULES_OK;
1412
+ }
1413
+
1414
+ static unsigned int createQueries(ruleset *tree,
1415
+ char *postfix,
1416
+ path *betaPath,
1417
+ any **anyResult) {
1418
+ any *currentAny = NULL;
1419
+ for (unsigned short i = 0; i < betaPath->expressionsLength; ++ i) {
1420
+ unsigned int result;
1421
+ expression *expr = &betaPath->expressions[i];
1422
+ if (betaPath->operator == OP_NOP) {
1423
+ result = createSingleQuery(tree, postfix, expr, anyResult);
1424
+ if (result != RULES_OK) {
1425
+ return result;
1426
+ }
1427
+
1428
+ free(betaPath->expressions);
1429
+ free(betaPath);
1430
+ return RULES_OK;
1431
+ }
1432
+
1433
+ char *name = &tree->stringPool[expr->nameOffset];
1434
+ int nameLength = strlen(name);
1435
+ #ifdef _WIN32
1436
+ char *nextPostfix = (char *)_alloca(sizeof(char)*(strlen(postfix) + nameLength + 2));
1437
+ #else
1438
+ char nextPostfix[strlen(postfix) + nameLength + 2];
1439
+ #endif
1440
+ strcpy(nextPostfix, name);
1441
+ nextPostfix[nameLength] = '!';
1442
+ strcpy(&nextPostfix[nameLength + 1], postfix);
1443
+
1444
+ any *newAny = NULL;
1445
+ if (i >= betaPath->parentsLength || !betaPath->parents[i]) {
1446
+ result = createSingleQuery(tree, nextPostfix, expr, &newAny);
1447
+ if (result != RULES_OK) {
1448
+ return result;
1449
+ }
1450
+ }
1451
+ else {
1452
+ result = createQueries(tree, nextPostfix, betaPath->parents[i], &newAny);
1453
+ if (result != RULES_OK) {
1454
+ return result;
1455
+ }
1456
+ }
1457
+
1458
+ if (!currentAny) {
1459
+ currentAny = newAny;
1460
+ }
1461
+ else if (betaPath->operator == OP_ANY) {
1462
+ result = add(currentAny, newAny, &currentAny);
1463
+ if (result != RULES_OK) {
1464
+ return result;
1465
+ }
1466
+ }
1467
+ else if (betaPath->operator == OP_ALL) {
1468
+ result = multiply(tree, currentAny, newAny, &currentAny);
1469
+ if (result != RULES_OK) {
1470
+ return result;
1471
+ }
1472
+ }
1473
+ }
1474
+
1475
+ free(betaPath->expressions);
1476
+ free(betaPath->parents);
1477
+ free(betaPath);
1478
+ *anyResult = currentAny;
1479
+ return RULES_OK;
1480
+ }
1481
+
1482
+ static unsigned int fixupQueries(ruleset *tree, unsigned int actionOffset, char* postfix, path *betaPath) {
1483
+ node *actionNode = &tree->nodePool[actionOffset];
1484
+ #ifdef _WIN32
1485
+ char *copyPostfix = (char *)_alloca(sizeof(char)*(strlen(postfix) + 1));
1486
+ #else
1487
+ char copyPostfix[strlen(postfix) + 1];
1488
+ #endif
1489
+
1490
+ strcpy(copyPostfix, postfix);
1491
+
1492
+ any *query;
1493
+ unsigned int result = createQueries(tree, copyPostfix, betaPath, &query);
1494
+ if (result != RULES_OK) {
1495
+ return result;
1496
+ }
1497
+
1498
+ actionNode->value.c.joinsLength = query->nodesLength;
1499
+ result = allocateNext(tree, query->nodesLength, &actionNode->value.c.joinsOffset);
1500
+ if (result != RULES_OK) {
1501
+ return result;
1502
+ }
1503
+
1504
+ for (unsigned int i = 0; i < query->nodesLength; ++i) {
1505
+ all *currentAll = query->nodes[i];
1506
+
1507
+ join *newJoin;
1508
+ result = storeJoin(tree, &newJoin, &tree->nextPool[actionNode->value.c.joinsOffset + i]);
1509
+ if (result != RULES_OK) {
1510
+ return result;
1511
+ }
1512
+
1513
+ newJoin->expressionsLength = currentAll->expressionsLength;
1514
+ result = allocateNext(tree, currentAll->expressionsLength, &newJoin->expressionsOffset);
1515
+ if (result != RULES_OK) {
1516
+ return result;
1517
+ }
1518
+
1519
+ for (unsigned int ii = 0; ii < currentAll->expressionsLength; ++ii) {
1520
+ tree->nextPool[newJoin->expressionsOffset + ii] = currentAll->expressions[ii];
1521
+ }
1522
+
1523
+ free(currentAll->expressions);
1524
+ free(currentAll);
1525
+ }
1526
+
1527
+ free(query->nodes);
1528
+ free(query);
1529
+ return RULES_OK;
1530
+ }
1531
+
1532
+ static unsigned int createTree(ruleset *tree, char *rules) {
1533
+ char *first;
1534
+ char *last;
1535
+ char *lastRuleValue;
1536
+ char *firstName;
1537
+ char *lastName;
1538
+ unsigned char type;
1539
+ unsigned int hash;
1540
+ unsigned int result = readNextName(rules, &firstName, &lastName, &hash);
1541
+ while (result == PARSE_OK) {
1542
+ path *betaPath = NULL;
1543
+ node *ruleAction;
1544
+ unsigned int actionOffset;
1545
+ result = storeNode(tree, &ruleAction, &actionOffset);
1546
+ if (result != RULES_OK) {
1547
+ return result;
1548
+ }
1549
+
1550
+ ruleAction->value.c.index = tree->actionCount;
1551
+ ++tree->actionCount;
1552
+ ruleAction->type = NODE_ACTION;
1553
+
1554
+ // tree->stringPool can change after storing strings
1555
+ // need to resolve namespace every time it is used.
1556
+ char *namespace = &tree->stringPool[tree->nameOffset];
1557
+ int namespaceLength = strlen(namespace);
1558
+ #ifdef _WIN32
1559
+ char *runtimeActionName = (char *)_alloca(sizeof(char)*(namespaceLength + lastName - firstName + 2));
1560
+ #else
1561
+ char runtimeActionName[namespaceLength + lastName - firstName + 2];
1562
+ #endif
1563
+
1564
+ strncpy(runtimeActionName, firstName, lastName - firstName);
1565
+ runtimeActionName[lastName - firstName] = '!';
1566
+ strncpy(&runtimeActionName[lastName - firstName + 1], namespace, namespaceLength);
1567
+ runtimeActionName[namespaceLength + lastName - firstName + 1] = '\0';
1568
+ result = storeString(tree, runtimeActionName, &ruleAction->nameOffset, namespaceLength + lastName - firstName + 1);
1569
+ if (result != RULES_OK) {
1570
+ return result;
1571
+ }
1572
+
1573
+ readNextValue(lastName, &first, &lastRuleValue, &type);
1574
+ ruleAction->value.c.priority = 0;
1575
+ ruleAction->value.c.count = 0;
1576
+ ruleAction->value.c.span = 0;
1577
+ ruleAction->value.c.cap = 0;
1578
+ ruleAction->value.c.partitionBy = 0;
1579
+ getSetting(HASH_PRI, first, &ruleAction->value.c.priority);
1580
+ getSetting(HASH_COUNT, first, &ruleAction->value.c.count);
1581
+ getSetting(HASH_SPAN, first, &ruleAction->value.c.span);
1582
+ getSetting(HASH_CAP, first, &ruleAction->value.c.cap);
1583
+ getSymbolSetting(HASH_BY, first, &ruleAction->value.c.partitionBy);
1584
+ if (!ruleAction->value.c.count && !ruleAction->value.c.span && !ruleAction->value.c.cap) {
1585
+ ruleAction->value.c.count = 1;
1586
+ }
1587
+
1588
+ result = readNextName(first, &first, &last, &hash);
1589
+ while (result == PARSE_OK) {
1590
+ readNextValue(last, &first, &last, &type);
1591
+ switch (hash) {
1592
+ case HASH_ANY:
1593
+ result = createBeta(tree, first, OP_ANY, actionOffset, NULL, &betaPath);
1594
+ break;
1595
+ case HASH_ALL:
1596
+ result = createBeta(tree, first, OP_ALL, actionOffset, NULL, &betaPath);
1597
+ break;
1598
+ }
1599
+ result = readNextName(last, &first, &last, &hash);
1600
+ }
1601
+
1602
+ result = fixupQueries(tree, actionOffset, runtimeActionName, betaPath);
1603
+ if (result != RULES_OK) {
1604
+ return result;
1605
+ }
1606
+
1607
+ result = readNextName(lastRuleValue, &firstName, &lastName, &hash);
1608
+ }
1609
+
1610
+ return RULES_OK;
1611
+ }
1612
+
1613
+ unsigned int createRuleset(void **handle, char *name, char *rules, unsigned int stateCaheSize) {
1614
+ node *newNode;
1615
+ unsigned int stringOffset;
1616
+ unsigned int nodeOffset;
1617
+ unsigned int result = validateRuleset(rules);
1618
+ if (result != PARSE_OK) {
1619
+ return result;
1620
+ }
1621
+
1622
+ ruleset *tree = malloc(sizeof(ruleset));
1623
+ if (!tree) {
1624
+ return ERR_OUT_OF_MEMORY;
1625
+ }
1626
+
1627
+ tree->stringPool = NULL;
1628
+ tree->stringPoolLength = 0;
1629
+ tree->nodePool = NULL;
1630
+ tree->nodeOffset = 0;
1631
+ tree->nextPool = NULL;
1632
+ tree->nextOffset = 0;
1633
+ tree->expressionPool = NULL;
1634
+ tree->expressionOffset = 0;
1635
+ tree->idiomPool = NULL;
1636
+ tree->idiomOffset = 0;
1637
+ tree->joinPool = NULL;
1638
+ tree->joinOffset = 0;
1639
+ tree->actionCount = 0;
1640
+ tree->bindingsList = NULL;
1641
+ tree->stateLength = 0;
1642
+ tree->state = calloc(stateCaheSize, sizeof(stateEntry));
1643
+ tree->maxStateLength = stateCaheSize;
1644
+ tree->stateBucketsLength = stateCaheSize / 4;
1645
+ tree->stateBuckets = malloc(tree->stateBucketsLength * sizeof(unsigned int));
1646
+ memset(tree->stateBuckets, 0xFF, tree->stateBucketsLength * sizeof(unsigned int));
1647
+ tree->lruStateOffset = UNDEFINED_HASH_OFFSET;
1648
+ tree->mruStateOffset = UNDEFINED_HASH_OFFSET;
1649
+
1650
+ result = storeString(tree, name, &tree->nameOffset, strlen(name));
1651
+ if (result != RULES_OK) {
1652
+ return result;
1653
+ }
1654
+
1655
+ result = storeString(tree, "m", &stringOffset, 1);
1656
+ if (result != RULES_OK) {
1657
+ return result;
1658
+ }
1659
+
1660
+ result = storeAlpha(tree, &newNode, &nodeOffset);
1661
+ if (result != RULES_OK) {
1662
+ return result;
1663
+ }
1664
+
1665
+ newNode->nameOffset = stringOffset;
1666
+ newNode->type = NODE_ALPHA;
1667
+ newNode->value.a.operator = OP_TYPE;
1668
+ result = storeAlpha(tree, &newNode, &tree->andNodeOffset);
1669
+ if (result != RULES_OK) {
1670
+ return result;
1671
+ }
1672
+
1673
+ newNode->nameOffset = 0;
1674
+ newNode->type = NODE_ALPHA;
1675
+ newNode->value.a.operator = OP_AND;
1676
+ result = storeAlpha(tree, &newNode, &tree->orNodeOffset);
1677
+ if (result != RULES_OK) {
1678
+ return result;
1679
+ }
1680
+
1681
+ newNode->nameOffset = 0;
1682
+ newNode->type = NODE_ALPHA;
1683
+ newNode->value.a.operator = OP_OR;
1684
+ result = storeAlpha(tree, &newNode, &tree->endNodeOffset);
1685
+ if (result != RULES_OK) {
1686
+ return result;
1687
+ }
1688
+
1689
+ newNode->nameOffset = 0;
1690
+ newNode->type = NODE_ALPHA;
1691
+ newNode->value.a.operator = OP_END;
1692
+
1693
+ *handle = tree;
1694
+
1695
+ // will use random numbers for state stored event mids
1696
+ srand(time(NULL));
1697
+ return createTree(tree, rules);
1698
+ }
1699
+
1700
+ unsigned int deleteRuleset(void *handle) {
1701
+ ruleset *tree = (ruleset*)(handle);
1702
+ deleteBindingsList(tree);
1703
+ free(tree->nodePool);
1704
+ free(tree->nextPool);
1705
+ free(tree->stringPool);
1706
+ free(tree->expressionPool);
1707
+ free(tree->idiomPool);
1708
+ free(tree->joinPool);
1709
+ free(tree->stateBuckets);
1710
+ for (unsigned int i = 0; i < tree->stateLength; ++i) {
1711
+ stateEntry *entry = &tree->state[i];
1712
+ if (entry->state) {
1713
+ free(entry->state);
1714
+ }
1715
+
1716
+ if (entry->sid) {
1717
+ free(entry->sid);
1718
+ }
1719
+ }
1720
+ free(tree->state);
1721
+ free(tree);
1722
+ return RULES_OK;
1723
+ }
1724
+
1725
+
1726
+