|
|
@@ -217,38 +217,250 @@ void TokenMatrix::FlipEndian() { |
|
|
|
// Evaluator Implementations ////////////////////////////////////////////////////////////// |
|
|
|
|
|
|
|
// 20030216 _M Optimization conversions |
|
|
|
|
|
|
|
inline int Evaluator::i_lower() { return myEvaluationMatrix->i_lower; } |
|
|
|
inline bool Evaluator::i_isDigit() { return myEvaluationMatrix->i_isDigit; } |
|
|
|
inline bool Evaluator::i_isSpace() { return myEvaluationMatrix->i_isSpace; } |
|
|
|
inline bool Evaluator::i_isAlpha() { return myEvaluationMatrix->i_isAlpha; } |
|
|
|
|
|
|
|
// 20140119 _M Deprecated by jump table in evaluator |
|
|
|
// inline int Evaluator::i_lower() { return myEvaluationMatrix->i_lower; } |
|
|
|
// inline bool Evaluator::i_isDigit() { return myEvaluationMatrix->i_isDigit; } |
|
|
|
// inline bool Evaluator::i_isSpace() { return myEvaluationMatrix->i_isSpace; } |
|
|
|
// inline bool Evaluator::i_isAlpha() { return myEvaluationMatrix->i_isAlpha; } |
|
|
|
|
|
|
|
|
|
|
|
// Evaluator::Evaluator(position,evalmatrix) Constructor |
|
|
|
|
|
|
|
Evaluator::Evaluator(unsigned int s, EvaluationMatrix* m) { // Constructor... |
|
|
|
Evaluator::Evaluator(unsigned int s, EvaluationMatrix* m)
|
|
|
|
: myEvaluationMatrix(m),
|
|
|
|
JumpPoint(0),
|
|
|
|
Condition(DOING_OK),
|
|
|
|
NextEvaluator(NULL),
|
|
|
|
StreamStartPosition(s),
|
|
|
|
CurrentPosition(0),
|
|
|
|
WildRunLength(0) { // Constructor... |
|
|
|
|
|
|
|
myEvaluationMatrix = m; // Capture the matrix I live in. |
|
|
|
Matrix = myEvaluationMatrix->getTokens(); // Capture the token matrix I walk in. |
|
|
|
MatrixSize = myEvaluationMatrix->getMatrixSize(); // And get it's size. |
|
|
|
PositionLimit = MatrixSize - 256; // Calculate the safety limit. |
|
|
|
MatrixSize = myEvaluationMatrix->getMatrixSize(); // And get it's size.
|
|
|
|
PositionLimit = MatrixSize - 256; |
|
|
|
} |
|
|
|
|
|
|
|
StreamStartPosition = s; // Always record our starting point. |
|
|
|
NextEvaluator = NULL; // Allways start off with no extensions. |
|
|
|
CurrentPosition = 0; // Always start at the root of the matrix; |
|
|
|
WildRunLength = 0; // No run length when new. |
|
|
|
// Of course I may need to resolve some of the following |
|
|
|
// wildcard characters. |
|
|
|
|
|
|
|
Condition = DOING_OK; // Start off being ok. |
|
|
|
} |
|
|
|
int Evaluator::xLetter() { return (JumpPoint + WILD_LETTER); } // Match Any letter. |
|
|
|
int Evaluator::xDigit() { return (JumpPoint + WILD_DIGIT); } // Match Any digit. |
|
|
|
int Evaluator::xNonWhite() { return (JumpPoint + WILD_NONWHITE); } // Match Any non-whitespace. |
|
|
|
int Evaluator::xWhiteSpace() { return (JumpPoint + WILD_WHITESPACE); } // Match Any whitespace. |
|
|
|
int Evaluator::xAnyInline() { return (JumpPoint + WILD_INLINE); } // Match Any byte but new line. |
|
|
|
int Evaluator::xAnything() { return (JumpPoint + WILD_ANYTHING); } // Match Any character at all. |
|
|
|
int Evaluator::xRunGateway() { return (JumpPoint + RUN_GATEWAY); } // Match the run-loop gateway. |
|
|
|
|
|
|
|
// void Evaluator::doFollowOrMakeBuddy()
|
|
|
|
|
|
|
|
void Evaluator::doFollowOrMakeBuddy(int xKey) {
|
|
|
|
|
|
|
|
bool shouldFollow = (FALLEN_OFF == Condition); // What should we do?
|
|
|
|
|
|
|
|
if(shouldFollow) { // This is how we follow |
|
|
|
Condition = DOING_OK; |
|
|
|
CurrentPosition = xKey + |
|
|
|
Matrix[xKey].Vector; |
|
|
|
} |
|
|
|
|
|
|
|
else { // This is how we make a buddy |
|
|
|
myEvaluationMatrix-> |
|
|
|
AddEvaluator(StreamStartPosition,Matrix[xKey].Vector+xKey); |
|
|
|
} |
|
|
|
}
|
|
|
|
|
|
|
|
void Evaluator::tryFollowingPrecisePath(unsigned short int i) {
|
|
|
|
int xPrecise = JumpPoint + i; // Match Precise Character |
|
|
|
if(Matrix[xPrecise].Character() == i) { // If we've matched our path
|
|
|
|
doFollowOrMakeBuddy(xPrecise); |
|
|
|
}
|
|
|
|
if(DOING_OK == Condition) WildRunLength = 0; |
|
|
|
}
|
|
|
|
|
|
|
|
void Evaluator::tryFollowingNoCasePath(unsigned short int i) {
|
|
|
|
i = tolower(i);
|
|
|
|
int xNoCase = JumpPoint + i; // Match caps to lower (case insensitive) |
|
|
|
if(Matrix[xNoCase].Character()==i){ |
|
|
|
doFollowOrMakeBuddy(xNoCase); |
|
|
|
} |
|
|
|
if(DOING_OK == Condition) WildRunLength = 0; |
|
|
|
}
|
|
|
|
|
|
|
|
void Evaluator::tryFollowingWildAlphaPath() {
|
|
|
|
if(Matrix[xLetter()].Character()==WILD_LETTER){ |
|
|
|
doFollowOrMakeBuddy(xLetter()); |
|
|
|
} |
|
|
|
}
|
|
|
|
|
|
|
|
void Evaluator::tryFollowingWildDigitPath() {
|
|
|
|
if(Matrix[xDigit()].Character()==WILD_DIGIT){ |
|
|
|
doFollowOrMakeBuddy(xDigit()); |
|
|
|
} |
|
|
|
}
|
|
|
|
|
|
|
|
void Evaluator::tryFollowingWildNonWhitePath() {
|
|
|
|
if(Matrix[xNonWhite()].Character()==WILD_NONWHITE){ |
|
|
|
doFollowOrMakeBuddy(xNonWhite()); |
|
|
|
} |
|
|
|
}
|
|
|
|
|
|
|
|
void Evaluator::tryFollowingWildWhitePath() {
|
|
|
|
if(Matrix[xWhiteSpace()].Character()==WILD_WHITESPACE){ |
|
|
|
doFollowOrMakeBuddy(xWhiteSpace()); |
|
|
|
} |
|
|
|
}
|
|
|
|
|
|
|
|
void Evaluator::tryFollowingWildInlinePath() {
|
|
|
|
if(Matrix[xAnyInline()].Character()==WILD_INLINE){ |
|
|
|
doFollowOrMakeBuddy(xAnyInline()); |
|
|
|
} |
|
|
|
}
|
|
|
|
|
|
|
|
void Evaluator::tryFollowingWildAnythingPath() {
|
|
|
|
if(Matrix[xAnything()].Character()==WILD_ANYTHING){ |
|
|
|
doFollowOrMakeBuddy(xAnything()); |
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Evaluator::doFollowerJumpTable(unsigned short int i) {
|
|
|
|
tryFollowingPrecisePath(i);
|
|
|
|
// tryFollowingUppercasePath(); 0x41 - 0x5A
|
|
|
|
// tryFollowingWildAlphaPath(); 0x61 - 0x7A
|
|
|
|
// tryFollowingWildDigitPath(); 0x30 - 0x39
|
|
|
|
// tryFollowingWildWhitePath(); 0x09 - 0x0D, 0x20
|
|
|
|
// tryFollowingWildNonWhitePath(); > 0x20
|
|
|
|
// tryFollowingWildInlinePath(); Not 0x0A, or 0x0D
|
|
|
|
|
|
|
|
switch(i) {
|
|
|
|
|
|
|
|
// These only match Precise, or WildAnything ...
|
|
|
|
// NUL, SOH, STX, ETX, EOT, ENQ, ACK, BEL, BS, TAB, LF, VT, FF, CR, SO, SI
|
|
|
|
case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
|
|
|
|
case 0x08: {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// tab
|
|
|
|
case 0x09: {
|
|
|
|
tryFollowingWildWhitePath();
|
|
|
|
tryFollowingWildInlinePath();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// LF, VT, FF, CR, SO, SI
|
|
|
|
case 0x0A: case 0x0B: case 0x0C: case 0x0D: case 0x0E: case 0x0F:
|
|
|
|
|
|
|
|
// DLE, DC1, DC2, DC3, DC4, NAK, SYN, ETB, CAN, EM, SUB, ESC, FS, GS, RS, US
|
|
|
|
case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
|
|
|
|
case 0x18: case 0x19: case 0x1A: case 0x1B: case 0x1C: case 0x1D: case 0x1E: case 0x1F: {
|
|
|
|
tryFollowingWildWhitePath();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// the final fronteer
|
|
|
|
case 0x20: {
|
|
|
|
tryFollowingWildWhitePath();
|
|
|
|
tryFollowingWildInlinePath();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ! " # $ % & ' ( ) * + , - . /
|
|
|
|
case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
|
|
|
|
case 0x28: case 0x29: case 0x2A: case 0x2B: case 0x2C: case 0x2D: case 0x2E: case 0x2F: {
|
|
|
|
tryFollowingWildNonWhitePath();
|
|
|
|
tryFollowingWildInlinePath();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0 - 9
|
|
|
|
case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
|
|
|
|
case 0x38: case 0x39: {
|
|
|
|
tryFollowingWildDigitPath();
|
|
|
|
tryFollowingWildNonWhitePath();
|
|
|
|
tryFollowingWildInlinePath();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// : ; < = > ? @
|
|
|
|
case 0x3A: case 0x3B: case 0x3C: case 0x3D: case 0x3E: case 0x3F:
|
|
|
|
case 0x40: {
|
|
|
|
tryFollowingWildNonWhitePath();
|
|
|
|
tryFollowingWildInlinePath();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// A - Z
|
|
|
|
case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47:
|
|
|
|
case 0x48: case 0x49: case 0x4A: case 0x4B: case 0x4C: case 0x4D: case 0x4E: case 0x4F:
|
|
|
|
case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57:
|
|
|
|
case 0x58: case 0x59: case 0x5A: {
|
|
|
|
tryFollowingNoCasePath(i);
|
|
|
|
tryFollowingWildAlphaPath();
|
|
|
|
tryFollowingWildNonWhitePath();
|
|
|
|
tryFollowingWildInlinePath();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// [ \ ] ^ _ `
|
|
|
|
case 0x5B: case 0x5C: case 0x5D: case 0x5E: case 0x5F:
|
|
|
|
case 0x60: {
|
|
|
|
tryFollowingWildNonWhitePath();
|
|
|
|
tryFollowingWildInlinePath();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// a - z
|
|
|
|
case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67:
|
|
|
|
case 0x68: case 0x69: case 0x6A: case 0x6B: case 0x6C: case 0x6D: case 0x6E: case 0x6F:
|
|
|
|
case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77:
|
|
|
|
case 0x78: case 0x79: case 0x7A: {
|
|
|
|
tryFollowingWildAlphaPath();
|
|
|
|
tryFollowingWildNonWhitePath();
|
|
|
|
tryFollowingWildInlinePath();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// { | } ~
|
|
|
|
case 0x7B: case 0x7C: case 0x7D: case 0x7E: case 0x7F: {
|
|
|
|
tryFollowingWildNonWhitePath();
|
|
|
|
tryFollowingWildInlinePath();
|
|
|
|
}
|
|
|
|
|
|
|
|
// high ascii
|
|
|
|
case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87:
|
|
|
|
case 0x88: case 0x89: case 0x8A: case 0x8B: case 0x8C: case 0x8D: case 0x8E: case 0x8F:
|
|
|
|
case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97:
|
|
|
|
case 0x98: case 0x99: case 0x9A: case 0x9B: case 0x9C: case 0x9D: case 0x9E: case 0x9F:
|
|
|
|
case 0xA0: case 0xA1: case 0xA2: case 0xA3: case 0xA4: case 0xA5: case 0xA6: case 0xA7:
|
|
|
|
case 0xA8: case 0xA9: case 0xAA: case 0xAB: case 0xAC: case 0xAD: case 0xAE: case 0xAF:
|
|
|
|
case 0xB0: case 0xB1: case 0xB2: case 0xB3: case 0xB4: case 0xB5: case 0xB6: case 0xB7:
|
|
|
|
case 0xB8: case 0xB9: case 0xBA: case 0xBB: case 0xBC: case 0xBD: case 0xBE: case 0xBF:
|
|
|
|
case 0xC0: case 0xC1: case 0xC2: case 0xC3: case 0xC4: case 0xC5: case 0xC6: case 0xC7:
|
|
|
|
case 0xC8: case 0xC9: case 0xCA: case 0xCB: case 0xCC: case 0xCD: case 0xCE: case 0xCF:
|
|
|
|
case 0xD0: case 0xD1: case 0xD2: case 0xD3: case 0xD4: case 0xD5: case 0xD6: case 0xD7:
|
|
|
|
case 0xD8: case 0xD9: case 0xDA: case 0xDB: case 0xDC: case 0xDD: case 0xDE: case 0xDF:
|
|
|
|
case 0xE0: case 0xE1: case 0xE2: case 0xE3: case 0xE4: case 0xE5: case 0xE6: case 0xE7:
|
|
|
|
case 0xE8: case 0xE9: case 0xEA: case 0xEB: case 0xEC: case 0xED: case 0xEE: case 0xEF:
|
|
|
|
case 0xF0: case 0xF1: case 0xF2: case 0xF3: case 0xF4: case 0xF5: case 0xF6: case 0xF7:
|
|
|
|
case 0xF8: case 0xF9: case 0xFA: case 0xFB: case 0xFC: case 0xFD: case 0xFE: case 0xFF: {
|
|
|
|
tryFollowingWildNonWhitePath();
|
|
|
|
tryFollowingWildInlinePath();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
tryFollowingWildAnythingPath();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Evaluator::EvaluateThis() |
|
|
|
|
|
|
|
|
|
|
|
Evaluator::States Evaluator::EvaluateThis(unsigned short int i) { // Follow the this byte. |
|
|
|
|
|
|
|
Condition = FALLEN_OFF; // Start off guessing we'll fall off. |
|
|
|
|
|
|
|
// First upgrade will be to DOING_OK, after that we launch buddies. |
|
|
|
|
|
|
|
Condition = FALLEN_OFF; // Start off guessing we'll fall off. |
|
|
|
|
|
|
|
// In order to handle wildcard characters, this evaluation function must actually |
|
|
|
// compare the character to a number of possibilities in most-specific to least- |
|
|
|
// specific order to see if any match. In order to support overlapping rule sets, |
|
|
@@ -257,33 +469,9 @@ Evaluator::States Evaluator::EvaluateThis(unsigned short int i) { |
|
|
|
// explored. New evaluators are always added at the TOP of the list so we are always |
|
|
|
// guaranteed not to overdrive an evaluator and end up in a recursive race condition. |
|
|
|
|
|
|
|
// 20030216 _M Optimizations. In order to reduce the number of instructions per byte |
|
|
|
// the parent Evaluation Matrix will now translate the byte i into boolean flags |
|
|
|
// indicating if they are digits, white, letters, etc... and converting to lower |
|
|
|
// case etc... This conversion is then done only once so that thereafter only a simple |
|
|
|
// comparison need be made. This should eliminate many function calls and a collection |
|
|
|
// of numeric comparisons. |
|
|
|
// |
|
|
|
// I am also moving the simple comparisons to the front of each logical section so |
|
|
|
// that failures there can short-circuit subsequent logic to view the state of the |
|
|
|
// matrix regardin that character. The matrix lookup is likely to be more expensive |
|
|
|
// than a single binary comparison. |
|
|
|
|
|
|
|
// For safety, we check our evaluation position here - If xNoCase is out of range |
|
|
|
// then we will return OUT_OF_RANGE to indicate the problem rather than accessing |
|
|
|
// data beyone our token matrix's limits. |
|
|
|
|
|
|
|
/*** 20070606 _M Reduced the strength of this check from 3 comparisons to 1. |
|
|
|
**** CurrentPosition is now an unsigned int so it cannot be negative. The limit |
|
|
|
**** is now calculated once in the constructor as PositionLimit. |
|
|
|
|
|
|
|
if( |
|
|
|
CurrentPosition < 0 || // Position should never be < 0 |
|
|
|
xPrecise >= MatrixSize || // nor xPrecise over the top. |
|
|
|
xNoCase >= MatrixSize // nor NoCase over the top. |
|
|
|
) // If either occur we have a |
|
|
|
return Condition = OUT_OF_RANGE; // bad matrix. |
|
|
|
***/ |
|
|
|
// 20140121_M The previous optimization with binary flags has been replaced with
|
|
|
|
// a jump table implementation. Now, each byte only excites behaviors that are
|
|
|
|
// possible for the current byte so only those paths will be tested.
|
|
|
|
|
|
|
|
if(CurrentPosition >= PositionLimit) return Condition = OUT_OF_RANGE; |
|
|
|
|
|
|
@@ -300,234 +488,17 @@ Evaluator::States Evaluator::EvaluateThis(unsigned short int i) { |
|
|
|
// to support deep - filters which will show every rule match and this will need to |
|
|
|
// be rewritten. |
|
|
|
|
|
|
|
// Evaluation order, most-to-least specific: |
|
|
|
|
|
|
|
int xPrecise = CurrentPosition + i; // Match Precise Character |
|
|
|
int xNoCase = CurrentPosition + i_lower(); // Match Case insensitive |
|
|
|
|
|
|
|
// Of course I may need to resolve some of the following |
|
|
|
// wildcard characters. |
|
|
|
|
|
|
|
int xLetter = CurrentPosition + WILD_LETTER; // Match Any letter. |
|
|
|
int xDigit = CurrentPosition + WILD_DIGIT; // Match Any digit. |
|
|
|
int xNonWhite = CurrentPosition + WILD_NONWHITE; // Match Any non-whitespace. |
|
|
|
int xWhiteSpace = CurrentPosition + WILD_WHITESPACE; // Match Any whitespace. |
|
|
|
int xAnyInline = CurrentPosition + WILD_INLINE; // Match Any byte but new line. |
|
|
|
int xAnything = CurrentPosition + WILD_ANYTHING; // Match Any character at all. |
|
|
|
int xRunGateway = CurrentPosition + RUN_GATEWAY; // Match the run-loop gateway. |
|
|
|
|
|
|
|
// Try to match the precise character. |
|
|
|
|
|
|
|
if(Matrix[xPrecise].Character() == i) { // If we've matched our path |
|
|
|
Condition = DOING_OK; // upgrade to doing ok. |
|
|
|
CurrentPosition = xPrecise + |
|
|
|
Matrix[xPrecise].Vector; // Move myself along this path. |
|
|
|
} |
|
|
|
|
|
|
|
// Try to match the case insensitive character. |
|
|
|
|
|
|
|
if(i_lower()!=i && Matrix[xNoCase].Character()==i_lower()){ |
|
|
|
|
|
|
|
// If we've matched our path |
|
|
|
// with a compromized case then |
|
|
|
if(Condition==FALLEN_OFF) { // check: if no matches yet, |
|
|
|
Condition = DOING_OK; // upgrade to doing ok. |
|
|
|
CurrentPosition = xNoCase + |
|
|
|
Matrix[xNoCase].Vector; // Move myself along this path. |
|
|
|
} |
|
|
|
// If we more than one match then |
|
|
|
else { // lets try to make a buddy... |
|
|
|
|
|
|
|
// If there's no duplicate buddy like this already, then we'll create one. |
|
|
|
// To create a buddy, add an evaluator at the top of the list (behind us) and |
|
|
|
// set it's position as if it had been here all along and had matched the current |
|
|
|
// character. Next time we evaluate it will be just like all the others. |
|
|
|
|
|
|
|
myEvaluationMatrix-> |
|
|
|
AddEvaluator(StreamStartPosition,Matrix[xNoCase].Vector+xNoCase); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// Start looking at wildcards... Here's where we must limit run length. |
|
|
|
|
|
|
|
if(Condition == DOING_OK) // If we matched above we'll |
|
|
|
WildRunLength = 0; // reset our wild run count. |
|
|
|
// If not then we need to keep |
|
|
|
else { // track of our run length. |
|
|
|
|
|
|
|
++WildRunLength; // Count up the run length. |
|
|
|
if(WildRunLength >= MaxWildRunLength) // If we exceed the max then |
|
|
|
return Condition = FALLEN_OFF; // we've fallen off the path |
|
|
|
} // and we do it immediately. |
|
|
|
|
|
|
|
// WILD_LETTER |
|
|
|
// If that didn't do it for us... |
|
|
|
// Try to match any letter character. |
|
|
|
|
|
|
|
// The way this next one works (and the rest of the wildcards) is we look into |
|
|
|
// the token matrix to see if the wildcard is part of the current path... If it |
|
|
|
// is then we compare the incoming character to that wildcard evaluation function |
|
|
|
// and if it is true, then we've got a match. |
|
|
|
|
|
|
|
if(i_isAlpha() && Matrix[xLetter].Character()==WILD_LETTER){ |
|
|
|
|
|
|
|
// If we've matched our path |
|
|
|
// with any letter then |
|
|
|
if(Condition==FALLEN_OFF) { // check: if no matches yet, |
|
|
|
Condition = DOING_OK; // upgrade to doing ok. |
|
|
|
CurrentPosition = xLetter + |
|
|
|
Matrix[xLetter].Vector; // Move myself along this path. |
|
|
|
} |
|
|
|
|
|
|
|
else { // Otherwise make a buddy... |
|
|
|
|
|
|
|
// If there's no duplicate buddy like this already, then we'll create one. |
|
|
|
// To create a buddy, add an evaluator at the top of the list (behind us) and |
|
|
|
// set it's position as if it had been here all along and had matched the current |
|
|
|
// character. Next time we evaluate it will be just like all the others. |
|
|
|
|
|
|
|
myEvaluationMatrix-> |
|
|
|
AddEvaluator(StreamStartPosition,Matrix[xLetter].Vector+xLetter); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// WILD_DIGIT |
|
|
|
// If that didn't do it for us... |
|
|
|
// Try to match any digit character. |
|
|
|
|
|
|
|
if(i_isDigit() && Matrix[xDigit].Character()==WILD_DIGIT){ |
|
|
|
|
|
|
|
// If we've matched our path |
|
|
|
// with any letter then |
|
|
|
if(Condition==FALLEN_OFF) { // check: if no matches yet, |
|
|
|
Condition = DOING_OK; // upgrade to doing ok. |
|
|
|
CurrentPosition = xDigit + |
|
|
|
Matrix[xDigit].Vector; // Move myself along this path. |
|
|
|
} |
|
|
|
|
|
|
|
else { // Otherwise make a buddy... |
|
|
|
|
|
|
|
// If there's no duplicate buddy like this already, then we'll create one. |
|
|
|
// To create a buddy, add an evaluator at the top of the list (behind us) and |
|
|
|
// set it's position as if it had been here all along and had matched the current |
|
|
|
// character. Next time we evaluate it will be just like all the others. |
|
|
|
|
|
|
|
myEvaluationMatrix-> |
|
|
|
AddEvaluator(StreamStartPosition,Matrix[xDigit].Vector+xDigit); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// WILD_NONWHITE |
|
|
|
// If that didn't do it for us... |
|
|
|
// Try to match any non-whitespace character. |
|
|
|
|
|
|
|
if(!i_isSpace() && Matrix[xNonWhite].Character()==WILD_NONWHITE){ |
|
|
|
|
|
|
|
// If we've matched our path |
|
|
|
// with any letter then |
|
|
|
if(Condition==FALLEN_OFF) { // check: if no matches yet, |
|
|
|
Condition = DOING_OK; // upgrade to doing ok. |
|
|
|
CurrentPosition = xNonWhite + |
|
|
|
Matrix[xNonWhite].Vector; // Move myself along this path. |
|
|
|
} |
|
|
|
|
|
|
|
else { // Otherwise make a buddy... |
|
|
|
|
|
|
|
// If there's no duplicate buddy like this already, then we'll create one. |
|
|
|
// To create a buddy, add an evaluator at the top of the list (behind us) and |
|
|
|
// set it's position as if it had been here all along and had matched the current |
|
|
|
// character. Next time we evaluate it will be just like all the others. |
|
|
|
|
|
|
|
myEvaluationMatrix-> |
|
|
|
AddEvaluator(StreamStartPosition,Matrix[xNonWhite].Vector+xNonWhite); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// WILD_WHITESPACE |
|
|
|
// If that didn't do it for us... |
|
|
|
// Try to match any whitespace character. |
|
|
|
|
|
|
|
if(i_isSpace() && Matrix[xWhiteSpace].Character()==WILD_WHITESPACE){ |
|
|
|
|
|
|
|
// If we've matched our path |
|
|
|
// with any whitespace then |
|
|
|
if(Condition==FALLEN_OFF) { // check: if no matches yet, |
|
|
|
Condition = DOING_OK; // upgrade to doing ok. |
|
|
|
CurrentPosition = xWhiteSpace + |
|
|
|
Matrix[xWhiteSpace].Vector; // Move myself along this path. |
|
|
|
} |
|
|
|
|
|
|
|
else { // Otherwise make a buddy... |
|
|
|
|
|
|
|
// If there's no duplicate buddy like this already, then we'll create one. |
|
|
|
// To create a buddy, add an evaluator at the top of the list (behind us) and |
|
|
|
// set it's position as if it had been here all along and had matched the current |
|
|
|
// character. Next time we evaluate it will be just like all the others. |
|
|
|
|
|
|
|
myEvaluationMatrix-> |
|
|
|
AddEvaluator(StreamStartPosition,Matrix[xWhiteSpace].Vector+xWhiteSpace); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// WILD_INLINE |
|
|
|
// If that didn't do it for us... |
|
|
|
// Try to match any character EXCEPT a new line. |
|
|
|
|
|
|
|
if(i != '\n' && Matrix[xAnyInline].Character()==WILD_INLINE){ |
|
|
|
|
|
|
|
// If we've matched our path |
|
|
|
// with any byte but \n then |
|
|
|
if(Condition==FALLEN_OFF) { // check: if no matches yet, |
|
|
|
Condition = DOING_OK; // upgrade to doing ok. |
|
|
|
CurrentPosition = xAnyInline + |
|
|
|
Matrix[xAnyInline].Vector; // Move myself along this path. |
|
|
|
} |
|
|
|
|
|
|
|
else { // Otherwise make a buddy... |
|
|
|
|
|
|
|
// If there's no duplicate buddy like this already, then we'll create one. |
|
|
|
// To create a buddy, add an evaluator at the top of the list (behind us) and |
|
|
|
// set it's position as if it had been here all along and had matched the current |
|
|
|
// character. Next time we evaluate it will be just like all the others. |
|
|
|
|
|
|
|
myEvaluationMatrix-> |
|
|
|
AddEvaluator(StreamStartPosition,Matrix[xAnyInline].Vector+xAnyInline); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// WILD_ANYTHING |
|
|
|
// If that didn't do it for us... |
|
|
|
// Try to match any character. |
|
|
|
|
|
|
|
if(Matrix[xAnything].Character()==WILD_ANYTHING){ |
|
|
|
|
|
|
|
// If we've matched our path |
|
|
|
// with any letter then |
|
|
|
if(Condition==FALLEN_OFF) { // check: if no matches yet, |
|
|
|
Condition = DOING_OK; // upgrade to doing ok. |
|
|
|
CurrentPosition = xAnything + |
|
|
|
Matrix[xAnything].Vector; // Move myself along this path. |
|
|
|
} |
|
|
|
|
|
|
|
else { // Otherwise make a buddy... |
|
|
|
|
|
|
|
// If there's no duplicate buddy like this already, then we'll create one. |
|
|
|
// To create a buddy, add an evaluator at the top of the list (behind us) and |
|
|
|
// set it's position as if it had been here all along and had matched the current |
|
|
|
// character. Next time we evaluate it will be just like all the others. |
|
|
|
|
|
|
|
myEvaluationMatrix-> |
|
|
|
AddEvaluator(StreamStartPosition,Matrix[xAnything].Vector+xAnything); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
// Evaluation order, most-to-least specific with what is possible for that byte. |
|
|
|
|
|
|
|
JumpPoint = CurrentPosition; |
|
|
|
doFollowerJumpTable(i); // Excite followers based on this byte.
|
|
|
|
|
|
|
|
{ // Precise matches reset the wild run counter.
|
|
|
|
++WildRunLength; // Count up the run length. |
|
|
|
if(WildRunLength >= MaxWildRunLength) // If we exceed the max then |
|
|
|
return Condition = FALLEN_OFF; // we've fallen off the path |
|
|
|
} // and we do it immediately.
|
|
|
|
|
|
|
|
// 20021112 _M |
|
|
|
// Beginning with version 2 of Message Sniffer we've implemented a new construct |
|
|
|
// for run-loops that prevents any interference between rules where run-loops might |
|
|
@@ -550,9 +521,9 @@ Evaluator::States Evaluator::EvaluateThis(unsigned short int i) { |
|
|
|
// could be behind the gateway - so we launch the buddy behind us and he will be able |
|
|
|
// to match anything in this pass that we missed when looking for a non-run match. |
|
|
|
|
|
|
|
if(Matrix[xRunGateway].Character() == RUN_GATEWAY) |
|
|
|
if(Matrix[xRunGateway()].Character() == RUN_GATEWAY) |
|
|
|
myEvaluationMatrix-> |
|
|
|
InsEvaluator(StreamStartPosition,Matrix[xRunGateway].Vector+xRunGateway); |
|
|
|
InsEvaluator(StreamStartPosition,Matrix[xRunGateway()].Vector+xRunGateway()); |
|
|
|
|
|
|
|
// At this point, we've tried all of our rules, and created any buddies we needed. |
|
|
|
// If we got a match, we terminated long ago. If we didn't, then we either stayed |
|
|
@@ -721,11 +692,12 @@ int EvaluationMatrix::EvaluateThis(unsigned short int i) { |
|
|
|
// Next do some basic conversions and evaluations so they don't need to be done |
|
|
|
// again within the evaluators. From now on the evaluators will look here for basic |
|
|
|
// conversions and boolean check values rather than performing the checks themselves. |
|
|
|
|
|
|
|
i_lower = tolower(i); // Convert i to lower case. |
|
|
|
i_isDigit = isdigit(i); // Check for a digit. |
|
|
|
i_isSpace = isspace(i); // Check for whitespace. |
|
|
|
i_isAlpha = isalpha(i); // Check for letters. |
|
|
|
|
|
|
|
// 20140119 _M deprecated by jump table in evaluator |
|
|
|
// i_lower = tolower(i); // Convert i to lower case. |
|
|
|
// i_isDigit = isdigit(i); // Check for a digit. |
|
|
|
// i_isSpace = isspace(i); // Check for whitespace. |
|
|
|
// i_isAlpha = isalpha(i); // Check for letters. |
|
|
|
|
|
|
|
// Next, loop through the list and pass the incoming character to |
|
|
|
// each evaluator. Drop those that fall off, and record those that terminate. The |