durable_rules 2.00.3 → 2.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: da7281352c66d7ee7dfda3145829aee0ce0bd006
4
- data.tar.gz: 04f8626eca2fc8a6d8da3d6da53afe932efbe2e5
3
+ metadata.gz: 0adaaf5bd93fde23db48196c84cc4c19a6e54eab
4
+ data.tar.gz: f4a48336da9a8b928da8baf5b0288796b89820e4
5
5
  SHA512:
6
- metadata.gz: 1ef6301996e4db96709c006409915a66aedd409379ac08bbb94c3a24d003a8a0dbe42a6c401919b5bdfc3e9c4fe78b2957afc5dcbc57465eda74b90d00265b2d
7
- data.tar.gz: fcc4e5f9785cd8566b0c74a0b6aef53d4e532e07ccd70df9eed62cce6a0a7867a7d53053ef694bc95c5bf53c2a0d5137d0fbb3d1d9ecf5d5228eb789b9389970
6
+ metadata.gz: e23ee1d4cbf5e2b42e5054bb862c56b502473759e3d468b66c12e08b41a8dba35a96845c30c2a57d003a9f7cd0ed61653ac830dcf579a9013bb48c65b2e361d7
7
+ data.tar.gz: aaf8e986ee09e907c794145f2d9cd2052cf75a1e1c4493c38e750a3d32eefbb9e701cf3234b7bc4280d736c9c2b8b2dfeb537f8b45a8069483ccb2397878ae7a
data/src/rules/events.c CHANGED
@@ -1403,12 +1403,82 @@ static unsigned int handleBetaMessage(ruleset *tree,
1403
1403
  messageHash);
1404
1404
  }
1405
1405
 
1406
+ static unsigned int isArrayMatch(ruleset *tree,
1407
+ jsonObject *messageObject,
1408
+ jsonProperty *currentProperty,
1409
+ alpha *arrayAlpha,
1410
+ unsigned char *propertyMatch);
1406
1411
 
1407
- static unsigned int handleAplhaArray(ruleset *tree,
1408
- jsonObject *messageObject,
1409
- jsonProperty *currentProperty,
1410
- alpha *arrayAlpha,
1411
- unsigned char *propertyMatch) {
1412
+ static unsigned int isNextMatch(ruleset *tree,
1413
+ jsonObject *jo,
1414
+ alpha *currentAlpha,
1415
+ unsigned char *propertyMatch) {
1416
+ *propertyMatch = 0;
1417
+ if (currentAlpha->nextListOffset) {
1418
+ unsigned int *nextList = &tree->nextPool[currentAlpha->nextListOffset];
1419
+ for (unsigned int entry = 0; nextList[entry] != 0; ++entry) {
1420
+ node *listNode = &tree->nodePool[nextList[entry]];
1421
+ jsonProperty *currentProperty;
1422
+ unsigned int aresult = getObjectProperty(jo, listNode->value.a.expression.left.value.id.propertyNameHash, &currentProperty);
1423
+ if (aresult == ERR_PROPERTY_NOT_FOUND) {
1424
+ *propertyMatch = 1;
1425
+ if (listNode->value.a.nextOffset || listNode->value.a.nextListOffset) {
1426
+ CHECK_RESULT(isNextMatch(tree,
1427
+ jo,
1428
+ &listNode->value.a,
1429
+ propertyMatch));
1430
+ }
1431
+
1432
+ if (*propertyMatch) {
1433
+ break;
1434
+ }
1435
+
1436
+ }
1437
+ }
1438
+ }
1439
+
1440
+ if (currentAlpha->nextOffset) {
1441
+ unsigned int *nextHashset = &tree->nextPool[currentAlpha->nextOffset];
1442
+ for(unsigned int propertyIndex = 0; propertyIndex < jo->propertiesLength; ++propertyIndex) {
1443
+ jsonProperty *currentProperty = &jo->properties[propertyIndex];
1444
+ for (unsigned int entry = currentProperty->hash & HASH_MASK; nextHashset[entry] != 0; entry = (entry + 1) % NEXT_BUCKET_LENGTH) {
1445
+ node *hashNode = &tree->nodePool[nextHashset[entry]];
1446
+ if (hashNode->value.a.expression.operator == OP_IALL || hashNode->value.a.expression.operator == OP_IANY) {
1447
+ CHECK_RESULT(isArrayMatch(tree,
1448
+ jo,
1449
+ currentProperty,
1450
+ &hashNode->value.a,
1451
+ propertyMatch));
1452
+ } else {
1453
+ CHECK_RESULT(isAlphaMatch(tree,
1454
+ &hashNode->value.a,
1455
+ jo,
1456
+ propertyMatch));
1457
+ }
1458
+
1459
+ if (*propertyMatch && (hashNode->value.a.nextOffset || hashNode->value.a.nextListOffset)) {
1460
+ CHECK_RESULT(isNextMatch(tree,
1461
+ jo,
1462
+ &hashNode->value.a,
1463
+ propertyMatch));
1464
+
1465
+ }
1466
+
1467
+ if (*propertyMatch) {
1468
+ break;
1469
+ }
1470
+ }
1471
+ }
1472
+ }
1473
+
1474
+ return RULES_OK;
1475
+ }
1476
+
1477
+ static unsigned int isArrayMatch(ruleset *tree,
1478
+ jsonObject *messageObject,
1479
+ jsonProperty *currentProperty,
1480
+ alpha *arrayAlpha,
1481
+ unsigned char *propertyMatch) {
1412
1482
  unsigned int result = RULES_OK;
1413
1483
  if (currentProperty->type != JSON_ARRAY) {
1414
1484
  return RULES_OK;
@@ -1421,10 +1491,6 @@ static unsigned int handleAplhaArray(ruleset *tree,
1421
1491
  result = readNextArrayValue(first, &first, &last, &type);
1422
1492
  while (result == PARSE_OK) {
1423
1493
  *propertyMatch = 0;
1424
- unsigned short top = 1;
1425
- alpha *stack[MAX_STACK_SIZE];
1426
- stack[0] = arrayAlpha;
1427
- alpha *currentAlpha;
1428
1494
  if (type == JSON_OBJECT) {
1429
1495
  char *next;
1430
1496
  jo.propertiesLength = 0;
@@ -1450,75 +1516,61 @@ static unsigned int handleAplhaArray(ruleset *tree,
1450
1516
  last - first + 1));
1451
1517
  }
1452
1518
 
1453
- while (top) {
1454
- --top;
1455
- currentAlpha = stack[top];
1456
- // add all disjunctive nodes to stack
1457
- if (currentAlpha->nextListOffset) {
1458
- unsigned int *nextList = &tree->nextPool[currentAlpha->nextListOffset];
1459
- for (unsigned int entry = 0; nextList[entry] != 0; ++entry) {
1460
- node *listNode = &tree->nodePool[nextList[entry]];
1461
- char exists = 0;
1462
- for(unsigned int propertyIndex = 0; propertyIndex < jo.propertiesLength; ++propertyIndex) {
1463
- if (listNode->value.a.expression.left.value.id.propertyNameHash == jo.properties[propertyIndex].hash) {
1464
- // filter out not exists (OP_NEX)
1465
- exists = 1;
1466
- break;
1467
- }
1468
- }
1469
-
1470
- if (!exists) {
1471
- if (top == MAX_STACK_SIZE) {
1472
- return ERR_MAX_STACK_SIZE;
1473
- }
1474
-
1475
- stack[top] = &listNode->value.a;
1476
- ++top;
1519
+ if (arrayAlpha->nextListOffset) {
1520
+ unsigned int *nextList = &tree->nextPool[arrayAlpha->nextListOffset];
1521
+ for (unsigned int entry = 0; nextList[entry] != 0; ++entry) {
1522
+ node *listNode = &tree->nodePool[nextList[entry]];
1523
+ jsonProperty *currentProperty;
1524
+ unsigned int aresult = getObjectProperty(&jo, listNode->value.a.expression.left.value.id.propertyNameHash, &currentProperty);
1525
+ if (aresult == ERR_PROPERTY_NOT_FOUND) {
1526
+ *propertyMatch = 1;
1527
+ if (listNode->value.a.nextOffset || listNode->value.a.nextListOffset) {
1528
+ CHECK_RESULT(isNextMatch(tree,
1529
+ &jo,
1530
+ &listNode->value.a,
1531
+ propertyMatch));
1532
+ }
1533
+
1534
+ if (*propertyMatch) {
1535
+ break;
1477
1536
  }
1537
+
1478
1538
  }
1479
1539
  }
1540
+ }
1480
1541
 
1481
- // calculate conjunctive nodes
1482
- if (currentAlpha->nextOffset) {
1483
- unsigned int *nextHashset = &tree->nextPool[currentAlpha->nextOffset];
1484
- for(unsigned int propertyIndex = 0; propertyIndex < jo.propertiesLength; ++propertyIndex) {
1485
- jsonProperty *currentProperty = &jo.properties[propertyIndex];
1486
- for (unsigned int entry = currentProperty->hash & HASH_MASK; nextHashset[entry] != 0; entry = (entry + 1) % NEXT_BUCKET_LENGTH) {
1487
- node *hashNode = &tree->nodePool[nextHashset[entry]];
1488
- if (currentProperty->hash == hashNode->value.a.expression.left.value.id.propertyNameHash) {
1489
- unsigned char match = 0;
1490
- if (hashNode->value.a.expression.operator == OP_IALL || hashNode->value.a.expression.operator == OP_IANY) {
1491
- // handleAplhaArray finds a valid path, thus use propertyMatch
1492
- CHECK_RESULT(handleAplhaArray(tree,
1493
- &jo,
1494
- currentProperty,
1495
- &hashNode->value.a,
1496
- propertyMatch));
1497
- } else {
1498
- CHECK_RESULT(isAlphaMatch(tree,
1499
- &hashNode->value.a,
1500
- &jo,
1501
- &match));
1542
+ if (arrayAlpha->arrayListOffset) {
1543
+ unsigned int *nextHashset = &tree->nextPool[arrayAlpha->arrayListOffset];
1544
+ for(unsigned int propertyIndex = 0; propertyIndex < jo.propertiesLength; ++propertyIndex) {
1545
+ jsonProperty *currentProperty = &jo.properties[propertyIndex];
1546
+ for (unsigned int entry = currentProperty->hash & HASH_MASK; nextHashset[entry] != 0; entry = (entry + 1) % NEXT_BUCKET_LENGTH) {
1547
+ node *hashNode = &tree->nodePool[nextHashset[entry]];
1548
+ if (hashNode->value.a.expression.operator == OP_IALL || hashNode->value.a.expression.operator == OP_IANY) {
1549
+ CHECK_RESULT(isArrayMatch(tree,
1550
+ &jo,
1551
+ currentProperty,
1552
+ &hashNode->value.a,
1553
+ propertyMatch));
1554
+ } else {
1555
+ CHECK_RESULT(isAlphaMatch(tree,
1556
+ &hashNode->value.a,
1557
+ &jo,
1558
+ propertyMatch));
1559
+ }
1502
1560
 
1503
- if (match) {
1504
- if (top == MAX_STACK_SIZE) {
1505
- return ERR_MAX_STACK_SIZE;
1506
- }
1561
+ if (*propertyMatch && hashNode->value.a.nextOffset) {
1562
+ CHECK_RESULT(isNextMatch(tree,
1563
+ &jo,
1564
+ &hashNode->value.a,
1565
+ propertyMatch));
1507
1566
 
1508
- stack[top] = &hashNode->value.a;
1509
- ++top;
1510
- }
1511
- }
1512
- }
1513
- }
1567
+ }
1568
+
1569
+ if (*propertyMatch && (hashNode->value.a.nextOffset || hashNode->value.a.nextListOffset)) {
1570
+ break;
1571
+ }
1514
1572
  }
1515
1573
  }
1516
-
1517
- // no next offset and no nextListOffest means we found a valid path
1518
- if (!currentAlpha->nextOffset && !currentAlpha->nextListOffset) {
1519
- *propertyMatch = 1;
1520
- break;
1521
- }
1522
1574
  }
1523
1575
 
1524
1576
  // OP_IANY, one element led a a valid path
@@ -1586,11 +1638,11 @@ static unsigned int handleAlpha(ruleset *tree,
1586
1638
  } else {
1587
1639
  unsigned char match = 0;
1588
1640
  if (hashNode->value.a.expression.operator == OP_IALL || hashNode->value.a.expression.operator == OP_IANY) {
1589
- CHECK_RESULT(handleAplhaArray(tree,
1590
- jo,
1591
- currentProperty,
1592
- &hashNode->value.a,
1593
- &match));
1641
+ CHECK_RESULT(isArrayMatch(tree,
1642
+ jo,
1643
+ currentProperty,
1644
+ &hashNode->value.a,
1645
+ &match));
1594
1646
  } else {
1595
1647
  CHECK_RESULT(isAlphaMatch(tree,
1596
1648
  &hashNode->value.a,
data/src/rules/rete.c CHANGED
@@ -156,6 +156,7 @@ static unsigned int storeAlpha(ruleset *tree,
156
156
  return result;
157
157
  }
158
158
 
159
+ (*newNode)->value.a.arrayListOffset = 0;
159
160
  (*newNode)->value.a.nextListOffset = 0;
160
161
  (*newNode)->value.a.betaListOffset = 0;
161
162
  (*newNode)->value.a.nextOffset = 0;
@@ -189,6 +190,13 @@ static unsigned int allocateNext(ruleset *tree,
189
190
  return RULES_OK;
190
191
  }
191
192
 
193
+ static unsigned int ensureNextArrayHashset(ruleset *tree, node *newNode) {
194
+ if (!newNode->value.a.arrayListOffset) {
195
+ return allocateNext(tree, NEXT_BUCKET_LENGTH, &newNode->value.a.arrayListOffset);
196
+ }
197
+
198
+ return RULES_OK;
199
+ }
192
200
 
193
201
  static unsigned int ensureNextHashset(ruleset *tree, node *newNode) {
194
202
  if (!newNode->value.a.nextOffset) {
@@ -753,9 +761,14 @@ static unsigned int validateRuleset(char *rules) {
753
761
  return (result == PARSE_END ? PARSE_OK: result);
754
762
  }
755
763
 
756
- static unsigned int linkAlpha(ruleset *tree,
764
+ static unsigned int linkAlpha(ruleset *tree,
765
+ char linkToArray,
757
766
  unsigned int parentOffset,
758
767
  unsigned int nextOffset) {
768
+ if (!nextOffset) {
769
+ return RULES_OK;
770
+ }
771
+
759
772
  unsigned int entry;
760
773
  node *parentAlpha = &tree->nodePool[parentOffset];
761
774
  node *nextNode = &tree->nodePool[nextOffset];
@@ -785,10 +798,19 @@ static unsigned int linkAlpha(ruleset *tree,
785
798
 
786
799
  parentNextList[entry] = nextOffset;
787
800
  } else {
788
- CHECK_RESULT(ensureNextHashset(tree,
789
- parentAlpha));
790
-
791
- unsigned int *parentNext = &tree->nextPool[parentAlpha->value.a.nextOffset];
801
+ unsigned int *parentNext = NULL;
802
+ if ((parentAlpha->value.a.expression.operator == OP_IALL || parentAlpha->value.a.expression.operator == OP_IANY) && linkToArray) {
803
+ CHECK_RESULT(ensureNextArrayHashset(tree,
804
+ parentAlpha));
805
+
806
+ parentNext = &tree->nextPool[parentAlpha->value.a.arrayListOffset];
807
+ } else {
808
+ CHECK_RESULT(ensureNextHashset(tree,
809
+ parentAlpha));
810
+
811
+ parentNext = &tree->nextPool[parentAlpha->value.a.nextOffset];
812
+ }
813
+
792
814
  unsigned int hash = nextNode->value.a.expression.left.value.id.propertyNameHash;
793
815
  for (entry = hash & HASH_MASK; parentNext[entry] != 0; entry = (entry + 1) % NEXT_BUCKET_LENGTH) {
794
816
  if ((entry + 1) % NEXT_BUCKET_LENGTH == (hash & HASH_MASK)) {
@@ -923,6 +945,7 @@ static unsigned int findAlpha(ruleset *tree,
923
945
  unsigned int parentOffset,
924
946
  unsigned char operator,
925
947
  char *rule,
948
+ char linkToArray,
926
949
  unsigned int betaOffset,
927
950
  unsigned int *resultOffset) {
928
951
  char *first;
@@ -1000,6 +1023,7 @@ static unsigned int findAlpha(ruleset *tree,
1000
1023
 
1001
1024
  newAlpha->nameOffset = stringOffset;
1002
1025
  newAlpha->type = NODE_ALPHA;
1026
+ newAlpha->value.a.stringOffset = stringOffset;
1003
1027
  newAlpha->value.a.expression.left.type = JSON_MESSAGE_IDENTIFIER;
1004
1028
  newAlpha->value.a.expression.left.value.id.propertyNameHash = hash;
1005
1029
  newAlpha->value.a.expression.left.value.id.propertyNameOffset = newAlpha->nameOffset;
@@ -1014,27 +1038,23 @@ static unsigned int findAlpha(ruleset *tree,
1014
1038
  type = JSON_IREGEX;
1015
1039
  }
1016
1040
 
1017
- //if (operator == OP_IANY || operator == OP_IALL) {
1018
- // newAlpha->value.a.expression.right.type = JSON_NIL;
1019
- //} else {
1020
- CHECK_RESULT(copyValue(tree,
1021
- &newAlpha->value.a.expression.right,
1022
- first,
1023
- last,
1024
- expressionOffset,
1025
- &id,
1026
- type));
1027
-
1028
- if (type == JSON_IDENTIFIER || type == JSON_EXPRESSION) {
1029
- expression *expr;
1030
- GET_EXPRESSION(tree,
1031
- betaOffset,
1032
- expr);
1033
- copyExpression(&newAlpha->value.a.expression, expr);
1034
- }
1035
- //}
1036
-
1037
- return linkAlpha(tree, parentOffset, *resultOffset);
1041
+ CHECK_RESULT(copyValue(tree,
1042
+ &newAlpha->value.a.expression.right,
1043
+ first,
1044
+ last,
1045
+ expressionOffset,
1046
+ &id,
1047
+ type));
1048
+
1049
+ if (type == JSON_IDENTIFIER || type == JSON_EXPRESSION) {
1050
+ expression *expr;
1051
+ GET_EXPRESSION(tree,
1052
+ betaOffset,
1053
+ expr);
1054
+ copyExpression(&newAlpha->value.a.expression, expr);
1055
+ }
1056
+
1057
+ return linkAlpha(tree, linkToArray, parentOffset, *resultOffset);
1038
1058
  }
1039
1059
 
1040
1060
  static unsigned int getSetting(unsigned int settingHash, char *rule, unsigned short *value) {
@@ -1077,6 +1097,7 @@ static unsigned int createForwardAlpha(ruleset *tree,
1077
1097
 
1078
1098
  newAlpha->nameOffset = 0;
1079
1099
  newAlpha->type = NODE_ALPHA;
1100
+ newAlpha->value.a.arrayListOffset = 0;
1080
1101
  newAlpha->value.a.expression.left.type = JSON_MESSAGE_IDENTIFIER;
1081
1102
  newAlpha->value.a.expression.left.value.id.propertyNameOffset = 0;
1082
1103
  newAlpha->value.a.expression.left.value.id.propertyNameHash = HASH_FORWARD;
@@ -1089,6 +1110,7 @@ static unsigned int createForwardAlpha(ruleset *tree,
1089
1110
 
1090
1111
  static unsigned int createAlpha(ruleset *tree,
1091
1112
  char *rule,
1113
+ char linkToArray,
1092
1114
  unsigned int betaOffset,
1093
1115
  unsigned int nextOffset,
1094
1116
  unsigned int *newOffset) {
@@ -1159,10 +1181,12 @@ static unsigned int createAlpha(ruleset *tree,
1159
1181
  while (result == PARSE_OK) {
1160
1182
  CHECK_RESULT(createAlpha(tree,
1161
1183
  first,
1184
+ linkToArray,
1162
1185
  betaOffset,
1163
1186
  0,
1164
1187
  &resultOffset));
1165
1188
 
1189
+ linkToArray = 0;
1166
1190
  previousOffset = resultOffset;
1167
1191
  result = readNextArrayValue(last,
1168
1192
  &first,
@@ -1176,6 +1200,7 @@ static unsigned int createAlpha(ruleset *tree,
1176
1200
  OP_END);
1177
1201
  if (nextOffset != 0) {
1178
1202
  return linkAlpha(tree,
1203
+ 0,
1179
1204
  previousOffset,
1180
1205
  nextOffset);
1181
1206
  }
@@ -1196,11 +1221,13 @@ static unsigned int createAlpha(ruleset *tree,
1196
1221
  unsigned int single_offset = parentOffset;
1197
1222
  CHECK_RESULT(createAlpha(tree,
1198
1223
  first,
1224
+ linkToArray,
1199
1225
  betaOffset,
1200
1226
  0,
1201
1227
  &single_offset));
1202
1228
 
1203
1229
  CHECK_RESULT(linkAlpha(tree,
1230
+ 0,
1204
1231
  single_offset,
1205
1232
  *newOffset));
1206
1233
 
@@ -1216,6 +1243,7 @@ static unsigned int createAlpha(ruleset *tree,
1216
1243
  OP_END);
1217
1244
  if (nextOffset != 0) {
1218
1245
  return linkAlpha(tree,
1246
+ 0,
1219
1247
  *newOffset,
1220
1248
  nextOffset);
1221
1249
  }
@@ -1237,7 +1265,8 @@ static unsigned int createAlpha(ruleset *tree,
1237
1265
  CHECK_RESULT(findAlpha(tree,
1238
1266
  parentOffset,
1239
1267
  operator,
1240
- first,
1268
+ first,
1269
+ linkToArray,
1241
1270
  betaOffset,
1242
1271
  newOffset));
1243
1272
 
@@ -1254,38 +1283,19 @@ static unsigned int createAlpha(ruleset *tree,
1254
1283
 
1255
1284
  CHECK_RESULT(createAlpha(tree,
1256
1285
  first,
1286
+ 1,
1257
1287
  betaOffset,
1258
- nextOffset,
1288
+ 0,
1259
1289
  &inner_offset));
1260
1290
 
1261
1291
  node *newAlpha = &tree->nodePool[inner_offset];
1262
1292
  if (newAlpha->value.a.expression.right.type != JSON_IDENTIFIER && newAlpha->value.a.expression.right.type != JSON_EXPRESSION) {
1263
- return linkAlpha(tree,
1293
+ return linkAlpha(tree,
1294
+ 0,
1264
1295
  *newOffset,
1265
1296
  nextOffset);
1266
1297
  } else {
1267
- // Functions that can execute in client or backend should follow this pattern
1268
- node *oldAlpha = &tree->nodePool[*newOffset];
1269
- expression *newExpression = NULL;
1270
- unsigned int expressionOffset = 0;
1271
- CHECK_RESULT(storeExpression(tree,
1272
- &newExpression,
1273
- &expressionOffset));
1274
-
1275
- oldAlpha->value.a.expression.right.type = JSON_EXPRESSION;
1276
- oldAlpha->value.a.expression.right.value.expressionOffset = expressionOffset;
1277
- copyExpression(&newAlpha->value.a.expression, newExpression);
1278
-
1279
- expression *betaExpression;
1280
- GET_EXPRESSION(tree,
1281
- betaOffset,
1282
- betaExpression);
1283
-
1284
- copyExpression(newExpression, betaExpression);
1285
-
1286
- return linkAlpha(tree,
1287
- *newOffset,
1288
- nextOffset);
1298
+ return ERR_UNEXPECTED_TYPE;
1289
1299
  }
1290
1300
  }
1291
1301
 
@@ -1294,6 +1304,7 @@ static unsigned int createAlpha(ruleset *tree,
1294
1304
  parentOffset,
1295
1305
  operator,
1296
1306
  first,
1307
+ linkToArray,
1297
1308
  betaOffset,
1298
1309
  newOffset);
1299
1310
  } else {
@@ -1301,10 +1312,12 @@ static unsigned int createAlpha(ruleset *tree,
1301
1312
  parentOffset,
1302
1313
  operator,
1303
1314
  first,
1315
+ linkToArray,
1304
1316
  betaOffset,
1305
1317
  newOffset));
1306
1318
 
1307
- return linkAlpha(tree,
1319
+ return linkAlpha(tree,
1320
+ 0,
1308
1321
  *newOffset,
1309
1322
  nextOffset);
1310
1323
  }
@@ -1408,6 +1421,7 @@ static unsigned int createBeta(ruleset *tree,
1408
1421
  &type));
1409
1422
  CHECK_RESULT(createAlpha(tree,
1410
1423
  first,
1424
+ 0,
1411
1425
  betaOffset,
1412
1426
  betaOffset,
1413
1427
  &resultOffset));
@@ -1626,11 +1640,15 @@ static void printBetaNode(ruleset *tree, node *betaNode, int level, unsigned int
1626
1640
  }
1627
1641
  }
1628
1642
 
1629
- static void printAlphaNode(ruleset *tree, node *alphaNode, int level, unsigned int offset) {
1643
+ static void printAlphaNode(ruleset *tree, node *alphaNode, int level, char *prefix, unsigned int offset) {
1630
1644
  for (int i = 0; i < level; ++ i) {
1631
1645
  printf(" ");
1632
1646
  }
1633
1647
 
1648
+ if (prefix) {
1649
+ printf("%s", prefix);
1650
+ }
1651
+
1634
1652
  printf("-> alpha: name %s, offset %u\n", &tree->stringPool[alphaNode->nameOffset], offset);
1635
1653
 
1636
1654
  for (int i = 0; i < level; ++ i) {
@@ -1640,11 +1658,20 @@ static void printAlphaNode(ruleset *tree, node *alphaNode, int level, unsigned i
1640
1658
  printSimpleExpression(tree, &alphaNode->value.a.expression, 1, NULL);
1641
1659
 
1642
1660
  printf("\n");
1661
+ if (alphaNode->value.a.arrayListOffset) {
1662
+ unsigned int *nextHashset = &tree->nextPool[alphaNode->value.a.arrayListOffset];
1663
+ for (unsigned int entry = 0; entry < NEXT_BUCKET_LENGTH; ++entry) {
1664
+ if (nextHashset[entry]) {
1665
+ printAlphaNode(tree, &tree->nodePool[nextHashset[entry]], level + 1, "Next Array ", nextHashset[entry]);
1666
+ }
1667
+ }
1668
+ }
1669
+
1643
1670
  if (alphaNode->value.a.nextOffset) {
1644
1671
  unsigned int *nextHashset = &tree->nextPool[alphaNode->value.a.nextOffset];
1645
1672
  for (unsigned int entry = 0; entry < NEXT_BUCKET_LENGTH; ++entry) {
1646
1673
  if (nextHashset[entry]) {
1647
- printAlphaNode(tree, &tree->nodePool[nextHashset[entry]], level + 1, nextHashset[entry]);
1674
+ printAlphaNode(tree, &tree->nodePool[nextHashset[entry]], level + 1, "Next ", nextHashset[entry]);
1648
1675
  }
1649
1676
  }
1650
1677
  }
@@ -1652,7 +1679,7 @@ static void printAlphaNode(ruleset *tree, node *alphaNode, int level, unsigned i
1652
1679
  if (alphaNode->value.a.nextListOffset) {
1653
1680
  unsigned int *nextList = &tree->nextPool[alphaNode->value.a.nextListOffset];
1654
1681
  for (unsigned int entry = 0; nextList[entry] != 0; ++entry) {
1655
- printAlphaNode(tree, &tree->nodePool[nextList[entry]], level + 1, nextList[entry]);
1682
+ printAlphaNode(tree, &tree->nodePool[nextList[entry]], level + 1, "Next List ", nextList[entry]);
1656
1683
  }
1657
1684
  }
1658
1685
 
@@ -1782,6 +1809,7 @@ static unsigned int createTree(ruleset *tree, char *rules) {
1782
1809
  printAlphaNode(tree,
1783
1810
  &tree->nodePool[NODE_M_OFFSET],
1784
1811
  0,
1812
+ NULL,
1785
1813
  NODE_M_OFFSET);
1786
1814
  #endif
1787
1815
 
@@ -1845,7 +1873,7 @@ unsigned int createRuleset(unsigned int *handle, char *name, char *rules) {
1845
1873
  newNode->nameOffset = stringOffset;
1846
1874
  newNode->type = NODE_ALPHA;
1847
1875
  newNode->value.a.expression.operator = OP_TYPE;
1848
-
1876
+
1849
1877
  // will use random numbers for state stored event mids
1850
1878
  srand(time(NULL));
1851
1879
  CREATE_HANDLE(tree, handle);
data/src/rules/rete.h CHANGED
@@ -1,6 +1,6 @@
1
1
  #include "state.h"
2
2
 
3
- //#define _PRINT 1
3
+ // #define _PRINT 1
4
4
 
5
5
  #define OP_NOP 0
6
6
  #define OP_LT 0x01
@@ -83,8 +83,10 @@ typedef struct expressionSequence {
83
83
 
84
84
  typedef struct alpha {
85
85
  expression expression;
86
+ unsigned int stringOffset;
86
87
  unsigned int betaListOffset;
87
88
  unsigned int nextListOffset;
89
+ unsigned int arrayListOffset;
88
90
  unsigned int nextOffset;
89
91
  } alpha;
90
92
 
data/src/rules/state.c CHANGED
@@ -796,6 +796,9 @@ unsigned int ensureStateNode(void *tree,
796
796
  sidHash,
797
797
  nodeOffset);
798
798
 
799
+ if (rulesetTree->statePool.count > MAX_STATE_INDEX_LENGTH) {
800
+ return ERR_OUT_OF_MEMORY;
801
+ }
799
802
  rulesetTree->reverseStateIndex[rulesetTree->statePool.count - 1] = nodeOffset;
800
803
  stateNode *node = STATE_NODE(tree, nodeOffset);
801
804
  node->offset = nodeOffset;
@@ -1118,7 +1121,7 @@ unsigned int getNextResult(void *tree,
1118
1121
  static void insertSortProperties(jsonObject *jo, jsonProperty **properties) {
1119
1122
  for (unsigned short i = 1; i < jo->propertiesLength; ++i) {
1120
1123
  unsigned short ii = i;
1121
- while (properties[ii]->hash < properties[ii - 1]->hash) {
1124
+ while (ii >= 1 && (properties[ii]->hash < properties[ii - 1]->hash)) {
1122
1125
  jsonProperty *temp = properties[ii];
1123
1126
  properties[ii] = properties[ii - 1];
1124
1127
  properties[ii - 1] = temp;
@@ -1200,7 +1203,7 @@ unsigned int calculateId(jsonObject *jo) {
1200
1203
 
1201
1204
  unsigned int candidate = HASH_ID % MAX_OBJECT_PROPERTIES;
1202
1205
  while (jo->propertyIndex[candidate] != 0) {
1203
- candidate = candidate + 1 % MAX_OBJECT_PROPERTIES;
1206
+ candidate = (candidate + 1) % MAX_OBJECT_PROPERTIES;
1204
1207
  }
1205
1208
 
1206
1209
  // Index intentionally offset by 1 to enable getObject
@@ -1234,7 +1237,7 @@ static unsigned int fixupIds(jsonObject *jo, char generateId) {
1234
1237
 
1235
1238
  unsigned int candidate = HASH_SID % MAX_OBJECT_PROPERTIES;
1236
1239
  while (jo->propertyIndex[candidate] != 0) {
1237
- candidate = candidate + 1 % MAX_OBJECT_PROPERTIES;
1240
+ candidate = (candidate + 1) % MAX_OBJECT_PROPERTIES;
1238
1241
  }
1239
1242
 
1240
1243
  // Index intentionally offset by 1 to enable getObject
@@ -1294,7 +1297,7 @@ unsigned int setObjectProperty(jsonObject *jo,
1294
1297
 
1295
1298
  unsigned int candidate = hash % MAX_OBJECT_PROPERTIES;
1296
1299
  while (jo->propertyIndex[candidate] != 0) {
1297
- candidate = candidate + 1 % MAX_OBJECT_PROPERTIES;
1300
+ candidate = (candidate + 1) % MAX_OBJECT_PROPERTIES;
1298
1301
  }
1299
1302
 
1300
1303
  // Index intentionally offset by 1 to enable getObject
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: durable_rules
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.00.3
4
+ version: 2.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jesus Ruiz
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-07-08 00:00:00.000000000 Z
11
+ date: 2019-07-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake