@@ -87,10 +87,6 @@ class EINPROGRESSWaitWritable < Errno::EINPROGRESS
87
87
# equals total, no additional bytes will be filled until the
88
88
# buffer is emptied.
89
89
#
90
- # As a write buffer, +empty_to+ removes bytes from +start+ up
91
- # to +used+. When +start+ equals +used+, no additional bytes
92
- # will be emptied until the buffer is filled.
93
- #
94
90
# IO presents a stream of input. Buffer presents buckets of
95
91
# input. IO's task is to chain the buckets so the user sees
96
92
# a stream. IO explicitly requests that the buffer be filled
@@ -108,7 +104,6 @@ def initialize
108
104
@start = 0
109
105
@used = 0
110
106
@total = SIZE
111
- @write_synced = true
112
107
@eof = false
113
108
end
114
109
@@ -144,26 +139,6 @@ def reset!
144
139
@start = 0
145
140
@used = 0
146
141
@eof = false
147
- @write_synced = true
148
- end
149
-
150
- def write_synced?
151
- @write_synced
152
- end
153
-
154
- # Returns the number of bytes that could be written to the buffer.
155
- # If the number is less then the expected, then we need to +empty_to+
156
- # the IO, and +unshift+ again beginning at +start_pos+.
157
- def unshift ( str , start_pos )
158
- @write_synced = false
159
- free = unused
160
- written = str . bytesize - start_pos
161
- if written > free
162
- written = free
163
- end
164
- @storage . fill ( @used , str , start_pos , written )
165
- @used += written
166
- written
167
142
end
168
143
169
144
def fill ( io , max = DEFAULT_READ_SIZE )
@@ -192,7 +167,6 @@ def fill(io, max = DEFAULT_READ_SIZE)
192
167
# Returns the number of bytes in the buffer.
193
168
def fill_from ( io , skip = nil , max = DEFAULT_READ_SIZE )
194
169
Truffle ::System . synchronized ( self ) do
195
- empty_to io
196
170
discard skip if skip
197
171
198
172
if empty?
@@ -207,16 +181,6 @@ def fill_from(io, skip = nil, max = DEFAULT_READ_SIZE)
207
181
end
208
182
end
209
183
210
- def empty_to ( io )
211
- return 0 if @write_synced or empty?
212
-
213
- data = String . from_bytearray ( @storage , @start , size , Encoding ::ASCII_8BIT )
214
- Truffle ::POSIX . write_string io , data , true
215
- reset!
216
-
217
- size
218
- end
219
-
220
184
# Advances the beginning-of-buffer marker past any number
221
185
# of contiguous characters == +skip+. For example, if +skip+
222
186
# is ?\n and the buffer contents are "\n\n\nAbc...", the
@@ -238,8 +202,6 @@ def find(pattern, discard = nil)
238
202
239
203
def unseek! ( io )
240
204
Truffle ::System . synchronized ( self ) do
241
- # Unseek the still buffered amount
242
- return unless write_synced?
243
205
unless empty?
244
206
amount = @start - @used
245
207
r = Truffle ::POSIX . lseek ( io . fileno , amount , IO ::SEEK_CUR )
@@ -1026,16 +988,19 @@ def self.setup(io, fd, mode=nil, sync=false)
1026
988
if cur_mode and ( cur_mode == RDONLY or cur_mode == WRONLY ) and mode != cur_mode
1027
989
raise Errno ::EINVAL , "Invalid new mode for existing descriptor #{ fd } "
1028
990
end
991
+ else
992
+ mode = cur_mode or raise 'No mode given for IO'
1029
993
end
1030
994
1031
995
# Close old descriptor if there was already one associated
1032
996
io . close if Primitive . io_fd ( io ) != -1
1033
997
1034
998
Primitive . io_set_fd ( io , fd )
1035
- io . instance_variable_set :@mode , mode || cur_mode
1036
- io . sync = !!sync
999
+ io . instance_variable_set :@mode , mode
1000
+ io . sync = !!sync
1037
1001
io . autoclose = true
1038
- io . instance_variable_set :@ibuffer , IO ::InternalBuffer . new
1002
+ ibuffer = mode != WRONLY ? IO ::InternalBuffer . new : nil
1003
+ io . instance_variable_set :@ibuffer , ibuffer
1039
1004
io . instance_variable_set :@lineno , 0
1040
1005
1041
1006
# Truffle: STDOUT isn't defined by the time this call is made during bootstrap, so we need to guard it.
@@ -1156,7 +1121,7 @@ def binmode?
1156
1121
1157
1122
# Used to find out if there is buffered data available.
1158
1123
private def buffer_empty?
1159
- @ibuffer . empty?
1124
+ @ibuffer . nil? or @ibuffer . empty?
1160
1125
end
1161
1126
1162
1127
def close_on_exec = ( value )
@@ -1640,7 +1605,6 @@ def fileno
1640
1605
# no newline
1641
1606
def flush
1642
1607
ensure_open
1643
- @ibuffer . empty_to self
1644
1608
self
1645
1609
end
1646
1610
@@ -1658,7 +1622,7 @@ def fsync
1658
1622
end
1659
1623
1660
1624
def getbyte
1661
- ensure_open
1625
+ ensure_open_and_readable
1662
1626
@ibuffer . getbyte ( self )
1663
1627
end
1664
1628
@@ -1670,7 +1634,7 @@ def getbyte
1670
1634
# f.getc #=> 84
1671
1635
# f.getc #=> 104
1672
1636
def getc
1673
- ensure_open
1637
+ ensure_open_and_readable
1674
1638
@ibuffer . getchar ( self )
1675
1639
end
1676
1640
@@ -1904,7 +1868,7 @@ def read(length=nil, buffer=nil)
1904
1868
# buffer like readpartial. In this case, read(2) is not called.
1905
1869
def read_nonblock ( size , buffer = nil , exception : true )
1906
1870
raise ArgumentError , 'illegal read size' if size < 0
1907
- ensure_open
1871
+ ensure_open_and_readable
1908
1872
self . nonblock = true
1909
1873
1910
1874
buffer = StringValue buffer if buffer
@@ -2026,7 +1990,7 @@ def readlines(sep_or_limit=$/, limit=nil)
2026
1990
# blocks on the situation IO#sysread causes Errno::EAGAIN as if the fd is blocking mode.
2027
1991
def readpartial ( size , buffer = nil )
2028
1992
raise ArgumentError , 'negative string size' unless size >= 0
2029
- ensure_open
1993
+ ensure_open_and_readable
2030
1994
2031
1995
if buffer
2032
1996
buffer = StringValue ( buffer )
@@ -2091,6 +2055,7 @@ def reopen(other, mode=undefined)
2091
2055
# We need to use that mode of other here like MRI, and not fcntl(), because fcntl(fd, F_GETFL)
2092
2056
# gives O_RDWR for the 3 standard IOs, even though they are not bidirectional.
2093
2057
@mode = other . instance_variable_get :@mode
2058
+ @ibuffer = ( @mode & ACCMODE ) != WRONLY ? IO ::InternalBuffer . new : nil
2094
2059
2095
2060
if io . respond_to? ( :path )
2096
2061
@path = io . path
@@ -2128,6 +2093,7 @@ def reopen(other, mode=undefined)
2128
2093
Errno . handle if mode < 0
2129
2094
2130
2095
@mode = mode
2096
+ @ibuffer = ( @mode & ACCMODE ) != WRONLY ? IO ::InternalBuffer . new : nil
2131
2097
end
2132
2098
2133
2099
self
@@ -2137,7 +2103,7 @@ def reopen(other, mode=undefined)
2137
2103
# Internal method used to reset the state of the buffer, including the
2138
2104
# physical position in the stream.
2139
2105
private def reset_buffering
2140
- @ibuffer . unseek! self
2106
+ @ibuffer . unseek! self if @ibuffer
2141
2107
end
2142
2108
2143
2109
##
@@ -2347,6 +2313,7 @@ def sync=(v)
2347
2313
# @todo Improve reading into provided buffer.
2348
2314
#
2349
2315
def sysread ( number_of_bytes , buffer = undefined )
2316
+ ensure_open_and_readable
2350
2317
flush
2351
2318
raise IOError unless @ibuffer . empty?
2352
2319
@@ -2370,11 +2337,7 @@ def sysread(number_of_bytes, buffer=undefined)
2370
2337
# f.sysread(10) #=> "And so on."
2371
2338
def sysseek ( amount , whence = SEEK_SET )
2372
2339
ensure_open
2373
- if @ibuffer . write_synced?
2374
- raise IOError unless @ibuffer . empty?
2375
- else
2376
- warn 'sysseek for buffered IO' , uplevel : 1
2377
- end
2340
+ raise IOError unless buffer_empty?
2378
2341
2379
2342
amount = Integer ( amount )
2380
2343
r = Truffle ::POSIX . lseek ( Primitive . io_fd ( self ) , amount , whence )
@@ -2457,19 +2420,7 @@ def write(data)
2457
2420
end
2458
2421
end
2459
2422
2460
- if @sync
2461
- Truffle ::POSIX . write_string self , data , true
2462
- else
2463
- reset_buffering
2464
- bytes_to_write = data . bytesize
2465
-
2466
- while bytes_to_write > 0
2467
- bytes_to_write -= @ibuffer . unshift ( data , data . bytesize - bytes_to_write )
2468
- @ibuffer . empty_to self if @ibuffer . full?
2469
- end
2470
- end
2471
-
2472
- data . bytesize
2423
+ Truffle ::POSIX . write_string self , data , true
2473
2424
end
2474
2425
2475
2426
def write_nonblock ( data , exception : true )
0 commit comments