/src/qtbase/src/gui/text/qfragmentmap_p.h
Line | Count | Source |
1 | | // Copyright (C) 2016 The Qt Company Ltd. |
2 | | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | | |
4 | | #ifndef QFRAGMENTMAP_P_H |
5 | | #define QFRAGMENTMAP_P_H |
6 | | |
7 | | // |
8 | | // W A R N I N G |
9 | | // ------------- |
10 | | // |
11 | | // This file is not part of the Qt API. It exists purely as an |
12 | | // implementation detail. This header file may change from version to |
13 | | // version without notice, or even be removed. |
14 | | // |
15 | | // We mean it. |
16 | | // |
17 | | |
18 | | #include <QtGui/private/qtguiglobal_p.h> |
19 | | #include <stdlib.h> |
20 | | #include <private/qtools_p.h> |
21 | | |
22 | | QT_BEGIN_NAMESPACE |
23 | | |
24 | | |
25 | | template <int N = 1> |
26 | | class QFragment |
27 | | { |
28 | | public: |
29 | | quint32 parent; |
30 | | quint32 left; |
31 | | quint32 right; |
32 | | quint32 color; |
33 | | quint32 size_left_array[N]; |
34 | | quint32 size_array[N]; |
35 | | enum {size_array_max = N }; |
36 | | }; |
37 | | |
38 | | template <class Fragment> |
39 | | class QFragmentMapData |
40 | | { |
41 | | enum Color { Red, Black }; |
42 | | public: |
43 | | QFragmentMapData(); |
44 | | ~QFragmentMapData(); |
45 | | |
46 | | void init(); |
47 | | |
48 | | class Header |
49 | | { |
50 | | public: |
51 | | quint32 root; // this relies on being at the same position as parent in the fragment struct |
52 | | quint32 tag; |
53 | | quint32 freelist; |
54 | | quint32 node_count; |
55 | | quint32 allocated; |
56 | | }; |
57 | | |
58 | | |
59 | | enum {fragmentSize = sizeof(Fragment) }; |
60 | | |
61 | | |
62 | | int length(uint field = 0) const; |
63 | | |
64 | | |
65 | 0 | inline Fragment *fragment(uint index) { |
66 | 0 | return (fragments + index); |
67 | 0 | } Unexecuted instantiation: QFragmentMapData<QTextBlockData>::fragment(unsigned int) Unexecuted instantiation: QFragmentMapData<QTextFragmentData>::fragment(unsigned int) |
68 | 0 | inline const Fragment *fragment(uint index) const { |
69 | 0 | return (fragments + index); |
70 | 0 | } Unexecuted instantiation: QFragmentMapData<QTextFragmentData>::fragment(unsigned int) const Unexecuted instantiation: QFragmentMapData<QTextBlockData>::fragment(unsigned int) const |
71 | | |
72 | | |
73 | 0 | inline Fragment &F(uint index) { return fragments[index] ; }Unexecuted instantiation: QFragmentMapData<QTextFragmentData>::F(unsigned int) Unexecuted instantiation: QFragmentMapData<QTextBlockData>::F(unsigned int) |
74 | 0 | inline const Fragment &F(uint index) const { return fragments[index] ; }Unexecuted instantiation: QFragmentMapData<QTextFragmentData>::F(unsigned int) const Unexecuted instantiation: QFragmentMapData<QTextBlockData>::F(unsigned int) const |
75 | | |
76 | | inline bool isRoot(uint index) const { |
77 | | return !fragment(index)->parent; |
78 | | } |
79 | | |
80 | 0 | inline uint position(uint node, uint field = 0) const { |
81 | 0 | Q_ASSERT(field < Fragment::size_array_max); |
82 | 0 | const Fragment *f = fragment(node); |
83 | 0 | uint offset = f->size_left_array[field]; |
84 | 0 | while (f->parent) { |
85 | 0 | uint p = f->parent; |
86 | 0 | f = fragment(p); |
87 | 0 | if (f->right == node) |
88 | 0 | offset += f->size_left_array[field] + f->size_array[field]; |
89 | 0 | node = p; |
90 | 0 | } |
91 | 0 | return offset; |
92 | 0 | } Unexecuted instantiation: QFragmentMapData<QTextFragmentData>::position(unsigned int, unsigned int) const Unexecuted instantiation: QFragmentMapData<QTextBlockData>::position(unsigned int, unsigned int) const |
93 | 0 | inline uint sizeRight(uint node, uint field = 0) const { |
94 | 0 | Q_ASSERT(field < Fragment::size_array_max); |
95 | 0 | uint sr = 0; |
96 | 0 | const Fragment *f = fragment(node); |
97 | 0 | node = f->right; |
98 | 0 | while (node) { |
99 | 0 | f = fragment(node); |
100 | 0 | sr += f->size_left_array[field] + f->size_array[field]; |
101 | 0 | node = f->right; |
102 | 0 | } |
103 | 0 | return sr; |
104 | 0 | } Unexecuted instantiation: QFragmentMapData<QTextFragmentData>::sizeRight(unsigned int, unsigned int) const Unexecuted instantiation: QFragmentMapData<QTextBlockData>::sizeRight(unsigned int, unsigned int) const |
105 | 0 | inline uint sizeLeft(uint node, uint field = 0) const { |
106 | 0 | Q_ASSERT(field < Fragment::size_array_max); |
107 | 0 | return fragment(node)->size_left_array[field]; |
108 | 0 | } Unexecuted instantiation: QFragmentMapData<QTextFragmentData>::sizeLeft(unsigned int, unsigned int) const Unexecuted instantiation: QFragmentMapData<QTextBlockData>::sizeLeft(unsigned int, unsigned int) const |
109 | | |
110 | | |
111 | 0 | inline uint size(uint node, uint field = 0) const { |
112 | 0 | Q_ASSERT(field < Fragment::size_array_max); |
113 | 0 | return fragment(node)->size_array[field]; |
114 | 0 | } Unexecuted instantiation: QFragmentMapData<QTextFragmentData>::size(unsigned int, unsigned int) const Unexecuted instantiation: QFragmentMapData<QTextBlockData>::size(unsigned int, unsigned int) const |
115 | | |
116 | 0 | inline void setSize(uint node, int new_size, uint field = 0) { |
117 | 0 | Q_ASSERT(field < Fragment::size_array_max); |
118 | 0 | Fragment *f = fragment(node); |
119 | 0 | int diff = new_size - f->size_array[field]; |
120 | 0 | f->size_array[field] = new_size; |
121 | 0 | while (f->parent) { |
122 | 0 | uint p = f->parent; |
123 | 0 | f = fragment(p); |
124 | 0 | if (f->left == node) |
125 | 0 | f->size_left_array[field] += diff; |
126 | 0 | node = p; |
127 | 0 | } |
128 | 0 | } Unexecuted instantiation: QFragmentMapData<QTextBlockData>::setSize(unsigned int, int, unsigned int) Unexecuted instantiation: QFragmentMapData<QTextFragmentData>::setSize(unsigned int, int, unsigned int) |
129 | | |
130 | | |
131 | | uint findNode(int k, uint field = 0) const; |
132 | | |
133 | | uint insert_single(int key, uint length); |
134 | | uint erase_single(uint f); |
135 | | |
136 | 0 | uint minimum(uint n) const { |
137 | 0 | while (n && fragment(n)->left) |
138 | 0 | n = fragment(n)->left; |
139 | 0 | return n; |
140 | 0 | } Unexecuted instantiation: QFragmentMapData<QTextFragmentData>::minimum(unsigned int) const Unexecuted instantiation: QFragmentMapData<QTextBlockData>::minimum(unsigned int) const |
141 | | |
142 | 0 | uint maximum(uint n) const { |
143 | 0 | while (n && fragment(n)->right) |
144 | 0 | n = fragment(n)->right; |
145 | 0 | return n; |
146 | 0 | } Unexecuted instantiation: QFragmentMapData<QTextBlockData>::maximum(unsigned int) const Unexecuted instantiation: QFragmentMapData<QTextFragmentData>::maximum(unsigned int) const |
147 | | |
148 | | uint next(uint n) const; |
149 | | uint previous(uint n) const; |
150 | | |
151 | 0 | inline uint root() const { |
152 | 0 | Q_ASSERT(!head->root || !fragment(head->root)->parent); |
153 | 0 | return head->root; |
154 | 0 | } Unexecuted instantiation: QFragmentMapData<QTextFragmentData>::root() const Unexecuted instantiation: QFragmentMapData<QTextBlockData>::root() const |
155 | | inline void setRoot(uint new_root) { |
156 | | Q_ASSERT(!head->root || !fragment(new_root)->parent); |
157 | | head->root = new_root; |
158 | | } |
159 | | |
160 | 0 | inline bool isValid(uint n) const { |
161 | 0 | return n > 0 && n != head->freelist; |
162 | 0 | } |
163 | | |
164 | | union { |
165 | | Header *head; |
166 | | Fragment *fragments; |
167 | | }; |
168 | | |
169 | | private: |
170 | | |
171 | | void rotateLeft(uint x); |
172 | | void rotateRight(uint x); |
173 | | void rebalance(uint x); |
174 | | void removeAndRebalance(uint z); |
175 | | |
176 | | uint createFragment(); |
177 | | void freeFragment(uint f); |
178 | | |
179 | | }; |
180 | | |
181 | | template <class Fragment> |
182 | | QFragmentMapData<Fragment>::QFragmentMapData() |
183 | 0 | : fragments(nullptr) |
184 | 0 | { |
185 | 0 | init(); |
186 | 0 | } Unexecuted instantiation: QFragmentMapData<QTextFragmentData>::QFragmentMapData() Unexecuted instantiation: QFragmentMapData<QTextBlockData>::QFragmentMapData() |
187 | | |
188 | | template <class Fragment> |
189 | | void QFragmentMapData<Fragment>::init() |
190 | 0 | { |
191 | | // the following code will realloc an existing fragment or create a new one. |
192 | | // it will also ignore errors when shrinking an existing fragment. |
193 | 0 | Fragment *newFragments = (Fragment *)realloc(fragments, 64*fragmentSize); |
194 | 0 | if (newFragments) { |
195 | 0 | fragments = newFragments; |
196 | 0 | head->allocated = 64; |
197 | 0 | } |
198 | 0 | Q_CHECK_PTR(fragments); |
199 | |
|
200 | 0 | head->tag = (((quint32)'p') << 24) | (((quint32)'m') << 16) | (((quint32)'a') << 8) | 'p'; //TAG('p', 'm', 'a', 'p'); |
201 | 0 | head->root = 0; |
202 | 0 | head->freelist = 1; |
203 | 0 | head->node_count = 0; |
204 | | // mark all items to the right as unused |
205 | 0 | F(head->freelist).right = 0; |
206 | 0 | } Unexecuted instantiation: QFragmentMapData<QTextFragmentData>::init() Unexecuted instantiation: QFragmentMapData<QTextBlockData>::init() |
207 | | |
208 | | template <class Fragment> |
209 | | QFragmentMapData<Fragment>::~QFragmentMapData() |
210 | 0 | { |
211 | 0 | free(fragments); |
212 | 0 | } Unexecuted instantiation: QFragmentMapData<QTextFragmentData>::~QFragmentMapData() Unexecuted instantiation: QFragmentMapData<QTextBlockData>::~QFragmentMapData() |
213 | | |
214 | | template <class Fragment> |
215 | | uint QFragmentMapData<Fragment>::createFragment() |
216 | 0 | { |
217 | 0 | Q_ASSERT(head->freelist <= head->allocated); |
218 | |
|
219 | 0 | uint freePos = head->freelist; |
220 | 0 | if (freePos == head->allocated) { |
221 | | // need to create some free space |
222 | 0 | auto blockInfo = qCalculateGrowingBlockSize(freePos + 1, fragmentSize); |
223 | 0 | Fragment *newFragments = (Fragment *)realloc(fragments, blockInfo.size); |
224 | 0 | Q_CHECK_PTR(newFragments); |
225 | 0 | fragments = newFragments; |
226 | 0 | head->allocated = quint32(blockInfo.elementCount); |
227 | 0 | F(freePos).right = 0; |
228 | 0 | } |
229 | |
|
230 | 0 | uint nextPos = F(freePos).right; |
231 | 0 | if (!nextPos) { |
232 | 0 | nextPos = freePos+1; |
233 | 0 | if (nextPos < head->allocated) |
234 | 0 | F(nextPos).right = 0; |
235 | 0 | } |
236 | |
|
237 | 0 | head->freelist = nextPos; |
238 | |
|
239 | 0 | ++head->node_count; |
240 | |
|
241 | 0 | return freePos; |
242 | 0 | } Unexecuted instantiation: QFragmentMapData<QTextFragmentData>::createFragment() Unexecuted instantiation: QFragmentMapData<QTextBlockData>::createFragment() |
243 | | |
244 | | template <class Fragment> |
245 | | void QFragmentMapData<Fragment>::freeFragment(uint i) |
246 | 0 | { |
247 | 0 | F(i).right = head->freelist; |
248 | 0 | head->freelist = i; |
249 | |
|
250 | 0 | --head->node_count; |
251 | 0 | } Unexecuted instantiation: QFragmentMapData<QTextFragmentData>::freeFragment(unsigned int) Unexecuted instantiation: QFragmentMapData<QTextBlockData>::freeFragment(unsigned int) |
252 | | |
253 | | |
254 | | template <class Fragment> |
255 | 0 | uint QFragmentMapData<Fragment>::next(uint n) const { |
256 | 0 | Q_ASSERT(n); |
257 | 0 | if (F(n).right) { |
258 | 0 | n = F(n).right; |
259 | 0 | while (F(n).left) |
260 | 0 | n = F(n).left; |
261 | 0 | } else { |
262 | 0 | uint y = F(n).parent; |
263 | 0 | while (F(n).parent && n == F(y).right) { |
264 | 0 | n = y; |
265 | 0 | y = F(y).parent; |
266 | 0 | } |
267 | 0 | n = y; |
268 | 0 | } |
269 | 0 | return n; |
270 | 0 | } Unexecuted instantiation: QFragmentMapData<QTextBlockData>::next(unsigned int) const Unexecuted instantiation: QFragmentMapData<QTextFragmentData>::next(unsigned int) const |
271 | | |
272 | | template <class Fragment> |
273 | 0 | uint QFragmentMapData<Fragment>::previous(uint n) const { |
274 | 0 | if (!n) |
275 | 0 | return maximum(root()); |
276 | | |
277 | 0 | if (F(n).left) { |
278 | 0 | n = F(n).left; |
279 | 0 | while (F(n).right) |
280 | 0 | n = F(n).right; |
281 | 0 | } else { |
282 | 0 | uint y = F(n).parent; |
283 | 0 | while (F(n).parent && n == F(y).left) { |
284 | 0 | n = y; |
285 | 0 | y = F(y).parent; |
286 | 0 | } |
287 | 0 | n = y; |
288 | 0 | } |
289 | 0 | return n; |
290 | 0 | } Unexecuted instantiation: QFragmentMapData<QTextFragmentData>::previous(unsigned int) const Unexecuted instantiation: QFragmentMapData<QTextBlockData>::previous(unsigned int) const |
291 | | |
292 | | |
293 | | /* |
294 | | x y |
295 | | \ / \ |
296 | | y --> x b |
297 | | / \ \ |
298 | | a b a |
299 | | */ |
300 | | template <class Fragment> |
301 | | void QFragmentMapData<Fragment>::rotateLeft(uint x) |
302 | 0 | { |
303 | 0 | uint p = F(x).parent; |
304 | 0 | uint y = F(x).right; |
305 | | |
306 | |
|
307 | 0 | if (y) { |
308 | 0 | F(x).right = F(y).left; |
309 | 0 | if (F(y).left) |
310 | 0 | F(F(y).left).parent = x; |
311 | 0 | F(y).left = x; |
312 | 0 | F(y).parent = p; |
313 | 0 | } else { |
314 | 0 | F(x).right = 0; |
315 | 0 | } |
316 | 0 | if (!p) { |
317 | 0 | Q_ASSERT(head->root == x); |
318 | 0 | head->root = y; |
319 | 0 | } |
320 | 0 | else if (x == F(p).left) |
321 | 0 | F(p).left = y; |
322 | 0 | else |
323 | 0 | F(p).right = y; |
324 | 0 | F(x).parent = y; |
325 | 0 | for (uint field = 0; field < Fragment::size_array_max; ++field) |
326 | 0 | F(y).size_left_array[field] += F(x).size_left_array[field] + F(x).size_array[field]; |
327 | 0 | } Unexecuted instantiation: QFragmentMapData<QTextFragmentData>::rotateLeft(unsigned int) Unexecuted instantiation: QFragmentMapData<QTextBlockData>::rotateLeft(unsigned int) |
328 | | |
329 | | |
330 | | /* |
331 | | x y |
332 | | / / \ |
333 | | y --> a x |
334 | | / \ / |
335 | | a b b |
336 | | */ |
337 | | template <class Fragment> |
338 | | void QFragmentMapData<Fragment>::rotateRight(uint x) |
339 | 0 | { |
340 | 0 | uint y = F(x).left; |
341 | 0 | uint p = F(x).parent; |
342 | |
|
343 | 0 | if (y) { |
344 | 0 | F(x).left = F(y).right; |
345 | 0 | if (F(y).right) |
346 | 0 | F(F(y).right).parent = x; |
347 | 0 | F(y).right = x; |
348 | 0 | F(y).parent = p; |
349 | 0 | } else { |
350 | 0 | F(x).left = 0; |
351 | 0 | } |
352 | 0 | if (!p) { |
353 | 0 | Q_ASSERT(head->root == x); |
354 | 0 | head->root = y; |
355 | 0 | } |
356 | 0 | else if (x == F(p).right) |
357 | 0 | F(p).right = y; |
358 | 0 | else |
359 | 0 | F(p).left = y; |
360 | 0 | F(x).parent = y; |
361 | 0 | for (uint field = 0; field < Fragment::size_array_max; ++field) |
362 | 0 | F(x).size_left_array[field] -= F(y).size_left_array[field] + F(y).size_array[field]; |
363 | 0 | } Unexecuted instantiation: QFragmentMapData<QTextFragmentData>::rotateRight(unsigned int) Unexecuted instantiation: QFragmentMapData<QTextBlockData>::rotateRight(unsigned int) |
364 | | |
365 | | |
366 | | template <class Fragment> |
367 | | void QFragmentMapData<Fragment>::rebalance(uint x) |
368 | 0 | { |
369 | 0 | F(x).color = Red; |
370 | |
|
371 | 0 | while (F(x).parent && F(F(x).parent).color == Red) { |
372 | 0 | uint p = F(x).parent; |
373 | 0 | uint pp = F(p).parent; |
374 | 0 | Q_ASSERT(pp); |
375 | 0 | if (p == F(pp).left) { |
376 | 0 | uint y = F(pp).right; |
377 | 0 | if (y && F(y).color == Red) { |
378 | 0 | F(p).color = Black; |
379 | 0 | F(y).color = Black; |
380 | 0 | F(pp).color = Red; |
381 | 0 | x = pp; |
382 | 0 | } else { |
383 | 0 | if (x == F(p).right) { |
384 | 0 | x = p; |
385 | 0 | rotateLeft(x); |
386 | 0 | p = F(x).parent; |
387 | 0 | pp = F(p).parent; |
388 | 0 | } |
389 | 0 | F(p).color = Black; |
390 | 0 | if (pp) { |
391 | 0 | F(pp).color = Red; |
392 | 0 | rotateRight(pp); |
393 | 0 | } |
394 | 0 | } |
395 | 0 | } else { |
396 | 0 | uint y = F(pp).left; |
397 | 0 | if (y && F(y).color == Red) { |
398 | 0 | F(p).color = Black; |
399 | 0 | F(y).color = Black; |
400 | 0 | F(pp).color = Red; |
401 | 0 | x = pp; |
402 | 0 | } else { |
403 | 0 | if (x == F(p).left) { |
404 | 0 | x = p; |
405 | 0 | rotateRight(x); |
406 | 0 | p = F(x).parent; |
407 | 0 | pp = F(p).parent; |
408 | 0 | } |
409 | 0 | F(p).color = Black; |
410 | 0 | if (pp) { |
411 | 0 | F(pp).color = Red; |
412 | 0 | rotateLeft(pp); |
413 | 0 | } |
414 | 0 | } |
415 | 0 | } |
416 | 0 | } |
417 | 0 | F(root()).color = Black; |
418 | 0 | } Unexecuted instantiation: QFragmentMapData<QTextFragmentData>::rebalance(unsigned int) Unexecuted instantiation: QFragmentMapData<QTextBlockData>::rebalance(unsigned int) |
419 | | |
420 | | |
421 | | template <class Fragment> |
422 | | uint QFragmentMapData<Fragment>::erase_single(uint z) |
423 | 0 | { |
424 | 0 | uint w = previous(z); |
425 | 0 | uint y = z; |
426 | 0 | uint x; |
427 | 0 | uint p; |
428 | |
|
429 | 0 | if (!F(y).left) { |
430 | 0 | x = F(y).right; |
431 | 0 | } else if (!F(y).right) { |
432 | 0 | x = F(y).left; |
433 | 0 | } else { |
434 | 0 | y = F(y).right; |
435 | 0 | while (F(y).left) |
436 | 0 | y = F(y).left; |
437 | 0 | x = F(y).right; |
438 | 0 | } |
439 | |
|
440 | 0 | if (y != z) { |
441 | 0 | F(F(z).left).parent = y; |
442 | 0 | F(y).left = F(z).left; |
443 | 0 | for (uint field = 0; field < Fragment::size_array_max; ++field) |
444 | 0 | F(y).size_left_array[field] = F(z).size_left_array[field]; |
445 | 0 | if (y != F(z).right) { |
446 | | /* |
447 | | z y |
448 | | / \ / \ |
449 | | a b a b |
450 | | / / |
451 | | ... --> ... |
452 | | / / |
453 | | y x |
454 | | / \ |
455 | | 0 x |
456 | | */ |
457 | 0 | p = F(y).parent; |
458 | 0 | if (x) |
459 | 0 | F(x).parent = p; |
460 | 0 | F(p).left = x; |
461 | 0 | F(y).right = F(z).right; |
462 | 0 | F(F(z).right).parent = y; |
463 | 0 | uint n = p; |
464 | 0 | while (n != y) { |
465 | 0 | for (uint field = 0; field < Fragment::size_array_max; ++field) |
466 | 0 | F(n).size_left_array[field] -= F(y).size_array[field]; |
467 | 0 | n = F(n).parent; |
468 | 0 | } |
469 | 0 | } else { |
470 | | /* |
471 | | z y |
472 | | / \ / \ |
473 | | a y --> a x |
474 | | / \ |
475 | | 0 x |
476 | | */ |
477 | 0 | p = y; |
478 | 0 | } |
479 | 0 | uint zp = F(z).parent; |
480 | 0 | if (!zp) { |
481 | 0 | Q_ASSERT(head->root == z); |
482 | 0 | head->root = y; |
483 | 0 | } else if (F(zp).left == z) { |
484 | 0 | F(zp).left = y; |
485 | 0 | for (uint field = 0; field < Fragment::size_array_max; ++field) |
486 | 0 | F(zp).size_left_array[field] -= F(z).size_array[field]; |
487 | 0 | } else { |
488 | 0 | F(zp).right = y; |
489 | 0 | } |
490 | 0 | F(y).parent = zp; |
491 | | // Swap the colors |
492 | 0 | uint c = F(y).color; |
493 | 0 | F(y).color = F(z).color; |
494 | 0 | F(z).color = c; |
495 | 0 | y = z; |
496 | 0 | } else { |
497 | | /* |
498 | | p p p p |
499 | | / / \ \ |
500 | | z --> x z --> x |
501 | | | | |
502 | | x x |
503 | | */ |
504 | 0 | p = F(z).parent; |
505 | 0 | if (x) |
506 | 0 | F(x).parent = p; |
507 | 0 | if (!p) { |
508 | 0 | Q_ASSERT(head->root == z); |
509 | 0 | head->root = x; |
510 | 0 | } else if (F(p).left == z) { |
511 | 0 | F(p).left = x; |
512 | 0 | for (uint field = 0; field < Fragment::size_array_max; ++field) |
513 | 0 | F(p).size_left_array[field] -= F(z).size_array[field]; |
514 | 0 | } else { |
515 | 0 | F(p).right = x; |
516 | 0 | } |
517 | 0 | } |
518 | 0 | uint n = z; |
519 | 0 | while (F(n).parent) { |
520 | 0 | uint p = F(n).parent; |
521 | 0 | if (F(p).left == n) { |
522 | 0 | for (uint field = 0; field < Fragment::size_array_max; ++field) |
523 | 0 | F(p).size_left_array[field] -= F(z).size_array[field]; |
524 | 0 | } |
525 | 0 | n = p; |
526 | 0 | } |
527 | |
|
528 | 0 | freeFragment(z); |
529 | | |
530 | |
|
531 | 0 | if (F(y).color != Red) { |
532 | 0 | while (F(x).parent && (x == 0 || F(x).color == Black)) { |
533 | 0 | if (x == F(p).left) { |
534 | 0 | uint w = F(p).right; |
535 | 0 | if (F(w).color == Red) { |
536 | 0 | F(w).color = Black; |
537 | 0 | F(p).color = Red; |
538 | 0 | rotateLeft(p); |
539 | 0 | w = F(p).right; |
540 | 0 | } |
541 | 0 | if ((F(w).left == 0 || F(F(w).left).color == Black) && |
542 | 0 | (F(w).right == 0 || F(F(w).right).color == Black)) { |
543 | 0 | F(w).color = Red; |
544 | 0 | x = p; |
545 | 0 | p = F(x).parent; |
546 | 0 | } else { |
547 | 0 | if (F(w).right == 0 || F(F(w).right).color == Black) { |
548 | 0 | if (F(w).left) |
549 | 0 | F(F(w).left).color = Black; |
550 | 0 | F(w).color = Red; |
551 | 0 | rotateRight(F(p).right); |
552 | 0 | w = F(p).right; |
553 | 0 | } |
554 | 0 | F(w).color = F(p).color; |
555 | 0 | F(p).color = Black; |
556 | 0 | if (F(w).right) |
557 | 0 | F(F(w).right).color = Black; |
558 | 0 | rotateLeft(p); |
559 | 0 | break; |
560 | 0 | } |
561 | 0 | } else { |
562 | 0 | uint w = F(p).left; |
563 | 0 | if (F(w).color == Red) { |
564 | 0 | F(w).color = Black; |
565 | 0 | F(p).color = Red; |
566 | 0 | rotateRight(p); |
567 | 0 | w = F(p).left; |
568 | 0 | } |
569 | 0 | if ((F(w).right == 0 || F(F(w).right).color == Black) && |
570 | 0 | (F(w).left == 0 || F(F(w).left).color == Black)) { |
571 | 0 | F(w).color = Red; |
572 | 0 | x = p; |
573 | 0 | p = F(x).parent; |
574 | 0 | } else { |
575 | 0 | if (F(w).left == 0 || F(F(w).left).color == Black) { |
576 | 0 | if (F(w).right) |
577 | 0 | F(F(w).right).color = Black; |
578 | 0 | F(w).color = Red; |
579 | 0 | rotateLeft(F(p).left); |
580 | 0 | w = F(p).left; |
581 | 0 | } |
582 | 0 | F(w).color = F(p).color; |
583 | 0 | F(p).color = Black; |
584 | 0 | if (F(w).left) |
585 | 0 | F(F(w).left).color = Black; |
586 | 0 | rotateRight(p); |
587 | 0 | break; |
588 | 0 | } |
589 | 0 | } |
590 | 0 | } |
591 | 0 | if (x) |
592 | 0 | F(x).color = Black; |
593 | 0 | } |
594 | |
|
595 | 0 | return w; |
596 | 0 | } Unexecuted instantiation: QFragmentMapData<QTextFragmentData>::erase_single(unsigned int) Unexecuted instantiation: QFragmentMapData<QTextBlockData>::erase_single(unsigned int) |
597 | | |
598 | | template <class Fragment> |
599 | | uint QFragmentMapData<Fragment>::findNode(int k, uint field) const |
600 | 0 | { |
601 | 0 | Q_ASSERT(field < Fragment::size_array_max); |
602 | 0 | uint x = root(); |
603 | |
|
604 | 0 | uint s = k; |
605 | 0 | while (x) { |
606 | 0 | if (sizeLeft(x, field) <= s) { |
607 | 0 | if (s < sizeLeft(x, field) + size(x, field)) |
608 | 0 | return x; |
609 | 0 | s -= sizeLeft(x, field) + size(x, field); |
610 | 0 | x = F(x).right; |
611 | 0 | } else { |
612 | 0 | x = F(x).left; |
613 | 0 | } |
614 | 0 | } |
615 | 0 | return 0; |
616 | 0 | } Unexecuted instantiation: QFragmentMapData<QTextFragmentData>::findNode(int, unsigned int) const Unexecuted instantiation: QFragmentMapData<QTextBlockData>::findNode(int, unsigned int) const |
617 | | |
618 | | template <class Fragment> |
619 | | uint QFragmentMapData<Fragment>::insert_single(int key, uint length) |
620 | 0 | { |
621 | 0 | Q_ASSERT(!findNode(key) || (int)this->position(findNode(key)) == key); |
622 | |
|
623 | 0 | uint z = createFragment(); |
624 | |
|
625 | 0 | F(z).left = 0; |
626 | 0 | F(z).right = 0; |
627 | 0 | F(z).size_array[0] = length; |
628 | 0 | for (uint field = 1; field < Fragment::size_array_max; ++field) |
629 | 0 | F(z).size_array[field] = 1; |
630 | 0 | for (uint field = 0; field < Fragment::size_array_max; ++field) |
631 | 0 | F(z).size_left_array[field] = 0; |
632 | |
|
633 | 0 | uint y = 0; |
634 | 0 | uint x = root(); |
635 | |
|
636 | 0 | Q_ASSERT(!x || F(x).parent == 0); |
637 | |
|
638 | 0 | uint s = key; |
639 | 0 | bool right = false; |
640 | 0 | while (x) { |
641 | 0 | y = x; |
642 | 0 | if (s <= F(x).size_left_array[0]) { |
643 | 0 | x = F(x).left; |
644 | 0 | right = false; |
645 | 0 | } else { |
646 | 0 | s -= F(x).size_left_array[0] + F(x).size_array[0]; |
647 | 0 | x = F(x).right; |
648 | 0 | right = true; |
649 | 0 | } |
650 | 0 | } |
651 | |
|
652 | 0 | F(z).parent = y; |
653 | 0 | if (!y) { |
654 | 0 | head->root = z; |
655 | 0 | } else if (!right) { |
656 | 0 | F(y).left = z; |
657 | 0 | for (uint field = 0; field < Fragment::size_array_max; ++field) |
658 | 0 | F(y).size_left_array[field] = F(z).size_array[field]; |
659 | 0 | } else { |
660 | 0 | F(y).right = z; |
661 | 0 | } |
662 | 0 | while (y && F(y).parent) { |
663 | 0 | uint p = F(y).parent; |
664 | 0 | if (F(p).left == y) { |
665 | 0 | for (uint field = 0; field < Fragment::size_array_max; ++field) |
666 | 0 | F(p).size_left_array[field] += F(z).size_array[field]; |
667 | 0 | } |
668 | 0 | y = p; |
669 | 0 | } |
670 | 0 | rebalance(z); |
671 | |
|
672 | 0 | return z; |
673 | 0 | } Unexecuted instantiation: QFragmentMapData<QTextFragmentData>::insert_single(int, unsigned int) Unexecuted instantiation: QFragmentMapData<QTextBlockData>::insert_single(int, unsigned int) |
674 | | |
675 | | |
676 | | template <class Fragment> |
677 | 0 | int QFragmentMapData<Fragment>::length(uint field) const { |
678 | 0 | uint root = this->root(); |
679 | 0 | return root ? sizeLeft(root, field) + size(root, field) + sizeRight(root, field) : 0; |
680 | 0 | } Unexecuted instantiation: QFragmentMapData<QTextFragmentData>::length(unsigned int) const Unexecuted instantiation: QFragmentMapData<QTextBlockData>::length(unsigned int) const |
681 | | |
682 | | |
683 | | template <class Fragment> // NOTE: must inherit QFragment |
684 | | class QFragmentMap |
685 | | { |
686 | | public: |
687 | | class Iterator |
688 | | { |
689 | | public: |
690 | | QFragmentMap *pt; |
691 | | quint32 n; |
692 | | |
693 | | Iterator() : pt(0), n(0) {} |
694 | 0 | Iterator(QFragmentMap *p, int node) : pt(p), n(node) {}Unexecuted instantiation: QFragmentMap<QTextBlockData>::Iterator::Iterator(QFragmentMap<QTextBlockData>*, int) Unexecuted instantiation: QFragmentMap<QTextFragmentData>::Iterator::Iterator(QFragmentMap<QTextFragmentData>*, int) |
695 | | Iterator(const Iterator& it) : pt(it.pt), n(it.n) {} |
696 | | |
697 | 0 | inline bool atEnd() const { return !n; }Unexecuted instantiation: QFragmentMap<QTextBlockData>::Iterator::atEnd() const Unexecuted instantiation: QFragmentMap<QTextFragmentData>::Iterator::atEnd() const |
698 | | |
699 | | bool operator==(const Iterator& it) const { return pt == it.pt && n == it.n; } |
700 | | bool operator!=(const Iterator& it) const { return pt != it.pt || n != it.n; } |
701 | | bool operator<(const Iterator &it) const { return position() < it.position(); } |
702 | | |
703 | | Fragment *operator*() { Q_ASSERT(!atEnd()); return pt->fragment(n); } |
704 | | const Fragment *operator*() const { Q_ASSERT(!atEnd()); return pt->fragment(n); } |
705 | 0 | Fragment *operator->() { Q_ASSERT(!atEnd()); return pt->fragment(n); }Unexecuted instantiation: QFragmentMap<QTextBlockData>::Iterator::operator->() Unexecuted instantiation: QFragmentMap<QTextFragmentData>::Iterator::operator->() |
706 | | const Fragment *operator->() const { Q_ASSERT(!atEnd()); return pt->fragment(n); } |
707 | | |
708 | 0 | int position() const { Q_ASSERT(!atEnd()); return pt->data.position(n); } |
709 | | const Fragment *value() const { Q_ASSERT(!atEnd()); return pt->fragment(n); } |
710 | 0 | Fragment *value() { Q_ASSERT(!atEnd()); return pt->fragment(n); }Unexecuted instantiation: QFragmentMap<QTextBlockData>::Iterator::value() Unexecuted instantiation: QFragmentMap<QTextFragmentData>::Iterator::value() |
711 | | |
712 | 0 | Iterator& operator++() { |
713 | 0 | n = pt->data.next(n); |
714 | 0 | return *this; |
715 | 0 | } Unexecuted instantiation: QFragmentMap<QTextBlockData>::Iterator::operator++() Unexecuted instantiation: QFragmentMap<QTextFragmentData>::Iterator::operator++() |
716 | | Iterator& operator--() { |
717 | | n = pt->data.previous(n); |
718 | | return *this; |
719 | | } |
720 | | |
721 | | }; |
722 | | |
723 | | |
724 | | class ConstIterator |
725 | | { |
726 | | public: |
727 | | const QFragmentMap *pt; |
728 | | quint32 n; |
729 | | |
730 | | /** |
731 | | * Functions |
732 | | */ |
733 | | ConstIterator() : pt(0), n(0) {} |
734 | 0 | ConstIterator(const QFragmentMap *p, int node) : pt(p), n(node) {}Unexecuted instantiation: QFragmentMap<QTextFragmentData>::ConstIterator::ConstIterator(QFragmentMap<QTextFragmentData> const*, int) Unexecuted instantiation: QFragmentMap<QTextBlockData>::ConstIterator::ConstIterator(QFragmentMap<QTextBlockData> const*, int) |
735 | | ConstIterator(const ConstIterator& it) : pt(it.pt), n(it.n) {} |
736 | | ConstIterator(const Iterator& it) : pt(it.pt), n(it.n) {} |
737 | | |
738 | 0 | inline bool atEnd() const { return !n; } |
739 | | |
740 | 0 | bool operator==(const ConstIterator& it) const { return pt == it.pt && n == it.n; } |
741 | 0 | bool operator!=(const ConstIterator& it) const { return pt != it.pt || n != it.n; } |
742 | | bool operator<(const ConstIterator &it) const { return position() < it.position(); } |
743 | | |
744 | 0 | const Fragment *operator*() const { Q_ASSERT(!atEnd()); return pt->fragment(n); } |
745 | 0 | const Fragment *operator->() const { Q_ASSERT(!atEnd()); return pt->fragment(n); } |
746 | | |
747 | 0 | int position() const { Q_ASSERT(!atEnd()); return pt->data.position(n); } |
748 | 0 | int size() const { Q_ASSERT(!atEnd()); return pt->data.size(n); } |
749 | 0 | const Fragment *value() const { Q_ASSERT(!atEnd()); return pt->fragment(n); } |
750 | | |
751 | 0 | ConstIterator& operator++() { |
752 | 0 | n = pt->data.next(n); |
753 | 0 | return *this; |
754 | 0 | } |
755 | | ConstIterator& operator--() { |
756 | | n = pt->data.previous(n); |
757 | | return *this; |
758 | | } |
759 | | }; |
760 | | |
761 | | |
762 | 0 | QFragmentMap() {}Unexecuted instantiation: QFragmentMap<QTextFragmentData>::QFragmentMap() Unexecuted instantiation: QFragmentMap<QTextBlockData>::QFragmentMap() |
763 | | ~QFragmentMap() |
764 | 0 | { |
765 | 0 | if (!data.fragments) |
766 | 0 | return; // in case of out-of-memory, we won't have fragments |
767 | 0 | for (Iterator it = begin(); !it.atEnd(); ++it) |
768 | 0 | it.value()->free(); |
769 | 0 | } Unexecuted instantiation: QFragmentMap<QTextFragmentData>::~QFragmentMap() Unexecuted instantiation: QFragmentMap<QTextBlockData>::~QFragmentMap() |
770 | | |
771 | 0 | inline void clear() { |
772 | 0 | for (Iterator it = begin(); !it.atEnd(); ++it) |
773 | 0 | it.value()->free(); |
774 | 0 | data.init(); |
775 | 0 | } Unexecuted instantiation: QFragmentMap<QTextFragmentData>::clear() Unexecuted instantiation: QFragmentMap<QTextBlockData>::clear() |
776 | | |
777 | 0 | inline Iterator begin() { return Iterator(this, data.minimum(data.root())); }Unexecuted instantiation: QFragmentMap<QTextBlockData>::begin() Unexecuted instantiation: QFragmentMap<QTextFragmentData>::begin() |
778 | | inline Iterator end() { return Iterator(this, 0); } |
779 | 0 | inline ConstIterator begin() const { return ConstIterator(this, data.minimum(data.root())); }Unexecuted instantiation: QFragmentMap<QTextFragmentData>::begin() const Unexecuted instantiation: QFragmentMap<QTextBlockData>::begin() const |
780 | 0 | inline ConstIterator end() const { return ConstIterator(this, 0); } |
781 | | |
782 | 0 | inline ConstIterator last() const { return ConstIterator(this, data.maximum(data.root())); } |
783 | | |
784 | | inline bool isEmpty() const { return data.head->node_count == 0; } |
785 | 0 | inline int numNodes() const { return data.head->node_count; } |
786 | 0 | int length(uint field = 0) const { return data.length(field); }Unexecuted instantiation: QFragmentMap<QTextFragmentData>::length(unsigned int) const Unexecuted instantiation: QFragmentMap<QTextBlockData>::length(unsigned int) const |
787 | | |
788 | 0 | Iterator find(int k, uint field = 0) { return Iterator(this, data.findNode(k, field)); }Unexecuted instantiation: QFragmentMap<QTextFragmentData>::find(int, unsigned int) Unexecuted instantiation: QFragmentMap<QTextBlockData>::find(int, unsigned int) |
789 | 0 | ConstIterator find(int k, uint field = 0) const { return ConstIterator(this, data.findNode(k, field)); } |
790 | | |
791 | 0 | uint findNode(int k, uint field = 0) const { return data.findNode(k, field); }Unexecuted instantiation: QFragmentMap<QTextBlockData>::findNode(int, unsigned int) const Unexecuted instantiation: QFragmentMap<QTextFragmentData>::findNode(int, unsigned int) const |
792 | | |
793 | | uint insert_single(int key, uint length) |
794 | 0 | { |
795 | 0 | uint f = data.insert_single(key, length); |
796 | 0 | if (f != 0) { |
797 | 0 | Fragment *frag = fragment(f); |
798 | 0 | Q_ASSERT(frag); |
799 | 0 | frag->initialize(); |
800 | 0 | } |
801 | 0 | return f; |
802 | 0 | } Unexecuted instantiation: QFragmentMap<QTextFragmentData>::insert_single(int, unsigned int) Unexecuted instantiation: QFragmentMap<QTextBlockData>::insert_single(int, unsigned int) |
803 | | uint erase_single(uint f) |
804 | 0 | { |
805 | 0 | if (f != 0) { |
806 | 0 | Fragment *frag = fragment(f); |
807 | 0 | Q_ASSERT(frag); |
808 | 0 | frag->free(); |
809 | 0 | } |
810 | 0 | return data.erase_single(f); |
811 | 0 | } Unexecuted instantiation: QFragmentMap<QTextFragmentData>::erase_single(unsigned int) Unexecuted instantiation: QFragmentMap<QTextBlockData>::erase_single(unsigned int) |
812 | | |
813 | 0 | inline Fragment *fragment(uint index) { |
814 | 0 | Q_ASSERT(index != 0); |
815 | 0 | return data.fragment(index); |
816 | 0 | } Unexecuted instantiation: QFragmentMap<QTextBlockData>::fragment(unsigned int) Unexecuted instantiation: QFragmentMap<QTextFragmentData>::fragment(unsigned int) |
817 | 0 | inline const Fragment *fragment(uint index) const { |
818 | 0 | Q_ASSERT(index != 0); |
819 | 0 | return data.fragment(index); |
820 | 0 | } Unexecuted instantiation: QFragmentMap<QTextFragmentData>::fragment(unsigned int) const Unexecuted instantiation: QFragmentMap<QTextBlockData>::fragment(unsigned int) const |
821 | 0 | inline uint position(uint node, uint field = 0) const { return data.position(node, field); }Unexecuted instantiation: QFragmentMap<QTextBlockData>::position(unsigned int, unsigned int) const Unexecuted instantiation: QFragmentMap<QTextFragmentData>::position(unsigned int, unsigned int) const |
822 | 0 | inline bool isValid(uint n) const { return data.isValid(n); } |
823 | 0 | inline uint next(uint n) const { return data.next(n); }Unexecuted instantiation: QFragmentMap<QTextBlockData>::next(unsigned int) const Unexecuted instantiation: QFragmentMap<QTextFragmentData>::next(unsigned int) const |
824 | 0 | inline uint previous(uint n) const { return data.previous(n); }Unexecuted instantiation: QFragmentMap<QTextFragmentData>::previous(unsigned int) const Unexecuted instantiation: QFragmentMap<QTextBlockData>::previous(unsigned int) const |
825 | 0 | inline uint size(uint node, uint field = 0) const { return data.size(node, field); }Unexecuted instantiation: QFragmentMap<QTextBlockData>::size(unsigned int, unsigned int) const Unexecuted instantiation: QFragmentMap<QTextFragmentData>::size(unsigned int, unsigned int) const |
826 | | inline void setSize(uint node, int new_size, uint field = 0) |
827 | 0 | { data.setSize(node, new_size, field); |
828 | 0 | if (node != 0 && field == 0) { |
829 | 0 | Fragment *frag = fragment(node); |
830 | 0 | Q_ASSERT(frag); |
831 | 0 | frag->invalidate(); |
832 | 0 | } |
833 | 0 | } Unexecuted instantiation: QFragmentMap<QTextBlockData>::setSize(unsigned int, int, unsigned int) Unexecuted instantiation: QFragmentMap<QTextFragmentData>::setSize(unsigned int, int, unsigned int) |
834 | | |
835 | 0 | inline int firstNode() const { return data.minimum(data.root()); } |
836 | | |
837 | | private: |
838 | | friend class Iterator; |
839 | | friend class ConstIterator; |
840 | | |
841 | | QFragmentMapData<Fragment> data; |
842 | | |
843 | | QFragmentMap(const QFragmentMap& m); |
844 | | QFragmentMap& operator= (const QFragmentMap& m); |
845 | | }; |
846 | | |
847 | | QT_END_NAMESPACE |
848 | | |
849 | | #endif // QFRAGMENTMAP_P_H |