www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 19020] New: findSkip, findSplit and findSplitBefore return


          Issue ID: 19020
           Summary: findSkip, findSplit and findSplitBefore return wrong
           Product: D
           Version: D2
          Hardware: All
                OS: Linux
            Status: NEW
          Severity: critical
          Priority: P1
         Component: phobos
          Assignee: nobody puremagic.com
          Reporter: jeromerichard111 msn.com

findSkip does not check properly the end of searched ranges: it wrongly assumes
that if the beginning of the needle string is found at the end of the haystack
string, the whole needle string is found.
The following code return true while s does not contain the substring "*/".
Note that the code works well without a wrapper range (findSkip call findSplit
which uses another implementation in this case).
At first glance, the issue seems to come from the line "if (parts[1].empty)
return false; // found" in the implementation: parts[1], returned by findSplit,
can contain just a part of the whole needle string.
However, the documentation of findSplit say that "If needle was not found,
result[0] comprehends haystack entirely and result[1] and result[2] are empty."
which is wrong here.
Moreover, why findSkip does not use rather findSplitAfter?

Also note that findSplitBefore is also as wrong as findSplit is the current
implementation in this case (but findSplitAfter is OK).

import std.stdio;
import std.algorithm.searching;
import std.string;
import std.range;
import std.conv;

void main()
    string s = "there is a bug here: *";

    struct WrapperRange(R)
        private R _r;
        this(R r) { _r = r; }
         property auto empty() { return _r.empty(); }
         property auto front() { return _r.front(); }
        auto popFront() { return _r.popFront(); }
         property auto save() { return WrapperRange!R(_r.save); }

    auto tmp = WrapperRange!string(s);
    writeln(tmp.findSkip("*/")); // true
    writeln("findSkip result: `", to!string(tmp), "`"); // findSkip result: ``

Jun 24 2018