зеркало из https://github.com/mozilla/pjs.git
Bug 281987 - Finish out XPath extension functions. Patch by aaronr, r=sicking sr=tor a=mkaply
This commit is contained in:
Родитель
00f6b0b461
Коммит
7ec7a492ed
|
@ -1,532 +0,0 @@
|
||||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
||||||
/* ***** BEGIN LICENSE BLOCK *****
|
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the Mozilla Public License Version
|
|
||||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
||||||
* the License. You may obtain a copy of the License at
|
|
||||||
* http://www.mozilla.org/MPL/
|
|
||||||
*
|
|
||||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
||||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
||||||
* for the specific language governing rights and limitations under the
|
|
||||||
* License.
|
|
||||||
*
|
|
||||||
* The Original Code is Mozilla XForms support.
|
|
||||||
*
|
|
||||||
* The Initial Developer of the Original Code is
|
|
||||||
* IBM Corporation.
|
|
||||||
* Portions created by the Initial Developer are Copyright (C) 2004
|
|
||||||
* the Initial Developer. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* Aaron Reed <aaronr@us.ibm.com>
|
|
||||||
*
|
|
||||||
* Alternatively, the contents of this file may be used under the terms of
|
|
||||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
||||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
||||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
||||||
* of those above. If you wish to allow use of your version of this file only
|
|
||||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
||||||
* use your version of this file under the terms of the MPL, indicate your
|
|
||||||
* decision by deleting the provisions above and replace them with the notice
|
|
||||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
||||||
* the provisions above, a recipient may use your version of this file under
|
|
||||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
||||||
*
|
|
||||||
* ***** END LICENSE BLOCK ***** */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* XFormsFunctionCall
|
|
||||||
* A representation of the XPath NodeSet funtions
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "FunctionLib.h"
|
|
||||||
#include "nsAutoPtr.h"
|
|
||||||
#include "txNodeSet.h"
|
|
||||||
#include "txAtoms.h"
|
|
||||||
#include "txIXPathContext.h"
|
|
||||||
#include "txTokenizer.h"
|
|
||||||
#include "XFormsFunctions.h"
|
|
||||||
#include <math.h>
|
|
||||||
#include "nsIDOMDocument.h"
|
|
||||||
#include "nsIDOMDocumentEvent.h"
|
|
||||||
#include "nsIDOMEvent.h"
|
|
||||||
#include "nsIDOMEventTarget.h"
|
|
||||||
#include "nsIDOMElement.h"
|
|
||||||
#include "nsIXFormsUtilityService.h"
|
|
||||||
#include "nsServiceManagerUtils.h" // needed for do_GetService?
|
|
||||||
#include "prprf.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Creates a XFormsFunctionCall of the given type
|
|
||||||
*/
|
|
||||||
XFormsFunctionCall::XFormsFunctionCall(XFormsFunctions aType, nsIDOMNode *aResolverNode)
|
|
||||||
: mType(aType)
|
|
||||||
, mResolverNode(aResolverNode)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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
|
|
||||||
XFormsFunctionCall::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
|
|
||||||
{
|
|
||||||
*aResult = nsnull;
|
|
||||||
nsresult rv = NS_OK;
|
|
||||||
txListIterator iter(¶ms);
|
|
||||||
|
|
||||||
switch (mType) {
|
|
||||||
case AVG:
|
|
||||||
{
|
|
||||||
if (!requireParams(1, 1, aContext))
|
|
||||||
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
|
|
||||||
|
|
||||||
nsRefPtr<txNodeSet> nodes;
|
|
||||||
nsresult rv = evaluateToNodeSet((Expr*)iter.next(), 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i > 0) {
|
|
||||||
res = (res/i);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
res = Double::NaN;
|
|
||||||
}
|
|
||||||
return aContext->recycler()->getNumberResult(res, aResult);
|
|
||||||
}
|
|
||||||
case BOOLEANFROMSTRING:
|
|
||||||
{
|
|
||||||
if (!requireParams(1, 1, aContext))
|
|
||||||
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
|
|
||||||
|
|
||||||
PRInt32 retvalue = -1;
|
|
||||||
nsAutoString booleanValue;
|
|
||||||
evaluateToString((Expr*)iter.next(), aContext, booleanValue);
|
|
||||||
|
|
||||||
aContext->recycler()->getBoolResult(
|
|
||||||
booleanValue.EqualsLiteral("1") ||
|
|
||||||
booleanValue.LowerCaseEqualsLiteral("true"),
|
|
||||||
aResult);
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
case COUNTNONEMPTY:
|
|
||||||
{
|
|
||||||
if (!requireParams(1, 1, aContext))
|
|
||||||
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
|
|
||||||
|
|
||||||
nsRefPtr<txNodeSet> nodes;
|
|
||||||
nsresult rv = evaluateToNodeSet((Expr*)iter.next(), aContext,
|
|
||||||
getter_AddRefs(nodes));
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
double res = 0, test = 0;
|
|
||||||
PRInt32 i, count=0;
|
|
||||||
for (i = 0; i < nodes->size(); ++i) {
|
|
||||||
nsAutoString resultStr;
|
|
||||||
txXPathNodeUtils::appendNodeValue(nodes->get(i), resultStr);
|
|
||||||
if (!resultStr.IsEmpty()) {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return aContext->recycler()->getNumberResult(count, aResult);
|
|
||||||
}
|
|
||||||
case DAYSFROMDATE:
|
|
||||||
{
|
|
||||||
if (!requireParams(1, 1, aContext))
|
|
||||||
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
|
|
||||||
|
|
||||||
return NS_ERROR_NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
case IF:
|
|
||||||
{
|
|
||||||
if (!requireParams(3, 3, aContext))
|
|
||||||
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
|
|
||||||
|
|
||||||
PRBool test;
|
|
||||||
nsAutoString valueToReturn;
|
|
||||||
test = evaluateToBoolean((Expr*)iter.next(), aContext);
|
|
||||||
|
|
||||||
// grab 'true' value to return
|
|
||||||
Expr *getvalue = (Expr*)iter.next();
|
|
||||||
|
|
||||||
if (!test) {
|
|
||||||
// grab 'false' value to return
|
|
||||||
getvalue = (Expr*)iter.next();
|
|
||||||
}
|
|
||||||
evaluateToString(getvalue, aContext, valueToReturn);
|
|
||||||
|
|
||||||
return aContext->recycler()->getStringResult(valueToReturn, aResult);
|
|
||||||
}
|
|
||||||
case INDEX:
|
|
||||||
{
|
|
||||||
// Given an element's id as the parameter, need to query the element and
|
|
||||||
// make sure that it is a xforms:repeat node. Given that, must query
|
|
||||||
// its index.
|
|
||||||
if (!requireParams(1, 1, aContext))
|
|
||||||
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
|
|
||||||
|
|
||||||
nsAutoString indexId;
|
|
||||||
evaluateToString((Expr*)iter.next(), aContext, indexId);
|
|
||||||
|
|
||||||
// here document is the XForms document
|
|
||||||
nsCOMPtr<nsIDOMDocument> document;
|
|
||||||
rv = mResolverNode->GetOwnerDocument(getter_AddRefs(document));
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
NS_ENSURE_TRUE(document, NS_ERROR_NULL_POINTER);
|
|
||||||
|
|
||||||
// indexId should be the id of a nsIXFormsRepeatElement
|
|
||||||
nsCOMPtr<nsIDOMElement> repeatEle;
|
|
||||||
rv = document->GetElementById(indexId, getter_AddRefs(repeatEle));
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
// now get the index value from the xforms:repeat. Need to use the
|
|
||||||
// service to do this work so that we don't have dependencies in
|
|
||||||
// transformiix on XForms.
|
|
||||||
nsCOMPtr<nsIXFormsUtilityService>xformsService =
|
|
||||||
do_GetService("@mozilla.org/xforms-utility-service;1", &rv);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
PRUint32 index;
|
|
||||||
rv = xformsService->GetRepeatIndex(repeatEle, &index);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
return aContext->recycler()->getNumberResult(index, aResult);
|
|
||||||
|
|
||||||
}
|
|
||||||
case INSTANCE:
|
|
||||||
{
|
|
||||||
nsresult rv;
|
|
||||||
if (!requireParams(1, 1, aContext))
|
|
||||||
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
|
|
||||||
|
|
||||||
nsRefPtr<txNodeSet> resultSet;
|
|
||||||
rv = aContext->recycler()->getNodeSet(getter_AddRefs(resultSet));
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
nsAutoString instanceId;
|
|
||||||
evaluateToString((Expr*)iter.next(), aContext, instanceId);
|
|
||||||
|
|
||||||
// here document is the XForms document
|
|
||||||
nsCOMPtr<nsIDOMDocument> document;
|
|
||||||
rv = mResolverNode->GetOwnerDocument(getter_AddRefs(document));
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
NS_ENSURE_TRUE(document, NS_ERROR_NULL_POINTER);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMElement> instEle;
|
|
||||||
rv = document->GetElementById(instanceId, getter_AddRefs(instEle));
|
|
||||||
|
|
||||||
PRBool foundInstance = PR_FALSE;
|
|
||||||
nsAutoString localname, namespaceURI;
|
|
||||||
if (instEle) {
|
|
||||||
instEle->GetLocalName(localname);
|
|
||||||
instEle->GetNamespaceURI(namespaceURI);
|
|
||||||
if (localname.EqualsLiteral("instance") &&
|
|
||||||
namespaceURI.EqualsLiteral(NS_NAMESPACE_XFORMS)) {
|
|
||||||
foundInstance = PR_TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!foundInstance) {
|
|
||||||
// We didn't find an instance element with the given id. Return the
|
|
||||||
// empty result set.
|
|
||||||
*aResult = resultSet;
|
|
||||||
NS_ADDREF(*aResult);
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure that this element is contained in the same
|
|
||||||
// model as the context node of the expression as per
|
|
||||||
// the XForms 1.0 spec.
|
|
||||||
|
|
||||||
// first step is to get the contextNode passed in to
|
|
||||||
// the evaluation
|
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMNode> xfContextNode;
|
|
||||||
rv = txXPathNativeNode::getNode(aContext->getContextNode(),
|
|
||||||
getter_AddRefs(xfContextNode));
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
// now see if the node we found (instEle) and the
|
|
||||||
// context node for the evaluation (xfContextNode) link
|
|
||||||
// back to the same model.
|
|
||||||
nsCOMPtr<nsIXFormsUtilityService>xformsService =
|
|
||||||
do_GetService("@mozilla.org/xforms-utility-service;1", &rv);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMNode> instNode, modelInstance;
|
|
||||||
instNode = do_QueryInterface(instEle);
|
|
||||||
rv = xformsService->GetModelFromNode(instNode,
|
|
||||||
getter_AddRefs(modelInstance));
|
|
||||||
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
PRBool modelContainsNode = PR_FALSE;
|
|
||||||
rv = xformsService->IsNodeAssocWithModel(xfContextNode,
|
|
||||||
modelInstance,
|
|
||||||
&modelContainsNode);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
if (modelContainsNode) {
|
|
||||||
// ok, we've found an instance node with the proper id
|
|
||||||
// that fulfills the requirement of being from the
|
|
||||||
// same model as the context node. Now we need to
|
|
||||||
// return a 'node-set containing just the root
|
|
||||||
// element node of the referenced instance data'.
|
|
||||||
// Wonderful.
|
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMNode> instanceRoot;
|
|
||||||
rv = xformsService->GetInstanceDocumentRoot(
|
|
||||||
instanceId,
|
|
||||||
modelInstance,
|
|
||||||
getter_AddRefs(instanceRoot));
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
NS_ENSURE_TRUE(instanceRoot, NS_ERROR_NULL_POINTER);
|
|
||||||
|
|
||||||
nsAutoPtr<txXPathNode> txNode(txXPathNativeNode::createXPathNode(instanceRoot));
|
|
||||||
if (txNode) {
|
|
||||||
resultSet->add(*txNode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// XXX where we need to do the work
|
|
||||||
// if (walker.moveToElementById(instanceId)) {
|
|
||||||
// resultSet->add(walker.getCurrentPosition());
|
|
||||||
// }
|
|
||||||
|
|
||||||
*aResult = resultSet;
|
|
||||||
NS_ADDREF(*aResult);
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
case MAX:
|
|
||||||
{
|
|
||||||
if (!requireParams(1, 1, aContext))
|
|
||||||
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
|
|
||||||
|
|
||||||
nsRefPtr<txNodeSet> nodes;
|
|
||||||
nsresult rv = evaluateToNodeSet((Expr*)iter.next(), aContext,
|
|
||||||
getter_AddRefs(nodes));
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
double res = Double::NaN;
|
|
||||||
PRInt32 i;
|
|
||||||
for (i = 0; i < nodes->size(); ++i) {
|
|
||||||
double test;
|
|
||||||
nsAutoString resultStr;
|
|
||||||
txXPathNodeUtils::appendNodeValue(nodes->get(i), resultStr);
|
|
||||||
test = Double::toDouble(resultStr);
|
|
||||||
if (Double::isNaN(test)) {
|
|
||||||
res = Double::NaN;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (test > res || i == 0) {
|
|
||||||
res = test;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return aContext->recycler()->getNumberResult(res, aResult);
|
|
||||||
}
|
|
||||||
case MIN:
|
|
||||||
{
|
|
||||||
if (!requireParams(1, 1, aContext))
|
|
||||||
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
|
|
||||||
|
|
||||||
nsRefPtr<txNodeSet> nodes;
|
|
||||||
nsresult rv = evaluateToNodeSet((Expr*)iter.next(), aContext,
|
|
||||||
getter_AddRefs(nodes));
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
double res = Double::NaN;
|
|
||||||
PRInt32 i;
|
|
||||||
for (i = 0; i < nodes->size(); ++i) {
|
|
||||||
double test;
|
|
||||||
nsAutoString resultStr;
|
|
||||||
txXPathNodeUtils::appendNodeValue(nodes->get(i), resultStr);
|
|
||||||
test = Double::toDouble(resultStr);
|
|
||||||
if (Double::isNaN(test)) {
|
|
||||||
res = Double::NaN;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if ((test < res) || (i==0)) {
|
|
||||||
res = test;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return aContext->recycler()->getNumberResult(res, aResult);
|
|
||||||
}
|
|
||||||
case MONTHS:
|
|
||||||
{
|
|
||||||
if (!requireParams(1, 1, aContext))
|
|
||||||
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
|
|
||||||
|
|
||||||
return NS_ERROR_NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
case NOW:
|
|
||||||
{
|
|
||||||
if (!requireParams(0, 0, aContext))
|
|
||||||
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
|
|
||||||
|
|
||||||
PRExplodedTime time;
|
|
||||||
char ctime[60];
|
|
||||||
|
|
||||||
PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters, &time);
|
|
||||||
int gmtoffsethour = time.tm_params.tp_gmt_offset < 0 ?
|
|
||||||
-1*time.tm_params.tp_gmt_offset / 3600 :
|
|
||||||
time.tm_params.tp_gmt_offset / 3600;
|
|
||||||
int remainder = time.tm_params.tp_gmt_offset%3600;
|
|
||||||
int gmtoffsetminute = remainder ? remainder/60 : 00;
|
|
||||||
|
|
||||||
char zone_location[40];
|
|
||||||
const int zoneBufSize = sizeof(zone_location);
|
|
||||||
PR_snprintf(zone_location, zoneBufSize, "%c%02d:%02d\0",
|
|
||||||
time.tm_params.tp_gmt_offset < 0 ? '-' : '+',
|
|
||||||
gmtoffsethour, gmtoffsetminute);
|
|
||||||
|
|
||||||
PR_FormatTime(ctime, sizeof(ctime), "%Y-%m-%dT%H:%M:%S\0", &time);
|
|
||||||
nsString sTime = NS_ConvertASCIItoUTF16(ctime) + NS_ConvertASCIItoUTF16(zone_location);
|
|
||||||
|
|
||||||
return aContext->recycler()->getStringResult(sTime, aResult);
|
|
||||||
}
|
|
||||||
case PROPERTY:
|
|
||||||
{
|
|
||||||
if (!requireParams(1, 1, aContext))
|
|
||||||
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
|
|
||||||
|
|
||||||
nsAutoString property;
|
|
||||||
evaluateToString((Expr*)iter.next(), aContext, property);
|
|
||||||
|
|
||||||
// This function can handle "version" and "conformance-level"
|
|
||||||
// which is all that the XForms 1.0 spec is worried about
|
|
||||||
if (property.Equals(NS_LITERAL_STRING("version")))
|
|
||||||
property.Assign(NS_LITERAL_STRING("1.0"));
|
|
||||||
else if (property.Equals(NS_LITERAL_STRING("conformance-level")))
|
|
||||||
property.Assign(NS_LITERAL_STRING("basic"));
|
|
||||||
|
|
||||||
return aContext->recycler()->getStringResult(property, aResult);
|
|
||||||
}
|
|
||||||
case SECONDS:
|
|
||||||
{
|
|
||||||
double dbl=0;
|
|
||||||
if (!requireParams(1, 1, aContext))
|
|
||||||
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
|
|
||||||
|
|
||||||
return NS_ERROR_NOT_IMPLEMENTED;
|
|
||||||
|
|
||||||
}
|
|
||||||
case SECONDSFROMDATETIME:
|
|
||||||
{
|
|
||||||
if (!requireParams(1, 1, aContext))
|
|
||||||
return NS_ERROR_XPATH_BAD_ARGUMENT_COUNT;
|
|
||||||
|
|
||||||
return NS_ERROR_NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
} /* switch() */
|
|
||||||
|
|
||||||
aContext->receiveError(NS_LITERAL_STRING("Internal error"),
|
|
||||||
NS_ERROR_UNEXPECTED);
|
|
||||||
return NS_ERROR_UNEXPECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef TX_TO_STRING
|
|
||||||
nsresult
|
|
||||||
XFormsFunctionCall::getNameAtom(nsIAtom** aAtom)
|
|
||||||
{
|
|
||||||
switch (mType) {
|
|
||||||
case AVG:
|
|
||||||
{
|
|
||||||
*aAtom = txXPathAtoms::avg;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case BOOLEANFROMSTRING:
|
|
||||||
{
|
|
||||||
*aAtom = txXPathAtoms::booleanFromString;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case COUNTNONEMPTY:
|
|
||||||
{
|
|
||||||
*aAtom = txXPathAtoms::countNonEmpty;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case DAYSFROMDATE:
|
|
||||||
{
|
|
||||||
*aAtom = txXPathAtoms::daysFromDate;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case IF:
|
|
||||||
{
|
|
||||||
*aAtom = txXPathAtoms::ifFunc;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case INDEX:
|
|
||||||
{
|
|
||||||
*aAtom = txXPathAtoms::index;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case INSTANCE:
|
|
||||||
{
|
|
||||||
*aAtom = txXPathAtoms::instance;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MAX:
|
|
||||||
{
|
|
||||||
*aAtom = txXPathAtoms::max;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MIN:
|
|
||||||
{
|
|
||||||
*aAtom = txXPathAtoms::min;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MONTHS:
|
|
||||||
{
|
|
||||||
*aAtom = txXPathAtoms::months;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case NOW:
|
|
||||||
{
|
|
||||||
*aAtom = txXPathAtoms::now;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PROPERTY:
|
|
||||||
{
|
|
||||||
*aAtom = txXPathAtoms::property;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SECONDS:
|
|
||||||
{
|
|
||||||
*aAtom = txXPathAtoms::seconds;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SECONDSFROMDATETIME:
|
|
||||||
{
|
|
||||||
*aAtom = txXPathAtoms::secondsFromDateTime;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
*aAtom = 0;
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
NS_ADDREF(*aAtom);
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
#endif
|
|
|
@ -1,131 +0,0 @@
|
||||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
||||||
/* ***** BEGIN LICENSE BLOCK *****
|
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the Mozilla Public License Version
|
|
||||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
||||||
* the License. You may obtain a copy of the License at
|
|
||||||
* http://www.mozilla.org/MPL/
|
|
||||||
*
|
|
||||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
||||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
||||||
* for the specific language governing rights and limitations under the
|
|
||||||
* License.
|
|
||||||
*
|
|
||||||
* The Original Code is Mozilla XForms support.
|
|
||||||
*
|
|
||||||
* The Initial Developer of the Original Code is
|
|
||||||
* IBM Corporation.
|
|
||||||
* Portions created by the Initial Developer are Copyright (C) 2004
|
|
||||||
* the Initial Developer. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* Aaron Reed <aaronr@us.ibm.com>
|
|
||||||
*
|
|
||||||
* Alternatively, the contents of this file may be used under the terms of
|
|
||||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
||||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
||||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
||||||
* of those above. If you wish to allow use of your version of this file only
|
|
||||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
||||||
* use your version of this file under the terms of the MPL, indicate your
|
|
||||||
* decision by deleting the provisions above and replace them with the notice
|
|
||||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
||||||
* the provisions above, a recipient may use your version of this file under
|
|
||||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
||||||
*
|
|
||||||
* ***** END LICENSE BLOCK ***** */
|
|
||||||
|
|
||||||
#ifndef nsIXFormsUtilityService_h
|
|
||||||
#define nsIXFormsUtilityService_h
|
|
||||||
|
|
||||||
|
|
||||||
#include "nsISupports.h"
|
|
||||||
|
|
||||||
/* For IDL files that don't want to include root IDL files. */
|
|
||||||
#ifndef NS_NO_VTABLE
|
|
||||||
#define NS_NO_VTABLE
|
|
||||||
#endif
|
|
||||||
class nsIDOMNode; /* forward declaration */
|
|
||||||
|
|
||||||
class nsIXFormsModelElement; /* forward declaration */
|
|
||||||
|
|
||||||
|
|
||||||
/* starting interface: nsIXFormsUtilityService */
|
|
||||||
#define NS_IXFORMSUTILITYSERVICE_IID_STR "4a744a59-8771-4065-959d-b8de3dad81da"
|
|
||||||
|
|
||||||
#define NS_IXFORMSUTILITYSERVICE_IID \
|
|
||||||
{0x4a744a59, 0x8771, 0x4065, \
|
|
||||||
{ 0x95, 0x9d, 0xb8, 0xde, 0x3d, 0xad, 0x81, 0xda }}
|
|
||||||
|
|
||||||
#define NS_XFORMS_UTILITY_CONTRACTID "@mozilla.org/xforms-utility-service;1"
|
|
||||||
|
|
||||||
/* Use this macro when declaring classes that implement this interface. */
|
|
||||||
#define NS_DECL_NSIXFORMSUTILITYSERVICE \
|
|
||||||
NS_IMETHOD GetModelFromNode(nsIDOMNode *node, nsIDOMNode **_retval); \
|
|
||||||
NS_IMETHOD IsNodeAssocWithModel(nsIDOMNode *aNode, nsIDOMNode *aModel, PRBool *_retval); \
|
|
||||||
NS_IMETHOD GetInstanceDocumentRoot(const nsAString & aID, nsIDOMNode *aModelNode, nsIDOMNode **_retval); \
|
|
||||||
NS_IMETHOD ValidateString(const nsAString & aValue, const nsAString & aType, const nsAString & aNamespace, PRBool *_retval); \
|
|
||||||
NS_IMETHOD GetRepeatIndex(nsIDOMNode *aRepeat, PRUint32 *aIndex);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Private interface implemented by the nsXFormsUtilityService in XForms extension.
|
|
||||||
* Defining it here to prevent XPath requiring XForms extension.
|
|
||||||
*/
|
|
||||||
class NS_NO_VTABLE nsIXFormsUtilityService : public nsISupports {
|
|
||||||
public:
|
|
||||||
|
|
||||||
NS_DEFINE_STATIC_IID_ACCESSOR(NS_IXFORMSUTILITYSERVICE_IID)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function to get the corresponding model element from a xforms node or
|
|
||||||
* a xforms instance data node.
|
|
||||||
*/
|
|
||||||
/* nsIDOMNode getModelFromNode (in nsIDOMNode node); */
|
|
||||||
NS_IMETHOD GetModelFromNode(nsIDOMNode *node, nsIDOMNode **_retval) = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function to see if the given node is associated with the given model.
|
|
||||||
* Right now this function is only called by XPath in the case of the
|
|
||||||
* instance() function.
|
|
||||||
* The provided node can be an instance node from an instance
|
|
||||||
* document and thus be associated to the model in that way (model elements
|
|
||||||
* contain instance elements). Otherwise the node will be an XForms element
|
|
||||||
* that was used as the context node of the XPath expression (i.e the
|
|
||||||
* XForms control has an attribute that contains an XPath expression).
|
|
||||||
* Form controls are associated with model elements either explicitly through
|
|
||||||
* single-node binding or implicitly (if model cannot by calculated, it
|
|
||||||
* will use the first model element encountered in the document). The model
|
|
||||||
* can also be inherited from a containing element like xforms:group or
|
|
||||||
* xforms:repeat.
|
|
||||||
*/
|
|
||||||
/* PRBool isNodeAssocWithModel (in nsIDOMNode aNode, in nsIDOMNode aModel); */
|
|
||||||
NS_IMETHOD IsNodeAssocWithModel(nsIDOMNode *aNode, nsIDOMNode *aModel, PRBool *_retval) = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function to get the instance document root for the instance element with
|
|
||||||
* the given id. The instance element must be associated with the given
|
|
||||||
* model.
|
|
||||||
*/
|
|
||||||
/* nsIDOMNode getInstanceDocumentRoot (in DOMString aID, in nsIDOMNode aModelNode); */
|
|
||||||
NS_IMETHOD GetInstanceDocumentRoot(const nsAString & aID, nsIDOMNode *aModelNode, nsIDOMNode **_retval) = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function to ensure that aValue is of the schema type aType. Will basically
|
|
||||||
* be a forwarder to the nsISchemaValidator function of the same name.
|
|
||||||
*/
|
|
||||||
/* boolean validateString (in AString aValue, in AString aType, in AString aNamespace); */
|
|
||||||
NS_IMETHOD ValidateString(const nsAString & aValue, const nsAString & aType, const nsAString & aNamespace, PRBool *_retval) = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function to retrieve the index from the given repeat element.
|
|
||||||
*/
|
|
||||||
/* unsigned long getRepeatIndex (in nsIDOMNode aRepeat); */
|
|
||||||
NS_IMETHOD GetRepeatIndex(nsIDOMNode *aRepeat, PRUint32 *aIndex) = 0;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#define NS_ERROR_XFORMS_CALCUATION_EXCEPTION \
|
|
||||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_GENERAL, 3001)
|
|
||||||
|
|
||||||
#endif /* nsIXFormsUtilityService_h */
|
|
|
@ -36,6 +36,7 @@
|
||||||
*
|
*
|
||||||
* ***** END LICENSE BLOCK ***** */
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
#include "nsIServiceManager.h"
|
||||||
#include "nsXFormsUtilityService.h"
|
#include "nsXFormsUtilityService.h"
|
||||||
#include "nsXFormsUtils.h"
|
#include "nsXFormsUtils.h"
|
||||||
#include "nsIXTFElement.h"
|
#include "nsIXTFElement.h"
|
||||||
|
@ -47,12 +48,22 @@
|
||||||
#include "nsIDOMNodeList.h"
|
#include "nsIDOMNodeList.h"
|
||||||
#include "nsIInstanceElementPrivate.h"
|
#include "nsIInstanceElementPrivate.h"
|
||||||
#include "nsIXFormsRepeatElement.h"
|
#include "nsIXFormsRepeatElement.h"
|
||||||
|
#include "nsISchemaValidator.h"
|
||||||
|
#include "nsISchemaDuration.h"
|
||||||
|
#include "nsXFormsSchemaValidator.h"
|
||||||
|
#include "prdtoa.h"
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS1(nsXFormsUtilityService, nsIXFormsUtilityService)
|
NS_IMPL_ISUPPORTS1(nsXFormsUtilityService, nsIXFormsUtilityService)
|
||||||
|
|
||||||
|
/* I don't know why Doron didn't put this in the .idl so that it could be added
|
||||||
|
* to the generated .h file. Put it here for now
|
||||||
|
*/
|
||||||
|
#define NS_SCHEMAVALIDATOR_CONTRACTID "@mozilla.org/schemavalidator;1"
|
||||||
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsXFormsUtilityService::GetModelFromNode(nsIDOMNode *aNode,
|
nsXFormsUtilityService::GetModelFromNode(nsIDOMNode *aNode,
|
||||||
nsIDOMNode **aModel)
|
nsIDOMNode **aModel)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(aNode);
|
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(aNode);
|
||||||
NS_ASSERTION(aModel, "no return buffer, we'll crash soon");
|
NS_ASSERTION(aModel, "no return buffer, we'll crash soon");
|
||||||
|
@ -163,8 +174,8 @@ nsXFormsUtilityService::IsNodeAssocWithModel( nsIDOMNode *aNode,
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsXFormsUtilityService::GetInstanceDocumentRoot(const nsAString& aID,
|
nsXFormsUtilityService::GetInstanceDocumentRoot(const nsAString& aID,
|
||||||
nsIDOMNode *aModelNode,
|
nsIDOMNode *aModelNode,
|
||||||
nsIDOMNode **aInstanceRoot)
|
nsIDOMNode **aInstanceRoot)
|
||||||
{
|
{
|
||||||
nsresult rv = NS_ERROR_FAILURE;
|
nsresult rv = NS_ERROR_FAILURE;
|
||||||
NS_ASSERTION(aInstanceRoot, "no return buffer, we'll crash soon");
|
NS_ASSERTION(aInstanceRoot, "no return buffer, we'll crash soon");
|
||||||
|
@ -195,22 +206,20 @@ nsXFormsUtilityService::GetInstanceDocumentRoot(const nsAString& aID,
|
||||||
*/
|
*/
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsXFormsUtilityService::ValidateString(const nsAString & aValue,
|
nsXFormsUtilityService::ValidateString(const nsAString & aValue,
|
||||||
const nsAString & aType,
|
const nsAString & aType,
|
||||||
const nsAString & aNamespace,
|
const nsAString & aNamespace,
|
||||||
PRBool *aResult)
|
PRBool *aResult)
|
||||||
{
|
{
|
||||||
|
|
||||||
// XXX TODO This function needs to call the XForms validator layer from
|
NS_ASSERTION(aResult, "no return buffer for result so we'll crash soon");
|
||||||
// bug 274083 when it goes into the build.
|
*aResult = PR_FALSE;
|
||||||
|
|
||||||
#if 0
|
|
||||||
nsresult rv = NS_ERROR_FAILURE;
|
|
||||||
nsXFormsSchemaValidator *validator = new nsXFormsSchemaValidator();
|
nsXFormsSchemaValidator *validator = new nsXFormsSchemaValidator();
|
||||||
*aResult = validator->ValidateString(aValue, aType, aNamespace);
|
if (validator) {
|
||||||
return rv;
|
*aResult = validator->ValidateString(aValue, aType, aNamespace);
|
||||||
#endif
|
delete validator;
|
||||||
|
}
|
||||||
return NS_ERROR_NOT_IMPLEMENTED;
|
return *aResult ? NS_OK : NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
|
@ -225,3 +234,210 @@ nsXFormsUtilityService::GetRepeatIndex(nsIDOMNode *aRepeat, PRUint32 *aIndex)
|
||||||
/// @bug This should somehow end up in a NaN per the XForms 1.0 Errata (XXX)
|
/// @bug This should somehow end up in a NaN per the XForms 1.0 Errata (XXX)
|
||||||
return repeatEle ? repeatEle->GetIndex(aIndex) : NS_OK;
|
return repeatEle ? repeatEle->GetIndex(aIndex) : NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsXFormsUtilityService::GetMonths(const nsAString & aValue,
|
||||||
|
PRInt32 * aMonths)
|
||||||
|
{
|
||||||
|
NS_ASSERTION(aMonths, "no return buffer for months, we'll crash soon");
|
||||||
|
|
||||||
|
*aMonths = 0;
|
||||||
|
nsCOMPtr<nsISchemaDuration> duration;
|
||||||
|
nsCOMPtr<nsISchemaValidator> schemaValidator =
|
||||||
|
do_GetService(NS_SCHEMAVALIDATOR_CONTRACTID);
|
||||||
|
NS_ENSURE_TRUE(schemaValidator, NS_ERROR_FAILURE);
|
||||||
|
|
||||||
|
nsresult rv = schemaValidator->ValidateBuiltinTypeDuration(aValue,
|
||||||
|
getter_AddRefs(duration));
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
PRInt32 sumMonths;
|
||||||
|
PRUint32 years;
|
||||||
|
PRUint32 months;
|
||||||
|
|
||||||
|
duration->GetYears(&years);
|
||||||
|
duration->GetMonths(&months);
|
||||||
|
|
||||||
|
sumMonths = months + years*12;
|
||||||
|
PRBool negative;
|
||||||
|
duration->GetNegative(&negative);
|
||||||
|
if (negative) {
|
||||||
|
// according to the spec, "the sign of the result will match the sign
|
||||||
|
// of the duration"
|
||||||
|
sumMonths *= -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*aMonths = sumMonths;
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsXFormsUtilityService::GetSeconds(const nsAString & aValue,
|
||||||
|
double * aSeconds)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsISchemaDuration> duration;
|
||||||
|
nsCOMPtr<nsISchemaValidator> schemaValidator =
|
||||||
|
do_GetService(NS_SCHEMAVALIDATOR_CONTRACTID);
|
||||||
|
NS_ENSURE_TRUE(schemaValidator, NS_ERROR_FAILURE);
|
||||||
|
|
||||||
|
nsresult rv = schemaValidator->ValidateBuiltinTypeDuration(aValue,
|
||||||
|
getter_AddRefs(duration));
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
double sumSeconds;
|
||||||
|
PRUint32 days;
|
||||||
|
PRUint32 hours;
|
||||||
|
PRUint32 minutes;
|
||||||
|
PRUint32 seconds;
|
||||||
|
double fractSecs;
|
||||||
|
|
||||||
|
duration->GetDays(&days);
|
||||||
|
duration->GetHours(&hours);
|
||||||
|
duration->GetMinutes(&minutes);
|
||||||
|
duration->GetSeconds(&seconds);
|
||||||
|
duration->GetFractionSeconds(&fractSecs);
|
||||||
|
|
||||||
|
sumSeconds = seconds + minutes*60 + hours*3600 + days*24*3600 + fractSecs;
|
||||||
|
|
||||||
|
PRBool negative;
|
||||||
|
duration->GetNegative(&negative);
|
||||||
|
if (negative) {
|
||||||
|
// according to the spec, "the sign of the result will match the sign
|
||||||
|
// of the duration"
|
||||||
|
sumSeconds *= -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*aSeconds = sumSeconds;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsXFormsUtilityService::GetSecondsFromDateTime(const nsAString & aValue,
|
||||||
|
double * aSeconds)
|
||||||
|
{
|
||||||
|
PRTime dateTime;
|
||||||
|
nsCOMPtr<nsISchemaValidator> schemaValidator =
|
||||||
|
do_GetService(NS_SCHEMAVALIDATOR_CONTRACTID);
|
||||||
|
NS_ENSURE_TRUE(schemaValidator, NS_ERROR_FAILURE);
|
||||||
|
|
||||||
|
nsresult rv = schemaValidator->ValidateBuiltinTypeDateTime(aValue, &dateTime);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
PRTime secs64 = dateTime, remain64;
|
||||||
|
PRInt64 usecPerSec;
|
||||||
|
PRInt32 secs32, remain32;
|
||||||
|
|
||||||
|
// convert from PRTime (microseconds from epoch) to seconds.
|
||||||
|
LL_I2L(usecPerSec, PR_USEC_PER_SEC);
|
||||||
|
LL_MOD(remain64, secs64, usecPerSec); /* remainder after conversion */
|
||||||
|
LL_DIV(secs64, secs64, usecPerSec); /* Conversion in whole seconds */
|
||||||
|
|
||||||
|
// convert whole seconds and remainder to PRInt32
|
||||||
|
LL_L2I(secs32, secs64);
|
||||||
|
LL_L2I(remain32, remain64);
|
||||||
|
|
||||||
|
// ready the result to send back to transformiix land now in case there are
|
||||||
|
// no fractional seconds or we end up having a problem parsing them out. If
|
||||||
|
// we do, we'll just ignore the fractional seconds.
|
||||||
|
double totalSeconds = secs32;
|
||||||
|
*aSeconds = totalSeconds;
|
||||||
|
|
||||||
|
// We're not getting fractional seconds back in the PRTime we get from
|
||||||
|
// the schemaValidator. We'll have to figure out the fractions from
|
||||||
|
// the original value. Since ValidateBuiltinTypeDateTime returned
|
||||||
|
// successful for us to get this far, we know that the value is in
|
||||||
|
// the proper format.
|
||||||
|
int findFractionalSeconds = aValue.FindChar('.');
|
||||||
|
if (findFractionalSeconds < 0) {
|
||||||
|
// no fractions of seconds, so we are good to go as we are
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nsAString& fraction = Substring(aValue, findFractionalSeconds+1,
|
||||||
|
aValue.Length());
|
||||||
|
|
||||||
|
PRBool done = PR_FALSE;
|
||||||
|
PRUnichar currentChar;
|
||||||
|
nsCAutoString fractionResult;
|
||||||
|
nsAString::const_iterator start, end, buffStart;
|
||||||
|
fraction.BeginReading(start);
|
||||||
|
fraction.BeginReading(buffStart);
|
||||||
|
fraction.EndReading(end);
|
||||||
|
|
||||||
|
while ((start != end) && !done) {
|
||||||
|
currentChar = *start++;
|
||||||
|
|
||||||
|
// Time is usually terminated with Z or followed by a time zone
|
||||||
|
// (i.e. -05:00). Time can also be terminated by the end of the string, so
|
||||||
|
// test for that as well. All of this specified at:
|
||||||
|
// http://www.w3.org/TR/xmlschema-2/#dateTime
|
||||||
|
if ((currentChar == 'Z') || (currentChar == '+') || (currentChar == '-') ||
|
||||||
|
(start == end)) {
|
||||||
|
fractionResult.AssignLiteral("0.");
|
||||||
|
AppendUTF16toUTF8(Substring(buffStart.get(), start.get()-1),
|
||||||
|
fractionResult);
|
||||||
|
} else if ((currentChar > '9') || (currentChar < '0')) {
|
||||||
|
// has to be a numerical character or else abort. This should have been
|
||||||
|
// caught by the schemavalidator, but it is worth double checking.
|
||||||
|
done = PR_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fractionResult.IsEmpty()) {
|
||||||
|
// couldn't successfully parse the fractional seconds, so we'll just return
|
||||||
|
// without them.
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert the result string that we have to a double and add it to the total
|
||||||
|
totalSeconds += PR_strtod(fractionResult.get(), nsnull);
|
||||||
|
*aSeconds = totalSeconds;
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsXFormsUtilityService::GetDaysFromDateTime(const nsAString & aValue,
|
||||||
|
PRInt32 * aDays)
|
||||||
|
{
|
||||||
|
NS_ASSERTION(aDays, "no return buffer for days, we'll crash soon");
|
||||||
|
*aDays = 0;
|
||||||
|
|
||||||
|
PRTime date;
|
||||||
|
nsCOMPtr<nsISchemaValidator> schemaValidator =
|
||||||
|
do_GetService(NS_SCHEMAVALIDATOR_CONTRACTID);
|
||||||
|
NS_ENSURE_TRUE(schemaValidator, NS_ERROR_FAILURE);
|
||||||
|
|
||||||
|
// aValue could be a xsd:date or a xsd:dateTime. If it is a dateTime, we
|
||||||
|
// should ignore the hours, minutes, and seconds according to 7.10.2 in
|
||||||
|
// the spec. So search for such things now. If they are there, strip 'em.
|
||||||
|
int findTime = aValue.FindChar('T');
|
||||||
|
|
||||||
|
nsAutoString dateString;
|
||||||
|
dateString.Assign(aValue);
|
||||||
|
if (findTime >= 0) {
|
||||||
|
dateString.Assign(Substring(dateString, 0, findTime));
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult rv = schemaValidator->ValidateBuiltinTypeDate(dateString, &date);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
PRTime secs64 = date;
|
||||||
|
PRInt64 usecPerSec;
|
||||||
|
PRInt32 secs32;
|
||||||
|
|
||||||
|
// convert from PRTime (microseconds from epoch) to seconds. Shouldn't
|
||||||
|
// have to worry about remainders since input is a date. Smallest value
|
||||||
|
// is in whole days.
|
||||||
|
LL_I2L(usecPerSec, PR_USEC_PER_SEC);
|
||||||
|
LL_DIV(secs64, secs64, usecPerSec);
|
||||||
|
|
||||||
|
// convert whole seconds to PRInt32
|
||||||
|
LL_L2I(secs32, secs64);
|
||||||
|
|
||||||
|
// convert whole seconds to days. 86400 seconds in a day.
|
||||||
|
*aDays = secs32/86400;
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче