LCOV - code coverage report
Current view: top level - dom/xul/templates - nsTemplateRule.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 202 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 15 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "nsTemplateRule.h"
       7             : #include "nsTemplateMatch.h"
       8             : #include "nsXULContentUtils.h"
       9             : #include "nsUnicharUtils.h"
      10             : #include "nsReadableUtils.h"
      11             : #include "nsICollation.h"
      12             : 
      13           0 : nsTemplateCondition::nsTemplateCondition(nsIAtom* aSourceVariable,
      14             :                                          const nsAString& aRelation,
      15             :                                          nsIAtom* aTargetVariable,
      16             :                                          bool aIgnoreCase,
      17           0 :                                          bool aNegate)
      18             :     : mSourceVariable(aSourceVariable),
      19             :       mTargetVariable(aTargetVariable),
      20             :       mIgnoreCase(aIgnoreCase),
      21             :       mNegate(aNegate),
      22           0 :       mNext(nullptr)
      23             : {
      24           0 :     SetRelation(aRelation);
      25             : 
      26           0 :     MOZ_COUNT_CTOR(nsTemplateCondition);
      27           0 : }
      28             : 
      29           0 : nsTemplateCondition::nsTemplateCondition(nsIAtom* aSourceVariable,
      30             :                                          const nsAString& aRelation,
      31             :                                          const nsAString& aTargets,
      32             :                                          bool aIgnoreCase,
      33             :                                          bool aNegate,
      34           0 :                                          bool aIsMultiple)
      35             :     : mSourceVariable(aSourceVariable),
      36             :       mIgnoreCase(aIgnoreCase),
      37             :       mNegate(aNegate),
      38           0 :       mNext(nullptr)
      39             : {
      40           0 :     SetRelation(aRelation);
      41             : 
      42           0 :     if (aIsMultiple) {
      43           0 :         int32_t start = 0, end = 0;
      44           0 :         while ((end = aTargets.FindChar(',',start)) >= 0) {
      45           0 :             if (end > start) {
      46           0 :                 mTargetList.AppendElement(Substring(aTargets, start, end - start));
      47             :             }
      48           0 :             start = end + 1;
      49             :         }
      50           0 :         if (start < int32_t(aTargets.Length())) {
      51           0 :             mTargetList.AppendElement(Substring(aTargets, start));
      52             :         }
      53             :     }
      54             :     else {
      55           0 :         mTargetList.AppendElement(aTargets);
      56             :     }
      57             : 
      58           0 :     MOZ_COUNT_CTOR(nsTemplateCondition);
      59           0 : }
      60             : 
      61           0 : nsTemplateCondition::nsTemplateCondition(const nsAString& aSource,
      62             :                                          const nsAString& aRelation,
      63             :                                          nsIAtom* aTargetVariable,
      64             :                                          bool aIgnoreCase,
      65           0 :                                          bool aNegate)
      66             :     : mSource(aSource),
      67             :       mTargetVariable(aTargetVariable),
      68             :       mIgnoreCase(aIgnoreCase),
      69             :       mNegate(aNegate),
      70           0 :       mNext(nullptr)
      71             : {
      72           0 :     SetRelation(aRelation);
      73             : 
      74           0 :     MOZ_COUNT_CTOR(nsTemplateCondition);
      75           0 : }
      76             : 
      77             : void
      78           0 : nsTemplateCondition::SetRelation(const nsAString& aRelation)
      79             : {
      80           0 :     if (aRelation.EqualsLiteral("equals") || aRelation.IsEmpty())
      81           0 :         mRelation = eEquals;
      82           0 :     else if (aRelation.EqualsLiteral("less"))
      83           0 :         mRelation = eLess;
      84           0 :     else if (aRelation.EqualsLiteral("greater"))
      85           0 :         mRelation = eGreater;
      86           0 :     else if (aRelation.EqualsLiteral("before"))
      87           0 :         mRelation = eBefore;
      88           0 :     else if (aRelation.EqualsLiteral("after"))
      89           0 :         mRelation = eAfter;
      90           0 :     else if (aRelation.EqualsLiteral("startswith"))
      91           0 :         mRelation = eStartswith;
      92           0 :     else if (aRelation.EqualsLiteral("endswith"))
      93           0 :         mRelation = eEndswith;
      94           0 :     else if (aRelation.EqualsLiteral("contains"))
      95           0 :         mRelation = eContains;
      96             :     else
      97           0 :         mRelation = eUnknown;
      98           0 : }
      99             : 
     100             : bool
     101           0 : nsTemplateCondition::CheckMatch(nsIXULTemplateResult* aResult)
     102             : {
     103           0 :     bool match = false;
     104             : 
     105           0 :     nsAutoString leftString;
     106           0 :     if (mSourceVariable)
     107           0 :       aResult->GetBindingFor(mSourceVariable, leftString);
     108             :     else
     109           0 :       leftString.Assign(mSource);
     110             : 
     111           0 :     if (mTargetVariable) {
     112           0 :         nsAutoString rightString;
     113           0 :         aResult->GetBindingFor(mTargetVariable, rightString);
     114             : 
     115           0 :         match = CheckMatchStrings(leftString, rightString);
     116             :     }
     117             :     else {
     118             :         // iterate over the strings in the target and determine
     119             :         // whether there is a match.
     120           0 :         uint32_t length = mTargetList.Length();
     121           0 :         for (uint32_t t = 0; t < length; t++) {
     122           0 :             match = CheckMatchStrings(leftString, mTargetList[t]);
     123             : 
     124             :             // stop once a match is found. In negate mode, stop once a
     125             :             // target does not match.
     126           0 :             if (match != mNegate) break;
     127             :         }
     128             :     }
     129             : 
     130           0 :     return match;
     131             : }
     132             : 
     133             : 
     134             : bool
     135           0 : nsTemplateCondition::CheckMatchStrings(const nsAString& aLeftString,
     136             :                                        const nsAString& aRightString)
     137             : {
     138           0 :     bool match = false;
     139             : 
     140           0 :     if (aRightString.IsEmpty()) {
     141           0 :         if ((mRelation == eEquals) && aLeftString.IsEmpty())
     142           0 :             match = true;
     143             :     }
     144             :     else {
     145           0 :         switch (mRelation) {
     146             :             case eEquals:
     147           0 :                 if (mIgnoreCase)
     148           0 :                     match = aLeftString.Equals(aRightString,
     149           0 :                                                nsCaseInsensitiveStringComparator());
     150             :                 else
     151           0 :                     match = aLeftString.Equals(aRightString);
     152           0 :                 break;
     153             : 
     154             :             case eLess:
     155             :             case eGreater:
     156             :             {
     157             :                 // non-numbers always compare false
     158             :                 nsresult err;
     159           0 :                 int32_t leftint = PromiseFlatString(aLeftString).ToInteger(&err);
     160           0 :                 if (NS_SUCCEEDED(err)) {
     161           0 :                     int32_t rightint = PromiseFlatString(aRightString).ToInteger(&err);
     162           0 :                     if (NS_SUCCEEDED(err)) {
     163           0 :                         match = (mRelation == eLess) ? (leftint < rightint) :
     164             :                                                        (leftint > rightint);
     165             :                     }
     166             :                 }
     167             : 
     168           0 :                 break;
     169             :             }
     170             : 
     171             :             case eBefore:
     172             :             {
     173           0 :                 nsICollation* collation = nsXULContentUtils::GetCollation();
     174           0 :                 if (collation) {
     175             :                     int32_t sortOrder;
     176           0 :                     collation->CompareString((mIgnoreCase ?
     177             :                                               static_cast<int32_t>(nsICollation::kCollationCaseInSensitive) :
     178             :                                               static_cast<int32_t>(nsICollation::kCollationCaseSensitive)),
     179             :                                               aLeftString,
     180             :                                               aRightString,
     181           0 :                                               &sortOrder);
     182           0 :                     match = (sortOrder < 0);
     183             :                 }
     184           0 :                 else if (mIgnoreCase) {
     185           0 :                     match = (Compare(aLeftString, aRightString,
     186           0 :                                      nsCaseInsensitiveStringComparator()) < 0);
     187             :                 }
     188             :                 else {
     189           0 :                     match = (Compare(aLeftString, aRightString) < 0);
     190             :                 }
     191           0 :                 break;
     192             :             }
     193             : 
     194             :             case eAfter:
     195             :             {
     196           0 :                 nsICollation* collation = nsXULContentUtils::GetCollation();
     197           0 :                 if (collation) {
     198             :                     int32_t sortOrder;
     199           0 :                     collation->CompareString((mIgnoreCase ?
     200             :                                               static_cast<int32_t>(nsICollation::kCollationCaseInSensitive) :
     201             :                                               static_cast<int32_t>(nsICollation::kCollationCaseSensitive)),
     202             :                                               aLeftString,
     203             :                                               aRightString,
     204           0 :                                               &sortOrder);
     205           0 :                     match = (sortOrder > 0);
     206             :                 }
     207           0 :                 else if (mIgnoreCase) {
     208           0 :                     match = (Compare(aLeftString, aRightString,
     209           0 :                                      nsCaseInsensitiveStringComparator()) > 0);
     210             :                 }
     211             :                 else {
     212           0 :                     match = (Compare(aLeftString, aRightString) > 0);
     213             :                 }
     214           0 :                 break;
     215             :             }
     216             : 
     217             :             case eStartswith:
     218           0 :                 if (mIgnoreCase)
     219             :                     match = (StringBeginsWith(aLeftString, aRightString,
     220           0 :                                               nsCaseInsensitiveStringComparator()));
     221             :                 else
     222           0 :                     match = (StringBeginsWith(aLeftString, aRightString));
     223           0 :                 break;
     224             : 
     225             :             case eEndswith:
     226           0 :                 if (mIgnoreCase)
     227             :                     match = (StringEndsWith(aLeftString, aRightString,
     228           0 :                                             nsCaseInsensitiveStringComparator()));
     229             :                 else
     230           0 :                     match = (StringEndsWith(aLeftString, aRightString));
     231           0 :                 break;
     232             : 
     233             :             case eContains:
     234             :             {
     235           0 :                 nsAString::const_iterator start, end;
     236           0 :                 aLeftString.BeginReading(start);
     237           0 :                 aLeftString.EndReading(end);
     238           0 :                 if (mIgnoreCase)
     239           0 :                     match = CaseInsensitiveFindInReadable(aRightString, start, end);
     240             :                 else
     241           0 :                     match = FindInReadable(aRightString, start, end);
     242           0 :                 break;
     243             :             }
     244             : 
     245             :             default:
     246           0 :                 break;
     247             :         }
     248             :     }
     249             : 
     250           0 :     if (mNegate) match = !match;
     251             : 
     252           0 :     return match;
     253             : }
     254             : 
     255           0 : nsTemplateRule::nsTemplateRule(nsIContent* aRuleNode,
     256             :                                nsIContent* aAction,
     257           0 :                                nsTemplateQuerySet* aQuerySet)
     258             :         : mQuerySet(aQuerySet),
     259             :           mAction(aAction),
     260             :           mBindings(nullptr),
     261           0 :           mConditions(nullptr)
     262             : {
     263           0 :     MOZ_COUNT_CTOR(nsTemplateRule);
     264           0 :     mRuleNode = do_QueryInterface(aRuleNode);
     265           0 : }
     266             : 
     267           0 : nsTemplateRule::nsTemplateRule(const nsTemplateRule& aOtherRule)
     268           0 :         : mQuerySet(aOtherRule.mQuerySet),
     269             :           mRuleNode(aOtherRule.mRuleNode),
     270             :           mAction(aOtherRule.mAction),
     271             :           mBindings(nullptr),
     272           0 :           mConditions(nullptr)
     273             : {
     274           0 :     MOZ_COUNT_CTOR(nsTemplateRule);
     275           0 : }
     276             : 
     277           0 : nsTemplateRule::~nsTemplateRule()
     278             : {
     279           0 :     MOZ_COUNT_DTOR(nsTemplateRule);
     280             : 
     281           0 :     while (mBindings) {
     282           0 :         Binding* doomed = mBindings;
     283           0 :         mBindings = mBindings->mNext;
     284           0 :         delete doomed;
     285             :     }
     286             : 
     287           0 :     while (mConditions) {
     288           0 :         nsTemplateCondition* cdel = mConditions;
     289           0 :         mConditions = mConditions->GetNext();
     290           0 :         delete cdel;
     291             :     }
     292           0 : }
     293             : 
     294             : nsresult
     295           0 : nsTemplateRule::GetRuleNode(nsIDOMNode** aRuleNode) const
     296             : {
     297           0 :     *aRuleNode = mRuleNode;
     298           0 :     NS_IF_ADDREF(*aRuleNode);
     299           0 :     return NS_OK;
     300             : }
     301             : 
     302           0 : void nsTemplateRule::SetCondition(nsTemplateCondition* aCondition)
     303             : {
     304           0 :     while (mConditions) {
     305           0 :         nsTemplateCondition* cdel = mConditions;
     306           0 :         mConditions = mConditions->GetNext();
     307           0 :         delete cdel;
     308             :     }
     309             : 
     310           0 :     mConditions = aCondition;
     311           0 : }
     312             : 
     313             : bool
     314           0 : nsTemplateRule::CheckMatch(nsIXULTemplateResult* aResult) const
     315             : {
     316             :     // check the conditions in the rule first
     317           0 :     nsTemplateCondition* condition = mConditions;
     318           0 :     while (condition) {
     319           0 :         if (!condition->CheckMatch(aResult))
     320           0 :             return false;
     321             : 
     322           0 :         condition = condition->GetNext();
     323             :     }
     324             : 
     325           0 :     if (mRuleFilter) {
     326             :         // if a rule filter was set, check it for a match. If an error occurs,
     327             :         // assume that the match was acceptable
     328             :         bool match;
     329           0 :         nsresult rv = mRuleFilter->Match(aResult, mRuleNode, &match);
     330           0 :         return NS_FAILED(rv) || match;
     331             :     }
     332             : 
     333           0 :     return true;
     334             : }
     335             : 
     336             : bool
     337           0 : nsTemplateRule::HasBinding(nsIAtom* aSourceVariable,
     338             :                            nsAString& aExpr,
     339             :                            nsIAtom* aTargetVariable) const
     340             : {
     341           0 :     for (Binding* binding = mBindings; binding != nullptr; binding = binding->mNext) {
     342           0 :         if ((binding->mSourceVariable == aSourceVariable) &&
     343           0 :             (binding->mExpr.Equals(aExpr)) &&
     344           0 :             (binding->mTargetVariable == aTargetVariable))
     345           0 :             return true;
     346             :     }
     347             : 
     348           0 :     return false;
     349             : }
     350             : 
     351             : nsresult
     352           0 : nsTemplateRule::AddBinding(nsIAtom* aSourceVariable,
     353             :                            nsAString& aExpr,
     354             :                            nsIAtom* aTargetVariable)
     355             : {
     356           0 :     NS_PRECONDITION(aSourceVariable != 0, "no source variable!");
     357           0 :     if (! aSourceVariable)
     358           0 :         return NS_ERROR_INVALID_ARG;
     359             : 
     360           0 :     NS_PRECONDITION(aTargetVariable != 0, "no target variable!");
     361           0 :     if (! aTargetVariable)
     362           0 :         return NS_ERROR_INVALID_ARG;
     363             : 
     364           0 :     NS_ASSERTION(! HasBinding(aSourceVariable, aExpr, aTargetVariable),
     365             :                  "binding added twice");
     366             : 
     367           0 :     Binding* newbinding = new Binding;
     368           0 :     if (! newbinding)
     369           0 :         return NS_ERROR_OUT_OF_MEMORY;
     370             : 
     371           0 :     newbinding->mSourceVariable = aSourceVariable;
     372           0 :     newbinding->mTargetVariable = aTargetVariable;
     373           0 :     newbinding->mParent         = nullptr;
     374             : 
     375           0 :     newbinding->mExpr.Assign(aExpr);
     376             : 
     377           0 :     Binding* binding = mBindings;
     378           0 :     Binding** link = &mBindings;
     379             : 
     380             :     // Insert it at the end, unless we detect that an existing
     381             :     // binding's source is dependent on the newbinding's target.
     382             :     //
     383             :     // XXXwaterson this isn't enough to make sure that we get all of
     384             :     // the dependencies worked out right, but it'll do for now. For
     385             :     // example, if you have (ab, bc, cd), and insert them in the order
     386             :     // (cd, ab, bc), you'll get (bc, cd, ab). The good news is, if the
     387             :     // person uses a natural ordering when writing the XUL, it'll all
     388             :     // work out ok.
     389           0 :     while (binding) {
     390           0 :         if (binding->mSourceVariable == newbinding->mTargetVariable) {
     391           0 :             binding->mParent = newbinding;
     392           0 :             break;
     393             :         }
     394           0 :         else if (binding->mTargetVariable == newbinding->mSourceVariable) {
     395           0 :             newbinding->mParent = binding;
     396             :         }
     397             : 
     398           0 :         link = &binding->mNext;
     399           0 :         binding = binding->mNext;
     400             :     }
     401             : 
     402             :     // Insert the newbinding
     403           0 :     *link = newbinding;
     404           0 :     newbinding->mNext = binding;
     405           0 :     return NS_OK;
     406             : }
     407             : 
     408             : nsresult
     409           0 : nsTemplateRule::AddBindingsToQueryProcessor(nsIXULTemplateQueryProcessor* aProcessor)
     410             : {
     411           0 :     Binding* binding = mBindings;
     412             : 
     413           0 :     while (binding) {
     414           0 :         nsresult rv = aProcessor->AddBinding(mRuleNode, binding->mTargetVariable,
     415           0 :                                              binding->mSourceVariable, binding->mExpr);
     416           0 :         if (NS_FAILED(rv)) return rv;
     417             : 
     418           0 :         binding = binding->mNext;
     419             :     }
     420             : 
     421           0 :     return NS_OK;
     422             : }

Generated by: LCOV version 1.13