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
= nullptr)
131 return IntervalType(low
, high
, data
);
134 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 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