durable_rules 2.00.3 → 2.0.4

Sign up to get free protection for your applications and to get access to all the features.
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