|
90 | 90 | import com.oracle.graal.python.nodes.subscript.SliceLiteralNode.CastToSliceComponentNode;
|
91 | 91 | import com.oracle.graal.python.nodes.truffle.PythonArithmeticTypes;
|
92 | 92 | import com.oracle.graal.python.nodes.util.CastToByteNode;
|
| 93 | +import com.oracle.graal.python.nodes.util.CastToJavaIntExactNode; |
93 | 94 | import com.oracle.graal.python.runtime.exception.PythonErrorType;
|
94 | 95 | import com.oracle.graal.python.runtime.sequence.storage.ByteSequenceStorage;
|
95 | 96 | import com.oracle.graal.python.runtime.sequence.storage.IntSequenceStorage;
|
@@ -1645,6 +1646,61 @@ protected AbstractSplitNode createRecursiveNode() {
|
1645 | 1646 | }
|
1646 | 1647 | }
|
1647 | 1648 |
|
| 1649 | + // bytes.splitlines([keepends]) |
| 1650 | + @Builtin(name = "splitlines", minNumOfPositionalArgs = 1, parameterNames = {"self", "keepends"}) |
| 1651 | + @GenerateNodeFactory |
| 1652 | + public abstract static class SplitLinesNode extends PythonBinaryBuiltinNode { |
| 1653 | + @Child private BytesNodes.ToBytesNode toBytesNode = BytesNodes.ToBytesNode.create(); |
| 1654 | + @Child private AppendNode appendNode = AppendNode.create(); |
| 1655 | + |
| 1656 | + @Specialization |
| 1657 | + PList doSplitlinesDefault(VirtualFrame frame, PIBytesLike self, @SuppressWarnings("unused") PNone keepends) { |
| 1658 | + return doSplitlines(frame, self, false); |
| 1659 | + } |
| 1660 | + |
| 1661 | + @Specialization(guards = "!isPNone(keepends)") |
| 1662 | + PList doSplitlinesDefault(VirtualFrame frame, PIBytesLike self, Object keepends, |
| 1663 | + @Cached CastToJavaIntExactNode cast) { |
| 1664 | + return doSplitlines(frame, self, cast.execute(keepends) != 0); |
| 1665 | + } |
| 1666 | + |
| 1667 | + @Specialization |
| 1668 | + PList doSplitlines(VirtualFrame frame, PIBytesLike self, boolean keepends) { |
| 1669 | + byte[] bytes = toBytesNode.execute(frame, self); |
| 1670 | + PList list = factory().createList(); |
| 1671 | + int sliceStart = 0; |
| 1672 | + for (int i = 0; i < bytes.length; i++) { |
| 1673 | + if (bytes[i] == '\n' || bytes[i] == '\r') { |
| 1674 | + int sliceEnd = i; |
| 1675 | + if (bytes[i] == '\r' && i + 1 != bytes.length && bytes[i + 1] == '\n') { |
| 1676 | + i++; |
| 1677 | + } |
| 1678 | + if (keepends) { |
| 1679 | + sliceEnd = i + 1; |
| 1680 | + } |
| 1681 | + appendSlice(bytes, list, sliceStart, sliceEnd); |
| 1682 | + sliceStart = i + 1; |
| 1683 | + } |
| 1684 | + } |
| 1685 | + // Process the remaining part if any |
| 1686 | + if (sliceStart != bytes.length) { |
| 1687 | + appendSlice(bytes, list, sliceStart, bytes.length); |
| 1688 | + } |
| 1689 | + return list; |
| 1690 | + } |
| 1691 | + |
| 1692 | + private void appendSlice(byte[] bytes, PList list, int sliceStart, int sliceEnd) { |
| 1693 | + byte[] slice = new byte[sliceEnd - sliceStart]; |
| 1694 | + PythonUtils.arraycopy(bytes, sliceStart, slice, 0, slice.length); |
| 1695 | + appendNode.execute(list, createElement(slice)); |
| 1696 | + } |
| 1697 | + |
| 1698 | + // Overriden in bytearray |
| 1699 | + protected PIBytesLike createElement(byte[] bytes) { |
| 1700 | + return factory().createBytes(bytes); |
| 1701 | + } |
| 1702 | + } |
| 1703 | + |
1648 | 1704 | // static bytes.maketrans()
|
1649 | 1705 | // static bytearray.maketrans()
|
1650 | 1706 | @Builtin(name = "maketrans", minNumOfPositionalArgs = 3, isClassmethod = true)
|
|
0 commit comments