2 * Copyright (C) 2010 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 #ifndef PODIntervalTree_h
27 #define PODIntervalTree_h
29 #include "platform/PODArena.h"
30 #include "platform/PODInterval.h"
31 #include "platform/PODRedBlackTree.h"
32 #include "wtf/Assertions.h"
33 #include "wtf/Noncopyable.h"
34 #include "wtf/Vector.h"
43 template <class T, class UserData = void*>
44 class PODIntervalSearchAdapter {
46 typedef PODInterval<T, UserData> IntervalType;
48 PODIntervalSearchAdapter(Vector<IntervalType>& result, const T& lowValue, const T& highValue)
50 , m_lowValue(lowValue)
51 , m_highValue(highValue)
55 const T& lowValue() const { return m_lowValue; }
56 const T& highValue() const { return m_highValue; }
57 void collectIfNeeded(const IntervalType& data) const
59 if (data.overlaps(m_lowValue, m_highValue))
60 m_result.append(data);
64 Vector<IntervalType>& m_result;
69 // An interval tree, which is a form of augmented red-black tree. It
70 // supports efficient (O(lg n)) insertion, removal and querying of
71 // intervals in the tree.
72 template<class T, class UserData = void*>
73 class PODIntervalTree final : public PODRedBlackTree<PODInterval<T, UserData> > {
74 WTF_MAKE_NONCOPYABLE(PODIntervalTree);
76 // Typedef to reduce typing when declaring intervals to be stored in
78 typedef PODInterval<T, UserData> IntervalType;
79 typedef PODIntervalSearchAdapter<T, UserData> IntervalSearchAdapterType;
81 PODIntervalTree(UninitializedTreeEnum unitializedTree)
82 : PODRedBlackTree<IntervalType>(unitializedTree)
88 : PODRedBlackTree<IntervalType>()
93 explicit PODIntervalTree(PassRefPtr<PODArena> arena)
94 : PODRedBlackTree<IntervalType>(arena)
99 // Returns all intervals in the tree which overlap the given query
100 // interval. The returned intervals are sorted by increasing low
102 Vector<IntervalType> allOverlaps(const IntervalType& interval) const
104 Vector<IntervalType> result;
105 allOverlaps(interval, result);
109 // Returns all intervals in the tree which overlap the given query
110 // interval. The returned intervals are sorted by increasing low
112 void allOverlaps(const IntervalType& interval, Vector<IntervalType>& result) const
114 // Explicit dereference of "this" required because of
115 // inheritance rules in template classes.
116 IntervalSearchAdapterType adapter(result, interval.low(), interval.high());
117 searchForOverlapsFrom<IntervalSearchAdapterType>(this->root(), adapter);
120 template <class AdapterType>
121 void allOverlapsWithAdapter(AdapterType& adapter) const
123 // Explicit dereference of "this" required because of
124 // inheritance rules in template classes.
125 searchForOverlapsFrom<AdapterType>(this->root(), adapter);
128 // Helper to create interval objects.
129 static IntervalType createInterval(const T& low, const T& high, const UserData data = 0)
131 return IntervalType(low, high, data);
134 virtual bool checkInvariants() const override
136 if (!PODRedBlackTree<IntervalType>::checkInvariants())
140 return checkInvariantsFromNode(this->root(), 0);
144 typedef typename PODRedBlackTree<IntervalType>::Node IntervalNode;
146 // Initializes the tree.
149 // Explicit dereference of "this" required because of
150 // inheritance rules in template classes.
151 this->setNeedsFullOrderingComparisons(true);
154 // Starting from the given node, adds all overlaps with the given
155 // interval to the result vector. The intervals are sorted by
156 // increasing low endpoint.
157 template <class AdapterType>
158 void searchForOverlapsFrom(IntervalNode* node, AdapterType& adapter) const
163 // Because the intervals are sorted by left endpoint, inorder
164 // traversal produces results sorted as desired.
166 // See whether we need to traverse the left subtree.
167 IntervalNode* left = node->left();
169 // This is phrased this way to avoid the need for operator
171 && !(left->data().maxHigh() < adapter.lowValue()))
172 searchForOverlapsFrom<AdapterType>(left, adapter);
174 // Check for overlap with current node.
175 adapter.collectIfNeeded(node->data());
177 // See whether we need to traverse the right subtree.
178 // This is phrased this way to avoid the need for operator <=
180 if (!(adapter.highValue() < node->data().low()))
181 searchForOverlapsFrom<AdapterType>(node->right(), adapter);
184 virtual bool updateNode(IntervalNode* node) override
186 // Would use const T&, but need to reassign this reference in this
188 const T* curMax = &node->data().high();
189 IntervalNode* left = node->left();
191 if (*curMax < left->data().maxHigh())
192 curMax = &left->data().maxHigh();
194 IntervalNode* right = node->right();
196 if (*curMax < right->data().maxHigh())
197 curMax = &right->data().maxHigh();
199 // This is phrased like this to avoid needing operator!= on type T.
200 if (!(*curMax == node->data().maxHigh())) {
201 node->data().setMaxHigh(*curMax);
207 bool checkInvariantsFromNode(IntervalNode* node, T* currentMaxValue) const
209 // These assignments are only done in order to avoid requiring
210 // a default constructor on type T.
211 T leftMaxValue(node->data().maxHigh());
212 T rightMaxValue(node->data().maxHigh());
213 IntervalNode* left = node->left();
214 IntervalNode* right = node->right();
216 if (!checkInvariantsFromNode(left, &leftMaxValue))
220 if (!checkInvariantsFromNode(right, &rightMaxValue))
223 if (!left && !right) {
226 *currentMaxValue = node->data().high();
227 return (node->data().high() == node->data().maxHigh());
229 T localMaxValue(node->data().maxHigh());
230 if (!left || !right) {
232 localMaxValue = leftMaxValue;
234 localMaxValue = rightMaxValue;
236 localMaxValue = (leftMaxValue < rightMaxValue) ? rightMaxValue : leftMaxValue;
238 if (localMaxValue < node->data().high())
239 localMaxValue = node->data().high();
240 if (!(localMaxValue == node->data().maxHigh())) {
242 String localMaxValueString = ValueToString<T>::string(localMaxValue);
243 WTF_LOG_ERROR("PODIntervalTree verification failed at node 0x%p: localMaxValue=%s and data=%s",
244 node, localMaxValueString.utf8().data(), node->data().toString().utf8().data());
249 *currentMaxValue = localMaxValue;
255 // Support for printing PODIntervals at the PODRedBlackTree level.
256 template<class T, class UserData>
257 struct ValueToString<PODInterval<T, UserData> > {
258 static String string(const PODInterval<T, UserData>& interval)
260 return interval.toString();
267 #endif // PODIntervalTree_h