LCOV - code coverage report
Current view: directory - content/xul/templates/src - nsTemplateRule.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 191 0 0.0 %
Date: 2012-06-02 Functions: 15 0 0.0 %

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

Generated by: LCOV version 1.7