OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef NthIndexCache_h | 5 #ifndef NthIndexCache_h |
6 #define NthIndexCache_h | 6 #define NthIndexCache_h |
7 | 7 |
8 #include "core/dom/Element.h" | 8 #include "core/dom/Element.h" |
9 #include "core/dom/ElementTraversal.h" | 9 #include "core/dom/ElementTraversal.h" |
10 #include "platform/heap/Handle.h" | 10 #include "platform/heap/Handle.h" |
11 #include "wtf/HashMap.h" | 11 #include "wtf/HashMap.h" |
12 #include "wtf/OwnPtr.h" | 12 #include "wtf/OwnPtr.h" |
13 #include "wtf/RefPtr.h" | 13 #include "wtf/RefPtr.h" |
14 | 14 |
15 namespace blink { | 15 namespace blink { |
16 | 16 |
17 class Document; | 17 class Document; |
18 | 18 |
19 class NthIndexCache final { | 19 class NthIndexCache final { |
20 STACK_ALLOCATED(); | 20 STACK_ALLOCATED(); |
21 WTF_MAKE_NONCOPYABLE(NthIndexCache); | 21 WTF_MAKE_NONCOPYABLE(NthIndexCache); |
22 public: | 22 public: |
23 explicit NthIndexCache(Document&); | 23 explicit NthIndexCache(Document&); |
24 ~NthIndexCache(); | 24 ~NthIndexCache(); |
25 | 25 |
26 inline unsigned nthChildIndex(Element&); | 26 inline unsigned nthChildIndex(Element&); |
27 inline unsigned nthChildIndexOfType(Element&, const QualifiedName&); | |
27 inline unsigned nthLastChildIndex(Element&); | 28 inline unsigned nthLastChildIndex(Element&); |
29 inline unsigned nthLastChildIndexOfType(Element&, const QualifiedName&); | |
28 | 30 |
29 private: | 31 private: |
30 class NthIndexData final : public NoBaseWillBeGarbageCollected<NthIndexData> { | 32 class NthIndexData final : public NoBaseWillBeGarbageCollected<NthIndexData> { |
31 WTF_MAKE_NONCOPYABLE(NthIndexData); | 33 WTF_MAKE_NONCOPYABLE(NthIndexData); |
32 DECLARE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(NthIndexData); | 34 DECLARE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(NthIndexData); |
33 public: | 35 public: |
34 NthIndexData() { } | 36 NthIndexData() { } |
35 | 37 |
36 inline unsigned nthIndex(Element&); | 38 inline unsigned nthIndex(Element&); |
39 inline unsigned nthIndexOfType(Element&, const QualifiedName&); | |
37 inline unsigned nthLastIndex(Element&); | 40 inline unsigned nthLastIndex(Element&); |
41 inline unsigned nthLastIndexOfType(Element&, const QualifiedName&); | |
38 | 42 |
39 unsigned cacheNthIndices(Element&); | 43 unsigned cacheNthIndices(Element&); |
44 unsigned cacheNthIndicesOfType(Element&, const QualifiedName&); | |
40 | 45 |
41 WillBeHeapHashMap<RawPtrWillBeMember<Element>, unsigned> m_elementIndexM ap; | 46 WillBeHeapHashMap<RawPtrWillBeMember<Element>, unsigned> m_elementIndexM ap; |
42 unsigned m_count = 0; | 47 unsigned m_count = 0; |
43 | 48 |
44 DECLARE_TRACE(); | 49 DECLARE_TRACE(); |
45 }; | 50 }; |
46 | 51 |
47 NthIndexData& ensureNthIndexDataFor(Node&); | 52 class HasTagName { |
esprehn
2015/04/30 04:55:05
This already exists elsewhere in the code. Just us
| |
53 public: | |
54 explicit HasTagName(const QualifiedName& tagName) : m_tagName(tagName) { } | |
55 bool operator() (const Element& element) const { return element.hasTagNa me(m_tagName); } | |
56 private: | |
57 const QualifiedName m_tagName; | |
58 }; | |
59 | |
48 inline unsigned nthIndex(Element&); | 60 inline unsigned nthIndex(Element&); |
49 | 61 |
50 using ParentMap = WillBeHeapHashMap<RefPtrWillBeMember<Node>, OwnPtrWillBeMe mber<NthIndexData>>; | 62 using ParentMap = WillBeHeapHashMap<RefPtrWillBeMember<Node>, OwnPtrWillBeMe mber<NthIndexData>>; |
63 OwnPtrWillBeMember<ParentMap> m_parentMap; | |
51 | 64 |
52 OwnPtrWillBeMember<ParentMap> m_parentMap; | 65 using ElementTagNameAndNthIndexMap = WillBeHeapHashMap<String, OwnPtrWillBeM ember<NthIndexData>>; |
66 OwnPtrWillBeMember<ElementTagNameAndNthIndexMap> m_elementTagNameAndNthIndex Map; | |
67 | |
68 using ParentMapForType = WillBeHeapHashMap<RefPtrWillBeMember<Node>, OwnPtrW illBeMember<ElementTagNameAndNthIndexMap>>; | |
69 OwnPtrWillBeMember<ParentMapForType> m_parentMapForType; | |
70 | |
71 | |
72 NthIndexData& ensureNthIndexDataFor(Node&); | |
73 NthIndexCache::ElementTagNameAndNthIndexMap& ensureElementTagNameAndNthIndex MapForType(Node&); | |
74 | |
75 NthIndexCache::NthIndexData& nthIndexDataWithTagName(ElementTagNameAndNthInd exMap&, Element&); | |
53 RawPtrWillBeMember<Document> m_document; | 76 RawPtrWillBeMember<Document> m_document; |
54 uint64_t m_domTreeVersion; | 77 uint64_t m_domTreeVersion; |
55 }; | 78 }; |
56 | 79 |
57 inline unsigned NthIndexCache::NthIndexData::nthIndex(Element& element) | 80 inline unsigned NthIndexCache::NthIndexData::nthIndex(Element& element) |
58 { | 81 { |
59 if (!m_count) | 82 if (!m_count) |
60 return cacheNthIndices(element); | 83 return cacheNthIndices(element); |
61 | 84 |
62 unsigned index = 0; | 85 unsigned index = 0; |
63 for (Element* sibling = &element; sibling; sibling = ElementTraversal::previ ousSibling(*sibling), index++) { | 86 for (Element* sibling = &element; sibling; sibling = ElementTraversal::previ ousSibling(*sibling), index++) { |
64 auto it = m_elementIndexMap.find(sibling); | 87 auto it = m_elementIndexMap.find(sibling); |
65 if (it != m_elementIndexMap.end()) | 88 if (it != m_elementIndexMap.end()) |
66 return it->value + index; | 89 return it->value + index; |
67 } | 90 } |
68 return index; | 91 return index; |
69 } | 92 } |
70 | 93 |
94 inline unsigned NthIndexCache::NthIndexData::nthIndexOfType(Element& element, co nst QualifiedName& type) | |
95 { | |
96 if (!m_count) | |
esprehn
2015/04/30 04:55:05
This will need the same pseudo element fix from ru
| |
97 return cacheNthIndicesOfType(element, type); | |
98 unsigned index = 0; | |
99 for (Element* sibling = &element; sibling; sibling = ElementTraversal::previ ousSibling(*sibling, HasTagName(type)), index++) { | |
100 auto it = m_elementIndexMap.find(sibling); | |
101 if (it != m_elementIndexMap.end()) | |
102 return it->value + index; | |
103 } | |
104 return index; | |
105 } | |
106 | |
71 inline unsigned NthIndexCache::NthIndexData::nthLastIndex(Element& element) | 107 inline unsigned NthIndexCache::NthIndexData::nthLastIndex(Element& element) |
72 { | 108 { |
73 unsigned index = nthIndex(element); | 109 unsigned index = nthIndex(element); |
74 return m_count - index + 1; | 110 return m_count - index + 1; |
75 } | 111 } |
76 | 112 |
113 inline unsigned NthIndexCache::NthIndexData::nthLastIndexOfType(Element& element , const QualifiedName& type) | |
114 { | |
115 unsigned index = nthIndexOfType(element, type); | |
116 return m_count - index + 1; | |
117 } | |
118 | |
77 inline unsigned NthIndexCache::nthChildIndex(Element& element) | 119 inline unsigned NthIndexCache::nthChildIndex(Element& element) |
78 { | 120 { |
79 ASSERT(element.parentNode()); | 121 ASSERT(element.parentNode()); |
80 return ensureNthIndexDataFor(*element.parentNode()).nthIndex(element); | 122 return ensureNthIndexDataFor(*element.parentNode()).nthIndex(element); |
81 } | 123 } |
82 | 124 |
125 inline unsigned NthIndexCache::nthChildIndexOfType(Element& element, const Quali fiedName& type) | |
126 { | |
127 ASSERT(element.parentNode()); | |
128 return nthIndexDataWithTagName(ensureElementTagNameAndNthIndexMapForType(*el ement.parentNode()), element).nthIndexOfType(element, type); | |
esprehn
2015/04/30 04:55:05
nthIndexDataWithTagName should call ensureElementT
| |
129 } | |
130 | |
83 inline unsigned NthIndexCache::nthLastChildIndex(Element& element) | 131 inline unsigned NthIndexCache::nthLastChildIndex(Element& element) |
84 { | 132 { |
85 ASSERT(element.parentNode()); | 133 ASSERT(element.parentNode()); |
86 return ensureNthIndexDataFor(*element.parentNode()).nthLastIndex(element); | 134 return ensureNthIndexDataFor(*element.parentNode()).nthLastIndex(element); |
87 } | 135 } |
88 | 136 |
137 inline unsigned NthIndexCache::nthLastChildIndexOfType(Element& element, const Q ualifiedName& type) | |
138 { | |
139 ASSERT(element.parentNode()); | |
140 return nthIndexDataWithTagName(ensureElementTagNameAndNthIndexMapForType(*el ement.parentNode()), element).nthLastIndexOfType(element, type); | |
esprehn
2015/04/30 04:55:05
ditto
| |
141 } | |
142 | |
143 | |
89 } // namespace blink | 144 } // namespace blink |
90 | 145 |
91 #endif // NthIndexCache_h | 146 #endif // NthIndexCache_h |
OLD | NEW |