Skip to content

Commit

Permalink
Remove RevString and deprecate reverse(::AbstractString)
Browse files Browse the repository at this point in the history
The `RevString` type for lazily reversed strings has been moved to the
LegacyStrings package. Fixes #22611.

Calling `reverse` on an `AbstractString` with no more specific method
has been deprecated in favor of explicitly converting to `String` before
reversing.
  • Loading branch information
ararslan committed Sep 20, 2017
1 parent 83a89a1 commit a384401
Show file tree
Hide file tree
Showing 13 changed files with 82 additions and 116 deletions.
8 changes: 8 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,12 @@ Language changes
* Prefix `&` for by-reference arguments to `ccall` has been deprecated in favor of
`Ref` argument types ([#6080]).

* The `RevString` type for lazily reversed strings has been moved to the LegacyStrings
package ([#22611]).

* `reverse` on `AbstractString`s has been deprecated in favor of converting to `String`
before reversing ([#23612]).

Breaking changes
----------------

Expand Down Expand Up @@ -1311,6 +1317,7 @@ Command-line option changes
[#22532]: https://github.com/JuliaLang/julia/issues/22532
[#22588]: https://github.com/JuliaLang/julia/issues/22588
[#22605]: https://github.com/JuliaLang/julia/issues/22605
[#22611]: https://github.com/JuliaLang/julia/issues/22611
[#22666]: https://github.com/JuliaLang/julia/issues/22666
[#22696]: https://github.com/JuliaLang/julia/issues/22696
[#22703]: https://github.com/JuliaLang/julia/issues/22703
Expand Down Expand Up @@ -1340,3 +1347,4 @@ Command-line option changes
[#23233]: https://github.com/JuliaLang/julia/issues/23233
[#23342]: https://github.com/JuliaLang/julia/issues/23342
[#23404]: https://github.com/JuliaLang/julia/issues/23404
[#23612]: https://github.com/JuliaLang/julia/issues/23612
6 changes: 6 additions & 0 deletions base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1855,6 +1855,12 @@ end
nothing
end

# Issue #22611
@deprecate_moved RevString "LegacyStrings"

# PR 23612
@deprecate reverse(s::AbstractString) reverse(String(s))

# END 0.7 deprecations

# BEGIN 1.0 deprecations
Expand Down
1 change: 0 additions & 1 deletion base/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,6 @@ export
Rational,
Regex,
RegexMatch,
RevString,
RoundFromZero,
RoundDown,
RoundingMode,
Expand Down
3 changes: 0 additions & 3 deletions base/precompile.jl
Original file line number Diff line number Diff line change
Expand Up @@ -581,9 +581,6 @@ precompile(Tuple{typeof(Base.LineEdit.complete_line), Base.LineEdit.PromptState,
precompile(Tuple{typeof(Base.LineEdit.input_string_newlines_aftercursor), Base.LineEdit.PromptState})
precompile(Tuple{typeof(Base.LineEdit.complete_line), Base.REPL.REPLCompletionProvider, Base.LineEdit.PromptState})
precompile(Tuple{getfield(Base, Symbol("#kw##parse")), Array{Any, 1}, typeof(Base.parse), String})
precompile(Tuple{typeof(Base.isvalid), Base.RevString{String}, Int64})
precompile(Tuple{typeof(Base.nextind), Base.RevString{String}, Int64})
precompile(Tuple{typeof(Base.search), Base.RevString{String}, Array{Char, 1}, Int64})
precompile(Tuple{typeof(Base.rsearch), String, Array{Char, 1}, Int64})
precompile(Tuple{getfield(Base.REPLCompletions, Symbol("#kw##find_start_brace")), Array{Any, 1}, typeof(Base.REPLCompletions.find_start_brace), String})
precompile(Tuple{typeof(Core.Inference.isbits), Tuple{Void, Void, Void}})
Expand Down
17 changes: 9 additions & 8 deletions base/repl/REPLCompletions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -225,13 +225,13 @@ end
# closed start brace from the end of the string.
function find_start_brace(s::AbstractString; c_start='(', c_end=')')
braces = 0
r = RevString(s)
i = start(r)
i = endof(s)
in_single_quotes = false
in_double_quotes = false
in_back_ticks = false
while !done(r, i)
c, i = next(r, i)
while i > 0
c = s[i]
nexti = prevind(s, i)
if !in_single_quotes && !in_double_quotes && !in_back_ticks
if c == c_start
braces += 1
Expand All @@ -245,18 +245,19 @@ function find_start_brace(s::AbstractString; c_start='(', c_end=')')
in_back_ticks = true
end
else
if !in_back_ticks && !in_double_quotes && c == '\'' && !done(r, i) && next(r, i)[1]!='\\'
if !in_back_ticks && !in_double_quotes && c == '\'' && i > 0 && s[nexti] != '\\'
in_single_quotes = !in_single_quotes
elseif !in_back_ticks && !in_single_quotes && c == '"' && !done(r, i) && next(r, i)[1]!='\\'
elseif !in_back_ticks && !in_single_quotes && c == '"' && i > 0 && s[nexti] != '\\'
in_double_quotes = !in_double_quotes
elseif !in_single_quotes && !in_double_quotes && c == '`' && !done(r, i) && next(r, i)[1]!='\\'
elseif !in_single_quotes && !in_double_quotes && c == '`' && i > 0 && s[nexti] != '\\'
in_back_ticks = !in_back_ticks
end
end
braces == 1 && break
i = nexti
end
braces != 1 && return 0:-1, -1
method_name_end = reverseind(r, i)
method_name_end = i - 1
startind = nextind(s, rsearch(s, non_identifier_chars, method_name_end))
return (startind:endof(s), method_name_end)
end
Expand Down
15 changes: 7 additions & 8 deletions base/shell.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,20 @@ function shell_parse(str::AbstractString, interpolate::Bool=true;
special::AbstractString="")
s = lstrip(str)
# strips the end but respects the space when the string ends with "\\ "
r = RevString(s)
i = start(r)
c_old = nothing
while !done(r,i)
c, j = next(r,i)
i = endof(s)
c_old = '\0' # initialized to a null byte for type stability
while i > 0
c = s[i]
if c == '\\' && c_old == ' '
i -= 1
i += 1
break
elseif !(c in _default_delims)
break
end
i = j
i = prevind(s, i)
c_old = c
end
s = s[1:end-i+1]
s = s[1:i]

last_parse = 0:-1
isempty(s) && return interpolate ? (Expr(:tuple,:()),last_parse) : ([],last_parse)
Expand Down
58 changes: 30 additions & 28 deletions base/strings/search.jl
Original file line number Diff line number Diff line change
Expand Up @@ -194,12 +194,6 @@ end
search(s::AbstractString, t::AbstractString, i::Integer=start(s)) = _search(s, t, i)
search(s::ByteArray, t::ByteArray, i::Integer=start(s)) = _search(s, t, i)

function rsearch(s::AbstractString, c::Chars)
j = search(RevString(s), c)
j == 0 && return 0
endof(s)-j+1
end

"""
rsearch(s::AbstractString, chars::Chars, [start::Integer])
Expand All @@ -212,44 +206,52 @@ julia> rsearch("aaabbb","b")
6:6
```
"""
function rsearch(s::AbstractString, c::Chars, i::Integer)
e = endof(s)
j = search(RevString(s), c, e-i+1)
j == 0 && return 0
e-j+1
function rsearch(s::AbstractString, c::Chars, i::Integer=start(s))
@boundscheck checkbounds(s, i)
isempty(c) && return i
j = Int(i)
@inbounds while j > 0
s[j] in c && return j
j = prevind(s, j)
end
return 0
end

function _rsearchindex(s, t, i)
if isempty(t)
return 1 <= i <= nextind(s,endof(s)) ? i :
throw(BoundsError(s, i))
@boundscheck checkbounds(s, i)
return i
end
t = RevString(t)
rs = RevString(s)
l = endof(s)
t1, j2 = next(t,start(t))
j2 = endof(t)
t1 = t[j2]
while true
i = rsearch(s,t1,i)
if i == 0 return 0 end
c, ii = next(rs,l-i+1)
j = j2; k = ii
i = rsearch(s, t1, i)
i == 0 && return 0
c = s[i]
ii = prevind(s, i)
j, k = j2, ii
matched = true
while !done(t,j)
if done(rs,k)
while j > 0
if k < 1
matched = false
break
end
c, k = next(rs,k)
d, j = next(t,j)
# Using `reverseind` with `prevind` mimics `next` but for iteration over
# `reverse(s)` (without actually having to call `reverse`) since `reverseind`
# is the current index in `reverse(s)` and `prevind` is the index for the
# next iteration.
rs_k = reverseind(s, k)
c, k = s[rs_k], prevind(s, rs_k)
rt_j = reverseind(t, j)
d, j = t[rt_j], prevind(t, rt_j)
if c != d
matched = false
break
end
end
if matched
return nextind(s,l-k+1)
end
i = l-ii+1
matched && return nextind(s, k)
i = ii
end
end

Expand Down
32 changes: 1 addition & 31 deletions base/strings/types.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This file is a part of Julia. License is MIT: https://julialang.org/license

# SubString and RevString types
# SubString type

## substrings reference original strings ##

Expand Down Expand Up @@ -97,35 +97,6 @@ function unsafe_convert(::Type{Ptr{R}}, s::SubString{String}) where R<:Union{Int
convert(Ptr{R}, pointer(s.string)) + s.offset
end

## reversed strings without data movement ##

struct RevString{T<:AbstractString} <: AbstractString
string::T
end

endof(s::RevString) = endof(s.string)
length(s::RevString) = length(s.string)
sizeof(s::RevString) = sizeof(s.string)

function next(s::RevString, i::Int)
n = endof(s); j = n-i+1
(s.string[j], n-prevind(s.string,j)+1)
end

"""
reverse(s::AbstractString) -> AbstractString
Reverses a string.
# Examples
```jldoctest
julia> reverse("JuliaLang")
"gnaLailuJ"
```
"""
reverse(s::AbstractString) = RevString(s)
reverse(s::RevString) = s.string

## reverse an index i so that reverse(s)[i] == s[reverseind(s,i)]

"""
Expand All @@ -148,7 +119,6 @@ Julia
"""
reverseind(s::AbstractString, i) = chr2ind(s, length(s) + 1 - ind2chr(reverse(s), i))
reverseind(s::Union{DirectIndexString,SubString{DirectIndexString}}, i::Integer) = length(s) + 1 - i
reverseind(s::RevString, i::Integer) = endof(s) - i + 1
reverseind(s::SubString{String}, i::Integer) =
reverseind(s.string, nextind(s.string, endof(s.string))-s.offset-s.endof+i-1) - s.offset

Expand Down
13 changes: 5 additions & 8 deletions base/strings/util.jl
Original file line number Diff line number Diff line change
Expand Up @@ -173,14 +173,11 @@ julia> rstrip(a)
```
"""
function rstrip(s::AbstractString, chars::Chars=_default_delims)
r = RevString(s)
i = start(r)
while !done(r,i)
c, j = next(r,i)
if !(c in chars)
return SubString(s, 1, endof(s)-i+1)
end
i = j
i = endof(s)
while i > 0
c = s[i]
c in chars || return SubString(s, 1, i)
i = prevind(s, i)
end
SubString(s, 1, 0)
end
Expand Down
2 changes: 1 addition & 1 deletion contrib/Julia_Notepad++.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
<Keywords name="Folders in comment, middle"></Keywords>
<Keywords name="Folders in comment, close"></Keywords>
<Keywords name="Keywords1">true false C_NULL Inf NaN Inf32 NaN32 nothing</Keywords>
<Keywords name="Keywords2">AbstractArray AbstractMatrix AbstractRange AbstractRemoteRef AbstractSparseMatrix AbstractString AbstractVector Any ArgumentError Array Associative BigFloat BigInt BitArray BitMatrix BitVector Bool BunchKaufman Cchar Cdouble Cfloat Char CharString CholeskyDense CholeskyPivotedDense Cint Cintmax_t Clong Clonglong Colon Complex Complex128 Complex64 ComplexPair Cptrdiff_t Cshort Csize_t Cuchar Cuint Cuintmax_t Culong Culonglong Cushort DArray Dict Dims DisconnectException EOFError EachLine EnvHash ErrorException Exception Expr Factorization Filter Float Float32 Float64 Function GSVDDense IO IOBuffer IOStream ImaginaryUnit InsertionSort Int Int128 Int16 Int32 Int64 Int8 IntSet Integer KeyError LDLTTridiagonal LUDense LUTridiagonal LoadError LocalProcess Matrix MergeSort MethodError NTuple Number ObjectIdDict ObjectIdDict OrdinalRange ParseError PipeBuffer ProcessGroup Ptr QRDense QRPivotedDense QuickSort RangeIndex Rational Real Regex RegexMatch RegexMatchIterator RepString RevString Reverse SVDDense Set Signed SparseMatrixCSC SpawnNullStream Stat StridedArray StridedMatrix StridedVecOrMat StridedVector String SubArray SubDArray SubOrDArray SubString SymTridiagonal Symbol SystemError Task TCPSocket TimSort Tridiagonal Tuple Type TypeError UInt UInt128 UInt16 UInt32 UInt64 UInt8 UVError Union UnitRange Unsigned VecOrMat Vector VersionNumber Void WeakKeyDict WeakRef Zip</Keywords>
<Keywords name="Keywords2">AbstractArray AbstractMatrix AbstractRange AbstractRemoteRef AbstractSparseMatrix AbstractString AbstractVector Any ArgumentError Array Associative BigFloat BigInt BitArray BitMatrix BitVector Bool BunchKaufman Cchar Cdouble Cfloat Char CharString CholeskyDense CholeskyPivotedDense Cint Cintmax_t Clong Clonglong Colon Complex Complex128 Complex64 ComplexPair Cptrdiff_t Cshort Csize_t Cuchar Cuint Cuintmax_t Culong Culonglong Cushort DArray Dict Dims DisconnectException EOFError EachLine EnvHash ErrorException Exception Expr Factorization Filter Float Float32 Float64 Function GSVDDense IO IOBuffer IOStream ImaginaryUnit InsertionSort Int Int128 Int16 Int32 Int64 Int8 IntSet Integer KeyError LDLTTridiagonal LUDense LUTridiagonal LoadError LocalProcess Matrix MergeSort MethodError NTuple Number ObjectIdDict ObjectIdDict OrdinalRange ParseError PipeBuffer ProcessGroup Ptr QRDense QRPivotedDense QuickSort RangeIndex Rational Real Regex RegexMatch RegexMatchIterator RepString Reverse SVDDense Set Signed SparseMatrixCSC SpawnNullStream Stat StridedArray StridedMatrix StridedVecOrMat StridedVector String SubArray SubDArray SubOrDArray SubString SymTridiagonal Symbol SystemError Task TCPSocket TimSort Tridiagonal Tuple Type TypeError UInt UInt128 UInt16 UInt32 UInt64 UInt8 UVError Union UnitRange Unsigned VecOrMat Vector VersionNumber Void WeakKeyDict WeakRef Zip</Keywords>
<Keywords name="Keywords3">abstract begin baremodule primitive break catch ccall const continue do else elseif end export finally for function global if struct import importall let local macro module quote return try mutable typealias using while</Keywords>
<Keywords name="Keywords4">close enumerate error info open print println read write warn</Keywords>
<Keywords name="Keywords5">print println</Keywords>
Expand Down
1 change: 0 additions & 1 deletion contrib/julia.xml
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,6 @@
<item> RegexMatch </item>
<item> RegexMatchIterator </item>
<item> RepString </item>
<item> RevString </item>
<item> Reverse </item>
<item> Schur </item>
<item> Set </item>
Expand Down
2 changes: 1 addition & 1 deletion doc/src/manual/interacting-with-julia.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ When the cursor is at the beginning of the line, the prompt can be changed to a
julia> ? # upon typing ?, the prompt changes (in place) to: help?>
help?> string
search: string String stringmime Cstring Cwstring RevString randstring bytestring SubString
search: string String stringmime Cstring Cwstring randstring bytestring SubString
string(xs...)
Expand Down
40 changes: 14 additions & 26 deletions test/strings/types.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This file is a part of Julia. License is MIT: https://julialang.org/license

## SubString, RevString and Cstring tests ##
## SubString and Cstring tests ##

## SubString tests ##
u8str = "∀ ε > 0, ∃ δ > 0: |x-y| < δ ⇒ |f(x)-f(y)| < ε"
Expand Down Expand Up @@ -163,36 +163,24 @@ end

## Reverse strings ##

let rs = RevString("foobar")
@test length(rs) == 6
@test sizeof(rs) == 6
@test isascii(rs)
end

# issue #4586
@test rsplit(RevString("ailuj"),'l') == ["ju","ia"]
@test parse(Float64,RevString("64")) === 46.0

# reverseind
for T in (String, GenericString)
for prefix in ("", "abcd", "\U0001d6a4\U0001d4c1", "\U0001d6a4\U0001d4c1c", " \U0001d6a4\U0001d4c1")
for suffix in ("", "abcde", "\U0001d4c1β\U0001d6a4", "\U0001d4c1β\U0001d6a4c", " \U0001d4c1β\U0001d6a4")
for c in ('X', 'δ', '\U0001d6a5')
s = convert(T, string(prefix, c, suffix))
r = reverse(s)
ri = search(r, c)
@test r == RevString(s)
@test c == s[reverseind(s, ri)] == r[ri]
s = RevString(s)
r = reverse(s)
ri = search(r, c)
@test c == s[reverseind(s, ri)] == r[ri]
s = convert(T, string(prefix, prefix, c, suffix, suffix))
pre = convert(T, prefix)
sb = SubString(s, nextind(pre, endof(pre)), endof(convert(T, string(prefix, prefix, c, suffix))))
r = reverse(sb)
ri = search(r, c)
@test c == sb[reverseind(sb, ri)] == r[ri]
let s = convert(T, string(prefix, c, suffix))
r = reverse(String(s))
ri = search(r, c)
@test c == s[reverseind(s, ri)] == r[ri]
end
let s = convert(T, string(prefix, prefix, c, suffix, suffix))
pre = convert(T, prefix)
sb = SubString(s, nextind(pre, endof(pre)), endof(convert(T, string(prefix, prefix, c, suffix))))
r = reverse(String(sb))
ri = search(r, c)
sbs = String(sb)
@test c == sbs[reverseind(sbs, ri)] == r[ri]
end
end
end
end
Expand Down

0 comments on commit a384401

Please sign in to comment.