The underlying data structure is a singly-linked list of Vector<T>.
We never shift any of the vector contents around, but we batch the memory
allocations into 1000-element segments.
Put together a pretty well-performing queue using a Vector and an offset.
By using the new Vector::shift_left(int) instead of Vector::take_first()
we can avoid shifting the vector contents every time and instead only
do it every so often.
Maybe this could be generalized into a separate class, I'm not sure if it's
the best algorithm though, it's just what I came up with right now. :^)
I've used a SinglyLinkedList<Point> for the flood fill queue, since Vector
was death slow. This could definitely be made faster with a better algorithm
and/or data structure. :^)
This method is used in BXVGADevice to create pages for the framebuffer;
we should neither make the PhysicalPage instances eternal, nor hand over
actual physical pages to the memory allocator.
After PhysicalPage::return_to_freelist(), an actual physical page
is returned back to the memory manager; which will create a new
PhysicalPage instance if it decides to reuse the physical page. This
means this PhysicalPage instance should be freed; otherwise it would
get leaked.
This makes no functional difference, but it makes it clear that
MemoryManager and PhysicalRegion take over the actual physical
page represented by this PhysicalPage instance.
Pages created with PhysicalPage::create_eternal() should *not* be
returnable to the freelist; and pages created with the regular
PhysicalPage::create() should be; not the other way around.
A glob has to be resolved against the directory corresponding to
the part of the path it is found in, not the current directory.
For example, in /usr/i*/AK/, the glob has to be resolved inside
/usr. Moreover, an argument can contain more than one glob, such
as /u*/*/?, in which case they have to be resolved recursively.
In case a glob matches nothing, the argument should be used as is.
Previously the check for an empty part would happen before the
check for access and for the parent being a directory, and so an
error in those would not be detected.
StringView character buffer is not guaranteed to be null-terminated;
in particular it will not be null-terminated when making a substring.
This means it is not correct to check whether we've reached the end
of a StringView by comparing the next character to null; instead, we
need to do an explicit length (or pointer) comparison.