/** * Called for the root of the list! */ bool GemTestCommand::operator == (GemTestCommand &other) { if (count() != other.count()) return false; for (GemTestCommand *mine = next(), *yours = other.next(); !mine->isRoot(); mine = mine->next(), yours = yours->next()) { if (mine->_id != yours->_id) return false; if (mine->_arg != yours->_arg) return false; if (mine->_negate != yours->_negate) return false; if (mine->_text != yours->_text) return false; } return true; }
bool GemTest::test(Gem *gem) { Gem *test = gem; // The test pointer. Gem *tryStart; bool result, trying = false, passed; int i; for(GemTestCommand *cmd = _commands.next(); !cmd->isRoot(); cmd = cmd->next()) { // We can skip commands if trying is passed. if(trying && ((passed && cmd->id() != CheckIfPassed) || (!test && cmd->id() != CheckIfPassed && cmd->id() != GoSelf))) continue; result = true; switch(cmd->id()) { case GoSelf: test = gem; break; case GoParent: for(i = 0; test && i < cmd->intArg(); i++) test = test->parentGem(); break; case GoNext: for(i = 0; test && i < cmd->intArg(); i++) test = test->nextGem(); break; case GoPrev: for(i = 0; test && i < cmd->intArg(); i++) test = test->prevGem(); break; case GoFirst: for(i = 0; test && i < cmd->intArg(); i++) test = test->firstGem(); break; case GoLast: for(i = 0; test && i < cmd->intArg(); i++) test = test->lastGem(); break; case GoFollowing: for(i = 0; test && i < cmd->intArg(); i++) test = test->followingGem(); break; case GoPreceding: for(i = 0; test && i < cmd->intArg(); i++) test = test->precedingGem(); break; case GoFinal: test = gem->finalGem(); break; case BeginTry: trying = true; passed = false; tryStart = test; break; case CheckIfPassed: trying = false; result = passed; test = tryStart; // Return to where the test began. break; default: // Are we escalating this check? if(cmd->escalating()) { result = false; for(Gem* it = test->parentGem(); it; it = it->parentGem()) { if(cmd->execute(gem, it)) { result = true; break; } } } else { result = cmd->execute(gem, test); } break; } // You can't fail the BeginTry command. if(cmd->id() == BeginTry) continue; // A null test pointer is an automatic failure. if(!test) { if(!trying) return false; result = false; } // Did it fail? if(trying) { if(result != cmd->negated()) passed = true; // Passed! } else { if(result == cmd->negated()) return false; // Failed! } } if(trying) { qCritical("A 'try..pass' is missing 'pass'."); exit(1); } // All commands were successful. return true; }