layout/style/nsNthIndexCache.cpp

Thu, 15 Jan 2015 21:03:48 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 21:03:48 +0100
branch
TOR_BUG_9701
changeset 11
deefc01c0e14
permissions
-rw-r--r--

Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)

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

mercurial