mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-24 01:17:34 +09:00
import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo
This commit is contained in:
commit
dcd9973243
150858 changed files with 23884658 additions and 0 deletions
422
dom/xul/templates/nsTemplateRule.cpp
Normal file
422
dom/xul/templates/nsTemplateRule.cpp
Normal file
|
|
@ -0,0 +1,422 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsTemplateRule.h"
|
||||
#include "nsTemplateMatch.h"
|
||||
#include "nsXULContentUtils.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsICollation.h"
|
||||
|
||||
nsTemplateCondition::nsTemplateCondition(nsIAtom* aSourceVariable,
|
||||
const nsAString& aRelation,
|
||||
nsIAtom* aTargetVariable,
|
||||
bool aIgnoreCase,
|
||||
bool aNegate)
|
||||
: mSourceVariable(aSourceVariable),
|
||||
mTargetVariable(aTargetVariable),
|
||||
mIgnoreCase(aIgnoreCase),
|
||||
mNegate(aNegate),
|
||||
mNext(nullptr)
|
||||
{
|
||||
SetRelation(aRelation);
|
||||
|
||||
MOZ_COUNT_CTOR(nsTemplateCondition);
|
||||
}
|
||||
|
||||
nsTemplateCondition::nsTemplateCondition(nsIAtom* aSourceVariable,
|
||||
const nsAString& aRelation,
|
||||
const nsAString& aTargets,
|
||||
bool aIgnoreCase,
|
||||
bool aNegate,
|
||||
bool aIsMultiple)
|
||||
: mSourceVariable(aSourceVariable),
|
||||
mIgnoreCase(aIgnoreCase),
|
||||
mNegate(aNegate),
|
||||
mNext(nullptr)
|
||||
{
|
||||
SetRelation(aRelation);
|
||||
|
||||
if (aIsMultiple) {
|
||||
int32_t start = 0, end = 0;
|
||||
while ((end = aTargets.FindChar(',',start)) >= 0) {
|
||||
if (end > start) {
|
||||
mTargetList.AppendElement(Substring(aTargets, start, end - start));
|
||||
}
|
||||
start = end + 1;
|
||||
}
|
||||
if (start < int32_t(aTargets.Length())) {
|
||||
mTargetList.AppendElement(Substring(aTargets, start));
|
||||
}
|
||||
}
|
||||
else {
|
||||
mTargetList.AppendElement(aTargets);
|
||||
}
|
||||
|
||||
MOZ_COUNT_CTOR(nsTemplateCondition);
|
||||
}
|
||||
|
||||
nsTemplateCondition::nsTemplateCondition(const nsAString& aSource,
|
||||
const nsAString& aRelation,
|
||||
nsIAtom* aTargetVariable,
|
||||
bool aIgnoreCase,
|
||||
bool aNegate)
|
||||
: mSource(aSource),
|
||||
mTargetVariable(aTargetVariable),
|
||||
mIgnoreCase(aIgnoreCase),
|
||||
mNegate(aNegate),
|
||||
mNext(nullptr)
|
||||
{
|
||||
SetRelation(aRelation);
|
||||
|
||||
MOZ_COUNT_CTOR(nsTemplateCondition);
|
||||
}
|
||||
|
||||
void
|
||||
nsTemplateCondition::SetRelation(const nsAString& aRelation)
|
||||
{
|
||||
if (aRelation.EqualsLiteral("equals") || aRelation.IsEmpty())
|
||||
mRelation = eEquals;
|
||||
else if (aRelation.EqualsLiteral("less"))
|
||||
mRelation = eLess;
|
||||
else if (aRelation.EqualsLiteral("greater"))
|
||||
mRelation = eGreater;
|
||||
else if (aRelation.EqualsLiteral("before"))
|
||||
mRelation = eBefore;
|
||||
else if (aRelation.EqualsLiteral("after"))
|
||||
mRelation = eAfter;
|
||||
else if (aRelation.EqualsLiteral("startswith"))
|
||||
mRelation = eStartswith;
|
||||
else if (aRelation.EqualsLiteral("endswith"))
|
||||
mRelation = eEndswith;
|
||||
else if (aRelation.EqualsLiteral("contains"))
|
||||
mRelation = eContains;
|
||||
else
|
||||
mRelation = eUnknown;
|
||||
}
|
||||
|
||||
bool
|
||||
nsTemplateCondition::CheckMatch(nsIXULTemplateResult* aResult)
|
||||
{
|
||||
bool match = false;
|
||||
|
||||
nsAutoString leftString;
|
||||
if (mSourceVariable)
|
||||
aResult->GetBindingFor(mSourceVariable, leftString);
|
||||
else
|
||||
leftString.Assign(mSource);
|
||||
|
||||
if (mTargetVariable) {
|
||||
nsAutoString rightString;
|
||||
aResult->GetBindingFor(mTargetVariable, rightString);
|
||||
|
||||
match = CheckMatchStrings(leftString, rightString);
|
||||
}
|
||||
else {
|
||||
// iterate over the strings in the target and determine
|
||||
// whether there is a match.
|
||||
uint32_t length = mTargetList.Length();
|
||||
for (uint32_t t = 0; t < length; t++) {
|
||||
match = CheckMatchStrings(leftString, mTargetList[t]);
|
||||
|
||||
// stop once a match is found. In negate mode, stop once a
|
||||
// target does not match.
|
||||
if (match != mNegate) break;
|
||||
}
|
||||
}
|
||||
|
||||
return match;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
nsTemplateCondition::CheckMatchStrings(const nsAString& aLeftString,
|
||||
const nsAString& aRightString)
|
||||
{
|
||||
bool match = false;
|
||||
|
||||
if (aRightString.IsEmpty()) {
|
||||
if ((mRelation == eEquals) && aLeftString.IsEmpty())
|
||||
match = true;
|
||||
}
|
||||
else {
|
||||
switch (mRelation) {
|
||||
case eEquals:
|
||||
if (mIgnoreCase)
|
||||
match = aLeftString.Equals(aRightString,
|
||||
nsCaseInsensitiveStringComparator());
|
||||
else
|
||||
match = aLeftString.Equals(aRightString);
|
||||
break;
|
||||
|
||||
case eLess:
|
||||
case eGreater:
|
||||
{
|
||||
// non-numbers always compare false
|
||||
nsresult err;
|
||||
int32_t leftint = PromiseFlatString(aLeftString).ToInteger(&err);
|
||||
if (NS_SUCCEEDED(err)) {
|
||||
int32_t rightint = PromiseFlatString(aRightString).ToInteger(&err);
|
||||
if (NS_SUCCEEDED(err)) {
|
||||
match = (mRelation == eLess) ? (leftint < rightint) :
|
||||
(leftint > rightint);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case eBefore:
|
||||
{
|
||||
nsICollation* collation = nsXULContentUtils::GetCollation();
|
||||
if (collation) {
|
||||
int32_t sortOrder;
|
||||
collation->CompareString((mIgnoreCase ?
|
||||
static_cast<int32_t>(nsICollation::kCollationCaseInSensitive) :
|
||||
static_cast<int32_t>(nsICollation::kCollationCaseSensitive)),
|
||||
aLeftString,
|
||||
aRightString,
|
||||
&sortOrder);
|
||||
match = (sortOrder < 0);
|
||||
}
|
||||
else if (mIgnoreCase) {
|
||||
match = (Compare(aLeftString, aRightString,
|
||||
nsCaseInsensitiveStringComparator()) < 0);
|
||||
}
|
||||
else {
|
||||
match = (Compare(aLeftString, aRightString) < 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case eAfter:
|
||||
{
|
||||
nsICollation* collation = nsXULContentUtils::GetCollation();
|
||||
if (collation) {
|
||||
int32_t sortOrder;
|
||||
collation->CompareString((mIgnoreCase ?
|
||||
static_cast<int32_t>(nsICollation::kCollationCaseInSensitive) :
|
||||
static_cast<int32_t>(nsICollation::kCollationCaseSensitive)),
|
||||
aLeftString,
|
||||
aRightString,
|
||||
&sortOrder);
|
||||
match = (sortOrder > 0);
|
||||
}
|
||||
else if (mIgnoreCase) {
|
||||
match = (Compare(aLeftString, aRightString,
|
||||
nsCaseInsensitiveStringComparator()) > 0);
|
||||
}
|
||||
else {
|
||||
match = (Compare(aLeftString, aRightString) > 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case eStartswith:
|
||||
if (mIgnoreCase)
|
||||
match = (StringBeginsWith(aLeftString, aRightString,
|
||||
nsCaseInsensitiveStringComparator()));
|
||||
else
|
||||
match = (StringBeginsWith(aLeftString, aRightString));
|
||||
break;
|
||||
|
||||
case eEndswith:
|
||||
if (mIgnoreCase)
|
||||
match = (StringEndsWith(aLeftString, aRightString,
|
||||
nsCaseInsensitiveStringComparator()));
|
||||
else
|
||||
match = (StringEndsWith(aLeftString, aRightString));
|
||||
break;
|
||||
|
||||
case eContains:
|
||||
{
|
||||
nsAString::const_iterator start, end;
|
||||
aLeftString.BeginReading(start);
|
||||
aLeftString.EndReading(end);
|
||||
if (mIgnoreCase)
|
||||
match = CaseInsensitiveFindInReadable(aRightString, start, end);
|
||||
else
|
||||
match = FindInReadable(aRightString, start, end);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (mNegate) match = !match;
|
||||
|
||||
return match;
|
||||
}
|
||||
|
||||
nsTemplateRule::nsTemplateRule(nsIContent* aRuleNode,
|
||||
nsIContent* aAction,
|
||||
nsTemplateQuerySet* aQuerySet)
|
||||
: mQuerySet(aQuerySet),
|
||||
mAction(aAction),
|
||||
mBindings(nullptr),
|
||||
mConditions(nullptr)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsTemplateRule);
|
||||
mRuleNode = do_QueryInterface(aRuleNode);
|
||||
}
|
||||
|
||||
nsTemplateRule::nsTemplateRule(const nsTemplateRule& aOtherRule)
|
||||
: mQuerySet(aOtherRule.mQuerySet),
|
||||
mRuleNode(aOtherRule.mRuleNode),
|
||||
mAction(aOtherRule.mAction),
|
||||
mBindings(nullptr),
|
||||
mConditions(nullptr)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsTemplateRule);
|
||||
}
|
||||
|
||||
nsTemplateRule::~nsTemplateRule()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsTemplateRule);
|
||||
|
||||
while (mBindings) {
|
||||
Binding* doomed = mBindings;
|
||||
mBindings = mBindings->mNext;
|
||||
delete doomed;
|
||||
}
|
||||
|
||||
while (mConditions) {
|
||||
nsTemplateCondition* cdel = mConditions;
|
||||
mConditions = mConditions->GetNext();
|
||||
delete cdel;
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsTemplateRule::GetRuleNode(nsIDOMNode** aRuleNode) const
|
||||
{
|
||||
*aRuleNode = mRuleNode;
|
||||
NS_IF_ADDREF(*aRuleNode);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void nsTemplateRule::SetCondition(nsTemplateCondition* aCondition)
|
||||
{
|
||||
while (mConditions) {
|
||||
nsTemplateCondition* cdel = mConditions;
|
||||
mConditions = mConditions->GetNext();
|
||||
delete cdel;
|
||||
}
|
||||
|
||||
mConditions = aCondition;
|
||||
}
|
||||
|
||||
bool
|
||||
nsTemplateRule::CheckMatch(nsIXULTemplateResult* aResult) const
|
||||
{
|
||||
// check the conditions in the rule first
|
||||
nsTemplateCondition* condition = mConditions;
|
||||
while (condition) {
|
||||
if (!condition->CheckMatch(aResult))
|
||||
return false;
|
||||
|
||||
condition = condition->GetNext();
|
||||
}
|
||||
|
||||
if (mRuleFilter) {
|
||||
// if a rule filter was set, check it for a match. If an error occurs,
|
||||
// assume that the match was acceptable
|
||||
bool match;
|
||||
nsresult rv = mRuleFilter->Match(aResult, mRuleNode, &match);
|
||||
return NS_FAILED(rv) || match;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
nsTemplateRule::HasBinding(nsIAtom* aSourceVariable,
|
||||
nsAString& aExpr,
|
||||
nsIAtom* aTargetVariable) const
|
||||
{
|
||||
for (Binding* binding = mBindings; binding != nullptr; binding = binding->mNext) {
|
||||
if ((binding->mSourceVariable == aSourceVariable) &&
|
||||
(binding->mExpr.Equals(aExpr)) &&
|
||||
(binding->mTargetVariable == aTargetVariable))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsTemplateRule::AddBinding(nsIAtom* aSourceVariable,
|
||||
nsAString& aExpr,
|
||||
nsIAtom* aTargetVariable)
|
||||
{
|
||||
NS_PRECONDITION(aSourceVariable != 0, "no source variable!");
|
||||
if (! aSourceVariable)
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
NS_PRECONDITION(aTargetVariable != 0, "no target variable!");
|
||||
if (! aTargetVariable)
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
NS_ASSERTION(! HasBinding(aSourceVariable, aExpr, aTargetVariable),
|
||||
"binding added twice");
|
||||
|
||||
Binding* newbinding = new Binding;
|
||||
if (! newbinding)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
newbinding->mSourceVariable = aSourceVariable;
|
||||
newbinding->mTargetVariable = aTargetVariable;
|
||||
newbinding->mParent = nullptr;
|
||||
|
||||
newbinding->mExpr.Assign(aExpr);
|
||||
|
||||
Binding* binding = mBindings;
|
||||
Binding** link = &mBindings;
|
||||
|
||||
// Insert it at the end, unless we detect that an existing
|
||||
// binding's source is dependent on the newbinding's target.
|
||||
//
|
||||
// XXXwaterson this isn't enough to make sure that we get all of
|
||||
// the dependencies worked out right, but it'll do for now. For
|
||||
// example, if you have (ab, bc, cd), and insert them in the order
|
||||
// (cd, ab, bc), you'll get (bc, cd, ab). The good news is, if the
|
||||
// person uses a natural ordering when writing the XUL, it'll all
|
||||
// work out ok.
|
||||
while (binding) {
|
||||
if (binding->mSourceVariable == newbinding->mTargetVariable) {
|
||||
binding->mParent = newbinding;
|
||||
break;
|
||||
}
|
||||
else if (binding->mTargetVariable == newbinding->mSourceVariable) {
|
||||
newbinding->mParent = binding;
|
||||
}
|
||||
|
||||
link = &binding->mNext;
|
||||
binding = binding->mNext;
|
||||
}
|
||||
|
||||
// Insert the newbinding
|
||||
*link = newbinding;
|
||||
newbinding->mNext = binding;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsTemplateRule::AddBindingsToQueryProcessor(nsIXULTemplateQueryProcessor* aProcessor)
|
||||
{
|
||||
Binding* binding = mBindings;
|
||||
|
||||
while (binding) {
|
||||
nsresult rv = aProcessor->AddBinding(mRuleNode, binding->mTargetVariable,
|
||||
binding->mSourceVariable, binding->mExpr);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
binding = binding->mNext;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue