mollusk 0e4acfb8f2 fix incorrect folder name for julia-0.6.x
Former-commit-id: ef2c7401e0876f22d2f7762d182cfbcd5a7d9c70
2018-06-11 03:28:36 -07:00

452 lines
12 KiB
Julia

# This file is a part of Julia. License is MIT: https://julialang.org/license
## core text I/O ##
"""
print(io::IO, x)
Write to `io` (or to the default output stream [`STDOUT`](@ref)
if `io` is not given) a canonical (un-decorated) text representation
of a value if there is one, otherwise call [`show`](@ref).
The representation used by `print` includes minimal formatting and tries to
avoid Julia-specific details.
```jldoctest
julia> print("Hello World!")
Hello World!
julia> io = IOBuffer();
julia> print(io, "Hello World!")
julia> String(take!(io))
"Hello World!"
```
"""
function print(io::IO, x)
lock(io)
try
show(io, x)
finally
unlock(io)
end
return nothing
end
function print(io::IO, xs...)
lock(io)
try
for x in xs
print(io, x)
end
finally
unlock(io)
end
return nothing
end
"""
println(io::IO, xs...)
Print (using [`print`](@ref)) `xs` followed by a newline.
If `io` is not supplied, prints to [`STDOUT`](@ref).
"""
println(io::IO, xs...) = print(io, xs..., '\n')
## conversion of general objects to strings ##
function sprint(size::Integer, f::Function, args...; env=nothing)
s = IOBuffer(StringVector(size), true, true)
# specialized version of truncate(s,0)
s.size = 0
s.ptr = 1
if env !== nothing
f(IOContext(s, env), args...)
else
f(s, args...)
end
String(resize!(s.data, s.size))
end
"""
sprint(f::Function, args...)
Call the given function with an I/O stream and the supplied extra arguments.
Everything written to this I/O stream is returned as a string.
```jldoctest
julia> sprint(showcompact, 66.66666)
"66.6667"
```
"""
sprint(f::Function, args...) = sprint(0, f, args...)
tostr_sizehint(x) = 0
tostr_sizehint(x::AbstractString) = endof(x)
tostr_sizehint(x::Float64) = 20
tostr_sizehint(x::Float32) = 12
function print_to_string(xs...; env=nothing)
# specialized for performance reasons
s = IOBuffer(StringVector(tostr_sizehint(xs[1])), true, true)
# specialized version of truncate(s,0)
s.size = 0
s.ptr = 1
if env !== nothing
env_io = IOContext(s, env)
for x in xs
print(env_io, x)
end
else
for x in xs
print(s, x)
end
end
String(resize!(s.data, s.size))
end
string_with_env(env, xs...) = print_to_string(xs...; env=env)
"""
string(xs...)
Create a string from any values using the [`print`](@ref) function.
```jldoctest
julia> string("a", 1, true)
"a1true"
```
"""
string(xs...) = print_to_string(xs...)
print(io::IO, s::AbstractString) = (write(io, s); nothing)
write(io::IO, s::AbstractString) = (len = 0; for c in s; len += write(io, c); end; len)
show(io::IO, s::AbstractString) = print_quoted(io, s)
write(to::AbstractIOBuffer, s::SubString{String}) =
s.endof==0 ? 0 : unsafe_write(to, pointer(s.string, s.offset + 1), UInt(nextind(s, s.endof) - 1))
## printing literal quoted string data ##
# this is the inverse of print_unescaped_chars(io, s, "\\\")
function print_quoted_literal(io, s::AbstractString)
print(io, '"')
for c = s; c == '"' ? print(io, "\\\"") : print(io, c); end
print(io, '"')
end
"""
repr(x)
Create a string from any value using the [`showall`](@ref) function.
"""
function repr(x)
s = IOBuffer()
showall(s, x)
String(take!(s))
end
# IOBuffer views of a (byte)string:
"""
IOBuffer(string::String)
Create a read-only `IOBuffer` on the data underlying the given string.
```jldoctest
julia> io = IOBuffer("Haho");
julia> String(take!(io))
"Haho"
julia> String(take!(io))
"Haho"
```
"""
IOBuffer(str::String) = IOBuffer(Vector{UInt8}(str))
IOBuffer(s::SubString{String}) = IOBuffer(view(Vector{UInt8}(s.string), s.offset + 1 : s.offset + sizeof(s)))
# join is implemented using IO
"""
join(io::IO, strings, delim, [last])
Join an array of `strings` into a single string, inserting the given delimiter between
adjacent strings. If `last` is given, it will be used instead of `delim` between the last
two strings. For example,
```jldoctest
julia> join(["apples", "bananas", "pineapples"], ", ", " and ")
"apples, bananas and pineapples"
```
`strings` can be any iterable over elements `x` which are convertible to strings
via `print(io::IOBuffer, x)`. `strings` will be printed to `io`.
"""
function join(io::IO, strings, delim, last)
i = start(strings)
if done(strings,i)
return
end
str, i = next(strings,i)
print(io, str)
is_done = done(strings,i)
while !is_done
str, i = next(strings,i)
is_done = done(strings,i)
print(io, is_done ? last : delim)
print(io, str)
end
end
function join(io::IO, strings, delim)
i = start(strings)
is_done = done(strings,i)
while !is_done
str, i = next(strings,i)
is_done = done(strings,i)
print(io, str)
if !is_done
print(io, delim)
end
end
end
join(io::IO, strings) = join(io, strings, "")
join(args...) = sprint(join, args...)
## string escaping & unescaping ##
need_full_hex(s::AbstractString, i::Int) = !done(s,i) && isxdigit(next(s,i)[1])
escape_nul(s::AbstractString, i::Int) =
!done(s,i) && '0' <= next(s,i)[1] <= '7' ? "\\x00" : "\\0"
"""
escape_string([io,] str::AbstractString[, esc::AbstractString]) -> AbstractString
General escaping of traditional C and Unicode escape sequences.
Any characters in `esc` are also escaped (with a backslash).
See also [`unescape_string`](@ref).
"""
function escape_string(io, s::AbstractString, esc::AbstractString)
i = start(s)
while !done(s,i)
c, j = next(s,i)
c == '\0' ? print(io, escape_nul(s,j)) :
c == '\e' ? print(io, "\\e") :
c == '\\' ? print(io, "\\\\") :
c in esc ? print(io, '\\', c) :
'\a' <= c <= '\r' ? print(io, '\\', "abtnvfr"[Int(c)-6]) :
isprint(c) ? print(io, c) :
c <= '\x7f' ? print(io, "\\x", hex(c, 2)) :
c <= '\uffff' ? print(io, "\\u", hex(c, need_full_hex(s,j) ? 4 : 2)) :
print(io, "\\U", hex(c, need_full_hex(s,j) ? 8 : 4))
i = j
end
end
escape_string(s::AbstractString) = sprint(endof(s), escape_string, s, "\"")
function print_quoted(io, s::AbstractString)
print(io, '"')
escape_string(io, s, "\"\$") #"# work around syntax highlighting problem
print(io, '"')
end
# bare minimum unescaping function unescapes only given characters
function print_unescaped_chars(io, s::AbstractString, esc::AbstractString)
if !('\\' in esc)
esc = string("\\", esc)
end
i = start(s)
while !done(s,i)
c, i = next(s,i)
if c == '\\' && !done(s,i) && s[i] in esc
c, i = next(s,i)
end
print(io, c)
end
end
unescape_chars(s::AbstractString, esc::AbstractString) =
sprint(endof(s), print_unescaped_chars, s, esc)
# general unescaping of traditional C and Unicode escape sequences
"""
unescape_string([io,] s::AbstractString) -> AbstractString
General unescaping of traditional C and Unicode escape sequences. Reverse of
[`escape_string`](@ref).
"""
function unescape_string(io, s::AbstractString)
i = start(s)
while !done(s,i)
c, i = next(s,i)
if !done(s,i) && c == '\\'
c, i = next(s,i)
if c == 'x' || c == 'u' || c == 'U'
n = k = 0
m = c == 'x' ? 2 :
c == 'u' ? 4 : 8
while (k+=1) <= m && !done(s,i)
c, j = next(s,i)
n = '0' <= c <= '9' ? n<<4 + c-'0' :
'a' <= c <= 'f' ? n<<4 + c-'a'+10 :
'A' <= c <= 'F' ? n<<4 + c-'A'+10 : break
i = j
end
if k == 1
throw(ArgumentError("invalid $(m == 2 ? "hex (\\x)" :
"unicode (\\u)") escape sequence used in $(repr(s))"))
end
if m == 2 # \x escape sequence
write(io, UInt8(n))
else
print(io, Char(n))
end
elseif '0' <= c <= '7'
k = 1
n = c-'0'
while (k+=1) <= 3 && !done(s,i)
c, j = next(s,i)
n = ('0' <= c <= '7') ? n<<3 + c-'0' : break
i = j
end
if n > 255
throw(ArgumentError("octal escape sequence out of range"))
end
write(io, UInt8(n))
else
print(io, c == 'a' ? '\a' :
c == 'b' ? '\b' :
c == 't' ? '\t' :
c == 'n' ? '\n' :
c == 'v' ? '\v' :
c == 'f' ? '\f' :
c == 'r' ? '\r' :
c == 'e' ? '\e' : c)
end
else
print(io, c)
end
end
end
unescape_string(s::AbstractString) = sprint(endof(s), unescape_string, s)
macro b_str(s); :(Vector{UInt8}($(unescape_string(s)))); end
macro raw_str(s); s; end
## multiline strings ##
"""
Calculate the width of leading blank space, and also return if string is blank
Returns:
* width of leading whitespace, flag if string is totally blank
"""
function indentation(str::AbstractString; tabwidth=8)
count = 0
for ch in str
if ch == ' '
count += 1
elseif ch == '\t'
count = div(count + tabwidth, tabwidth) * tabwidth
else
return count, false
end
end
count, true
end
"""
Removes leading indentation from string
Returns:
* `String` of multiline string, with leading indentation of `indent` removed
"""
function unindent(str::AbstractString, indent::Int; tabwidth=8)
indent == 0 && return str
pos = start(str)
endpos = endof(str)
# Note: this loses the type of the original string
buf = IOBuffer(StringVector(endpos), true, true)
truncate(buf,0)
cutting = true
col = 0 # current column (0 based)
while pos <= endpos
ch, pos = next(str,pos)
if cutting
if ch == ' '
col += 1
elseif ch == '\t'
col = div(col + tabwidth, tabwidth) * tabwidth
elseif ch == '\n'
# Now we need to output enough indentation
for i = 1:col-indent
write(buf, ' ')
end
col = 0
write(buf, '\n')
else
cutting = false
# Now we need to output enough indentation to get to
# correct place
for i = 1:col-indent
write(buf, ' ')
end
col += 1
write(buf, ch)
end
elseif ch == '\t' # Handle internal tabs
upd = div(col + tabwidth, tabwidth) * tabwidth
# output the number of spaces that would have been seen
# with original indentation
for i = 1:(upd-col)
write(buf, ' ')
end
col = upd
elseif ch == '\n'
cutting = true
col = 0
write(buf, '\n')
else
col += 1
write(buf, ch)
end
end
# If we were still "cutting" when we hit the end of the string,
# we need to output the right number of spaces for the indentation
if cutting
for i = 1:col-indent
write(buf, ' ')
end
end
String(take!(buf))
end
function convert(::Type{String}, chars::AbstractVector{Char})
sprint(length(chars), io->begin
state = start(chars)
while !done(chars, state)
c, state = next(chars, state)
if '\ud7ff' < c && c + 1024 < '\ue000'
d, state = next(chars, state)
if '\ud7ff' < d - 1024 && d < '\ue000'
c = Char(0x10000 + ((UInt32(c) & 0x03ff) << 10) | (UInt32(d) & 0x03ff))
else
write(io, c)
c = d
end
end
write(io, c)
end
end)
end