int findAllVariants(String const &packageId, FS::FoundFiles &found) const { QStringList const components = packageId.split('.'); String id; // The package may actually be inside other packages, so we need to check // each component of the package identifier. for(int i = components.size() - 1; i >= 0; --i) { id = components.at(i) + (!id.isEmpty()? "." + id : ""); FS::FoundFiles files; App::fileSystem().findAllOfTypes(StringList() << DENG2_TYPE_NAME(Folder) << DENG2_TYPE_NAME(ArchiveFolder), id + ".pack", files); files.remove_if(PackageIdentifierDoesNotMatch(packageId)); std::copy(files.begin(), files.end(), std::back_inserter(found)); } return int(found.size()); }
Value *OperatorExpression::evaluate(Evaluator &evaluator) const { // Get the operands. Value *rightValue = (_op == MEMBER? 0 : evaluator.popResult()); Value *leftValue = (_leftOperand? evaluator.popResult() : 0); Value *result = (leftValue? leftValue : rightValue); try { switch(_op) { case PLUS: if(leftValue) { leftValue->sum(*rightValue); } else { // Unary plus is a no-op. } break; case PLUS_ASSIGN: verifyAssignable(leftValue); leftValue->sum(*rightValue); break; case MINUS: if(leftValue) { leftValue->subtract(*rightValue); } else { // Negation. rightValue->negate(); } break; case MINUS_ASSIGN: verifyAssignable(leftValue); leftValue->subtract(*rightValue); break; case DIVIDE: leftValue->divide(*rightValue); break; case DIVIDE_ASSIGN: verifyAssignable(leftValue); leftValue->divide(*rightValue); break; case MULTIPLY: leftValue->multiply(*rightValue); break; case MULTIPLY_ASSIGN: verifyAssignable(leftValue); leftValue->multiply(*rightValue); break; case MODULO: leftValue->modulo(*rightValue); break; case MODULO_ASSIGN: verifyAssignable(leftValue); leftValue->modulo(*rightValue); break; case NOT: result = newBooleanValue(rightValue->isFalse()); break; case AND: result = newBooleanValue(leftValue->isTrue() && rightValue->isTrue()); break; case OR: result = newBooleanValue(leftValue->isTrue() || rightValue->isTrue()); break; case EQUAL: result = newBooleanValue(!leftValue->compare(*rightValue)); break; case NOT_EQUAL: result = newBooleanValue(leftValue->compare(*rightValue) != 0); break; case LESS: result = newBooleanValue(leftValue->compare(*rightValue) < 0); break; case GREATER: result = newBooleanValue(leftValue->compare(*rightValue) > 0); break; case LEQUAL: result = newBooleanValue(leftValue->compare(*rightValue) <= 0); break; case GEQUAL: result = newBooleanValue(leftValue->compare(*rightValue) >= 0); break; case IN: result = newBooleanValue(rightValue->contains(*leftValue)); break; case CALL: leftValue->call(evaluator.process(), *rightValue); // Result comes from whatever is being called. result = 0; break; case INDEX: { /* LOG_DEV_TRACE("INDEX: types %s [ %s ] byref:%b", DENG2_TYPE_NAME(*leftValue) << DENG2_TYPE_NAME(*rightValue) << flags().testFlag(ByReference)); */ // As a special case, records can be indexed also by reference. RecordValue *recValue = dynamic_cast<RecordValue *>(leftValue); if(flags().testFlag(ByReference) && recValue) { result = new RefValue(&recValue->dereference()[rightValue->asText()]); } else { // Index by value. result = leftValue->duplicateElement(*rightValue); } break; } case SLICE: result = performSlice(leftValue, rightValue); break; case MEMBER: { RecordValue const *recValue = dynamic_cast<RecordValue const *>(leftValue); if(!recValue) { throw ScopeError("OperatorExpression::evaluate", "Left side of " + operatorToText(_op) + " must evaluate to a record [" + DENG2_TYPE_NAME(*leftValue) + "]"); } // Now that we know what the scope is, push the rest of the expression // for evaluation (in this specific scope). _rightOperand->push(evaluator, recValue->record()); // Cleanup. delete leftValue; DENG2_ASSERT(rightValue == NULL); // The MEMBER operator does not evaluate to any result. // Whatever is on the right side will be the result. return NULL; } default: throw Error("OperatorExpression::evaluate", "Operator " + operatorToText(_op) + " not implemented"); } } catch(Error const &) { delete rightValue; delete leftValue; throw; } // Delete the unnecessary values. if(result != rightValue) delete rightValue; if(result != leftValue) delete leftValue; return result; }