void ServerMethods::create (const Json::Value ¶ms, Json::Value &response) { std::string type; std::shared_ptr<Factory> factory; std::string sessionId; requireParams (params); JsonRpc::getValue (params, "type", type); try { JsonRpc::getValue (params, SESSION_ID, sessionId); } catch (JsonRpc::CallException e) { generateUUID (sessionId); } if (!objectRegistrar) { KurentoException e (MEDIA_OBJECT_TYPE_NOT_FOUND, "Class '" + type + "' does not exist"); throw e; } factory = objectRegistrar->getFactory (type); if (factory) { try { std::shared_ptr <MediaObjectImpl> object; object = std::dynamic_pointer_cast<MediaObjectImpl> ( factory->createObject (params["constructorParams"]) ); MediaSet::getMediaSet().ref (sessionId, object); try { object->getMediaPipeline(); } catch (...) { GST_ERROR ("Error getting pipeline"); } MediaSet::getMediaSet().ref (sessionId, object); response["value"] = object->getId(); response["sessionId"] = sessionId; } catch (KurentoException &ex) { Json::Value data; data["code"] = ex.getCode(); data["message"] = ex.getMessage(); JsonRpc::CallException e (JsonRpc::ErrorCode::SERVER_ERROR_INIT, ex.what(), data); throw e; } } else { JsonRpc::CallException e (JsonRpc::ErrorCode::SERVER_ERROR_INIT, "Class '" + type + "' does not exist"); // TODO: Define error data and code throw e; } }
void ServerMethods::unref (const Json::Value ¶ms, Json::Value &response) { std::shared_ptr<MediaObject> obj; std::string subscription; std::string objectId; std::string sessionId; requireParams (params); JsonRpc::getValue (params, OBJECT, objectId); JsonRpc::getValue (params, SESSION_ID, sessionId); try { MediaSet::getMediaSet().unref (sessionId, objectId); } catch (KurentoException &ex) { Json::Value data; data["code"] = ex.getCode(); data["message"] = ex.getMessage(); JsonRpc::CallException e (JsonRpc::ErrorCode::SERVER_ERROR_INIT, ex.what(), data); throw e; } }
void ServerMethods::describe (const Json::Value ¶ms, Json::Value &response) { std::shared_ptr<MediaObjectImpl> obj; std::string sessionId; std::string objectId; requireParams (params); getOrCreateSessionId (sessionId, params); JsonRpc::getValue (params, OBJECT, objectId); try { obj = MediaSet::getMediaSet()->getMediaObject (sessionId, objectId); } catch (KurentoException &ex) { Json::Value data; data[TYPE] = ex.getType(); throw JsonRpc::CallException (ex.getCode (), ex.getMessage (), data); } response[SESSION_ID] = sessionId; response[TYPE] = obj->getType (); }
void ServerMethods::describe (const Json::Value ¶ms, Json::Value &response) { std::shared_ptr<MediaObjectImpl> obj; std::string subscription; std::string sessionId; std::string objectId; requireParams (params); try { JsonRpc::getValue (params, SESSION_ID, sessionId); } catch (JsonRpc::CallException e) { generateUUID (sessionId); } JsonRpc::getValue (params, OBJECT, objectId); try { obj = MediaSet::getMediaSet().getMediaObject (sessionId, objectId); } catch (KurentoException &ex) { Json::Value data; data["code"] = ex.getCode(); data["message"] = ex.getMessage(); JsonRpc::CallException e (JsonRpc::ErrorCode::SERVER_ERROR_INIT, ex.what(), data); throw e; } response["sessionId"] = sessionId; response["type"] = obj->getType (); }
void ServerMethods::transaction (const Json::Value ¶ms, Json::Value &response) { std::string sessionId; Json::Value operations; std::string uniqueId = generateUUID(); requireParams (params); getOrCreateSessionId (sessionId, params); JsonRpc::getArray (params, "operations", operations); Json::Value responses; for (uint i = 0; i < operations.size(); i++) { bool ret; Json::Value &reqParams = operations[i][JSON_RPC_PARAMS]; reqParams[SESSION_ID] = sessionId; if (!operations[i][JSON_RPC_ID].isConvertibleTo (Json::ValueType::uintValue) || operations[i][JSON_RPC_ID].asUInt() != i) { Json::Value data; KurentoException ke (MALFORMED_TRANSACTION, "Id of request '" + std::to_string (i) + "' should be '" + std::to_string (i) + "'"); data[TYPE] = ke.getType(); throw JsonRpc::CallException (ke.getCode (), ke.getMessage (), data); } try { operations[i][JSON_RPC_ID] = uniqueId + "_" + std::to_string ( operations[i][JSON_RPC_ID].asUInt() ); } catch (...) { GST_ERROR ("Error setting id"); } injectRefs (reqParams, responses); ret = handler.process (operations[i], responses[i]); responses[i][JSON_RPC_ID] = i; if (!ret) { break; } } if (responses.isNull () ) { responses.resize (0); } response[VALUE] = responses; response[SESSION_ID] = sessionId; }
/** * Evaluates this Expr based on the given context node and processor state * @param context the context node for evaluation of this Expr * @param ps the ContextState containing the stack information needed * for evaluation * @return the result of the evaluation * @see FunctionCall.h **/ nsresult GenerateIdFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult) { *aResult = nullptr; if (!requireParams(0, 1, aContext)) return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT; txExecutionState* es = static_cast<txExecutionState*>(aContext->getPrivateContext()); if (!es) { NS_ERROR( "called xslt extension function \"generate-id\" with wrong context"); return NS_ERROR_UNEXPECTED; } nsresult rv = NS_OK; if (mParams.IsEmpty()) { StringResult* strRes; rv = aContext->recycler()->getStringResult(&strRes); NS_ENSURE_SUCCESS(rv, rv); txXPathNodeUtils::getXSLTId(aContext->getContextNode(), es->getSourceDocument(), strRes->mValue); *aResult = strRes; return NS_OK; } RefPtr<txNodeSet> nodes; rv = evaluateToNodeSet(mParams[0], aContext, getter_AddRefs(nodes)); NS_ENSURE_SUCCESS(rv, rv); if (nodes->isEmpty()) { aContext->recycler()->getEmptyStringResult(aResult); return NS_OK; } StringResult* strRes; rv = aContext->recycler()->getStringResult(&strRes); NS_ENSURE_SUCCESS(rv, rv); txXPathNodeUtils::getXSLTId(nodes->get(0), es->getSourceDocument(), strRes->mValue); *aResult = strRes; return NS_OK; }
void ServerMethods::invoke (const Json::Value ¶ms, Json::Value &response) { std::shared_ptr<MediaObject> obj; std::string sessionId; std::string operation; Json::Value operationParams; std::string objectId; requireParams (params); JsonRpc::getValue (params, "operation", operation); JsonRpc::getValue (params, OBJECT, objectId); try { JsonRpc::getValue (params, "operationParams", operationParams); } catch (JsonRpc::CallException e) { /* operationParams is optional at this point */ } try { JsonRpc::getValue (params, SESSION_ID, sessionId); } catch (JsonRpc::CallException e) { generateUUID (sessionId); } try { Json::Value value; obj = MediaSet::getMediaSet().getMediaObject (sessionId, objectId); if (!obj) { throw KurentoException (MEDIA_OBJECT_NOT_FOUND, "Object not found"); } obj->getInvoker().invoke (obj, operation, operationParams, value); response["value"] = value; response["sessionId"] = sessionId; } catch (KurentoException &ex) { Json::Value data; data["code"] = ex.getCode(); data["message"] = ex.getMessage(); JsonRpc::CallException e (JsonRpc::ErrorCode::SERVER_ERROR_INIT, ex.what(), data); throw e; } }
void ServerMethods::unsubscribe (const Json::Value ¶ms, Json::Value &response) { std::string subscription; std::string sessionId; std::string objectId; requireParams (params); JsonRpc::getValue (params, OBJECT, objectId); JsonRpc::getValue (params, SUBSCRIPTION, subscription); JsonRpc::getValue (params, SESSION_ID, sessionId); MediaSet::getMediaSet().removeEventHandler (sessionId, objectId, subscription); }
/* * Evaluates this Expr * * @return NodeSet containing the context node used for the complete * Expr or Pattern. */ nsresult CurrentFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult) { *aResult = nsnull; if (!requireParams(0, 0, aContext)) return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT; txExecutionState* es = static_cast<txExecutionState*>(aContext->getPrivateContext()); if (!es) { NS_ERROR( "called xslt extension function \"current\" with wrong context"); return NS_ERROR_UNEXPECTED; } return aContext->recycler()->getNodeSet( es->getEvalContext()->getContextNode(), aResult); }
/** * Evaluates this Expr based on the given context node and processor state * @param context the context node for evaluation of this Expr * @param ps the ContextState containing the stack information needed * for evaluation * @return the result of the evaluation * @see FunctionCall.h **/ nsresult GenerateIdFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult) { *aResult = nsnull; if (!requireParams(0, 1, aContext)) return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT; nsresult rv = NS_OK; if (mParams.IsEmpty()) { StringResult* strRes; rv = aContext->recycler()->getStringResult(&strRes); NS_ENSURE_SUCCESS(rv, rv); txXPathNodeUtils::getXSLTId(aContext->getContextNode(), strRes->mValue); *aResult = strRes; return NS_OK; } nsRefPtr<txNodeSet> nodes; rv = evaluateToNodeSet(mParams[0], aContext, getter_AddRefs(nodes)); NS_ENSURE_SUCCESS(rv, rv); if (nodes->isEmpty()) { aContext->recycler()->getEmptyStringResult(aResult); return NS_OK; } StringResult* strRes; rv = aContext->recycler()->getStringResult(&strRes); NS_ENSURE_SUCCESS(rv, rv); txXPathNodeUtils::getXSLTId(nodes->get(0), strRes->mValue); *aResult = strRes; return NS_OK; }
void ServerMethods::invoke (const Json::Value ¶ms, Json::Value &response) { std::shared_ptr<MediaObjectImpl> obj; std::string sessionId; std::string operation; Json::Value operationParams; std::string objectId; requireParams (params); JsonRpc::getValue (params, "operation", operation); JsonRpc::getValue (params, OBJECT, objectId); try { JsonRpc::getValue (params, "operationParams", operationParams); } catch (JsonRpc::CallException e) { /* operationParams is optional at this point */ } getOrCreateSessionId (sessionId, params); try { Json::Value value; obj = MediaSet::getMediaSet()->getMediaObject (sessionId, objectId); if (!obj) { throw KurentoException (MEDIA_OBJECT_NOT_FOUND, "Object not found"); } obj->invoke (obj, operation, operationParams, value); response[VALUE] = value; response[SESSION_ID] = sessionId; } catch (KurentoException &ex) { Json::Value data; data[TYPE] = ex.getType(); throw JsonRpc::CallException (ex.getCode (), ex.getMessage (), data); } }
void ServerMethods::subscribe (const Json::Value ¶ms, Json::Value &response) { std::shared_ptr<MediaObject> obj; std::string eventType; std::string handlerId; std::string sessionId; std::string objectId; requireParams (params); JsonRpc::getValue (params, "type", eventType); JsonRpc::getValue (params, OBJECT, objectId); try { JsonRpc::getValue (params, SESSION_ID, sessionId); } catch (JsonRpc::CallException e) { generateUUID (sessionId); } try { obj = MediaSet::getMediaSet().getMediaObject (sessionId, objectId); handlerId = connectEventHandler (obj, sessionId, eventType, params); if (handlerId == "") { throw KurentoException (MEDIA_OBJECT_EVENT_NOT_SUPPORTED, "Event not found"); } } catch (KurentoException &ex) { Json::Value data; data["code"] = ex.getCode(); data["message"] = ex.getMessage(); JsonRpc::CallException e (JsonRpc::ErrorCode::SERVER_ERROR_INIT, ex.what(), data); throw e; } response["sessionId"] = sessionId; response["value"] = handlerId; }
void ServerMethods::keepAlive (const Json::Value ¶ms, Json::Value &response) { std::string sessionId; requireParams (params); JsonRpc::getValue (params, SESSION_ID, sessionId); try { MediaSet::getMediaSet()->keepAliveSession (sessionId); } catch (KurentoException &ex) { Json::Value data; data[TYPE] = ex.getType(); throw JsonRpc::CallException (ex.getCode (), ex.getMessage (), data); } response[SESSION_ID] = sessionId; }
void ServerMethods::subscribe (const Json::Value ¶ms, Json::Value &response) { std::shared_ptr<MediaObjectImpl> obj; std::string eventType; std::string handlerId; std::string sessionId; std::string objectId; requireParams (params); JsonRpc::getValue (params, TYPE, eventType); JsonRpc::getValue (params, OBJECT, objectId); getOrCreateSessionId (sessionId, params); try { obj = MediaSet::getMediaSet()->getMediaObject (sessionId, objectId); try { handlerId = eventSubscriptionHandler (obj, sessionId, eventType, params); } catch (std::bad_function_call &e) { throw KurentoException (NOT_IMPLEMENTED, "Current transport does not support events"); } if (handlerId == "") { throw KurentoException (MEDIA_OBJECT_EVENT_NOT_SUPPORTED, "Event not found"); } } catch (KurentoException &ex) { Json::Value data; data[TYPE] = ex.getType(); throw JsonRpc::CallException (ex.getCode (), ex.getMessage (), data); } response[SESSION_ID] = sessionId; response[VALUE] = handlerId; }
void ServerMethods::create (const Json::Value ¶ms, Json::Value &response) { std::string type; std::shared_ptr<Factory> factory; std::string sessionId; requireParams (params); JsonRpc::getValue (params, TYPE, type); try { JsonRpc::getValue (params, SESSION_ID, sessionId); } catch (JsonRpc::CallException e) { sessionId = generateUUID (); } try { factory = moduleManager.getFactory (type); checkResources (resourceLimitPercent); std::shared_ptr <MediaObjectImpl> object; object = std::dynamic_pointer_cast<MediaObjectImpl> ( factory->createObject (config, sessionId, params["constructorParams"]) ); response[VALUE] = object->getId(); response[SESSION_ID] = sessionId; } catch (KurentoException &ex) { Json::Value data; data[TYPE] = ex.getType(); throw JsonRpc::CallException (ex.getCode (), ex.getMessage (), data); } }
/* * Evaluates this Expr based on the given context node and processor state * @param context the context node for evaluation of this Expr * @param cs the ContextState containing the stack information needed * for evaluation * @return the result of the evaluation */ nsresult txFormatNumberFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult) { *aResult = nullptr; if (!requireParams(2, 3, aContext)) return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT; // Get number and format double value; txExpandedName formatName; nsresult rv = evaluateToNumber(mParams[0], aContext, &value); NS_ENSURE_SUCCESS(rv, rv); nsAutoString formatStr; rv = mParams[1]->evaluateToString(aContext, formatStr); NS_ENSURE_SUCCESS(rv, rv); if (mParams.Length() == 3) { nsAutoString formatQName; rv = mParams[2]->evaluateToString(aContext, formatQName); NS_ENSURE_SUCCESS(rv, rv); rv = formatName.init(formatQName, mMappings, false); NS_ENSURE_SUCCESS(rv, rv); } txDecimalFormat* format = mStylesheet->getDecimalFormat(formatName); if (!format) { nsAutoString err(NS_LITERAL_STRING("unknown decimal format")); #ifdef TX_TO_STRING err.AppendLiteral(" for: "); toString(err); #endif aContext->receiveError(err, NS_ERROR_XPATH_INVALID_ARG); return NS_ERROR_XPATH_INVALID_ARG; } // Special cases if (mozilla::IsNaN(value)) { return aContext->recycler()->getStringResult(format->mNaN, aResult); } if (value == mozilla::PositiveInfinity<double>()) { return aContext->recycler()->getStringResult(format->mInfinity, aResult); } if (value == mozilla::NegativeInfinity<double>()) { nsAutoString res; res.Append(format->mMinusSign); res.Append(format->mInfinity); return aContext->recycler()->getStringResult(res, aResult); } // Value is a normal finite number nsAutoString prefix; nsAutoString suffix; int minIntegerSize=0; int minFractionSize=0; int maxFractionSize=0; int multiplier=1; int groupSize=-1; uint32_t pos = 0; uint32_t formatLen = formatStr.Length(); bool inQuote; // Get right subexpression inQuote = false; if (mozilla::IsNegative(value)) { while (pos < formatLen && (inQuote || formatStr.CharAt(pos) != format->mPatternSeparator)) { if (formatStr.CharAt(pos) == FORMAT_QUOTE) inQuote = !inQuote; pos++; } if (pos == formatLen) { pos = 0; prefix.Append(format->mMinusSign); } else pos++; } // Parse the format string FormatParseState pState = Prefix; inQuote = false; char16_t c = 0; while (pos < formatLen && pState != Finished) { c=formatStr.CharAt(pos++); switch (pState) { case Prefix: case Suffix: if (!inQuote) { if (c == format->mPercent) { if (multiplier == 1) multiplier = 100; else { nsAutoString err(INVALID_PARAM_VALUE); #ifdef TX_TO_STRING err.AppendLiteral(": "); toString(err); #endif aContext->receiveError(err, NS_ERROR_XPATH_INVALID_ARG); return NS_ERROR_XPATH_INVALID_ARG; } } else if (c == format->mPerMille) { if (multiplier == 1) multiplier = 1000; else { nsAutoString err(INVALID_PARAM_VALUE); #ifdef TX_TO_STRING err.AppendLiteral(": "); toString(err); #endif aContext->receiveError(err, NS_ERROR_XPATH_INVALID_ARG); return NS_ERROR_XPATH_INVALID_ARG; } } else if (c == format->mDecimalSeparator || c == format->mGroupingSeparator || c == format->mZeroDigit || c == format->mDigit || c == format->mPatternSeparator) { pState = pState == Prefix ? IntDigit : Finished; pos--; break; } } if (c == FORMAT_QUOTE) inQuote = !inQuote; else if (pState == Prefix) prefix.Append(c); else suffix.Append(c); break; case IntDigit: if (c == format->mGroupingSeparator) groupSize=0; else if (c == format->mDigit) { if (groupSize >= 0) groupSize++; } else { pState = IntZero; pos--; } break; case IntZero: if (c == format->mGroupingSeparator) groupSize = 0; else if (c == format->mZeroDigit) { if (groupSize >= 0) groupSize++; minIntegerSize++; } else if (c == format->mDecimalSeparator) { pState = FracZero; } else { pState = Suffix; pos--; } break; case FracZero: if (c == format->mZeroDigit) { maxFractionSize++; minFractionSize++; } else { pState = FracDigit; pos--; } break; case FracDigit: if (c == format->mDigit) maxFractionSize++; else { pState = Suffix; pos--; } break; case Finished: break; } } // Did we manage to parse the entire formatstring and was it valid if ((c != format->mPatternSeparator && pos < formatLen) || inQuote || groupSize == 0) { nsAutoString err(INVALID_PARAM_VALUE); #ifdef TX_TO_STRING err.AppendLiteral(": "); toString(err); #endif aContext->receiveError(err, NS_ERROR_XPATH_INVALID_ARG); return NS_ERROR_XPATH_INVALID_ARG; } /* * FINALLY we're done with the parsing * now build the result string */ value = fabs(value) * multiplier; // Prefix nsAutoString res(prefix); int bufsize; if (value > 1) bufsize = (int)log10(value) + 30; else bufsize = 1 + 30; char* buf = new char[bufsize]; NS_ENSURE_TRUE(buf, NS_ERROR_OUT_OF_MEMORY); int bufIntDigits, sign; char* endp; PR_dtoa(value, 0, 0, &bufIntDigits, &sign, &endp, buf, bufsize-1); int buflen = endp - buf; int intDigits; intDigits = bufIntDigits > minIntegerSize ? bufIntDigits : minIntegerSize; if (groupSize < 0) groupSize = intDigits + 10; //to simplify grouping // XXX We shouldn't use SetLength. res.SetLength(res.Length() + intDigits + // integer digits 1 + // decimal separator maxFractionSize + // fractions (intDigits-1)/groupSize); // group separators int32_t i = bufIntDigits + maxFractionSize - 1; bool carry = (0 <= i+1) && (i+1 < buflen) && (buf[i+1] >= '5'); bool hasFraction = false; uint32_t resPos = res.Length()-1; // Fractions for (; i >= bufIntDigits; --i) { int digit; if (i >= buflen || i < 0) { digit = 0; } else { digit = buf[i] - '0'; } if (carry) { digit = (digit + 1) % 10; carry = digit == 0; } if (hasFraction || digit != 0 || i < bufIntDigits+minFractionSize) { hasFraction = true; res.SetCharAt((char16_t)(digit + format->mZeroDigit), resPos--); } else { res.Truncate(resPos--); } } // Decimal separator if (hasFraction) { res.SetCharAt(format->mDecimalSeparator, resPos--); } else { res.Truncate(resPos--); } // Integer digits for (i = 0; i < intDigits; ++i) { int digit; if (bufIntDigits-i-1 >= buflen || bufIntDigits-i-1 < 0) { digit = 0; } else { digit = buf[bufIntDigits-i-1] - '0'; } if (carry) { digit = (digit + 1) % 10; carry = digit == 0; } if (i != 0 && i%groupSize == 0) { res.SetCharAt(format->mGroupingSeparator, resPos--); } res.SetCharAt((char16_t)(digit + format->mZeroDigit), resPos--); } if (carry) { if (i%groupSize == 0) { res.Insert(format->mGroupingSeparator, resPos + 1); } res.Insert((char16_t)(1 + format->mZeroDigit), resPos + 1); } if (!hasFraction && !intDigits && !carry) { // If we havn't added any characters we add a '0' // This can only happen for formats like '##.##' res.Append(format->mZeroDigit); } delete [] buf; // Build suffix res.Append(suffix); return aContext->recycler()->getStringResult(res, aResult); } //-- evaluate
/* * Evaluates this Expr based on the given context node and processor state * @param context the context node for evaluation of this Expr * @param ps the ContextState containing the stack information needed * for evaluation * @return the result of the evaluation */ nsresult txCoreFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult) { *aResult = nsnull; if (!requireParams(descriptTable[mType].mMinParams, descriptTable[mType].mMaxParams, aContext)) { return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT; } nsresult rv = NS_OK; switch (mType) { case COUNT: { nsRefPtr<txNodeSet> nodes; rv = evaluateToNodeSet(mParams[0], aContext, getter_AddRefs(nodes)); NS_ENSURE_SUCCESS(rv, rv); return aContext->recycler()->getNumberResult(nodes->size(), aResult); } case ID: { nsRefPtr<txAExprResult> exprResult; rv = mParams[0]->evaluate(aContext, getter_AddRefs(exprResult)); NS_ENSURE_SUCCESS(rv, rv); nsRefPtr<txNodeSet> resultSet; rv = aContext->recycler()->getNodeSet(getter_AddRefs(resultSet)); NS_ENSURE_SUCCESS(rv, rv); txXPathTreeWalker walker(aContext->getContextNode()); if (exprResult->getResultType() == txAExprResult::NODESET) { txNodeSet* nodes = static_cast<txNodeSet*> (static_cast<txAExprResult*> (exprResult)); PRInt32 i; for (i = 0; i < nodes->size(); ++i) { nsAutoString idList; txXPathNodeUtils::appendNodeValue(nodes->get(i), idList); nsWhitespaceTokenizer tokenizer(idList); while (tokenizer.hasMoreTokens()) { if (walker.moveToElementById(tokenizer.nextToken())) { resultSet->add(walker.getCurrentPosition()); } } } } else { nsAutoString idList; exprResult->stringValue(idList); nsWhitespaceTokenizer tokenizer(idList); while (tokenizer.hasMoreTokens()) { if (walker.moveToElementById(tokenizer.nextToken())) { resultSet->add(walker.getCurrentPosition()); } } } *aResult = resultSet; NS_ADDREF(*aResult); return NS_OK; } case LAST: { return aContext->recycler()->getNumberResult(aContext->size(), aResult); } case LOCAL_NAME: case NAME: case NAMESPACE_URI: { // Check for optional arg nsRefPtr<txNodeSet> nodes; if (!mParams.IsEmpty()) { rv = evaluateToNodeSet(mParams[0], aContext, getter_AddRefs(nodes)); NS_ENSURE_SUCCESS(rv, rv); if (nodes->isEmpty()) { aContext->recycler()->getEmptyStringResult(aResult); return NS_OK; } } const txXPathNode& node = nodes ? nodes->get(0) : aContext->getContextNode(); switch (mType) { case LOCAL_NAME: { StringResult* strRes = nsnull; rv = aContext->recycler()->getStringResult(&strRes); NS_ENSURE_SUCCESS(rv, rv); *aResult = strRes; txXPathNodeUtils::getLocalName(node, strRes->mValue); return NS_OK; } case NAMESPACE_URI: { StringResult* strRes = nsnull; rv = aContext->recycler()->getStringResult(&strRes); NS_ENSURE_SUCCESS(rv, rv); *aResult = strRes; txXPathNodeUtils::getNamespaceURI(node, strRes->mValue); return NS_OK; } case NAME: { // XXX Namespace: namespaces have a name if (txXPathNodeUtils::isAttribute(node) || txXPathNodeUtils::isElement(node) || txXPathNodeUtils::isProcessingInstruction(node)) { StringResult* strRes = nsnull; rv = aContext->recycler()->getStringResult(&strRes); NS_ENSURE_SUCCESS(rv, rv); *aResult = strRes; txXPathNodeUtils::getNodeName(node, strRes->mValue); } else { aContext->recycler()->getEmptyStringResult(aResult); } return NS_OK; } default: { break; } } } case POSITION: { return aContext->recycler()->getNumberResult(aContext->position(), aResult); } // String functions case CONCAT: { nsRefPtr<StringResult> strRes; rv = aContext->recycler()->getStringResult(getter_AddRefs(strRes)); NS_ENSURE_SUCCESS(rv, rv); PRUint32 i, len = mParams.Length(); for (i = 0; i < len; ++i) { rv = mParams[i]->evaluateToString(aContext, strRes->mValue); NS_ENSURE_SUCCESS(rv, rv); } NS_ADDREF(*aResult = strRes); return NS_OK; } case CONTAINS: { nsAutoString arg2; rv = mParams[1]->evaluateToString(aContext, arg2); NS_ENSURE_SUCCESS(rv, rv); if (arg2.IsEmpty()) { aContext->recycler()->getBoolResult(PR_TRUE, aResult); } else { nsAutoString arg1; rv = mParams[0]->evaluateToString(aContext, arg1); NS_ENSURE_SUCCESS(rv, rv); aContext->recycler()->getBoolResult(FindInReadable(arg2, arg1), aResult); } return NS_OK; } case NORMALIZE_SPACE: { nsAutoString resultStr; if (!mParams.IsEmpty()) { rv = mParams[0]->evaluateToString(aContext, resultStr); NS_ENSURE_SUCCESS(rv, rv); } else { txXPathNodeUtils::appendNodeValue(aContext->getContextNode(), resultStr); } nsRefPtr<StringResult> strRes; rv = aContext->recycler()->getStringResult(getter_AddRefs(strRes)); NS_ENSURE_SUCCESS(rv, rv); MBool addSpace = MB_FALSE; MBool first = MB_TRUE; strRes->mValue.SetCapacity(resultStr.Length()); PRUnichar c; PRUint32 src; for (src = 0; src < resultStr.Length(); src++) { c = resultStr.CharAt(src); if (XMLUtils::isWhitespace(c)) { addSpace = MB_TRUE; } else { if (addSpace && !first) strRes->mValue.Append(PRUnichar(' ')); strRes->mValue.Append(c); addSpace = MB_FALSE; first = MB_FALSE; } } *aResult = strRes; NS_ADDREF(*aResult); return NS_OK; } case STARTS_WITH: { nsAutoString arg2; rv = mParams[1]->evaluateToString(aContext, arg2); NS_ENSURE_SUCCESS(rv, rv); PRBool result = PR_FALSE; if (arg2.IsEmpty()) { result = PR_TRUE; } else { nsAutoString arg1; rv = mParams[0]->evaluateToString(aContext, arg1); NS_ENSURE_SUCCESS(rv, rv); result = StringBeginsWith(arg1, arg2); } aContext->recycler()->getBoolResult(result, aResult); return NS_OK; } case STRING: { nsRefPtr<StringResult> strRes; rv = aContext->recycler()->getStringResult(getter_AddRefs(strRes)); NS_ENSURE_SUCCESS(rv, rv); if (!mParams.IsEmpty()) { rv = mParams[0]->evaluateToString(aContext, strRes->mValue); NS_ENSURE_SUCCESS(rv, rv); } else { txXPathNodeUtils::appendNodeValue(aContext->getContextNode(), strRes->mValue); } NS_ADDREF(*aResult = strRes); return NS_OK; } case STRING_LENGTH: { nsAutoString resultStr; if (!mParams.IsEmpty()) { rv = mParams[0]->evaluateToString(aContext, resultStr); NS_ENSURE_SUCCESS(rv, rv); } else { txXPathNodeUtils::appendNodeValue(aContext->getContextNode(), resultStr); } rv = aContext->recycler()->getNumberResult(resultStr.Length(), aResult); NS_ENSURE_SUCCESS(rv, rv); return NS_OK; } case SUBSTRING: { nsAutoString src; rv = mParams[0]->evaluateToString(aContext, src); NS_ENSURE_SUCCESS(rv, rv); double start; rv = evaluateToNumber(mParams[1], aContext, &start); NS_ENSURE_SUCCESS(rv, rv); // check for NaN or +/-Inf if (Double::isNaN(start) || Double::isInfinite(start) || start >= src.Length() + 0.5) { aContext->recycler()->getEmptyStringResult(aResult); return NS_OK; } start = floor(start + 0.5) - 1; double end; if (mParams.Length() == 3) { rv = evaluateToNumber(mParams[2], aContext, &end); NS_ENSURE_SUCCESS(rv, rv); end += start; if (Double::isNaN(end) || end < 0) { aContext->recycler()->getEmptyStringResult(aResult); return NS_OK; } if (end > src.Length()) end = src.Length(); else end = floor(end + 0.5); } else { end = src.Length(); } if (start < 0) start = 0; if (start > end) { aContext->recycler()->getEmptyStringResult(aResult); return NS_OK; } return aContext->recycler()->getStringResult( Substring(src, (PRUint32)start, (PRUint32)(end - start)), aResult); } case SUBSTRING_AFTER: { nsAutoString arg1; rv = mParams[0]->evaluateToString(aContext, arg1); NS_ENSURE_SUCCESS(rv, rv); nsAutoString arg2; rv = mParams[1]->evaluateToString(aContext, arg2); NS_ENSURE_SUCCESS(rv, rv); if (arg2.IsEmpty()) { return aContext->recycler()->getStringResult(arg1, aResult); } PRInt32 idx = arg1.Find(arg2); if (idx == kNotFound) { aContext->recycler()->getEmptyStringResult(aResult); return NS_OK; } const nsSubstring& result = Substring(arg1, idx + arg2.Length()); return aContext->recycler()->getStringResult(result, aResult); } case SUBSTRING_BEFORE: { nsAutoString arg2; rv = mParams[1]->evaluateToString(aContext, arg2); NS_ENSURE_SUCCESS(rv, rv); if (arg2.IsEmpty()) { aContext->recycler()->getEmptyStringResult(aResult); return NS_OK; } nsAutoString arg1; rv = mParams[0]->evaluateToString(aContext, arg1); NS_ENSURE_SUCCESS(rv, rv); PRInt32 idx = arg1.Find(arg2); if (idx == kNotFound) { aContext->recycler()->getEmptyStringResult(aResult); return NS_OK; } return aContext->recycler()->getStringResult(StringHead(arg1, idx), aResult); } case TRANSLATE: { nsAutoString src; rv = mParams[0]->evaluateToString(aContext, src); NS_ENSURE_SUCCESS(rv, rv); if (src.IsEmpty()) { aContext->recycler()->getEmptyStringResult(aResult); return NS_OK; } nsRefPtr<StringResult> strRes; rv = aContext->recycler()->getStringResult(getter_AddRefs(strRes)); NS_ENSURE_SUCCESS(rv, rv); strRes->mValue.SetCapacity(src.Length()); nsAutoString oldChars, newChars; rv = mParams[1]->evaluateToString(aContext, oldChars); NS_ENSURE_SUCCESS(rv, rv); rv = mParams[2]->evaluateToString(aContext, newChars); NS_ENSURE_SUCCESS(rv, rv); PRUint32 i; PRInt32 newCharsLength = (PRInt32)newChars.Length(); for (i = 0; i < src.Length(); i++) { PRInt32 idx = oldChars.FindChar(src.CharAt(i)); if (idx != kNotFound) { if (idx < newCharsLength) strRes->mValue.Append(newChars.CharAt((PRUint32)idx)); } else { strRes->mValue.Append(src.CharAt(i)); } } NS_ADDREF(*aResult = strRes); return NS_OK; } // Number functions case NUMBER: { double res; if (!mParams.IsEmpty()) { rv = evaluateToNumber(mParams[0], aContext, &res); NS_ENSURE_SUCCESS(rv, rv); } else { nsAutoString resultStr; txXPathNodeUtils::appendNodeValue(aContext->getContextNode(), resultStr); res = Double::toDouble(resultStr); } return aContext->recycler()->getNumberResult(res, aResult); } case ROUND: { double dbl; rv = evaluateToNumber(mParams[0], aContext, &dbl); NS_ENSURE_SUCCESS(rv, rv); if (!Double::isNaN(dbl) && !Double::isInfinite(dbl)) { if (Double::isNeg(dbl) && dbl >= -0.5) { dbl *= 0; } else { dbl = floor(dbl + 0.5); } } return aContext->recycler()->getNumberResult(dbl, aResult); } case FLOOR: { double dbl; rv = evaluateToNumber(mParams[0], aContext, &dbl); NS_ENSURE_SUCCESS(rv, rv); if (!Double::isNaN(dbl) && !Double::isInfinite(dbl) && !(dbl == 0 && Double::isNeg(dbl))) { dbl = floor(dbl); } return aContext->recycler()->getNumberResult(dbl, aResult); } case CEILING: { double dbl; rv = evaluateToNumber(mParams[0], aContext, &dbl); NS_ENSURE_SUCCESS(rv, rv); if (!Double::isNaN(dbl) && !Double::isInfinite(dbl)) { if (Double::isNeg(dbl) && dbl > -1) { dbl *= 0; } else { dbl = ceil(dbl); } } return aContext->recycler()->getNumberResult(dbl, aResult); } case SUM: { nsRefPtr<txNodeSet> nodes; nsresult rv = evaluateToNodeSet(mParams[0], aContext, getter_AddRefs(nodes)); NS_ENSURE_SUCCESS(rv, rv); double res = 0; PRInt32 i; for (i = 0; i < nodes->size(); ++i) { nsAutoString resultStr; txXPathNodeUtils::appendNodeValue(nodes->get(i), resultStr); res += Double::toDouble(resultStr); } return aContext->recycler()->getNumberResult(res, aResult); } // Boolean functions case BOOLEAN: { PRBool result; nsresult rv = mParams[0]->evaluateToBool(aContext, result); NS_ENSURE_SUCCESS(rv, rv); aContext->recycler()->getBoolResult(result, aResult); return NS_OK; } case _FALSE: { aContext->recycler()->getBoolResult(PR_FALSE, aResult); return NS_OK; } case LANG: { txXPathTreeWalker walker(aContext->getContextNode()); nsAutoString lang; PRBool found; do { found = walker.getAttr(txXMLAtoms::lang, kNameSpaceID_XML, lang); } while (!found && walker.moveToParent()); if (!found) { aContext->recycler()->getBoolResult(PR_FALSE, aResult); return NS_OK; } nsAutoString arg; rv = mParams[0]->evaluateToString(aContext, arg); NS_ENSURE_SUCCESS(rv, rv); PRBool result = StringBeginsWith(lang, arg, txCaseInsensitiveStringComparator()) && (lang.Length() == arg.Length() || lang.CharAt(arg.Length()) == '-'); aContext->recycler()->getBoolResult(result, aResult); return NS_OK; } case _NOT: { PRBool result; rv = mParams[0]->evaluateToBool(aContext, result); NS_ENSURE_SUCCESS(rv, rv); aContext->recycler()->getBoolResult(!result, aResult); return NS_OK; } case _TRUE: { aContext->recycler()->getBoolResult(PR_TRUE, aResult); return NS_OK; } } aContext->receiveError(NS_LITERAL_STRING("Internal error"), NS_ERROR_UNEXPECTED); return NS_ERROR_UNEXPECTED; }
nsresult txXSLTEnvironmentFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult) { *aResult = nsnull; if (!requireParams(1, 1, aContext)) { return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT; } nsAutoString property; nsresult rv = mParams[0]->evaluateToString(aContext, property); NS_ENSURE_SUCCESS(rv, rv); txExpandedName qname; rv = qname.init(property, mMappings, mType != FUNCTION_AVAILABLE); NS_ENSURE_SUCCESS(rv, rv); switch (mType) { case SYSTEM_PROPERTY: { if (qname.mNamespaceID == kNameSpaceID_XSLT) { if (qname.mLocalName == nsGkAtoms::version) { return aContext->recycler()->getNumberResult(1.0, aResult); } if (qname.mLocalName == nsGkAtoms::vendor) { return aContext->recycler()->getStringResult( NS_LITERAL_STRING("Transformiix"), aResult); } if (qname.mLocalName == nsGkAtoms::vendorUrl) { return aContext->recycler()->getStringResult( NS_LITERAL_STRING("http://www.mozilla.org/projects/xslt/"), aResult); } } aContext->recycler()->getEmptyStringResult(aResult); break; } case ELEMENT_AVAILABLE: { bool val = qname.mNamespaceID == kNameSpaceID_XSLT && (qname.mLocalName == nsGkAtoms::applyImports || qname.mLocalName == nsGkAtoms::applyTemplates || qname.mLocalName == nsGkAtoms::attribute || qname.mLocalName == nsGkAtoms::attributeSet || qname.mLocalName == nsGkAtoms::callTemplate || qname.mLocalName == nsGkAtoms::choose || qname.mLocalName == nsGkAtoms::comment || qname.mLocalName == nsGkAtoms::copy || qname.mLocalName == nsGkAtoms::copyOf || qname.mLocalName == nsGkAtoms::decimalFormat || qname.mLocalName == nsGkAtoms::element || qname.mLocalName == nsGkAtoms::fallback || qname.mLocalName == nsGkAtoms::forEach || qname.mLocalName == nsGkAtoms::_if || qname.mLocalName == nsGkAtoms::import || qname.mLocalName == nsGkAtoms::include || qname.mLocalName == nsGkAtoms::key || qname.mLocalName == nsGkAtoms::message || //qname.mLocalName == nsGkAtoms::namespaceAlias || qname.mLocalName == nsGkAtoms::number || qname.mLocalName == nsGkAtoms::otherwise || qname.mLocalName == nsGkAtoms::output || qname.mLocalName == nsGkAtoms::param || qname.mLocalName == nsGkAtoms::preserveSpace || qname.mLocalName == nsGkAtoms::processingInstruction || qname.mLocalName == nsGkAtoms::sort || qname.mLocalName == nsGkAtoms::stripSpace || qname.mLocalName == nsGkAtoms::stylesheet || qname.mLocalName == nsGkAtoms::_template || qname.mLocalName == nsGkAtoms::text || qname.mLocalName == nsGkAtoms::transform || qname.mLocalName == nsGkAtoms::valueOf || qname.mLocalName == nsGkAtoms::variable || qname.mLocalName == nsGkAtoms::when || qname.mLocalName == nsGkAtoms::withParam); aContext->recycler()->getBoolResult(val, aResult); break; } case FUNCTION_AVAILABLE: { extern bool TX_XSLTFunctionAvailable(nsIAtom* aName, PRInt32 aNameSpaceID); txCoreFunctionCall::eType type; bool val = (qname.mNamespaceID == kNameSpaceID_None && txCoreFunctionCall::getTypeFromAtom(qname.mLocalName, type)) || TX_XSLTFunctionAvailable(qname.mLocalName, qname.mNamespaceID); aContext->recycler()->getBoolResult(val, aResult); break; } } return NS_OK; }
/* * Evaluates this Expr based on the given context node and processor state * NOTE: the implementation is incomplete since it does not make use of the * second argument (base URI) * @param context the context node for evaluation of this Expr * @return the result of the evaluation */ nsresult DocumentFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult) { *aResult = nsnull; txExecutionState* es = static_cast<txExecutionState*>(aContext->getPrivateContext()); nsRefPtr<txNodeSet> nodeSet; nsresult rv = aContext->recycler()->getNodeSet(getter_AddRefs(nodeSet)); NS_ENSURE_SUCCESS(rv, rv); // document(object, node-set?) if (!requireParams(1, 2, aContext)) { return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT; } nsRefPtr<txAExprResult> exprResult1; rv = mParams[0]->evaluate(aContext, getter_AddRefs(exprResult1)); NS_ENSURE_SUCCESS(rv, rv); nsAutoString baseURI; MBool baseURISet = MB_FALSE; if (mParams.Length() == 2) { // We have 2 arguments, get baseURI from the first node // in the resulting nodeset nsRefPtr<txNodeSet> nodeSet2; rv = evaluateToNodeSet(mParams[1], aContext, getter_AddRefs(nodeSet2)); NS_ENSURE_SUCCESS(rv, rv); // Make this true, even if nodeSet2 is empty. For relative URLs, // we'll fail to load the document with an empty base URI, and for // absolute URLs, the base URI doesn't matter baseURISet = MB_TRUE; if (!nodeSet2->isEmpty()) { txXPathNodeUtils::getBaseURI(nodeSet2->get(0), baseURI); } } if (exprResult1->getResultType() == txAExprResult::NODESET) { // The first argument is a NodeSet, iterate on its nodes txNodeSet* nodeSet1 = static_cast<txNodeSet*> (static_cast<txAExprResult*> (exprResult1)); PRInt32 i; for (i = 0; i < nodeSet1->size(); ++i) { const txXPathNode& node = nodeSet1->get(i); nsAutoString uriStr; txXPathNodeUtils::appendNodeValue(node, uriStr); if (!baseURISet) { // if the second argument wasn't specified, use // the baseUri of node itself txXPathNodeUtils::getBaseURI(node, baseURI); } retrieveNode(es, uriStr, baseURI, nodeSet); } NS_ADDREF(*aResult = nodeSet); return NS_OK; } // The first argument is not a NodeSet nsAutoString uriStr; exprResult1->stringValue(uriStr); const nsAString* base = baseURISet ? &baseURI : &mBaseURI; retrieveNode(es, uriStr, *base, nodeSet); NS_ADDREF(*aResult = nodeSet); return NS_OK; }
/** * Evaluates this Expr based on the given context node and processor state * @param context the context node for evaluation of this Expr * @param ps the ContextState containing the stack information needed * for evaluation * @return the result of the evaluation **/ nsresult BooleanFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult) { *aResult = nsnull; txListIterator iter(¶ms); switch (mType) { case TX_BOOLEAN: { if (!requireParams(1, 1, aContext)) return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT; aContext->recycler()->getBoolResult( evaluateToBoolean((Expr*)iter.next(), aContext), aResult); return NS_OK; } case TX_LANG: { if (!requireParams(1, 1, aContext)) return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT; txXPathTreeWalker walker(aContext->getContextNode()); nsAutoString lang; PRBool found; do { found = walker.getAttr(txXMLAtoms::lang, kNameSpaceID_XML, lang); } while (!found && walker.moveToParent()); if (!found) { aContext->recycler()->getBoolResult(PR_FALSE, aResult); return NS_OK; } nsAutoString arg; evaluateToString((Expr*)iter.next(), aContext, arg); PRBool result = arg.Equals(Substring(lang, 0, arg.Length()), txCaseInsensitiveStringComparator()) && (lang.Length() == arg.Length() || lang.CharAt(arg.Length()) == '-'); aContext->recycler()->getBoolResult(result, aResult); return NS_OK; } case TX_NOT: { if (!requireParams(1, 1, aContext)) return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT; aContext->recycler()->getBoolResult( !evaluateToBoolean((Expr*)iter.next(), aContext), aResult); return NS_OK; } case TX_TRUE: { if (!requireParams(0, 0, aContext)) return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT; aContext->recycler()->getBoolResult(PR_TRUE, aResult); return NS_OK; } case TX_FALSE: { if (!requireParams(0, 0, aContext)) return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT; aContext->recycler()->getBoolResult(PR_FALSE, aResult); return NS_OK; } } aContext->receiveError(NS_LITERAL_STRING("Internal error"), NS_ERROR_UNEXPECTED); return NS_ERROR_UNEXPECTED; }