Skip to content

Commit f68dac1

Browse files
committed
Merge pull request #3878 from stevengj/readbytes
new readbytes and readbytes! functions
2 parents 6be1ba4 + c43ffb6 commit f68dac1

File tree

7 files changed

+122
-35
lines changed

7 files changed

+122
-35
lines changed

base/exports.jl

+2
Original file line numberDiff line numberDiff line change
@@ -1074,6 +1074,8 @@ export
10741074
position,
10751075
read,
10761076
readall,
1077+
readbytes,
1078+
readbytes!,
10771079
readchomp,
10781080
readdir,
10791081
readline,

base/fs.jl

+19-3
Original file line numberDiff line numberDiff line change
@@ -147,9 +147,12 @@ function read(f::File, ::Type{Uint8})
147147
return uint8(ret)
148148
end
149149

150-
function read{T}(f::File, a::Array{T})
150+
function read{T}(f::File, a::Array{T}, nel=length(a))
151+
if nel < 0 || nel > length(a)
152+
throw(BoundsError())
153+
end
151154
if isbits(T)
152-
nb = length(a)*sizeof(T)
155+
nb = nel*sizeof(T)
153156
ret = ccall(:jl_fs_read, Int32, (Int32, Ptr{Void}, Csize_t),
154157
f.handle, a, nb)
155158
uv_error("write",ret == -1)
@@ -159,8 +162,21 @@ function read{T}(f::File, a::Array{T})
159162
a
160163
end
161164

165+
nb_available(f::File) = filesize(f) - position(f)
166+
167+
function readbytes!(f::File, b::Array{Uint8}, nb=length(b))
168+
nr = min(nb, nb_available(f))
169+
if length(b) < nr
170+
resize!(b, nr)
171+
end
172+
read(f, b, nr)
173+
return nr
174+
end
175+
readbytes(io::File) = read(io, Array(Uint8, nb_available(io)))
176+
readbytes(io::File, nb) = read(io, Array(Uint8, min(nb, nb_available(io))))
177+
162178
function readbytes(f::File)
163-
a = Array(Uint8, filesize(f) - position(f))
179+
a = Array(Uint8, nb_available(f))
164180
read(f,a)
165181
a
166182
end

base/io.jl

+36-19
Original file line numberDiff line numberDiff line change
@@ -165,17 +165,33 @@ function readuntil{T}(s::IO, delim::T)
165165
end
166166

167167
readline(s::IO) = readuntil(s, '\n')
168+
readchomp(x) = chomp!(readall(x))
168169

169-
function readall(s::IO)
170-
out = IOBuffer()
171-
while !eof(s)
170+
# read up to nb bytes into nb, returning # bytes read
171+
function readbytes!(s::IO, b::AbstractArray{Uint8}, nb=length(b))
172+
olb = lb = length(b)
173+
nr = 0
174+
while !eof(s) && nr < nb
172175
a = read(s, Uint8)
173-
write(out, a)
176+
nr += 1
177+
if nr > lb
178+
lb = nr * 2
179+
resize!(b, lb)
180+
end
181+
b[nr] = a
174182
end
175-
takebuf_string(out)
183+
if lb > olb
184+
resize!(b, nr) # shrink to just contain input data if was resized
185+
end
186+
return nr
176187
end
177188

178-
readchomp(x) = chomp!(readall(x))
189+
# read up to nb bytes from s, returning a Vector{Uint8} of bytes read.
190+
function readbytes(s::IO, nb=typemax(Int))
191+
b = Array(Uint8, min(nb, 65536))
192+
nr = readbytes!(s, b, nb)
193+
resize!(b, nr)
194+
end
179195

180196
function readall(s::IO)
181197
b = readbytes(s)
@@ -414,21 +430,22 @@ function readuntil(s::IOStream, delim::Uint8)
414430
ccall(:jl_readuntil, Array{Uint8,1}, (Ptr{Void}, Uint8), s.ios, delim)
415431
end
416432

417-
function readbytes(s::IOStream)
418-
n = 65536
419-
b = Array(Uint8, n)
420-
p = 1
421-
while true
422-
nr = int(ccall(:ios_readall, Uint,
423-
(Ptr{Void}, Ptr{Void}, Uint), s.ios, pointer(b,p), n))
424-
if eof(s)
425-
resize!(b, p+nr-1)
426-
break
433+
function readbytes!(s::IOStream, b::Array{Uint8}, nb=length(b))
434+
olb = lb = length(b)
435+
nr = 0
436+
while !eof(s) && nr < nb
437+
if lb < nr+1
438+
lb = max(65536, (nr+1) * 2)
439+
resize!(b, lb)
427440
end
428-
p += nr
429-
resize!(b, p+n-1)
441+
nr += int(ccall(:ios_readall, Uint,
442+
(Ptr{Void}, Ptr{Void}, Uint),
443+
s.ios, pointer(b, nr+1), lb - nr))
444+
end
445+
if lb > olb
446+
resize!(b, nr) # shrink to just contain input data if was resized
430447
end
431-
b
448+
return nr
432449
end
433450

434451
# based on code by Glen Hertz

base/iobuffer.jl

+31-13
Original file line numberDiff line numberDiff line change
@@ -38,19 +38,28 @@ IOBuffer(readable::Bool,writable::Bool) = IOBuffer(Uint8[],readable,writable)
3838
IOBuffer() = IOBuffer(Uint8[], true, true)
3939
IOBuffer(maxsize::Int) = (x=IOBuffer(Array(Uint8,maxsize),true,true,maxsize); x.size=0; x)
4040

41-
function read{T}(from::IOBuffer, a::Array{T})
42-
if !from.readable error("read failed") end
43-
if isbits(T)
44-
nb = length(a)*sizeof(T)
45-
if nb > nb_available(from)
46-
throw(EOFError())
47-
end
48-
ccall(:memcpy, Ptr{Void}, (Ptr{Void}, Ptr{Void}, Uint), a, pointer(from.data,from.ptr), nb)
49-
from.ptr += nb
50-
return a
51-
else
41+
read(from::IOBuffer, a::Array) = read_sub(from, a, 1, length(a))
42+
43+
function read_sub{T}(from::IOBuffer, a::Array{T}, offs, nel)
44+
if offs+nel-1 > length(a) || offs < 1 || nel < 0
45+
throw(BoundsError())
46+
end
47+
if !isbits(T)
5248
error("Read from IOBuffer only supports bits types or arrays of bits types; got "*string(T)*".")
5349
end
50+
read(from, pointer(a, offs), nel*sizeof(T))
51+
return a
52+
end
53+
54+
read(from::IOBuffer, p::Ptr, nb::Integer) = read(from, p, int(nb))
55+
function read(from::IOBuffer, p::Ptr, nb::Int)
56+
if !from.readable error("read failed") end
57+
if nb > nb_available(from)
58+
throw(EOFError())
59+
end
60+
ccall(:memcpy, Ptr{Void}, (Ptr{Void}, Ptr{Void}, Uint), p, pointer(from.data,from.ptr), nb)
61+
from.ptr += nb
62+
p
5463
end
5564

5665
function read(from::IOBuffer, ::Type{Uint8})
@@ -216,8 +225,17 @@ end
216225

217226
write(to::IOBuffer, p::Ptr) = write(to, convert(Uint, p))
218227

219-
readbytes(io::IOBuffer,nb::Integer) = bytestring(read(io, Array(Uint8, nb)))
220-
readall(io::IOBuffer) = readbytes(io,nb_available(io))
228+
function readbytes!(io::IOBuffer, b::Array{Uint8}, nb=length(b))
229+
nr = min(nb, nb_available(io))
230+
if length(b) < nr
231+
resize!(b, nr)
232+
end
233+
read_sub(io, b, 1, nr)
234+
return nr
235+
end
236+
readbytes(io::IOBuffer) = read(io, Array(Uint8, nb_available(io)))
237+
readbytes(io::IOBuffer, nb) = read(io, Array(Uint8, min(nb, nb_available(io))))
238+
221239
function search(buf::IOBuffer, delim)
222240
p = pointer(buf.data, buf.ptr)
223241
q = ccall(:memchr,Ptr{Uint8},(Ptr{Uint8},Int32,Csize_t),p,delim,nb_available(buf))

base/multi.jl

+4
Original file line numberDiff line numberDiff line change
@@ -1006,6 +1006,10 @@ function create_worker(privhost, port, pubhost, stream, config)
10061006
if nread>0
10071007
try
10081008
line = readbytes(stream.buffer, nread)
1009+
if length(line) < nread
1010+
println(STDERR,"\tTruncated reply from worker $(wrker.id):\t",err)
1011+
return false
1012+
end
10091013
print("\tFrom worker $(wrker.id):\t",line)
10101014
catch err
10111015
println(STDERR,"\tError parsing reply from worker $(wrker.id):\t",err)

doc/helpdb.jl

+20
Original file line numberDiff line numberDiff line change
@@ -1667,6 +1667,26 @@
16671667
16681668
"),
16691669

1670+
("I/O","Base","readbytes!","readbytes!(stream, b::Vector{Uint8}, nb=length(b))
1671+
1672+
Read up to nb bytes from the stream into b, returning the
1673+
number of bytes read (increasing the size of b as needed).
1674+
1675+
"),
1676+
1677+
("I/O","Base","readbytes","readbytes(stream, nb=typemax(Int))
1678+
1679+
Read at most nb bytes from the stream, returning a
1680+
Vector{Uint8} of the bytes read.
1681+
1682+
"),
1683+
1684+
("Text I/O","Base","readall","readall(stream)
1685+
1686+
Read the entire contents of an I/O stream as a string.
1687+
1688+
"),
1689+
16701690
("Text I/O","Base","readline","readline(stream)
16711691
16721692
Read a single line of text, including a trailing newline character

doc/stdlib/base.rst

+10
Original file line numberDiff line numberDiff line change
@@ -970,6 +970,16 @@ I/O
970970

971971
Read a series of values of the given type from a stream, in canonical binary representation. ``dims`` is either a tuple or a series of integer arguments specifying the size of ``Array`` to return.
972972

973+
.. function:: readbytes!(stream, b::Vector{Uint8}, nb=length(b))
974+
975+
Read at most nb bytes from the stream into b, returning the
976+
number of bytes read (increasing the size of b as needed).
977+
978+
.. function:: readbytes(stream, nb=typemax(Int))
979+
980+
Read at most nb bytes from the stream, returning a
981+
Vector{Uint8} of the bytes read.
982+
973983
.. function:: position(s)
974984

975985
Get the current position of a stream.

0 commit comments

Comments
 (0)