Skip to content
This repository was archived by the owner on Apr 12, 2019. It is now read-only.

Commit 33f9184

Browse files
mpastellStefanKarpinski
authored andcommittedJan 23, 2017
add positional chomp argument to readline (squashed JuliaLang#19944)
1 parent 08adcd3 commit 33f9184

37 files changed

+187
-110
lines changed
 

‎NEWS.md

+3
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ Breaking changes
4646

4747
This section lists changes that do not have deprecation warnings.
4848

49+
* `readline`, `readlines` and `eachline` return lines without line endings by default.
50+
You can use `readline(s, false)` to get the old behavior and include EOL character(s). ([#19944]).
51+
4952
* `String`s no longer have a `.data` field (as part of a significant performance
5053
improvement). Use `Vector{UInt8}(str)` to access a string as a byte array.
5154
However, allocating the `Vector` object has overhead. You can also use

‎base/LineEdit.jl

+2-2
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ function refresh_multi_line(termbuf::TerminalBuffer, terminal::UnixTerminal, buf
211211
seek(buf, 0)
212212
moreinput = true # add a blank line if there is a trailing newline on the last line
213213
while moreinput
214-
l = readline(buf)
214+
l = readline(buf, false)
215215
moreinput = endswith(l, "\n")
216216
# We need to deal with on-screen characters, so use strwidth to compute occupied columns
217217
llength = strwidth(l)
@@ -549,7 +549,7 @@ end
549549
function edit_kill_line(s::MIState)
550550
buf = buffer(s)
551551
pos = position(buf)
552-
killbuf = readline(buf)
552+
killbuf = readline(buf, false)
553553
if length(killbuf) > 1 && killbuf[end] == '\n'
554554
killbuf = killbuf[1:end-1]
555555
char_move_left(buf)

‎base/REPL.jl

+3-3
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ function run_frontend(repl::BasicREPL, backend::REPLBackendRef)
205205
interrupted = false
206206
while true
207207
try
208-
line *= readline(repl.terminal)
208+
line *= readline(repl.terminal, false)
209209
catch e
210210
if isa(e,InterruptException)
211211
try # raise the debugger if present
@@ -337,7 +337,7 @@ An editor may have converted tabs to spaces at line """
337337

338338
function hist_getline(file)
339339
while !eof(file)
340-
line = readline(file)
340+
line = readline(file, false)
341341
isempty(line) && return line
342342
line[1] in "\r\n" || return line
343343
end
@@ -995,7 +995,7 @@ function run_frontend(repl::StreamREPL, backend::REPLBackendRef)
995995
if have_color
996996
print(repl.stream, input_color(repl))
997997
end
998-
line = readline(repl.stream)
998+
line = readline(repl.stream, false)
999999
if !isempty(line)
10001000
ast = Base.parse_input_line(line)
10011001
if have_color

‎base/client.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ parse_input_line(s::AbstractString) = parse_input_line(String(s))
216216
function parse_input_line(io::IO)
217217
s = ""
218218
while !eof(io)
219-
s = s*readline(io)
219+
s = s*readline(io, false)
220220
e = parse_input_line(s)
221221
if !(isa(e,Expr) && e.head === :incomplete)
222222
return e

‎base/io.jl

+55-22
Original file line numberDiff line numberDiff line change
@@ -170,24 +170,53 @@ The text is assumed to be encoded in UTF-8.
170170
readuntil(filename::AbstractString, args...) = open(io->readuntil(io, args...), filename)
171171

172172
"""
173-
readline(stream::IO=STDIN)
174-
readline(filename::AbstractString)
173+
readline()
174+
readline(stream, chomp::Bool=true)
175+
readline(filename::AbstractString, chomp::Bool=true)
175176
176-
Read a single line of text, including a trailing newline character (if one is reached before
177-
the end of the input), from the given I/O stream or file (defaults to `STDIN`).
178-
When reading from a file, the text is assumed to be encoded in UTF-8.
177+
Read a single line of text from the given I/O stream or file (defaults to `STDIN`).
178+
Lines in the input can end in `'\\n'` or `"\\r\\n"`. When reading from a file, the text is
179+
assumed to be encoded in UTF-8.
180+
181+
If `chomp=false` trailing newline character(s) will be included in the output
182+
(if reached before the end of the input); otherwise newline characters(s)
183+
are stripped from result.
179184
"""
180-
readline(filename::AbstractString) = open(readline, filename)
185+
function readline(filename::AbstractString, chomp::Bool=true)
186+
open(filename) do f
187+
readline(f, chomp)
188+
end
189+
end
190+
readline() = readline(STDIN, false)
191+
192+
function readline(s::IO, chomp::Bool=true)
193+
line = readuntil(s, 0x0a)
194+
i = length(line)
195+
if !chomp || i == 0 || line[i] != 0x0a
196+
return String(line)
197+
elseif i < 2 || line[i-1] != 0x0d
198+
return String(resize!(line,i-1))
199+
else
200+
return String(resize!(line,i-2))
201+
end
202+
end
181203

182204
"""
183-
readlines(stream::IO)
184-
readlines(filename::AbstractString)
205+
readlines(stream::IO, chomp::Bool=true)
206+
readlines(filename::AbstractString, chomp::Bool=true)
185207
186208
Read all lines of an I/O stream or a file as a vector of strings.
209+
Lines in the input can end in `'\\n'` or `"\\r\\n"`.
187210
The text is assumed to be encoded in UTF-8.
188-
"""
189-
readlines(filename::AbstractString) = open(readlines, filename)
190211
212+
If `chomp=false` trailing newline character(s) will be included in the output;
213+
otherwise newline characters(s) are stripped from result.
214+
"""
215+
function readlines(filename::AbstractString, chomp::Bool=true)
216+
open(filename) do f
217+
readlines(f, chomp)
218+
end
219+
end
191220

192221
## byte-order mark, ntoh & hton ##
193222

@@ -454,9 +483,6 @@ function readuntil(s::IO, t::AbstractString)
454483
return String(take!(out))
455484
end
456485

457-
readline() = readline(STDIN)
458-
readline(s::IO) = readuntil(s, '\n')
459-
460486
"""
461487
readchomp(x)
462488
@@ -519,22 +545,28 @@ readstring(filename::AbstractString) = open(readstring, filename)
519545

520546
type EachLine
521547
stream::IO
548+
chomp::Bool
522549
ondone::Function
523-
EachLine(stream) = EachLine(stream, ()->nothing)
524-
EachLine(stream, ondone) = new(stream, ondone)
550+
EachLine(stream, chomp) = EachLine(stream, chomp, ()->nothing)
551+
EachLine(stream, chomp, ondone) = new(stream, chomp, ondone)
525552
end
526553

527554
"""
528-
eachline(stream::IO)
529-
eachline(filename::AbstractString)
555+
eachline(stream::IO, chomp::Bool=true)
556+
eachline(filename::AbstractString, chomp::Bool=true)
530557
531558
Create an iterable object that will yield each line from an I/O stream or a file.
559+
Lines in the input can end in `'\\n'` or `"\\r\\n"`.
532560
The text is assumed to be encoded in UTF-8.
561+
562+
If `chomp=false` trailing newline character(s) will be included in the output;
563+
otherwise newline characters(s) are stripped from result.
533564
"""
534-
eachline(stream::IO) = EachLine(stream)
535-
function eachline(filename::AbstractString)
565+
eachline(stream::IO, chomp::Bool=true) = EachLine(stream, chomp)
566+
567+
function eachline(filename::AbstractString, chomp::Bool=true)
536568
s = open(filename)
537-
EachLine(s, ()->close(s))
569+
EachLine(s, chomp, ()->close(s))
538570
end
539571

540572
start(itr::EachLine) = nothing
@@ -545,10 +577,11 @@ function done(itr::EachLine, nada)
545577
itr.ondone()
546578
true
547579
end
548-
next(itr::EachLine, nada) = (readline(itr.stream), nothing)
580+
581+
next(itr::EachLine, nada) = (readline(itr.stream, itr.chomp), nothing)
549582
eltype(::Type{EachLine}) = String
550583

551-
readlines(s=STDIN) = collect(eachline(s))
584+
readlines(s::IO, chomp::Bool=true) = collect(eachline(s, chomp))
552585

553586
iteratorsize(::Type{EachLine}) = SizeUnknown()
554587

‎base/iostream.jl

+5-5
Original file line numberDiff line numberDiff line change
@@ -222,16 +222,16 @@ take!(s::IOStream) =
222222
ccall(:jl_take_buffer, Vector{UInt8}, (Ptr{Void},), s.ios)
223223

224224
function readuntil(s::IOStream, delim::UInt8)
225-
ccall(:jl_readuntil, Array{UInt8,1}, (Ptr{Void}, UInt8, UInt8), s.ios, delim, 0)
225+
ccall(:jl_readuntil, Array{UInt8,1}, (Ptr{Void}, UInt8, UInt8, UInt8), s.ios, delim, 0, 0)
226226
end
227227

228228
# like readuntil, above, but returns a String without requiring a copy
229229
function readuntil_string(s::IOStream, delim::UInt8)
230-
ccall(:jl_readuntil, Ref{String}, (Ptr{Void}, UInt8, UInt8), s.ios, delim, 1)
230+
ccall(:jl_readuntil, Ref{String}, (Ptr{Void}, UInt8, UInt8, UInt8), s.ios, delim, 1, false)
231231
end
232232

233-
function readline(s::IOStream)
234-
ccall(:jl_readuntil, Ref{String}, (Ptr{Void}, UInt8, UInt8), s.ios, '\n', 1)
233+
function readline(s::IOStream, chomp::Bool=true)
234+
ccall(:jl_readuntil, Ref{String}, (Ptr{Void}, UInt8, UInt8, UInt8), s.ios, '\n', 1, chomp)
235235
end
236236

237237
function readbytes_all!(s::IOStream, b::Array{UInt8}, nb)
@@ -325,7 +325,7 @@ function skipchars(s::IOStream, pred; linecomment::Char=Char(0xffffffff))
325325
ch = peekchar(s); status = Int(ch)
326326
while status >= 0 && (pred(ch) || ch == linecomment)
327327
if ch == linecomment
328-
readline(s)
328+
readline(s, false)
329329
else
330330
read(s, Char) # advance one character
331331
end

‎base/libgit2/callbacks.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ function authenticate_ssh(creds::SSHCredentials, libgit2credptr::Ptr{Ptr{Void}},
9999
else
100100
# In encrypted private keys, the second line is "Proc-Type: 4,ENCRYPTED"
101101
open(privatekey) do f
102-
passphrase_required = (readline(f); chomp(readline(f)) == "Proc-Type: 4,ENCRYPTED")
102+
passphrase_required = (readline(f, false); readline(f) == "Proc-Type: 4,ENCRYPTED")
103103
end
104104
end
105105

‎base/libgit2/utils.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ function prompt(msg::AbstractString; default::AbstractString="", password::Bool=
3131
Base.getpass(msg)
3232
else
3333
print(msg)
34-
chomp(readline(STDIN))
34+
readline(STDIN)
3535
end
3636
isempty(uinput) ? default : uinput
3737
end

‎base/markdown/Common/block.jl

+11-11
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ function hashheader(stream::IO, md::MD)
6161
return false
6262

6363
if c != '\n' # Empty header
64-
h = readline(stream) |> strip
64+
h = readline(stream, false) |> strip
6565
h = match(r"(.*?)( +#+)?$", h).captures[1]
6666
buffer = IOBuffer()
6767
print(buffer, h)
@@ -76,11 +76,11 @@ end
7676
function setextheader(stream::IO, md::MD)
7777
withstream(stream) do
7878
eatindent(stream) || return false
79-
header = readline(stream) |> strip
79+
header = readline(stream, false) |> strip
8080
header == "" && return false
8181

8282
eatindent(stream) || return false
83-
underline = readline(stream) |> strip
83+
underline = readline(stream, false) |> strip
8484
length(underline) < 3 && return false
8585
u = underline[1]
8686
u in "-=" || return false
@@ -108,7 +108,7 @@ function indentcode(stream::IO, block::MD)
108108
buffer = IOBuffer()
109109
while !eof(stream)
110110
if startswith(stream, " ") || startswith(stream, "\t")
111-
write(buffer, readline(stream))
111+
write(buffer, readline(stream, false))
112112
elseif blankline(stream)
113113
write(buffer, '\n')
114114
else
@@ -139,10 +139,10 @@ function footnote(stream::IO, block::MD)
139139
else
140140
ref = match(regex, str).captures[1]
141141
buffer = IOBuffer()
142-
write(buffer, readline(stream))
142+
write(buffer, readline(stream, false))
143143
while !eof(stream)
144144
if startswith(stream, " ")
145-
write(buffer, readline(stream))
145+
write(buffer, readline(stream, false))
146146
elseif blankline(stream)
147147
write(buffer, '\n')
148148
else
@@ -174,7 +174,7 @@ function blockquote(stream::IO, block::MD)
174174
empty = true
175175
while eatindent(stream) && startswith(stream, '>')
176176
startswith(stream, " ")
177-
write(buffer, readline(stream))
177+
write(buffer, readline(stream, false))
178178
empty = false
179179
end
180180
empty && return false
@@ -210,7 +210,7 @@ function admonition(stream::IO, block::MD)
210210
category, title =
211211
let untitled = r"^([a-z]+)$", # !!! <CATEGORY_NAME>
212212
titled = r"^([a-z]+) \"(.*)\"$", # !!! <CATEGORY_NAME> "<TITLE>"
213-
line = strip(readline(stream))
213+
line = strip(readline(stream, false))
214214
if ismatch(untitled, line)
215215
m = match(untitled, line)
216216
# When no title is provided we use CATEGORY_NAME, capitalising it.
@@ -229,7 +229,7 @@ function admonition(stream::IO, block::MD)
229229
buffer = IOBuffer()
230230
while !eof(stream)
231231
if startswith(stream, " ")
232-
write(buffer, readline(stream))
232+
write(buffer, readline(stream, false))
233233
elseif blankline(stream)
234234
write(buffer, '\n')
235235
else
@@ -305,7 +305,7 @@ function list(stream::IO, block::MD)
305305
newline = false
306306
if startswith(stream, " "^indent)
307307
# Indented text that is part of the current list item.
308-
print(buffer, readline(stream))
308+
print(buffer, readline(stream, false))
309309
else
310310
matched = startswith(stream, regex)
311311
if isempty(matched)
@@ -316,7 +316,7 @@ function list(stream::IO, block::MD)
316316
# Start of a new list item.
317317
count += 1
318318
count > 1 && pushitem!(list, buffer)
319-
print(buffer, readline(stream))
319+
print(buffer, readline(stream, false))
320320
end
321321
end
322322
end

‎base/markdown/GitHub/GitHub.jl

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ function fencedcode(stream::IO, block::MD)
88
startswith(stream, "~~~", padding = true) || startswith(stream, "```", padding = true) || return false
99
skip(stream, -1)
1010
ch = read(stream, Char)
11-
trailing = strip(readline(stream))
11+
trailing = strip(readline(stream, false))
1212
flavor = lstrip(trailing, ch)
1313
n = 3 + length(trailing) - length(flavor)
1414

@@ -30,7 +30,7 @@ function fencedcode(stream::IO, block::MD)
3030
seek(stream, line_start)
3131
end
3232
end
33-
write(buffer, readline(stream))
33+
write(buffer, readline(stream, false))
3434
end
3535
return false
3636
end

‎base/markdown/GitHub/table.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ end
77

88
function parserow(stream::IO)
99
withstream(stream) do
10-
line = readline(stream) |> chomp
10+
line = readline(stream)
1111
row = split(line, r"(?<!\\)\|")
1212
length(row) == 1 && return
1313
row[1] == "" && shift!(row)

‎base/markdown/parse/util.jl

+2-2
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ function linecontains(io::IO, chars; allow_whitespace = true,
4646
eat = true,
4747
allowempty = false)
4848
start = position(io)
49-
l = readline(io) |> chomp
49+
l = readline(io)
5050
length(l) == 0 && return allowempty
5151

5252
result = allowempty
@@ -99,7 +99,7 @@ function startswith(stream::IO, r::Regex; eat = true, padding = false)
9999
@assert Base.startswith(r.pattern, "^")
100100
start = position(stream)
101101
padding && skipwhitespace(stream)
102-
line = chomp(readline(stream))
102+
line = readline(stream)
103103
seek(stream, start)
104104
m = match(r, line)
105105
m === nothing && return ""

‎base/multi.jl

+2-2
Original file line numberDiff line numberDiff line change
@@ -1624,7 +1624,7 @@ end
16241624

16251625
function redirect_worker_output(ident, stream)
16261626
@schedule while !eof(stream)
1627-
line = readline(stream)
1627+
line = readline(stream, false)
16281628
if startswith(line, "\tFrom worker ")
16291629
# STDOUT's of "additional" workers started from an initial worker on a host are not available
16301630
# on the master directly - they are routed via the initial worker's STDOUT.
@@ -1642,7 +1642,7 @@ end
16421642
# setup a all-to-all network.
16431643
function read_worker_host_port(io::IO)
16441644
while true
1645-
conninfo = readline(io)
1645+
conninfo = readline(io, false)
16461646
bind_addr, port = parse_connection_info(conninfo)
16471647
if bind_addr != ""
16481648
return bind_addr, port

‎base/pkg/dir.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ end
6767

6868
function getmetabranch()
6969
try
70-
chomp(readline(joinpath(path(),"META_BRANCH")))
70+
readline(joinpath(path(),"META_BRANCH"))
7171
catch err
7272
META_BRANCH
7373
end

‎base/pkg/entry.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -608,7 +608,7 @@ function build!(pkgs::Vector, errs::Dict, seen::Set=Set())
608608
empty!(Base.DL_LOAD_PATH)
609609
append!(Base.DL_LOAD_PATH, $(repr(Base.DL_LOAD_PATH)))
610610
open("$(escape_string(errfile))", "a") do f
611-
for path_ in eachline(STDIN)
611+
for path_ in eachline(STDIN, false)
612612
path = chomp(path_)
613613
pkg = basename(dirname(dirname(path)))
614614
try

‎base/pkg/reqs.jl

-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ end
6666
function read(readable::Union{IO,Base.AbstractCmd})
6767
lines = Line[]
6868
for line in eachline(readable)
69-
line = chomp(line)
7069
push!(lines, ismatch(r"^\s*(?:#|$)", line) ? Comment(line) : Requirement(line))
7170
end
7271
return lines

‎base/precompile.jl

+3-1
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,9 @@ precompile(Base.read, (Base.Terminals.TTYTerminal, Type{Char}))
322322
precompile(Base.read, (IOBuffer, Type{Char}))
323323
precompile(Base.read, (IOBuffer, Type{UInt8}))
324324
precompile(Base.read, (IOStream, Array{UInt32,1}))
325-
precompile(Base.readline, (String,))
325+
precompile(Base.readline, (String, Bool))
326+
precompile(Base.readline, (IOBuffer, Bool))
327+
precompile(Base.readline, (IOStream, Bool))
326328
precompile(Base.readuntil, (IOBuffer, Char))
327329
precompile(Base.readuntil, (IOBuffer, UInt8))
328330
precompile(Base.rehash!, (Dict{Any,Any}, Int))

‎base/process.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -561,7 +561,7 @@ function eachline(cmd::AbstractCmd, stdin)
561561
close(stdout.in)
562562
out = stdout.out
563563
# implicitly close after reading lines, since we opened
564-
return EachLine(out, ()->(close(out); success(processes) || pipeline_error(processes)))
564+
return EachLine(out, false, ()->(close(out); success(processes) || pipeline_error(processes)))
565565
end
566566
eachline(cmd::AbstractCmd) = eachline(cmd, DevNull)
567567

‎contrib/add_license_to_files.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ function add_license_line!(unprocessed::Vector, src::AbstractString, new_license
135135
if ext in keys(ext_prefix)
136136
prefix = ext_prefix[ext]
137137
f = open(path, "r")
138-
lines = readlines(f)
138+
lines = readlines(f, false)
139139
close(f)
140140
isempty(lines) && (push!(unprocessed, path); continue)
141141
isempty(old_license) || check_lines!(path, lines, old_license, prefix, true)

‎examples/clustermanager/0mq/ZMQCM.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ end
270270

271271
function print_worker_stdout(io, pid)
272272
@schedule while !eof(io)
273-
line = readline(io)
273+
line = readline(io, false)
274274
print("\tFrom worker $(pid):\t$line")
275275
end
276276
end

‎examples/clustermanager/simple/UnixDomainCM.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ end
8181

8282
function print_worker_stdout(io, pid)
8383
@schedule while !eof(io)
84-
line = readline(io)
84+
line = readline(io, false)
8585
print("\tFrom worker $(pid):\t$line")
8686
end
8787
end

‎src/flisp/iostream.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ value_t fl_ioreaduntil(fl_context_t *fl_ctx, value_t *args, uint32_t nargs)
333333
ios_setbuf(&dest, data, 80, 0);
334334
char delim = get_delim_arg(fl_ctx, args[1], "io.readuntil");
335335
ios_t *src = toiostream(fl_ctx, args[0], "io.readuntil");
336-
size_t n = ios_copyuntil(&dest, src, delim);
336+
size_t n = ios_copyuntil(&dest, src, delim, 0);
337337
cv->len = n;
338338
if (dest.buf != data) {
339339
// outgrew initial space
@@ -352,7 +352,7 @@ value_t fl_iocopyuntil(fl_context_t *fl_ctx, value_t *args, uint32_t nargs)
352352
ios_t *dest = toiostream(fl_ctx, args[0], "io.copyuntil");
353353
ios_t *src = toiostream(fl_ctx, args[1], "io.copyuntil");
354354
char delim = get_delim_arg(fl_ctx, args[2], "io.copyuntil");
355-
return size_wrap(fl_ctx, ios_copyuntil(dest, src, delim));
355+
return size_wrap(fl_ctx, ios_copyuntil(dest, src, delim, 0));
356356
}
357357

358358
value_t fl_iocopy(fl_context_t *fl_ctx, value_t *args, uint32_t nargs)

‎src/gen_sysimg_symtab.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ function outputline(io, line)
2121
println(io, "jl_symbol(\"", row[2], "\"),")
2222
end
2323

24-
lines = eachline(io)
24+
lines = eachline(io, false)
2525

2626
open(f->foreach(l->outputline(f,l), take(lines,63)), "common_symbols1.inc", "w")
2727
open(f->foreach(l->outputline(f,l), lines), "common_symbols2.inc", "w")

‎src/support/ios.c

+20-3
Original file line numberDiff line numberDiff line change
@@ -802,7 +802,7 @@ size_t ios_copyall(ios_t *to, ios_t *from)
802802

803803
#define LINE_CHUNK_SIZE 160
804804

805-
size_t ios_copyuntil(ios_t *to, ios_t *from, char delim)
805+
size_t ios_copyuntil(ios_t *to, ios_t *from, char delim, uint8_t chomp)
806806
{
807807
size_t total = 0, avail = (size_t)(from->size - from->bpos);
808808
while (!ios_eof(from)) {
@@ -821,7 +821,11 @@ size_t ios_copyuntil(ios_t *to, ios_t *from, char delim)
821821
}
822822
else {
823823
size_t ntowrite = pd - (from->buf+from->bpos) + 1;
824-
written = ios_write(to, from->buf+from->bpos, ntowrite);
824+
size_t nchomp = 0;
825+
if (chomp) {
826+
nchomp = ios_nchomp(from, ntowrite);
827+
}
828+
written = ios_write(to, from->buf+from->bpos, ntowrite - nchomp);
825829
from->bpos += ntowrite;
826830
total += written;
827831
return total;
@@ -831,6 +835,19 @@ size_t ios_copyuntil(ios_t *to, ios_t *from, char delim)
831835
return total;
832836
}
833837

838+
size_t ios_nchomp(ios_t *from, size_t ntowrite)
839+
{
840+
assert(ntowrite > 0);
841+
size_t nchomp;
842+
if (ntowrite > 1 && from->buf[from->bpos+ntowrite - 2] == '\r') {
843+
nchomp = 2;
844+
}
845+
else {
846+
nchomp = 1;
847+
}
848+
return nchomp;
849+
}
850+
834851
static void _ios_init(ios_t *s)
835852
{
836853
// put all fields in a sane initial state
@@ -1135,7 +1152,7 @@ char *ios_readline(ios_t *s)
11351152
{
11361153
ios_t dest;
11371154
ios_mem(&dest, 0);
1138-
ios_copyuntil(&dest, s, '\n');
1155+
ios_copyuntil(&dest, s, '\n', 0);
11391156
size_t n;
11401157
return ios_take_buffer(&dest, &n);
11411158
}

‎src/support/ios.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,8 @@ JL_DLLEXPORT int ios_get_writable(ios_t *s);
9494
JL_DLLEXPORT void ios_set_readonly(ios_t *s);
9595
JL_DLLEXPORT size_t ios_copy(ios_t *to, ios_t *from, size_t nbytes);
9696
JL_DLLEXPORT size_t ios_copyall(ios_t *to, ios_t *from);
97-
JL_DLLEXPORT size_t ios_copyuntil(ios_t *to, ios_t *from, char delim);
97+
JL_DLLEXPORT size_t ios_copyuntil(ios_t *to, ios_t *from, char delim, uint8_t chomp);
98+
JL_DLLEXPORT size_t ios_nchomp(ios_t *from, size_t ntowrite);
9899
// ensure at least n bytes are buffered if possible. returns # available.
99100
JL_DLLEXPORT size_t ios_readprep(ios_t *from, size_t n);
100101

‎src/sys.c

+7-3
Original file line numberDiff line numberDiff line change
@@ -250,15 +250,19 @@ JL_DLLEXPORT jl_array_t *jl_take_buffer(ios_t *s)
250250
return a;
251251
}
252252

253-
JL_DLLEXPORT jl_value_t *jl_readuntil(ios_t *s, uint8_t delim, uint8_t str)
253+
JL_DLLEXPORT jl_value_t *jl_readuntil(ios_t *s, uint8_t delim, uint8_t str, uint8_t chomp)
254254
{
255255
jl_array_t *a;
256256
// manually inlined common case
257257
char *pd = (char*)memchr(s->buf+s->bpos, delim, (size_t)(s->size - s->bpos));
258258
if (pd) {
259259
size_t n = pd-(s->buf+s->bpos)+1;
260260
if (str) {
261-
jl_value_t *str = jl_pchar_to_string(s->buf + s->bpos, n);
261+
size_t nchomp = 0;
262+
if (chomp) {
263+
nchomp = ios_nchomp(s, n);
264+
}
265+
jl_value_t *str = jl_pchar_to_string(s->buf + s->bpos, n - nchomp);
262266
s->bpos += n;
263267
return str;
264268
}
@@ -271,7 +275,7 @@ JL_DLLEXPORT jl_value_t *jl_readuntil(ios_t *s, uint8_t delim, uint8_t str)
271275
ios_t dest;
272276
ios_mem(&dest, 0);
273277
ios_setbuf(&dest, (char*)a->data, 80, 0);
274-
size_t n = ios_copyuntil(&dest, s, delim);
278+
size_t n = ios_copyuntil(&dest, s, delim, chomp);
275279
if (dest.buf != a->data) {
276280
a = jl_take_buffer(&dest);
277281
}

‎test/file.jl

+4-4
Original file line numberDiff line numberDiff line change
@@ -277,15 +277,15 @@ write(s, "Goodbye world!\n")
277277
close(s)
278278
s = open(file)
279279
mark(s)
280-
str = readline(s)
280+
str = readline(s, false)
281281
@test startswith(str, "Marked!")
282282
@test ismarked(s)
283283
reset(s)
284284
@test !ismarked(s)
285-
str = readline(s)
285+
str = readline(s, false)
286286
@test startswith(str, "Marked!")
287287
mark(s)
288-
@test readline(s) == "Hello world!\n"
288+
@test readline(s, false) == "Hello world!\n"
289289
@test ismarked(s)
290290
unmark(s)
291291
@test !ismarked(s)
@@ -335,7 +335,7 @@ end
335335
emptyfile = joinpath(dir, "empty")
336336
touch(emptyfile)
337337
emptyf = open(emptyfile)
338-
@test isempty(readlines(emptyf))
338+
@test isempty(readlines(emptyf, false))
339339
close(emptyf)
340340
rm(emptyfile)
341341

‎test/iobuffer.jl

+20-6
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ end
4949

5050
let io = IOBuffer("hamster\nguinea pig\nturtle")
5151
@test position(io) == 0
52-
@test readline(io) == "hamster\n"
52+
@test readline(io, false) == "hamster\n"
5353
@test readstring(io) == "guinea pig\nturtle"
5454
@test_throws EOFError read(io,UInt8)
5555
seek(io,0)
@@ -66,14 +66,28 @@ let io = PipeBuffer()
6666
@test_throws EOFError read(io,UInt8)
6767
@test write(io,"pancakes\nwaffles\nblueberries\n") > 0
6868
@test position(io) == 0
69-
@test readline(io) == "pancakes\n"
69+
@test readline(io, false) == "pancakes\n"
7070
Base.compact(io)
71-
@test readline(io) == "waffles\n"
71+
@test readline(io, false) == "waffles\n"
7272
@test write(io,"whipped cream\n") > 0
73-
@test readline(io) == "blueberries\n"
73+
@test readline(io, false) == "blueberries\n"
7474
@test_throws ArgumentError seek(io,0)
7575
@test_throws ArgumentError truncate(io,0)
76-
@test readline(io) == "whipped cream\n"
76+
@test readline(io, false) == "whipped cream\n"
77+
@test write(io,"pancakes\nwaffles\nblueberries\n") > 0
78+
@test readlines(io, true) == String["pancakes", "waffles", "blueberries"]
79+
write(io,"\n\r\n\n\r \n") > 0
80+
@test readlines(io, false) == String["\n", "\r\n", "\n", "\r \n"]
81+
write(io,"\n\r\n\n\r \n") > 0
82+
@test readlines(io, true) == String["", "", "", "\r "]
83+
@test write(io,"α\nβ\nγ\nδ") > 0
84+
@test readlines(io, true) == String["α", "β", "γ", "δ"]
85+
@test write(io,"α\nβ\nγ\nδ") > 0
86+
@test readlines(io, false) == String["α\n","β\n","γ\n","δ"]
87+
@test readlines(IOBuffer(""), false) == []
88+
@test readlines(IOBuffer(""), true) == []
89+
@test readlines(IOBuffer("first\nsecond"), false) == String["first\n", "second"]
90+
@test readlines(IOBuffer("first\nsecond"), true) == String["first", "second"]
7791
Base.compact(io)
7892
@test position(io) == 0
7993
@test ioslength(io) == 0
@@ -133,7 +147,7 @@ a = Array{UInt8}(1024)
133147
@test eof(io)
134148
end
135149

136-
@test isempty(readlines(IOBuffer()))
150+
@test isempty(readlines(IOBuffer(), false))
137151

138152
# issue #8193
139153
let io=IOBuffer("asdf")

‎test/iterators.jl

+2-2
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ end
2727

2828
# enumerate (issue #6284)
2929
let b = IOBuffer("1\n2\n3\n"), a = []
30-
for (i,x) in enumerate(eachline(b))
30+
for (i,x) in enumerate(eachline(b, false))
3131
push!(a, (i,x))
3232
end
3333
@test a == [(1,"1\n"),(2,"2\n"),(3,"3\n")]
@@ -37,7 +37,7 @@ end
3737
let zeb = IOBuffer("1\n2\n3\n4\n5\n"),
3838
letters = ['a', 'b', 'c', 'd', 'e'],
3939
res = []
40-
for (number, letter) in zip(eachline(zeb), letters)
40+
for (number, letter) in zip(eachline(zeb, false), letters)
4141
push!(res, (parse(Int,strip(number)), letter))
4242
end
4343
@test res == [(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd'), (5, 'e')]

‎test/mmap.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ c[5] = UInt8('x')
130130
Mmap.sync!(c)
131131
close(s)
132132
s = open(file, "r")
133-
str = readline(s)
133+
str = readline(s, false)
134134
close(s)
135135
@test startswith(str, "Hellx World")
136136
finalize(c); c=nothing; gc()

‎test/perf/kernel/actor_centrality.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ function read_graph()
4343

4444
open(joinpath(@__DIR__, "imdb-1.tsv"), "r") do io
4545
while !eof(io)
46-
k = split(strip(readline(io)), "\t")
46+
k = split(strip(readline(io), false), "\t")
4747
actor, movie = k[1], join(k[2:3], "_")
4848
ac, mn = get(G, actor), get(G, movie)
4949
push!(actors, actor)

‎test/perf/kernel/perf.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ d = randn(len)
105105
writecsv("random.csv", rand(100000,4))
106106

107107
function parsecsv()
108-
for line in EachLine(open("random.csv"))
108+
for line in eachline("random.csv", false)
109109
split(line, ',')
110110
end
111111
end

‎test/perf/perfcomp.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
# The file format is the output of running `make` in this directory.
88

99
function readperf(f)
10-
Dict(rstrip(l[1:19])=>[parse(Float64,l[20:27]),parse(Float64,l[29:36]),parse(Float64,l[38:45]),parse(Float64,l[47:54])] for l in eachline(f))
10+
Dict(rstrip(l[1:19])=>[parse(Float64,l[20:27]),parse(Float64,l[29:36]),parse(Float64,l[38:45]),parse(Float64,l[47:54])] for l in eachline(f, false))
1111
end
1212

1313
function main()

‎test/perf/shootout/k_nucleotide.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ function k_nucleotide(infile="knucleotide-input.txt")
6464
input = open(infile, "r")
6565
three = ">THREE "
6666
while true
67-
line = readline(input)
67+
line = readline(input, false)
6868
if length(line) >= length(three) && line[1:length(three)] == three
6969
break
7070
end

‎test/read.jl

+9-5
Original file line numberDiff line numberDiff line change
@@ -241,12 +241,16 @@ for (name, f) in l
241241
cleanup()
242242

243243
verbose && println("$name readline...")
244-
@test readline(io()) == readline(IOBuffer(text))
245-
@test readline(io()) == readline(filename)
244+
@test readline(io(), false) == readline(IOBuffer(text), false)
245+
@test readline(io(), false) == readline(filename, false)
246246

247247
verbose && println("$name readlines...")
248+
@test readlines(io(), false) == readlines(IOBuffer(text), false)
249+
@test readlines(io(), false) == readlines(filename, false)
248250
@test readlines(io()) == readlines(IOBuffer(text))
249251
@test readlines(io()) == readlines(filename)
252+
@test collect(eachline(io(), false)) == collect(eachline(IOBuffer(text), false))
253+
@test collect(eachline(io(), false)) == collect(eachline(filename, false))
250254
@test collect(eachline(io())) == collect(eachline(IOBuffer(text)))
251255
@test collect(eachline(io())) == collect(eachline(filename))
252256

@@ -271,13 +275,13 @@ for (name, f) in l
271275

272276
verbose && println("$name seek...")
273277
for n = 0:length(text)-1
274-
@test readlines(seek(io(), n)) == readlines(seek(IOBuffer(text), n))
278+
@test readlines(seek(io(), n), false) == readlines(seek(IOBuffer(text), n), false)
275279
cleanup()
276280
end
277281
verbose && println("$name skip...")
278282
for n = 0:length(text)-1
279-
@test readlines(seek(io(), n)) == readlines(seek(IOBuffer(text), n))
280-
@test readlines(skip(io(), n)) == readlines(skip(IOBuffer(text), n))
283+
@test readlines(seek(io(), n), false) == readlines(seek(IOBuffer(text), n), false)
284+
@test readlines(skip(io(), n), false) == readlines(skip(IOBuffer(text), n), false)
281285
cleanup()
282286
end
283287
verbose && println("$name seekend...")

‎test/repl.jl

+10-10
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ if !is_windows() || Sys.windows_version() >= Sys.WINDOWS_VISTA_VER
103103
# Test that accepting a REPL result immediately shows up, not
104104
# just on the next keystroke
105105
write(stdin_write, "1+1\n") # populate history with a trivial input
106-
readline(stdout_read)
106+
readline(stdout_read, false)
107107
write(stdin_write, "\e[A\n")
108108
t = Timer(10) do t
109109
isopen(t) || return
@@ -116,19 +116,19 @@ if !is_windows() || Sys.windows_version() >= Sys.WINDOWS_VISTA_VER
116116
# Issue #10222
117117
# Test ignoring insert key in standard and prefix search modes
118118
write(stdin_write, "\e[2h\e[2h\n") # insert (VT100-style)
119-
@test search(readline(stdout_read), "[2h") == 0:-1
120-
readline(stdout_read)
119+
@test search(readline(stdout_read, false), "[2h") == 0:-1
120+
readline(stdout_read, false)
121121
write(stdin_write, "\e[2~\e[2~\n") # insert (VT220-style)
122-
@test search(readline(stdout_read), "[2~") == 0:-1
123-
readline(stdout_read)
122+
@test search(readline(stdout_read, false), "[2~") == 0:-1
123+
readline(stdout_read, false)
124124
write(stdin_write, "1+1\n") # populate history with a trivial input
125-
readline(stdout_read)
125+
readline(stdout_read, false)
126126
write(stdin_write, "\e[A\e[2h\n") # up arrow, insert (VT100-style)
127-
readline(stdout_read)
128-
readline(stdout_read)
127+
readline(stdout_read, false)
128+
readline(stdout_read, false)
129129
write(stdin_write, "\e[A\e[2~\n") # up arrow, insert (VT220-style)
130-
readline(stdout_read)
131-
readline(stdout_read)
130+
readline(stdout_read, false)
131+
readline(stdout_read, false)
132132

133133
# Test down arrow to go back to history
134134
# populate history with a trivial input

‎test/spawn.jl

+7-7
Original file line numberDiff line numberDiff line change
@@ -182,18 +182,18 @@ let r, t, sock
182182
sock = connect(fetch(r))
183183
mark(sock)
184184
@test ismarked(sock)
185-
@test readline(sock) == "Hello, world!\n"
186-
@test readline(sock) == "Goodbye, world...\n"
185+
@test readline(sock, false) == "Hello, world!\n"
186+
@test readline(sock, false) == "Goodbye, world...\n"
187187
@test reset(sock) == 0
188188
@test !ismarked(sock)
189189
mark(sock)
190190
@test ismarked(sock)
191-
@test readline(sock) == "Hello, world!\n"
191+
@test readline(sock, false) == "Hello, world!\n"
192192
unmark(sock)
193193
@test !ismarked(sock)
194194
@test_throws ArgumentError reset(sock)
195195
@test !unmark(sock)
196-
@test readline(sock) == "Goodbye, world...\n"
196+
@test readline(sock) == "Goodbye, world..."
197197
#@test eof(sock) ## doesn't work
198198
close(sock)
199199
@test wait(t)
@@ -316,8 +316,8 @@ let out = Pipe(), echo = `$exename --startup-file=no -e 'print(STDOUT, " 1\t", r
316316
@test c == read!(out, c)
317317
Base.wait_readnb(out, 1)
318318
@test nb_available(out) > 0
319-
ln1 = readline(out)
320-
ln2 = readline(out)
319+
ln1 = readline(out, false)
320+
ln2 = readline(out, false)
321321
desc = readstring(out)
322322
@test !isreadable(out)
323323
@test !iswritable(out)
@@ -345,7 +345,7 @@ let fname = tempname()
345345
cmd = pipeline(`busybox echo asdf`,`busybox cat`)
346346
end
347347
end
348-
for line in eachline(STDIN)
348+
for line in eachline(STDIN, false)
349349
run(cmd)
350350
end
351351
"""

0 commit comments

Comments
 (0)
This repository has been archived.