Skip to content

Commit

Permalink
DRY up allocation of 8-bit string buffers
Browse files Browse the repository at this point in the history
  • Loading branch information
chuckremes committed Nov 17, 2016
1 parent 2e82d42 commit a57071c
Showing 1 changed file with 27 additions and 19 deletions.
46 changes: 27 additions & 19 deletions core/io.rb
Expand Up @@ -165,6 +165,10 @@ def self.set_flag(flag, fd)
end
end

def self.get_empty_8bit_buffer
"".force_encoding(Encoding::ASCII_8BIT)
end


def initialize(fd, stat, io)
@descriptor, @stat, @io = fd, stat, io
Expand Down Expand Up @@ -600,7 +604,7 @@ def read(length, output_string=nil)
@offset += @unget_buffer.size
length -= @unget_buffer.size

str = @unget_buffer.inject("".force_encoding(Encoding::ASCII_8BIT)) { |sum, val| val.chr + sum }
str = @unget_buffer.inject(self.class.get_empty_8bit_buffer) { |sum, val| val.chr + sum }
str2 = super(length, output_string)

if str.size == 0 && str2.nil?
Expand All @@ -614,11 +618,11 @@ def read(length, output_string=nil)
@offset += length
length -= @unget_buffer.size

str = @unget_buffer.inject("".force_encoding(Encoding::ASCII_8BIT)) { |sum, val| val.chr + sum }
str = @unget_buffer.inject(self.class.get_empty_8bit_buffer) { |sum, val| val.chr + sum }
buffer_reset
else
@offset += @unget_buffer.size
str = "".force_encoding(Encoding::ASCII_8BIT)
str = self.class.get_empty_8bit_buffer

length.times do
str << @unget_buffer.pop
Expand All @@ -641,12 +645,12 @@ def read_only_buffer(length)
@offset += @unget_buffer.size
length -= @unget_buffer.size

str = @unget_buffer.inject("".force_encoding(Encoding::ASCII_8BIT)) { |sum, val| val.chr + sum }
str = @unget_buffer.inject(self.class.get_empty_8bit_buffer) { |sum, val| val.chr + sum }
buffer_reset
[str, length]
else
@offset += @unget_buffer.size
str = "".force_encoding(Encoding::ASCII_8BIT)
str = self.class.get_empty_8bit_buffer

length.times do
str << @unget_buffer.pop
Expand Down Expand Up @@ -2021,12 +2025,12 @@ def read_and_yield_count_chars(str, buffer, byte_count, &block)
if buffer.size < PEEK_AHEAD_LIMIT
# Use nonblocking read since existing +buffer+ might already have a valid encoding
# and we don't want to block forever if no more data is coming
result = "".force_encoding(Encoding::ASCII_8BIT)
result = @io.get_empty_8bit_buffer

# save and restore encodings around the read operation so that we ensure ASCII_8BIT
internal, external = @io.internal, @io.external
@io.external = Encoding::ASCII_8BIT
(@io.read_nonblock(PEEK_AHEAD_LIMIT, result, exception: false) || ''.force_encoding(Encoding::ASCII_8BIT))
(@io.read_nonblock(PEEK_AHEAD_LIMIT, result, exception: false) || @io.get_empty_8bit_buffer)
@io.internal, @io.external = internal, external

buffer += result
Expand Down Expand Up @@ -2061,8 +2065,8 @@ def read_and_yield_entire_string(str, &block)

# method A, D
def read_to_separator(&block)
str = "".force_encoding(Encoding::ASCII_8BIT)
buffer = "".force_encoding(Encoding::ASCII_8BIT)
str = @io.get_empty_8bit_buffer
buffer = @io.get_empty_8bit_buffer
separator_size = @separator.bytesize

begin
Expand All @@ -2078,7 +2082,7 @@ def read_to_separator(&block)
count += separator_size

read_and_yield_count_chars(str, buffer, count, &block)
str = "".force_encoding(Encoding::ASCII_8BIT)
str = @io.get_empty_8bit_buffer
else
str << buffer
buffer.clear
Expand All @@ -2095,8 +2099,8 @@ def read_to_separator(&block)
# method B, E

def read_to_separator_with_limit(&block)
str = "".force_encoding(Encoding::ASCII_8BIT)
buffer = "".force_encoding(Encoding::ASCII_8BIT)
str = @io.get_empty_8bit_buffer
buffer = @io.get_empty_8bit_buffer
separator_size = @separator.bytesize

#TODO: implement ignoring encoding with negative limit
Expand All @@ -2116,11 +2120,11 @@ def read_to_separator_with_limit(&block)
count = count < wanted ? count : wanted
read_and_yield_count_chars(str, buffer, count, &block)

str = "".force_encoding(Encoding::ASCII_8BIT)
str = @io.get_empty_8bit_buffer
else
if wanted < buffer.size
read_and_yield_count_chars(str, buffer, wanted, &block)
str = "".force_encoding(Encoding::ASCII_8BIT)
str = @io.get_empty_8bit_buffer
else
str << buffer
wanted -= buffer.size
Expand All @@ -2136,7 +2140,7 @@ def read_to_separator_with_limit(&block)

# Method G
def read_all(&block)
str = "".force_encoding(Encoding::ASCII_8BIT)
str = @io.get_empty_8bit_buffer

begin
str << @io.read
Expand All @@ -2149,13 +2153,13 @@ def read_all(&block)

# Method H
def read_to_limit(&block)
str = "".force_encoding(Encoding::ASCII_8BIT)
str = @io.get_empty_8bit_buffer
wanted = limit = @limit.abs

begin
str << @io.read(wanted)
read_and_yield_count_chars(str, '', str.bytesize, &block)
str = "".force_encoding(Encoding::ASCII_8BIT)
read_and_yield_count_chars(str, @io.get_empty_8bit_buffer, str.bytesize, &block)
str = @io.get_empty_8bit_buffer
end until @io.eof?

unless str.empty?
Expand Down Expand Up @@ -2517,7 +2521,7 @@ def getc
ensure_open
return if eof?

char = ""
char = get_empty_8bit_buffer
begin
char.force_encoding Encoding::ASCII_8BIT
char << read(1)
Expand Down Expand Up @@ -3470,6 +3474,10 @@ def ensure_open_and_writable
raise IOError, "not opened for writing" if @fd.read_only?
end

def get_empty_8bit_buffer
FileDescriptor.get_empty_8bit_buffer
end

def invalid_descriptor?
descriptor == -1 || descriptor.nil?
end
Expand Down

0 comments on commit a57071c

Please sign in to comment.