mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-05 04:06:08 -05:00
grid: refactor grid_row_uri_range_erase()
The old algorithm always created a new URI, followed by (maybe) removing the existing URI, when an URI needed to be modified. That is, if e.g. the tail of an URI was being erased, the old algorithm would create a new URI for the part of the URI that should remain, and then removed the old URI. This isn’t very effective. The new algorithm instead identifies all possible overlap cases, and handles each one differently: * URI ends *before* erase range starts - continue with the next URI without further checks * URI starts *after* the erase range ends - return, we’re done * Erase range erases the entire URI - remove the URI * Erase range erases a part in the middle - split the URI * Erase range erases the head of the URI - adjust the URI’s start * Erase range erases the tail of the URI - adjust the URI’s end
This commit is contained in:
parent
503c2ebd50
commit
f27ccd999e
1 changed files with 35 additions and 46 deletions
81
grid.c
81
grid.c
|
|
@ -878,60 +878,49 @@ void
|
|||
grid_row_uri_range_erase(struct row *row, int start, int end)
|
||||
{
|
||||
xassert(row->extra != NULL);
|
||||
xassert(start <= end);
|
||||
|
||||
/* Split up, or remove, URI ranges affected by the erase */
|
||||
tll_foreach(row->extra->uri_ranges, it) {
|
||||
if (it->item.start > end) {
|
||||
/* This range, and all subsequent ranges, start *after*
|
||||
* the erase range */
|
||||
break;
|
||||
}
|
||||
struct row_uri_range *old = &it->item;
|
||||
|
||||
if (it->item.start < start && it->item.end >= start) {
|
||||
/*
|
||||
* URI crosses the erase *start* point.
|
||||
*
|
||||
* Create a new range for the URI part *before* the erased
|
||||
* cells.
|
||||
*
|
||||
* Also modify this URI range’s start point so that we can
|
||||
* remove it below.
|
||||
*/
|
||||
struct row_uri_range range_before = {
|
||||
.start = it->item.start,
|
||||
.end = start - 1,
|
||||
.id = it->item.id,
|
||||
.uri = it->item.uri != NULL ? xstrdup(it->item.uri) : NULL,
|
||||
};
|
||||
tll_insert_before(row->extra->uri_ranges, it, range_before);
|
||||
it->item.start = start;
|
||||
}
|
||||
if (old->end < start)
|
||||
continue;
|
||||
|
||||
if (it->item.start <= end && it->item.end > end) {
|
||||
/*
|
||||
* URI crosses the erase *end* point.
|
||||
*
|
||||
* Create a new range for the URI part *after* the erased
|
||||
* cells.
|
||||
*
|
||||
* Also modify the URI range’s end point so that we can
|
||||
* remove it below.
|
||||
*/
|
||||
struct row_uri_range range_after = {
|
||||
.start = end + 1,
|
||||
.end = it->item.end,
|
||||
.id = it->item.id,
|
||||
.uri = it->item.uri != NULL ? xstrdup(it->item.uri) : NULL,
|
||||
};
|
||||
tll_insert_before(row->extra->uri_ranges, it, range_after);
|
||||
it->item.end = end;
|
||||
}
|
||||
if (old->start > end)
|
||||
return;
|
||||
|
||||
if (it->item.start >= start && it->item.end <= end) {
|
||||
/* URI range completey covered by the erase - remove it */
|
||||
free(it->item.uri);
|
||||
if (start <= old->start && end >= old->end) {
|
||||
/* Erase range covers URI completely - remove it */
|
||||
grid_row_uri_range_destroy(old);
|
||||
tll_remove(row->extra->uri_ranges, it);
|
||||
}
|
||||
|
||||
else if (start > old->start && end < old->end) {
|
||||
/* Erase range erases a part in the middle of the URI */
|
||||
struct row_uri_range old_tail = {
|
||||
.start = end + 1,
|
||||
.end = old->end,
|
||||
.id = old->id,
|
||||
.uri = old->uri != NULL ? xstrdup(old->uri) : NULL,
|
||||
};
|
||||
tll_insert_after(row->extra->uri_ranges, it, old_tail);
|
||||
old->end = start - 1;
|
||||
return; /* There can be no more URIs affected by the erase range */
|
||||
}
|
||||
|
||||
else if (start <= old->start && end >= old->start) {
|
||||
/* Erase range erases the head of the URI */
|
||||
xassert(start <= old->start);
|
||||
old->start = end + 1;
|
||||
return; /* There can be no more overlapping URIs */
|
||||
}
|
||||
|
||||
else if (start <= old->end && end >= old->end) {
|
||||
/* Erase range erases the tail of the URI */
|
||||
xassert(end >= old->end);
|
||||
old->end = start - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue