diff --git a/stdlib/src/utils/string_slice.mojo b/stdlib/src/utils/string_slice.mojo index e2a3e0587a..88fd0a039a 100644 --- a/stdlib/src/utils/string_slice.mojo +++ b/stdlib/src/utils/string_slice.mojo @@ -675,6 +675,7 @@ struct StringSlice[ Returns: The joined string. """ + # TODO(#3403): Simplify this when the linked conditional conformance # feature is added. Runs a faster algorithm if the concrete types are # able to be converted to a span of bytes. @@ -715,36 +716,35 @@ struct StringSlice[ Returns: The joined string. """ + var n_elems = len(elems) if n_elems == 0: return String("") - var len_self = self.byte_length() + var s_len = self.byte_length() var len_elems = 0 # Calculate the total size of the elements to join beforehand # to prevent alloc syscalls as we know the buffer size. # This can hugely improve the performance on large lists for e_ref in elems: len_elems += len(e_ref[].as_bytes_read()) - var capacity = len_self * (n_elems - 1) + len_elems + var capacity = s_len * (n_elems - 1) + len_elems var buf = Self._buffer_type(capacity=capacity) - var self_ptr = self.unsafe_ptr() - var ptr = buf.unsafe_ptr() + var s_ptr = self.unsafe_ptr() + var b_ptr = buf.unsafe_ptr() var offset = 0 var i = 0 - var is_first = True + var not_first = False while i < n_elems: - if is_first: - is_first = False - else: - memcpy(dest=ptr + offset, src=self_ptr, count=len_self) - offset += len_self + memcpy(dest=b_ptr + offset, src=s_ptr, count=s_len * int(not_first)) + offset += s_len * int(not_first) + not_first = True var e = elems[i].as_bytes_read() var e_len = len(e) - memcpy(dest=ptr + offset, src=e.unsafe_ptr(), count=e_len) + memcpy(dest=b_ptr + offset, src=e.unsafe_ptr(), count=e_len) offset += e_len i += 1 buf.size = capacity - buf.unsafe_set(capacity, 0) + b_ptr[capacity] = 0 return String(buf^) fn splitlines(self, keepends: Bool = False) -> List[String]: