Skip to content

Commit 114953c

Browse files
nhz2giordano
authored andcommitted
[backports-release-1.11] Make String(::Memory) copy
1 parent 4877204 commit 114953c

File tree

7 files changed

+31
-17
lines changed

7 files changed

+31
-17
lines changed

base/gmp.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import .Base: *, +, -, /, <, <<, >>, >>>, <=, ==, >, >=, ^, (~), (&), (|), xor,
1010
trailing_zeros, trailing_ones, count_ones, count_zeros, tryparse_internal,
1111
bin, oct, dec, hex, isequal, invmod, _prevpow2, _nextpow2, ndigits0zpb,
1212
widen, signed, unsafe_trunc, trunc, iszero, isone, big, flipsign, signbit,
13-
sign, hastypemax, isodd, iseven, digits!, hash, hash_integer, top_set_bit
13+
sign, hastypemax, isodd, iseven, digits!, hash, hash_integer, top_set_bit, unsafe_takestring
1414

1515
if Clong == Int32
1616
const ClongMax = Union{Int8, Int16, Int32}
@@ -760,7 +760,7 @@ function string(n::BigInt; base::Integer = 10, pad::Integer = 1)
760760
sv[i] = '0' % UInt8
761761
end
762762
isneg(n) && (sv[1] = '-' % UInt8)
763-
String(sv)
763+
unsafe_takestring(sv)
764764
end
765765

766766
function digits!(a::AbstractVector{T}, n::BigInt; base::Integer = 10) where {T<:Integer}

base/intfuncs.jl

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -763,7 +763,7 @@ function bin(x::Unsigned, pad::Int, neg::Bool)
763763
i -= 1
764764
end
765765
neg && (@inbounds a[1] = 0x2d) # UInt8('-')
766-
String(a)
766+
unsafe_takestring(a)
767767
end
768768

769769
function oct(x::Unsigned, pad::Int, neg::Bool)
@@ -777,7 +777,7 @@ function oct(x::Unsigned, pad::Int, neg::Bool)
777777
i -= 1
778778
end
779779
neg && (@inbounds a[1] = 0x2d) # UInt8('-')
780-
String(a)
780+
unsafe_takestring(a)
781781
end
782782

783783
# 2-digit decimal characters ("00":"99")
@@ -847,7 +847,7 @@ function dec(x::Unsigned, pad::Int, neg::Bool)
847847
a = StringMemory(n)
848848
append_c_digits_fast(n, x, a, 1)
849849
neg && (@inbounds a[1] = 0x2d) # UInt8('-')
850-
String(a)
850+
unsafe_takestring(a)
851851
end
852852

853853
function hex(x::Unsigned, pad::Int, neg::Bool)
@@ -868,7 +868,7 @@ function hex(x::Unsigned, pad::Int, neg::Bool)
868868
@inbounds a[i] = d + ifelse(d > 0x9, 0x57, 0x30)
869869
end
870870
neg && (@inbounds a[1] = 0x2d) # UInt8('-')
871-
String(a)
871+
unsafe_takestring(a)
872872
end
873873

874874
const base36digits = UInt8['0':'9';'a':'z']
@@ -893,7 +893,7 @@ function _base(base::Integer, x::Integer, pad::Int, neg::Bool)
893893
i -= 1
894894
end
895895
neg && (@inbounds a[1] = 0x2d) # UInt8('-')
896-
String(a)
896+
unsafe_takestring(a)
897897
end
898898

899899
split_sign(n::Integer) = unsigned(abs(n)), n < 0
@@ -968,7 +968,7 @@ function bitstring(x::T) where {T}
968968
x = lshr_int(x, 4)
969969
i -= 4
970970
end
971-
return String(str)
971+
return unsafe_takestring(str)
972972
end
973973

974974
"""

base/strings/string.jl

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,8 @@ by [`take!`](@ref) on a writable [`IOBuffer`](@ref) and by calls to
6363
In other cases, `Vector{UInt8}` data may be copied, but `v` is truncated anyway
6464
to guarantee consistent behavior.
6565
"""
66-
String(v::AbstractVector{UInt8}) = String(copyto!(StringMemory(length(v)), v))
67-
function String(v::Memory{UInt8})
68-
len = length(v)
69-
len == 0 && return ""
70-
return ccall(:jl_genericmemory_to_string, Ref{String}, (Any, Int), v, len)
71-
end
66+
String(v::AbstractVector{UInt8}) = unsafe_takestring(copyto!(StringMemory(length(v)), v))
67+
7268
function String(v::Vector{UInt8})
7369
#return ccall(:jl_array_to_string, Ref{String}, (Any,), v)
7470
len = length(v)
@@ -85,6 +81,13 @@ function String(v::Vector{UInt8})
8581
return str
8682
end
8783

84+
85+
"Create a string re-using the memory, if possible.
86+
Mutating or reading the memory after calling this function is undefined behaviour."
87+
function unsafe_takestring(m::Memory{UInt8})
88+
isempty(m) ? "" : ccall(:jl_genericmemory_to_string, Ref{String}, (Any, Int), m, length(m))
89+
end
90+
8891
"""
8992
unsafe_string(p::Ptr{UInt8}, [length::Integer])
9093

base/strings/util.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1066,7 +1066,7 @@ function bytes2hex(itr)
10661066
b[2i - 1] = hex_chars[1 + x >> 4]
10671067
b[2i ] = hex_chars[1 + x & 0xf]
10681068
end
1069-
return String(b)
1069+
return unsafe_takestring(b)
10701070
end
10711071

10721072
function bytes2hex(io::IO, itr)

base/uuid.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ let groupings = [36:-1:25; 23:-1:20; 18:-1:15; 13:-1:10; 8:-1:1]
9898
u >>= 4
9999
end
100100
@inbounds a[24] = a[19] = a[14] = a[9] = '-'
101-
return String(a)
101+
return unsafe_takestring(a)
102102
end
103103
end
104104

stdlib/FileWatching/src/pidfile.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ function open_exclusive(path::String;
282282
end
283283

284284
function _rand_filename(len::Int=4) # modified from Base.Libc
285-
slug = Base.StringMemory(len)
285+
slug = Base.StringVector(len)
286286
chars = b"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
287287
for i = 1:len
288288
slug[i] = chars[(Libc.rand() % length(chars)) + 1]

test/strings/basic.jl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1093,6 +1093,17 @@ let v = [0x40,0x41,0x42]
10931093
@test String(view(v, 2:3)) == "AB"
10941094
end
10951095

1096+
# issue #54369
1097+
let v = Base.StringMemory(3)
1098+
v .= [0x41,0x42,0x43]
1099+
s = String(v)
1100+
@test s == "ABC"
1101+
@test v == [0x41,0x42,0x43]
1102+
v[1] = 0x43
1103+
@test s == "ABC"
1104+
@test v == [0x43,0x42,0x43]
1105+
end
1106+
10961107
# make sure length for identical String and AbstractString return the same value, PR #25533
10971108
let rng = MersenneTwister(1), strs = ["∀εa∀aε"*String(rand(rng, UInt8, 100))*"∀εa∀aε",
10981109
String(rand(rng, UInt8, 200))]

0 commit comments

Comments
 (0)