Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion base/gmp.jl
Original file line number Diff line number Diff line change
Expand Up @@ -761,7 +761,7 @@ function string(n::BigInt; base::Integer = 10, pad::Integer = 1)
sv[i] = '0' % UInt8
end
isneg(n) && (sv[1] = '-' % UInt8)
String(sv)
Base._unsafe_takestring!(sv)
end

function digits!(a::AbstractVector{T}, n::BigInt; base::Integer = 10) where {T<:Integer}
Expand Down
12 changes: 6 additions & 6 deletions base/intfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -766,7 +766,7 @@ function bin(x::Unsigned, pad::Int, neg::Bool)
i -= 1
end
neg && (@inbounds a[1] = 0x2d) # UInt8('-')
String(a)
_unsafe_takestring!(a)
end

function oct(x::Unsigned, pad::Int, neg::Bool)
Expand All @@ -780,7 +780,7 @@ function oct(x::Unsigned, pad::Int, neg::Bool)
i -= 1
end
neg && (@inbounds a[1] = 0x2d) # UInt8('-')
String(a)
_unsafe_takestring!(a)
end

# 2-digit decimal characters ("00":"99")
Expand Down Expand Up @@ -850,7 +850,7 @@ function dec(x::Unsigned, pad::Int, neg::Bool)
a = StringMemory(n)
append_c_digits_fast(n, x, a, 1)
neg && (@inbounds a[1] = 0x2d) # UInt8('-')
String(a)
_unsafe_takestring!(a)
end

function hex(x::Unsigned, pad::Int, neg::Bool)
Expand All @@ -871,7 +871,7 @@ function hex(x::Unsigned, pad::Int, neg::Bool)
@inbounds a[i] = d + ifelse(d > 0x9, 0x57, 0x30)
end
neg && (@inbounds a[1] = 0x2d) # UInt8('-')
String(a)
_unsafe_takestring!(a)
end

const base36digits = UInt8['0':'9';'a':'z']
Expand All @@ -896,7 +896,7 @@ function _base(base::Integer, x::Integer, pad::Int, neg::Bool)
i -= 1
end
neg && (@inbounds a[1] = 0x2d) # UInt8('-')
String(a)
_unsafe_takestring!(a)
end

split_sign(n::Integer) = unsigned(abs(n)), n < 0
Expand Down Expand Up @@ -972,7 +972,7 @@ function bitstring(x::T) where {T}
x = lshr_int(x, 4)
i -= 4
end
return String(str)
return _unsafe_takestring!(str)
end

"""
Expand Down
19 changes: 13 additions & 6 deletions base/strings/string.jl
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,7 @@ by [`take!`](@ref) on a writable [`IOBuffer`](@ref) and by calls to
In other cases, `Vector{UInt8}` data may be copied, but `v` is truncated anyway
to guarantee consistent behavior.
"""
String(v::AbstractVector{UInt8}) = String(copyto!(StringMemory(length(v)), v))
function String(v::Memory{UInt8})
len = length(v)
len == 0 && return ""
return ccall(:jl_genericmemory_to_string, Ref{String}, (Any, Int), v, len)
end
String(v::AbstractVector{UInt8}) = _unsafe_takestring!(copyto!(StringMemory(length(v)), v))
function String(v::Vector{UInt8})
#return ccall(:jl_array_to_string, Ref{String}, (Any,), v)
len = length(v)
Expand All @@ -83,6 +78,18 @@ function String(v::Vector{UInt8})
return str
end

"""
_unsafe_takestring!(v::Memory{UInt8})

Create a new `String` object using the data buffer from byte vector `v`, and leaves `v` in an inconsistent state. This should only be used internally for performance-critical
`String` routines that immediately discard `v` afterwards.
"""
function _unsafe_takestring!(v::Memory{UInt8})
len = length(v)
len == 0 && return ""
return ccall(:jl_genericmemory_to_string, Ref{String}, (Any, Int), v, len)
end

"""
unsafe_string(p::Ptr{UInt8}, [length::Integer])

Expand Down
2 changes: 1 addition & 1 deletion base/strings/util.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1214,7 +1214,7 @@ function bytes2hex(itr)
b[2i - 1] = hex_chars[1 + x >> 4]
b[2i ] = hex_chars[1 + x & 0xf]
end
return String(b)
return Base._unsafe_takestring!(b)
end

function bytes2hex(io::IO, itr)
Expand Down
2 changes: 1 addition & 1 deletion base/uuid.jl
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ let groupings = [36:-1:25; 23:-1:20; 18:-1:15; 13:-1:10; 8:-1:1]
u >>= 4
end
@inbounds a[24] = a[19] = a[14] = a[9] = '-'
return String(a)
return Base._unsafe_takestring!(a)
end
end

Expand Down
2 changes: 1 addition & 1 deletion stdlib/FileWatching/src/pidfile.jl
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ function open_exclusive(path::String;
end

function _rand_filename(len::Int=4) # modified from Base.Libc
slug = Base.StringMemory(len)
slug = Base.StringVector(len)
chars = b"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
for i = 1:len
slug[i] = chars[(Libc.rand() % length(chars)) + 1]
Expand Down
11 changes: 11 additions & 0 deletions test/strings/basic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1093,6 +1093,17 @@ let v = [0x40,0x41,0x42]
@test String(view(v, 2:3)) == "AB"
end

# issue #54369
let v = Base.StringMemory(3)
v .= [0x41,0x42,0x43]
s = String(v)
@test s == "ABC"
@test v == [0x41,0x42,0x43]
v[1] = 0x43
@test s == "ABC"
@test v == [0x43,0x42,0x43]
end

# make sure length for identical String and AbstractString return the same value, PR #25533
let rng = MersenneTwister(1), strs = ["∀εa∀aε"*String(rand(rng, UInt8, 100))*"∀εa∀aε",
String(rand(rng, UInt8, 200))]
Expand Down