Skip to content

Commit 8f8ad16

Browse files
committed
Share str.splitlines and bytes.splitlines implementaion
1 parent ca24283 commit 8f8ad16

File tree

2 files changed

+45
-47
lines changed

2 files changed

+45
-47
lines changed

vm/src/obj/objbyteinner.rs

Lines changed: 22 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1035,45 +1035,35 @@ impl PyByteInner {
10351035
}
10361036

10371037
pub fn splitlines(&self, options: pystr::SplitLinesArgs) -> Vec<&[u8]> {
1038-
let mut res = vec![];
1039-
1040-
if self.elements.is_empty() {
1041-
return vec![];
1042-
}
1043-
1044-
let mut prev_index = 0;
1045-
let mut index = 0;
10461038
let keep = if options.keepends { 1 } else { 0 };
1047-
let slice = &self.elements;
1048-
1049-
while index < slice.len() {
1050-
match slice[index] {
1051-
b'\n' => {
1052-
res.push(&slice[prev_index..index + keep]);
1053-
index += 1;
1054-
prev_index = index;
1055-
}
1039+
let value = &self.elements;
1040+
let mut elements = Vec::new();
1041+
let mut last_i = 0;
1042+
let mut chars = value.iter().enumerate().peekable();
1043+
while let Some((i, ch)) = chars.next() {
1044+
let (end_len, i_diff) = match ch {
1045+
b'\n' => (keep, 1),
10561046
b'\r' => {
1057-
if index + 2 <= slice.len() && slice[index + 1] == b'\n' {
1058-
res.push(&slice[prev_index..index + keep + keep]);
1059-
index += 2;
1047+
let is_rn = chars.peek().map_or(false, |(_, ch)| *ch == &b'\n');
1048+
if is_rn {
1049+
let _ = chars.next();
1050+
(keep + keep, 2)
10601051
} else {
1061-
res.push(&slice[prev_index..index + keep]);
1062-
index += 1;
1052+
(keep, 1)
10631053
}
1064-
prev_index = index;
10651054
}
1066-
_x => {
1067-
if index == slice.len() - 1 {
1068-
res.push(&slice[prev_index..=index]);
1069-
break;
1070-
}
1071-
index += 1
1055+
_ => {
1056+
continue;
10721057
}
1073-
}
1058+
};
1059+
let range = last_i..i + end_len;
1060+
last_i = i + i_diff;
1061+
elements.push(&value[range]);
10741062
}
1075-
1076-
res
1063+
if last_i != value.len() {
1064+
elements.push(&value[last_i..]);
1065+
}
1066+
elements
10771067
}
10781068

10791069
pub fn zfill(&self, width: isize) -> Vec<u8> {

vm/src/obj/objstr.rs

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -786,25 +786,33 @@ impl PyString {
786786

787787
#[pymethod]
788788
fn splitlines(&self, args: pystr::SplitLinesArgs, vm: &VirtualMachine) -> PyObjectRef {
789-
let mut elements = vec![];
790-
let mut curr = "".to_owned();
791-
let mut chars = self.value.chars().peekable();
792-
while let Some(ch) = chars.next() {
793-
if ch == '\n' || ch == '\r' {
794-
if args.keepends {
795-
curr.push(ch);
789+
let keep = if args.keepends { 1 } else { 0 };
790+
let value = &self.value;
791+
let mut elements = Vec::new();
792+
let mut last_i = 0;
793+
let mut chars = value.chars().enumerate().peekable();
794+
while let Some((i, ch)) = chars.next() {
795+
let (end_len, i_diff) = match ch {
796+
'\n' => (keep, 1),
797+
'\r' => {
798+
let is_rn = chars.peek().map_or(false, |(_, ch)| *ch == '\n');
799+
if is_rn {
800+
let _ = chars.next();
801+
(keep + keep, 2)
802+
} else {
803+
(keep, 1)
804+
}
796805
}
797-
if ch == '\r' && chars.peek() == Some(&'\n') {
806+
_ => {
798807
continue;
799808
}
800-
elements.push(vm.ctx.new_str(curr.clone()));
801-
curr.clear();
802-
} else {
803-
curr.push(ch);
804-
}
809+
};
810+
let range = last_i..i + end_len;
811+
last_i = i + i_diff;
812+
elements.push(vm.ctx.new_str(&value[range]));
805813
}
806-
if !curr.is_empty() {
807-
elements.push(vm.ctx.new_str(curr));
814+
if last_i != value.len() {
815+
elements.push(vm.ctx.new_str(&value[last_i..]));
808816
}
809817
vm.ctx.new_list(elements)
810818
}

0 commit comments

Comments
 (0)