diff options
Diffstat (limited to 'src/itree.c')
| -rw-r--r-- | src/itree.c | 199 |
1 files changed, 16 insertions, 183 deletions
diff --git a/src/itree.c b/src/itree.c index 9e60071980d..e4d5fb304b7 100644 --- a/src/itree.c +++ b/src/itree.c | |||
| @@ -131,33 +131,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 131 | * | Stack | 131 | * | Stack |
| 132 | * +=======================================================================+ */ | 132 | * +=======================================================================+ */ |
| 133 | 133 | ||
| 134 | typedef uintptr_t nodeptr_and_flag; | ||
| 135 | |||
| 136 | static inline nodeptr_and_flag | ||
| 137 | make_nav (struct itree_node *ptr, bool flag) | ||
| 138 | { | ||
| 139 | uintptr_t v = (uintptr_t) ptr; | ||
| 140 | /* We assume alignment imposes the LSB is clear for us to use it. */ | ||
| 141 | eassert (!(v & 1)); | ||
| 142 | return v | !!flag; | ||
| 143 | } | ||
| 144 | |||
| 145 | static inline struct itree_node * | ||
| 146 | nav_nodeptr (nodeptr_and_flag nav) | ||
| 147 | { | ||
| 148 | return (struct itree_node *) (nav & (~(uintptr_t)1)); | ||
| 149 | } | ||
| 150 | |||
| 151 | static inline bool | ||
| 152 | nav_flag (nodeptr_and_flag nav) | ||
| 153 | { | ||
| 154 | return (bool) (nav & 1); | ||
| 155 | } | ||
| 156 | |||
| 157 | /* Simple dynamic array. */ | 134 | /* Simple dynamic array. */ |
| 158 | struct itree_stack | 135 | struct itree_stack |
| 159 | { | 136 | { |
| 160 | nodeptr_and_flag *nodes; | 137 | struct itree_node **nodes; |
| 161 | size_t size; | 138 | size_t size; |
| 162 | size_t length; | 139 | size_t length; |
| 163 | }; | 140 | }; |
| @@ -184,12 +161,6 @@ itree_stack_destroy (struct itree_stack *stack) | |||
| 184 | xfree (stack); | 161 | xfree (stack); |
| 185 | } | 162 | } |
| 186 | 163 | ||
| 187 | static void | ||
| 188 | itree_stack_clear (struct itree_stack *stack) | ||
| 189 | { | ||
| 190 | stack->length = 0; | ||
| 191 | } | ||
| 192 | |||
| 193 | static inline void | 164 | static inline void |
| 194 | itree_stack_ensure_space (struct itree_stack *stack, uintmax_t nelements) | 165 | itree_stack_ensure_space (struct itree_stack *stack, uintmax_t nelements) |
| 195 | { | 166 | { |
| @@ -204,34 +175,20 @@ itree_stack_ensure_space (struct itree_stack *stack, uintmax_t nelements) | |||
| 204 | /* Push NODE on the STACK, while settings its visited flag to FLAG. */ | 175 | /* Push NODE on the STACK, while settings its visited flag to FLAG. */ |
| 205 | 176 | ||
| 206 | static inline void | 177 | static inline void |
| 207 | itree_stack_push_flagged (struct itree_stack *stack, | 178 | itree_stack_push (struct itree_stack *stack, struct itree_node *node) |
| 208 | struct itree_node *node, bool flag) | ||
| 209 | { | 179 | { |
| 210 | eassert (node); | 180 | eassert (node); |
| 211 | |||
| 212 | /* FIXME: While the stack used in the iterator is bounded by the tree | ||
| 213 | depth and could be easily pre-allocated to a large enough size to avoid | ||
| 214 | this "ensure" check, `itree_stack_push` is also used elsewhere to | ||
| 215 | simply collect some subset of the overlays, where it's only bounded by | ||
| 216 | the total number of overlays in the buffer (which can be large and thus | ||
| 217 | preferably not pre-allocated needlessly). */ | ||
| 218 | itree_stack_ensure_space (stack, stack->length + 1); | 181 | itree_stack_ensure_space (stack, stack->length + 1); |
| 219 | 182 | ||
| 220 | stack->nodes[stack->length] = make_nav (node, flag); | 183 | stack->nodes[stack->length] = node; |
| 221 | stack->length++; | 184 | stack->length++; |
| 222 | } | 185 | } |
| 223 | 186 | ||
| 224 | static inline void | 187 | static inline struct itree_node * |
| 225 | itree_stack_push (struct itree_stack *stack, struct itree_node *node) | ||
| 226 | { | ||
| 227 | itree_stack_push_flagged (stack, node, false); | ||
| 228 | } | ||
| 229 | |||
| 230 | static inline nodeptr_and_flag | ||
| 231 | itree_stack_pop (struct itree_stack *stack) | 188 | itree_stack_pop (struct itree_stack *stack) |
| 232 | { | 189 | { |
| 233 | if (stack->length == 0) | 190 | if (stack->length == 0) |
| 234 | return make_nav (NULL, false); | 191 | return NULL; |
| 235 | return stack->nodes[--stack->length]; | 192 | return stack->nodes[--stack->length]; |
| 236 | } | 193 | } |
| 237 | 194 | ||
| @@ -815,10 +772,7 @@ itree_contains (struct itree_tree *tree, struct itree_node *node) | |||
| 815 | struct itree_node *other; | 772 | struct itree_node *other; |
| 816 | ITREE_FOREACH (other, tree, node->begin, PTRDIFF_MAX, ASCENDING) | 773 | ITREE_FOREACH (other, tree, node->begin, PTRDIFF_MAX, ASCENDING) |
| 817 | if (other == node) | 774 | if (other == node) |
| 818 | { | 775 | return true; |
| 819 | ITREE_FOREACH_ABORT (); | ||
| 820 | return true; | ||
| 821 | } | ||
| 822 | 776 | ||
| 823 | return false; | 777 | return false; |
| 824 | } | 778 | } |
| @@ -1122,7 +1076,7 @@ itree_insert_gap (struct itree_tree *tree, | |||
| 1122 | } | 1076 | } |
| 1123 | } | 1077 | } |
| 1124 | for (size_t i = 0; i < saved->length; ++i) | 1078 | for (size_t i = 0; i < saved->length; ++i) |
| 1125 | itree_remove (tree, nav_nodeptr (saved->nodes[i])); | 1079 | itree_remove (tree, saved->nodes[i]); |
| 1126 | 1080 | ||
| 1127 | /* We can't use an iterator here, because we can't effectively | 1081 | /* We can't use an iterator here, because we can't effectively |
| 1128 | narrow AND shift some subtree at the same time. */ | 1082 | narrow AND shift some subtree at the same time. */ |
| @@ -1131,9 +1085,7 @@ itree_insert_gap (struct itree_tree *tree, | |||
| 1131 | const int size = itree_max_height (tree) + 1; | 1085 | const int size = itree_max_height (tree) + 1; |
| 1132 | struct itree_stack *stack = itree_stack_create (size); | 1086 | struct itree_stack *stack = itree_stack_create (size); |
| 1133 | itree_stack_push (stack, tree->root); | 1087 | itree_stack_push (stack, tree->root); |
| 1134 | nodeptr_and_flag nav; | 1088 | while ((node = itree_stack_pop (stack))) |
| 1135 | while ((nav = itree_stack_pop (stack), | ||
| 1136 | node = nav_nodeptr (nav))) | ||
| 1137 | { | 1089 | { |
| 1138 | /* Process in pre-order. */ | 1090 | /* Process in pre-order. */ |
| 1139 | itree_inherit_offset (tree->otick, node); | 1091 | itree_inherit_offset (tree->otick, node); |
| @@ -1170,9 +1122,7 @@ itree_insert_gap (struct itree_tree *tree, | |||
| 1170 | 1122 | ||
| 1171 | /* Reinsert nodes starting at POS having front-advance. */ | 1123 | /* Reinsert nodes starting at POS having front-advance. */ |
| 1172 | uintmax_t notick = tree->otick; | 1124 | uintmax_t notick = tree->otick; |
| 1173 | nodeptr_and_flag nav; | 1125 | while ((node = itree_stack_pop (saved))) |
| 1174 | while ((nav = itree_stack_pop (saved), | ||
| 1175 | node = nav_nodeptr (nav))) | ||
| 1176 | { | 1126 | { |
| 1177 | eassert (node->otick == ootick); | 1127 | eassert (node->otick == ootick); |
| 1178 | eassert (node->begin == pos); | 1128 | eassert (node->begin == pos); |
| @@ -1205,10 +1155,8 @@ itree_delete_gap (struct itree_tree *tree, | |||
| 1205 | struct itree_node *node; | 1155 | struct itree_node *node; |
| 1206 | 1156 | ||
| 1207 | itree_stack_push (stack, tree->root); | 1157 | itree_stack_push (stack, tree->root); |
| 1208 | nodeptr_and_flag nav; | 1158 | while ((node = itree_stack_pop (stack))) |
| 1209 | while ((nav = itree_stack_pop (stack))) | ||
| 1210 | { | 1159 | { |
| 1211 | node = nav_nodeptr (nav); | ||
| 1212 | itree_inherit_offset (tree->otick, node); | 1160 | itree_inherit_offset (tree->otick, node); |
| 1213 | if (pos > node->limit) | 1161 | if (pos > node->limit) |
| 1214 | continue; | 1162 | continue; |
| @@ -1244,16 +1192,6 @@ itree_delete_gap (struct itree_tree *tree, | |||
| 1244 | * | Iterator | 1192 | * | Iterator |
| 1245 | * +=======================================================================+ */ | 1193 | * +=======================================================================+ */ |
| 1246 | 1194 | ||
| 1247 | /* Stop using the iterator. */ | ||
| 1248 | |||
| 1249 | void | ||
| 1250 | itree_iterator_finish (struct itree_iterator *iter) | ||
| 1251 | { | ||
| 1252 | eassert (iter && iter->running); | ||
| 1253 | itree_stack_destroy (iter->stack); | ||
| 1254 | iter->running = false; | ||
| 1255 | } | ||
| 1256 | |||
| 1257 | /* Return true, if NODE's interval intersects with [BEGIN, END). | 1195 | /* Return true, if NODE's interval intersects with [BEGIN, END). |
| 1258 | Note: We always include empty nodes at BEGIN (and not at END), | 1196 | Note: We always include empty nodes at BEGIN (and not at END), |
| 1259 | but if BEGIN==END, then we don't include non-empty nodes starting | 1197 | but if BEGIN==END, then we don't include non-empty nodes starting |
| @@ -1436,7 +1374,7 @@ itree_iterator_first_node (struct itree_tree *tree, | |||
| 1436 | } | 1374 | } |
| 1437 | 1375 | ||
| 1438 | /* Start a iterator enumerating all intervals in [BEGIN,END) in the | 1376 | /* Start a iterator enumerating all intervals in [BEGIN,END) in the |
| 1439 | given ORDER. Only one iterator per tree can be running at any time. */ | 1377 | given ORDER. */ |
| 1440 | 1378 | ||
| 1441 | struct itree_iterator * | 1379 | struct itree_iterator * |
| 1442 | itree_iterator_start (struct itree_iterator *iter, | 1380 | itree_iterator_start (struct itree_iterator *iter, |
| @@ -1444,133 +1382,28 @@ itree_iterator_start (struct itree_iterator *iter, | |||
| 1444 | ptrdiff_t begin, ptrdiff_t end, enum itree_order order) | 1382 | ptrdiff_t begin, ptrdiff_t end, enum itree_order order) |
| 1445 | { | 1383 | { |
| 1446 | eassert (iter); | 1384 | eassert (iter); |
| 1447 | /* eassert (!iter->running); */ | ||
| 1448 | /* 19 here just avoids starting with a silly-small stack. | ||
| 1449 | FIXME: Since this stack only needs to be about 2*max_depth | ||
| 1450 | in the worst case, we could completely pre-allocate it to something | ||
| 1451 | like word-bit-size * 2 and then never worry about growing it. */ | ||
| 1452 | const int size = (tree ? itree_max_height (tree) : 19) + 1; | ||
| 1453 | iter->stack = itree_stack_create (size); | ||
| 1454 | uintmax_t otick= tree->otick; | ||
| 1455 | iter->begin = begin; | 1385 | iter->begin = begin; |
| 1456 | iter->end = end; | 1386 | iter->end = end; |
| 1457 | iter->otick = otick; | 1387 | iter->otick = tree->otick; |
| 1458 | iter->order = order; | 1388 | iter->order = order; |
| 1459 | itree_stack_clear (iter->stack); | ||
| 1460 | if (begin <= end && tree->root != NULL) | ||
| 1461 | itree_stack_push_flagged (iter->stack, tree->root, false); | ||
| 1462 | iter->running = true; | ||
| 1463 | /* itree_stack_ensure_space (iter->stack, | ||
| 1464 | 2 * itree_max_height (tree)); */ | ||
| 1465 | iter->node = itree_iterator_first_node (tree, iter); | 1389 | iter->node = itree_iterator_first_node (tree, iter); |
| 1466 | return iter; | 1390 | return iter; |
| 1467 | } | 1391 | } |
| 1468 | 1392 | ||
| 1469 | static struct itree_node * | 1393 | struct itree_node * |
| 1470 | itree_iter_next (struct itree_iterator *iter) | 1394 | itree_iterator_next (struct itree_iterator *iter) |
| 1471 | { | 1395 | { |
| 1472 | struct itree_node *node = iter->node; | 1396 | struct itree_node *node = iter->node; |
| 1473 | while (node | 1397 | while (node |
| 1474 | && !itree_node_intersects (node, iter->begin, iter->end)) | 1398 | && !itree_node_intersects (node, iter->begin, iter->end)) |
| 1475 | { | 1399 | { |
| 1476 | node = itree_iter_next_in_subtree (node, iter); | 1400 | node = itree_iter_next_in_subtree (node, iter); |
| 1401 | eassert (itree_limit_is_stable (node)); | ||
| 1477 | } | 1402 | } |
| 1478 | iter->node = node ? itree_iter_next_in_subtree (node, iter) : NULL; | 1403 | iter->node = node ? itree_iter_next_in_subtree (node, iter) : NULL; |
| 1479 | return node; | 1404 | return node; |
| 1480 | } | 1405 | } |
| 1481 | 1406 | ||
| 1482 | /* Return the next node of the iterator in the order given when it was | ||
| 1483 | started; or NULL if there are no more nodes. */ | ||
| 1484 | |||
| 1485 | struct itree_node * | ||
| 1486 | itree_iterator_next (struct itree_iterator *g) | ||
| 1487 | { | ||
| 1488 | eassert (g && g->running); | ||
| 1489 | |||
| 1490 | struct itree_node *const null = NULL; | ||
| 1491 | struct itree_node *node; | ||
| 1492 | |||
| 1493 | /* The `visited` flag stored in each node is used here (and only here): | ||
| 1494 | We keep a "workstack" of nodes we need to consider. This stack | ||
| 1495 | consist of nodes of two types: nodes that we have decided | ||
| 1496 | should be returned by the iterator, and nodes which we may | ||
| 1497 | need to consider (including checking their children). | ||
| 1498 | We start an iteration with a stack containing just the root | ||
| 1499 | node marked as "not visited" which means that it (and its children) | ||
| 1500 | needs to be considered but we haven't yet decided whether it's included | ||
| 1501 | in the iterator's output. */ | ||
| 1502 | |||
| 1503 | do | ||
| 1504 | { | ||
| 1505 | nodeptr_and_flag nav; | ||
| 1506 | bool visited; | ||
| 1507 | while ((nav = itree_stack_pop (g->stack), | ||
| 1508 | node = nav_nodeptr (nav), | ||
| 1509 | visited = nav_flag (nav), | ||
| 1510 | node && !visited)) | ||
| 1511 | { | ||
| 1512 | struct itree_node *const left = node->left; | ||
| 1513 | struct itree_node *const right = node->right; | ||
| 1514 | |||
| 1515 | itree_inherit_offset (g->otick, node); | ||
| 1516 | eassert (itree_limit_is_stable (node)); | ||
| 1517 | switch (g->order) | ||
| 1518 | { | ||
| 1519 | case ITREE_ASCENDING: | ||
| 1520 | if (right != null && node->begin <= g->end) | ||
| 1521 | itree_stack_push_flagged (g->stack, right, false); | ||
| 1522 | if (itree_node_intersects (node, g->begin, g->end)) | ||
| 1523 | itree_stack_push_flagged (g->stack, node, true); | ||
| 1524 | /* Node's children may still be off-set and we need to add it. */ | ||
| 1525 | if (left != null && g->begin <= left->limit + left->offset) | ||
| 1526 | itree_stack_push_flagged (g->stack, left, false); | ||
| 1527 | break; | ||
| 1528 | case ITREE_DESCENDING: | ||
| 1529 | if (left != null && g->begin <= left->limit + left->offset) | ||
| 1530 | itree_stack_push_flagged (g->stack, left, false); | ||
| 1531 | if (itree_node_intersects (node, g->begin, g->end)) | ||
| 1532 | itree_stack_push_flagged (g->stack, node, true); | ||
| 1533 | if (right != null && node->begin <= g->end) | ||
| 1534 | itree_stack_push_flagged (g->stack, right, false); | ||
| 1535 | break; | ||
| 1536 | case ITREE_PRE_ORDER: | ||
| 1537 | if (right != null && node->begin <= g->end) | ||
| 1538 | itree_stack_push_flagged (g->stack, right, false); | ||
| 1539 | if (left != null && g->begin <= left->limit + left->offset) | ||
| 1540 | itree_stack_push_flagged (g->stack, left, false); | ||
| 1541 | if (itree_node_intersects (node, g->begin, g->end)) | ||
| 1542 | itree_stack_push_flagged (g->stack, node, true); | ||
| 1543 | break; | ||
| 1544 | case ITREE_POST_ORDER: | ||
| 1545 | if (itree_node_intersects (node, g->begin, g->end)) | ||
| 1546 | itree_stack_push_flagged (g->stack, node, true); | ||
| 1547 | if (right != null && node->begin <= g->end) | ||
| 1548 | itree_stack_push_flagged (g->stack, right, false); | ||
| 1549 | if (left != null && g->begin <= left->limit + left->offset) | ||
| 1550 | itree_stack_push_flagged (g->stack, left, false); | ||
| 1551 | break; | ||
| 1552 | } | ||
| 1553 | } | ||
| 1554 | /* Node may have been invalidated by itree_iterator_narrow | ||
| 1555 | after it was pushed: Check if it still intersects. */ | ||
| 1556 | } while (node && ! itree_node_intersects (node, g->begin, g->end)); | ||
| 1557 | |||
| 1558 | struct itree_node *old_node = g->node; | ||
| 1559 | struct itree_node *other_node = itree_iter_next (g); | ||
| 1560 | if (other_node != node) | ||
| 1561 | { | ||
| 1562 | fprintf (stderr, "WOW!! %ld..%ld vs %ld..%ld\n", | ||
| 1563 | other_node ? other_node->begin : -1, | ||
| 1564 | other_node ? other_node->end : -1, | ||
| 1565 | node ? node->begin : -1, | ||
| 1566 | node ? node->end : -1); | ||
| 1567 | fprintf (stderr, "ON=%lx N=%lx OlN=%lx\n", other_node, node, | ||
| 1568 | old_node); | ||
| 1569 | emacs_abort (); | ||
| 1570 | } | ||
| 1571 | return node; | ||
| 1572 | } | ||
| 1573 | |||
| 1574 | /* Limit G to the new interval [BEGIN, END), which must be a subset of | 1407 | /* Limit G to the new interval [BEGIN, END), which must be a subset of |
| 1575 | the current one. I.E. it can't grow on either side. */ | 1408 | the current one. I.E. it can't grow on either side. */ |
| 1576 | 1409 | ||
| @@ -1578,7 +1411,7 @@ void | |||
| 1578 | itree_iterator_narrow (struct itree_iterator *g, | 1411 | itree_iterator_narrow (struct itree_iterator *g, |
| 1579 | ptrdiff_t begin, ptrdiff_t end) | 1412 | ptrdiff_t begin, ptrdiff_t end) |
| 1580 | { | 1413 | { |
| 1581 | eassert (g && g->running); | 1414 | eassert (g); |
| 1582 | eassert (begin >= g->begin); | 1415 | eassert (begin >= g->begin); |
| 1583 | eassert (end <= g->end); | 1416 | eassert (end <= g->end); |
| 1584 | g->begin = max (begin, g->begin); | 1417 | g->begin = max (begin, g->begin); |