diff --git a/std/regex/internal/backtracking.d b/std/regex/internal/backtracking.d index d528f46d874..08e14246f0f 100644 --- a/std/regex/internal/backtracking.d +++ b/std/regex/internal/backtracking.d @@ -825,7 +825,7 @@ struct CtContext int addr; } - this(Char)(const Regex!Char re) + this(Char)(ref const Regex!Char re) { match = 1; reserved = 1; //first match is skipped diff --git a/std/regex/internal/ir.d b/std/regex/internal/ir.d index 448c081bdbf..3e77cbc8bf1 100644 --- a/std/regex/internal/ir.d +++ b/std/regex/internal/ir.d @@ -434,7 +434,7 @@ struct Group(DataIndex) interface MatcherFactory(Char) { @safe: - Matcher!Char create(const Regex!Char, in Char[] input) const; + Matcher!Char create(const ref Regex!Char, in Char[] input) const; Matcher!Char dup(Matcher!Char m, in Char[] input) const; size_t incRef(Matcher!Char m) const; size_t decRef(Matcher!Char m) const; @@ -448,9 +448,9 @@ abstract class GenericFactory(alias EngineType, Char) : MatcherFactory!Char // round up to next multiple of size_t for alignment purposes enum classSize = (__traits(classInstanceSize, EngineType!Char) + size_t.sizeof - 1) & ~(size_t.sizeof - 1); - Matcher!Char construct(const Regex!Char re, in Char[] input, void[] memory) const; + Matcher!Char construct(const ref Regex!Char re, in Char[] input, void[] memory) const; - override Matcher!Char create(const Regex!Char re, in Char[] input) const @trusted + override Matcher!Char create(const ref Regex!Char re, in Char[] input) const @trusted { immutable size = EngineType!Char.initialMemory(re) + classSize; auto memory = enforce(malloc(size), "malloc failed")[0 .. size]; @@ -496,7 +496,7 @@ abstract class GenericFactory(alias EngineType, Char) : MatcherFactory!Char // A factory for run-time engines class RuntimeFactory(alias EngineType, Char) : GenericFactory!(EngineType, Char) { - override EngineType!Char construct(const Regex!Char re, in Char[] input, void[] memory) const + override EngineType!Char construct(const ref Regex!Char re, in Char[] input, void[] memory) const { import std.conv : emplace; return emplace!(EngineType!Char)(memory[0 .. classSize], @@ -507,7 +507,7 @@ class RuntimeFactory(alias EngineType, Char) : GenericFactory!(EngineType, Char) // A factory for compile-time engine class CtfeFactory(alias EngineType, Char, alias func) : GenericFactory!(EngineType, Char) { - override EngineType!Char construct(const Regex!Char re, in Char[] input, void[] memory) const + override EngineType!Char construct(const ref Regex!Char re, in Char[] input, void[] memory) const { import std.conv : emplace; return emplace!(EngineType!Char)(memory[0 .. classSize], @@ -518,7 +518,7 @@ class CtfeFactory(alias EngineType, Char, alias func) : GenericFactory!(EngineTy // A workaround for R-T enum re = regex(...) template defaultFactory(Char) { - @property MatcherFactory!Char defaultFactory(const Regex!Char re) + @property MatcherFactory!Char defaultFactory(const ref Regex!Char re) @safe { import std.regex.internal.backtracking : BacktrackingMatcher; import std.regex.internal.thompson : ThompsonMatcher; diff --git a/std/regex/internal/thompson.d b/std/regex/internal/thompson.d index 5879639e438..9b35b2f6509 100644 --- a/std/regex/internal/thompson.d +++ b/std/regex/internal/thompson.d @@ -847,7 +847,7 @@ final: } } - this()(const Regex!Char program, Stream stream, void[] memory) + this()(ref const Regex!Char program, Stream stream, void[] memory) { // We are emplace'd to malloced memory w/o blitting T.init over it\ // make sure we initialize all fields explicitly diff --git a/std/regex/package.d b/std/regex/package.d index a8cb48da0d7..cf8fafac979 100644 --- a/std/regex/package.d +++ b/std/regex/package.d @@ -441,12 +441,22 @@ template ctRegexImpl(alias pattern, string flags=[]) { // allow code that expects mutable Regex to still work // we stay "logically const" - @trusted @property auto getRe() const { return cast() staticRe; } + @property @trusted ref getRe() const { return *cast(Regex!Char*)&staticRe; } alias getRe this; } enum wrapper = Wrapper(); } +@safe unittest +{ + // test compat for logical const workaround + static void test(StaticRegex!char) + { + } + enum re = ctRegex!``; + test(re); +} + /++ Compile regular expression using CTFE and generate optimized native machine code for matching it. @@ -476,8 +486,6 @@ if (isSomeString!R) alias String = R; private: import std.conv : text; - R _input; - int _nMatch; enum smallString = 3; enum SMALL_MASK = 0x8000_0000, REF_MASK= 0x1FFF_FFFF; union @@ -485,9 +493,11 @@ private: Group!DataIndex[] big_matches; Group!DataIndex[smallString] small_matches; } + const(NamedGroup)[] _names; + R _input; + int _nMatch; uint _f, _b; uint _refcount; // ref count or SMALL MASK + num groups - const(NamedGroup)[] _names; this(R input, uint n, const(NamedGroup)[] named) { @@ -671,6 +681,17 @@ public: ///A hook for compatibility with original std.regex. @property ref captures(){ return this; } + + void opAssign()(auto ref Captures rhs) + { + if (rhs._refcount & SMALL_MASK) + small_matches[0 .. rhs._refcount & 0xFF] = rhs.small_matches[0 .. rhs._refcount & 0xFF]; + else + big_matches = rhs.big_matches; + assert(&this.tupleof[0] is &big_matches); + assert(&this.tupleof[1] is &small_matches); + this.tupleof[2 .. $] = rhs.tupleof[2 .. $]; + } } /// @@ -802,7 +823,7 @@ public: @property inout(Captures!R) captures() inout { return _captures; } } -private @trusted auto matchOnce(RegEx, R)(R input, const RegEx prog) +private @trusted auto matchOnce(RegEx, R)(R input, const auto ref RegEx prog) { alias Char = BasicElementOf!R; auto factory = prog.factory is null ? defaultFactory!Char(prog) : prog.factory; @@ -813,7 +834,7 @@ private @trusted auto matchOnce(RegEx, R)(R input, const RegEx prog) return captures; } -private auto matchMany(RegEx, R)(R input, RegEx re) @safe +private auto matchMany(RegEx, R)(R input, auto ref RegEx re) @safe { return RegexMatch!R(input, re.withFlags(re.flags | RegexOption.global)); }