Skip to content

Commit 4a10fcd

Browse files
committed
[GR-17149] Implemented startswith call with tuple on byte arrays
PullRequest: graalpython/584
2 parents 348dd26 + a218b3d commit 4a10fcd

File tree

3 files changed

+45
-1
lines changed

3 files changed

+45
-1
lines changed

graalpython/com.oracle.graal.python.test/src/tests/test_bytes.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,16 @@ def test_startswith():
443443
assert not b.startswith(b"hellow")
444444
assert not b.startswith(b"ha")
445445

446+
assert b.startswith((b"hellow", b"he"))
447+
assert not b.startswith((b"hellow", b"ha"))
448+
449+
try:
450+
assert b.startswith(("hel", "hello"))
451+
except TypeError:
452+
assert True
453+
else:
454+
assert False
455+
446456

447457
def test_endswith():
448458
b = b'hello'

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/bytes/ByteArrayBuiltins.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,14 +67,18 @@
6767
import com.oracle.graal.python.builtins.objects.tuple.PTuple;
6868
import com.oracle.graal.python.nodes.SpecialMethodNames;
6969
import com.oracle.graal.python.nodes.call.special.LookupAndCallUnaryNode;
70+
import com.oracle.graal.python.nodes.control.GetIteratorExpressionNode.GetIteratorNode;
71+
import com.oracle.graal.python.nodes.control.GetNextNode;
7072
import com.oracle.graal.python.nodes.expression.BinaryComparisonNode;
7173
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
7274
import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
7375
import com.oracle.graal.python.nodes.function.builtins.PythonBinaryBuiltinNode;
7476
import com.oracle.graal.python.nodes.function.builtins.PythonTernaryBuiltinNode;
7577
import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
7678
import com.oracle.graal.python.nodes.object.GetLazyClassNode;
79+
import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile;
7780
import com.oracle.graal.python.nodes.truffle.PythonArithmeticTypes;
81+
import com.oracle.graal.python.runtime.exception.PException;
7882
import com.oracle.graal.python.runtime.sequence.PSequence;
7983
import com.oracle.graal.python.runtime.sequence.storage.ByteSequenceStorage;
8084
import com.oracle.graal.python.runtime.sequence.storage.IntSequenceStorage;
@@ -477,6 +481,31 @@ public Object iter(PByteArray byteArray) {
477481
abstract static class StartsWithNode extends PythonBuiltinNode {
478482
@Child private SequenceStorageNodes.LenNode lenNode;
479483

484+
@Specialization
485+
boolean startswith(VirtualFrame frame, PByteArray self, PTuple prefixes, @SuppressWarnings("unused") PNone start, @SuppressWarnings("unused") PNone end,
486+
@Cached GetIteratorNode getIteratorNode,
487+
@Cached IsBuiltinClassProfile errorProfile,
488+
@Cached GetNextNode getNextNode,
489+
@Cached BytesNodes.FindNode findNode) {
490+
Object iterator = getIteratorNode.executeWith(frame, prefixes);
491+
while (true) {
492+
try {
493+
Object arrayObj = getNextNode.execute(frame, iterator);
494+
if (arrayObj instanceof PIBytesLike) {
495+
PIBytesLike array = (PIBytesLike) arrayObj;
496+
if (startswith(self, array, start, end, findNode)) {
497+
return true;
498+
}
499+
} else {
500+
throw raise(PythonBuiltinClassType.TypeError, "a bytes-like object is required, not '%p'", arrayObj);
501+
}
502+
} catch (PException e) {
503+
e.expectStopIteration(errorProfile);
504+
return false;
505+
}
506+
}
507+
}
508+
480509
@Specialization
481510
boolean startswith(PByteArray self, PIBytesLike prefix, @SuppressWarnings("unused") PNone start, @SuppressWarnings("unused") PNone end,
482511
@Cached("create()") BytesNodes.FindNode findNode) {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/bytes/BytesNodes.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,9 +224,14 @@ int find(PIBytesLike primary, PIBytesLike sub, Object starting, Object ending) {
224224
// TODO implement a more efficient algorithm
225225
outer: for (int i = start; i < end; i++) {
226226
for (int j = 0; j < len2; j++) {
227+
if (i + j >= end) {
228+
continue outer;
229+
}
230+
227231
int hb = getGetLeftItemNode().executeInt(haystack, i + j);
228232
int nb = getGetRightItemNode().executeInt(needle, j);
229-
if (nb != hb || i + j >= end) {
233+
234+
if (nb != hb) {
230235
continue outer;
231236
}
232237
}

0 commit comments

Comments
 (0)