Skip to content

Commit

Permalink
Avoid unecessary slicing in find/rfind
Browse files Browse the repository at this point in the history
  • Loading branch information
pschanely committed Nov 9, 2023
1 parent 6949691 commit 7b55248
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 6 deletions.
18 changes: 12 additions & 6 deletions crosshair/libimpl/builtinslib.py
Original file line number Diff line number Diff line change
Expand Up @@ -3210,7 +3210,7 @@ def rpartition(self, substr):
)
return ("", "", self)

def _find(self, partitioner, substr, start=None, end=None):
def _find(self, substr, start=None, end=None, from_right=False):
if not isinstance(substr, str):
raise TypeError
mylen = len(self)
Expand All @@ -3222,7 +3222,7 @@ def _find(self, partitioner, substr, start=None, end=None):
end = mylen
elif end < 0:
end += mylen
matchstr = self[start:end]
matchstr = self[start:end] if start != 0 or end is not mylen else self
if len(substr) == 0:
# Add oddity of CPython. We can find the empty string when over-slicing
# off the left side of the string, but not off the right:
Expand All @@ -3231,18 +3231,24 @@ def _find(self, partitioner, substr, start=None, end=None):
if matchstr == "" and start > min(mylen, max(end, 0)):
return -1
else:
return max(start, 0)
if from_right:
return max(min(end, mylen), 0)
else:
return max(start, 0)
else:
(prefix, match, _) = partitioner(matchstr, substr)
if from_right:
(prefix, match, _) = LazyIntSymbolicStr.rpartition(matchstr, substr)
else:
(prefix, match, _) = LazyIntSymbolicStr.partition(matchstr, substr)
if match == "":
return -1
return start + len(prefix)

def find(self, substr, start=None, end=None):
return self._find(LazyIntSymbolicStr.partition, substr, start, end)
return self._find(substr, start, end, from_right=False)

def rfind(self, substr, start=None, end=None):
return self._find(LazyIntSymbolicStr.rpartition, substr, start, end)
return self._find(substr, start, end, from_right=True)


class SeqBasedSymbolicStr(AtomicSymbolicValue, SymbolicSequence, AnySymbolicStr):
Expand Down
9 changes: 9 additions & 0 deletions crosshair/libimpl/builtinslib_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -768,6 +768,15 @@ def f(a: str) -> str:
check_states(f, POST_FAIL)


def test_str_find_does_not_realize_string_length() -> None:
def f(a: str) -> str:
"""post: len(_) != 100"""
a.find("abc")
return a

check_states(f, POST_FAIL)


def test_str_find_with_limits_ok() -> None:
def f(a: str) -> int:
"""post: _ == -1"""
Expand Down

0 comments on commit 7b55248

Please sign in to comment.