<regex>: Perform insertions into character class NFA node buffers when parsing of the character class completes - #6441
Conversation
…hen parsing of the character class completes
This comment was marked as resolved.
This comment was marked as resolved.
The maximum length is actually restricted by the return values of
I think we probably have existing coverage for this, but I will check later. |
…ter class/bracket expression
|
It appears that we really didn't have any test coverage for combining two positive named character classes, except for the special case that combines |
The builder currently eagerly mutates a character class NFA node whenever it handles the next syntactic element in the character class. In some cases there is no downside to this approach, e.g., when a single encountered character is inserted into a bitmap. But there are other cases where this has drawbacks:
\dor[:alpha:]), the builder updates the bitmap immediately. This means that when[\d[:alpha:]]is parsed, the builder evaluates the membership of a character in the bitmap range first for class\dand then for class[:alpha:]. If this evaluation did not happen eagerly, the builder could evaluate the combined class\d[:alpha:]by passing the or'ed character class masks to theisctype()function in the traits class, as is intended by [re.grammar/9].regexobject exists, and can lead to more allocations if there are several character classes that insert into these buffers.This PR moves all of these insertions to the point when the parser considers the character class complete. This means that a single pass is used to update the character bitmap for all positive named character classes (except for
\wdue to #5242), and character buffers in the node class are immediately filled with their full contents by copying from some temporary storage.This delayed insertion into the character buffers of the node class will actually briefly deteriorate performance: This PR does nothing about the fact that these character buffers are very simple implementations of dynamic arrays that reallocate as if all elements are inserted one by one, so the number of allocations can only increase. But after this PR, the builder sets the whole and final content of
_Bufbuffers in a single insert call everywhere. This means that we can solve this problem by just pulling out the dynamic array implementation in a follow-up PR.To store individual large characters, this PR reuses the existing
_Charsstring in the builder class. This string is also used for character sequences in a regex, but it wasn't used while parsing a character class previously.In the other cases, this PR adds more strings or vectors of strings as temporary storage. This changes the layout of the
_Builder3and_Parser3classes, but this is not an ABI break because there hasn't yet been a stable release with these classes.The same temporary storage is used for all character classes. For this reason, the new tests check that content stored in these buffers doesn't leak to the following character class because the temporary storage wasn't reset correctly.