Skip to content

Commit

Permalink
Pre-compute String length after #chomp() if possible
Browse files Browse the repository at this point in the history
  • Loading branch information
HertzDevil committed Nov 5, 2024
1 parent 563d6d2 commit 4d7ddce
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 7 deletions.
18 changes: 18 additions & 0 deletions spec/std/string_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -773,6 +773,24 @@ describe "String" do
it { "hello\n\n\n\n".chomp("").should eq("hello\n\n\n\n") }

it { "hello\r\n".chomp("\n").should eq("hello") }

it "pre-computes string size if possible" do
{"!hello!", "\u{1f602}hello\u{1f602}", "\xFEhello\xFF"}.each do |str|
{"", "\n", "\r", "\r\n"}.each do |newline|
x = str + newline
x.size # side-effect
y = x.chomp
y.@length.should eq(7)
end
end
end

it "does not pre-compute string size if not possible" do
x = String.build &.<< "abc\n"
x.@length.should eq(0)
y = x.chomp
y.@length.should eq(0)
end
end

describe "lchop" do
Expand Down
14 changes: 7 additions & 7 deletions src/string.cr
Original file line number Diff line number Diff line change
Expand Up @@ -1661,12 +1661,12 @@ class String
case to_unsafe[bytesize - 1]
when '\n'
if bytesize > 1 && to_unsafe[bytesize - 2] === '\r'
unsafe_byte_slice_string(0, bytesize - 2)
unsafe_byte_slice_string(0, bytesize - 2, @length > 0 ? @length - 2 : 0)
else
unsafe_byte_slice_string(0, bytesize - 1)
unsafe_byte_slice_string(0, bytesize - 1, @length > 0 ? @length - 1 : 0)
end
when '\r'
unsafe_byte_slice_string(0, bytesize - 1)
unsafe_byte_slice_string(0, bytesize - 1, @length > 0 ? @length - 1 : 0)
else
self
end
Expand Down Expand Up @@ -5552,12 +5552,12 @@ class String
Slice.new(to_unsafe + byte_offset, bytesize - byte_offset, read_only: true)
end

protected def unsafe_byte_slice_string(byte_offset)
String.new(unsafe_byte_slice(byte_offset))
protected def unsafe_byte_slice_string(byte_offset, *, size = 0)
String.new(to_unsafe + byte_offset, bytesize - byte_offset, size)
end

protected def unsafe_byte_slice_string(byte_offset, count)
String.new(unsafe_byte_slice(byte_offset, count))
protected def unsafe_byte_slice_string(byte_offset, count, size = 0)
String.new(to_unsafe + byte_offset, count, size)
end

protected def self.char_bytes_and_bytesize(char : Char)
Expand Down

0 comments on commit 4d7ddce

Please sign in to comment.