LCOV - code coverage report
Current view: top level - layout/style - nsNthIndexCache.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 26 67 38.8 %
Date: 2017-07-14 16:53:18 Functions: 4 6 66.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       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             : /*
       7             :  * A class that computes and caches the indices used for :nth-* pseudo-class
       8             :  * matching.
       9             :  */
      10             : 
      11             : #include "nsNthIndexCache.h"
      12             : #include "mozilla/dom/Element.h"
      13             : #include "mozilla/dom/NodeInfoInlines.h"
      14             : 
      15        2029 : nsNthIndexCache::nsNthIndexCache()
      16             : {
      17        2029 : }
      18             : 
      19        2029 : nsNthIndexCache::~nsNthIndexCache()
      20             : {
      21        2029 : }
      22             : 
      23             : void
      24           0 : nsNthIndexCache::Reset()
      25             : {
      26           0 :   mCaches[0][0].clear();
      27           0 :   mCaches[0][1].clear();
      28           0 :   mCaches[1][0].clear();
      29           0 :   mCaches[1][1].clear();
      30           0 : }
      31             : 
      32             : inline bool
      33           6 : nsNthIndexCache::SiblingMatchesElement(nsIContent* aSibling, Element* aElement,
      34             :                                        bool aIsOfType)
      35             : {
      36          18 :   return aSibling->IsElement() &&
      37           6 :     (!aIsOfType ||
      38           6 :      aSibling->NodeInfo()->NameAndNamespaceEquals(aElement->NodeInfo()));
      39             : }
      40             : 
      41             : inline bool
      42           0 : nsNthIndexCache::IndexDeterminedFromPreviousSibling(nsIContent* aSibling,
      43             :                                                     Element* aChild,
      44             :                                                     bool aIsOfType,
      45             :                                                     bool aIsFromEnd,
      46             :                                                     const Cache& aCache,
      47             :                                                     int32_t& aResult)
      48             : {
      49           0 :   if (SiblingMatchesElement(aSibling, aChild, aIsOfType)) {
      50           0 :     Cache::Ptr siblingEntry = aCache.lookup(aSibling);
      51           0 :     if (siblingEntry) {
      52           0 :       int32_t siblingIndex = siblingEntry->value();
      53           0 :       NS_ASSERTION(siblingIndex != 0,
      54             :                    "How can a non-anonymous node have an anonymous sibling?");
      55           0 :       if (siblingIndex > 0) {
      56             :         // At this point, aResult is a count of how many elements matching
      57             :         // aChild we have seen after aSibling, including aChild itself.
      58             :         // |siblingIndex| is the index of aSibling.
      59             :         // So if aIsFromEnd, we want |aResult = siblingIndex - aResult| and
      60             :         // otherwise we want |aResult = siblingIndex + aResult|.
      61           0 :         aResult = siblingIndex + aResult * (1 - 2 * aIsFromEnd);
      62           0 :         return true;
      63             :       }
      64             :     }
      65             : 
      66           0 :     ++aResult;
      67             :   }
      68             : 
      69           0 :   return false;
      70             : }
      71             : 
      72             : int32_t
      73           6 : nsNthIndexCache::GetNthIndex(Element* aChild, bool aIsOfType,
      74             :                              bool aIsFromEnd, bool aCheckEdgeOnly)
      75             : {
      76           6 :   if (aChild->IsRootOfAnonymousSubtree()) {
      77           0 :     return 0;
      78             :   }
      79             : 
      80           6 :   Cache& cache = mCaches[aIsOfType][aIsFromEnd];
      81             : 
      82           6 :   if (!cache.initialized() && !cache.init()) {
      83             :     // Give up and just don't match.
      84           0 :     return 0;
      85             :   }
      86             : 
      87           6 :   Cache::AddPtr entry = cache.lookupForAdd(aChild);
      88             : 
      89             :   // Default the value to -2 when adding
      90           6 :   if (!entry && !cache.add(entry, aChild, -2)) {
      91             :     // No good; don't match.
      92           0 :     return 0;
      93             :   }
      94             : 
      95           6 :   int32_t& slot = entry->value();
      96           6 :   if (slot != -2 && (slot != -1 || aCheckEdgeOnly)) {
      97           0 :     return slot;
      98             :   }
      99             : 
     100           6 :   int32_t result = 1;
     101           6 :   if (aCheckEdgeOnly) {
     102             :     // The caller only cares whether or not the result is 1, so we can
     103             :     // stop as soon as we see any other elements that match us.
     104           6 :     if (aIsFromEnd) {
     105           0 :       for (nsIContent *cur = aChild->GetNextSibling();
     106           0 :            cur;
     107           0 :            cur = cur->GetNextSibling()) {
     108           0 :         if (SiblingMatchesElement(cur, aChild, aIsOfType)) {
     109           0 :           result = -1;
     110           0 :           break;
     111             :         }
     112             :       }
     113             :     } else {
     114           6 :       for (nsIContent *cur = aChild->GetPreviousSibling();
     115           6 :            cur;
     116           0 :            cur = cur->GetPreviousSibling()) {
     117           6 :         if (SiblingMatchesElement(cur, aChild, aIsOfType)) {
     118           6 :           result = -1;
     119           6 :           break;
     120             :         }
     121             :       }
     122             :     }
     123             :   } else {
     124             :     // In the common case, we already have a cached index for one of
     125             :     // our previous siblings, so check that first.
     126           0 :     for (nsIContent *cur = aChild->GetPreviousSibling();
     127           0 :          cur;
     128           0 :          cur = cur->GetPreviousSibling()) {
     129           0 :       if (IndexDeterminedFromPreviousSibling(cur, aChild, aIsOfType,
     130             :                                              aIsFromEnd, cache, result)) {
     131           0 :         slot = result;
     132           0 :         return result;
     133             :       }
     134             :     }
     135             : 
     136             :     // Now if aIsFromEnd we lose: need to actually compute our index,
     137             :     // since looking at previous siblings wouldn't have told us
     138             :     // anything about it.  Note that it doesn't make sense to do cache
     139             :     // lookups on our following siblings, since chances are the cache
     140             :     // is not primed for them.
     141           0 :     if (aIsFromEnd) {
     142           0 :       result = 1;
     143           0 :       for (nsIContent *cur = aChild->GetNextSibling();
     144           0 :            cur;
     145           0 :            cur = cur->GetNextSibling()) {
     146           0 :         if (SiblingMatchesElement(cur, aChild, aIsOfType)) {
     147           0 :           ++result;
     148             :         }
     149             :       }
     150             :     }
     151             :   }
     152             : 
     153           6 :   slot = result;
     154           6 :   return result;
     155             : }

Generated by: LCOV version 1.13