diff --git a/base/c.jl b/base/c.jl index b9dd62f8a4d6c..3d7eab2954469 100644 --- a/base/c.jl +++ b/base/c.jl @@ -73,10 +73,6 @@ pointer(p::Cwstring) = convert(Ptr{Cwchar_t}, p) ==(x::Union{Cstring,Cwstring}, y::Ptr) = pointer(x) == y ==(x::Ptr, y::Union{Cstring,Cwstring}) = x == pointer(y) -# here, not in pointer.jl, to avoid bootstrapping problems in coreimg.jl -unsafe_wrap(::Type{String}, p::Cstring, own::Bool=false) = unsafe_wrap(String, convert(Ptr{UInt8}, p), own) -unsafe_wrap(::Type{String}, p::Cstring, len::Integer, own::Bool=false) = - unsafe_wrap(String, convert(Ptr{UInt8}, p), len, own) unsafe_string(s::Cstring) = unsafe_string(convert(Ptr{UInt8}, s)) # convert strings to String etc. to pass as pointers diff --git a/base/deprecated.jl b/base/deprecated.jl index 9ae6fc3d8101a..43cb2db3745e2 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -1483,4 +1483,17 @@ end # Calling promote_op is likely a bad idea, so deprecate its convenience wrapper promote_eltype_op @deprecate promote_eltype_op(op, As...) promote_op(op, map(eltype, As)...) +function unsafe_wrap(::Type{String}, p::Union{Ptr{UInt8},Ptr{Int8}}, len::Integer, own::Bool=false) + Base.depwarn("unsafe_wrap(String, ...) is deprecated; use `unsafe_string` instead.", :unsafe_wrap) + #ccall(:jl_array_to_string, Ref{String}, (Any,), + # ccall(:jl_ptr_to_array_1d, Vector{UInt8}, (Any, Ptr{UInt8}, Csize_t, Cint), + # Vector{UInt8}, p, len, own)) + unsafe_string(p, len) +end +unsafe_wrap(::Type{String}, p::Union{Ptr{UInt8},Ptr{Int8}}, own::Bool=false) = + unsafe_wrap(String, p, ccall(:strlen, Csize_t, (Ptr{UInt8},), p), own) +unsafe_wrap(::Type{String}, p::Cstring, own::Bool=false) = unsafe_wrap(String, convert(Ptr{UInt8}, p), own) +unsafe_wrap(::Type{String}, p::Cstring, len::Integer, own::Bool=false) = + unsafe_wrap(String, convert(Ptr{UInt8}, p), len, own) + # End deprecations scheduled for 0.6 diff --git a/base/fft/FFTW.jl b/base/fft/FFTW.jl index ea885ce670c2e..465646773d7af 100644 --- a/base/fft/FFTW.jl +++ b/base/fft/FFTW.jl @@ -282,7 +282,10 @@ sprint_plan_{T<:fftwDouble}(plan::FFTWPlan{T}) = sprint_plan_{T<:fftwSingle}(plan::FFTWPlan{T}) = ccall((:fftwf_sprint_plan,libfftwf), Ptr{UInt8}, (PlanPtr,), plan) function sprint_plan(plan::FFTWPlan) - unsafe_wrap(String, sprint_plan_(plan), true) + p = sprint_plan_(plan) + str = unsafe_string(p) + Libc.free(p) + return str end function show{T,K,inplace}(io::IO, p::cFFTWPlan{T,K,inplace}) diff --git a/base/gmp.jl b/base/gmp.jl index 4ecb28c87eb88..f9e0e48d3b8da 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -532,8 +532,10 @@ hex(n::BigInt, pad::Int) = base(16, n, pad) function base(b::Integer, n::BigInt) 2 <= b <= 62 || throw(ArgumentError("base must be 2 ≤ base ≤ 62, got $b")) - p = ccall((:__gmpz_get_str,:libgmp), Ptr{UInt8}, (Ptr{UInt8}, Cint, Ptr{BigInt}), C_NULL, b, &n) - unsafe_wrap(String, p, true) + nd = ndigits(n, b) + str = Base._string_n(n < 0 ? nd+1 : nd) + ccall((:__gmpz_get_str,:libgmp), Ptr{UInt8}, (Ptr{UInt8}, Cint, Ptr{BigInt}), str, b, &n) + return str end function base(b::Integer, n::BigInt, pad::Integer) diff --git a/base/path.jl b/base/path.jl index 1f4e6eb8b547b..8a8d1f1e0616f 100644 --- a/base/path.jl +++ b/base/path.jl @@ -288,7 +288,9 @@ else # !windows function realpath(path::AbstractString) p = ccall(:realpath, Ptr{UInt8}, (Cstring, Ptr{UInt8}), path, C_NULL) systemerror(:realpath, p == C_NULL) - return unsafe_wrap(String, p, true) + str = unsafe_string(p) + Libc.free(p) + return str end end # os-test diff --git a/base/pointer.jl b/base/pointer.jl index 8dcbed8a03c46..688e69ebe8ba5 100644 --- a/base/pointer.jl +++ b/base/pointer.jl @@ -93,32 +93,6 @@ program, in the same manner as C. unsafe_store!(p::Ptr{Any}, x::ANY, i::Integer=1) = pointerset(p, x, Int(i), 1) unsafe_store!{T}(p::Ptr{T}, x, i::Integer=1) = pointerset(p, convert(T,x), Int(i), 1) -# unsafe pointer to string conversions (don't make a copy, unlike unsafe_string) -# (Cstring versions are in c.jl) -""" - unsafe_wrap(String, p::Ptr{UInt8}, [length,] own=false) - -Wrap a pointer `p` to an array of bytes in a `String` object, -interpreting the bytes as UTF-8 encoded characters *without making a -copy*. The optional `length` argument indicates the length in bytes of -the pointer's data; if it is omitted, the data is assumed to be -NUL-terminated. The `own` argument optionally specifies whether Julia -should take ownership of the memory, calling `free` on the pointer -when the array is no longer referenced. - -This function is labelled "unsafe" because it will crash if `p` is not -a valid memory address to data of the requested length. - -See also [`unsafe_string`](@ref), which takes a pointer -and makes a copy of the data. -""" -unsafe_wrap(::Type{String}, p::Union{Ptr{UInt8},Ptr{Int8}}, len::Integer, own::Bool=false) = - ccall(:jl_array_to_string, Ref{String}, (Any,), - ccall(:jl_ptr_to_array_1d, Vector{UInt8}, (Any, Ptr{UInt8}, Csize_t, Cint), - Vector{UInt8}, p, len, own)) -unsafe_wrap(::Type{String}, p::Union{Ptr{UInt8},Ptr{Int8}}, own::Bool=false) = - unsafe_wrap(String, p, ccall(:strlen, Csize_t, (Ptr{UInt8},), p), own) - # convert a raw Ptr to an object reference, and vice-versa """ unsafe_pointer_to_objref(p::Ptr) diff --git a/base/strings/string.jl b/base/strings/string.jl index 73e758eed59e7..1cc67be1c2d6b 100644 --- a/base/strings/string.jl +++ b/base/strings/string.jl @@ -30,9 +30,6 @@ Copy a string from the address of a C-style (NUL-terminated) string encoded as U This function is labelled "unsafe" because it will crash if `p` is not a valid memory address to data of the requested length. - -See also [`unsafe_wrap(String, p, [length])`](@ref), which takes a pointer -and wraps a string object around it without making a copy. """ function unsafe_string(p::Union{Ptr{UInt8},Ptr{Int8}}, len::Integer) p == C_NULL && throw(ArgumentError("cannot convert NULL to string")) diff --git a/base/strings/utf8proc.jl b/base/strings/utf8proc.jl index d83095b508abb..32850fdd9418a 100644 --- a/base/strings/utf8proc.jl +++ b/base/strings/utf8proc.jl @@ -68,14 +68,19 @@ const UTF8PROC_STRIPMARK = (1<<13) ############################################################################ -function utf8proc_map(s::String, flags::Integer) - p = Ref{Ptr{UInt8}}() - result = ccall(:utf8proc_map, Cssize_t, - (Ptr{UInt8}, Cssize_t, Ref{Ptr{UInt8}}, Cint), - s, sizeof(s), p, flags) - result < 0 && error(unsafe_string(ccall(:utf8proc_errmsg, Cstring, - (Cssize_t,), result))) - unsafe_wrap(String, p[], result, true)::String +utf8proc_error(result) = error(unsafe_string(ccall(:utf8proc_errmsg, Cstring, (Cssize_t,), result))) + +function utf8proc_map(str::String, options::Integer) + nwords = ccall(:utf8proc_decompose, Int, (Ptr{UInt8}, Int, Ptr{UInt8}, Int, Cint), + str, sizeof(str), C_NULL, 0, options) + nwords < 0 && utf8proc_error(nwords) + buffer = Base.StringVector(nwords*4) + nwords = ccall(:utf8proc_decompose, Int, (Ptr{UInt8}, Int, Ptr{UInt8}, Int, Cint), + str, sizeof(str), buffer, nwords, options) + nwords < 0 && utf8proc_error(nwords) + nbytes = ccall(:utf8proc_reencode, Int, (Ptr{UInt8}, Int, Cint), buffer, nwords, options) + nbytes < 0 && utf8proc_error(nbytes) + return String(resize!(buffer, nbytes)) end utf8proc_map(s::AbstractString, flags::Integer) = utf8proc_map(String(s), flags) diff --git a/doc/src/stdlib/strings.md b/doc/src/stdlib/strings.md index a9895595484c7..be655da87e526 100644 --- a/doc/src/stdlib/strings.md +++ b/doc/src/stdlib/strings.md @@ -10,7 +10,6 @@ Base.repr Core.String(::AbstractString) Base.transcode Base.unsafe_string -Base.unsafe_wrap(::Type{String}, ::Union{Ptr{Int8}, Ptr{UInt8}}, ::Integer, ::Bool) Base.codeunit(::AbstractString, ::Integer) Base.ascii Base.@r_str diff --git a/test/strings/basic.jl b/test/strings/basic.jl index 41ac521e4fe89..9048ba7e2036a 100644 --- a/test/strings/basic.jl +++ b/test/strings/basic.jl @@ -245,7 +245,7 @@ end cstrdup(s) = @static is_windows() ? ccall(:_strdup, Cstring, (Cstring,), s) : ccall(:strdup, Cstring, (Cstring,), s) let p = cstrdup("hello") - @test unsafe_string(p) == "hello" == unsafe_wrap(String, cstrdup(p), true) + @test unsafe_string(p) == "hello" Libc.free(p) end