Skip to content

Commit

Permalink
Remove RevString
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
now unconditionally returns a `String`.
  • Loading branch information
ararslan committed Nov 22, 2017
1 parent b8a488b commit 0e7b347
Show file tree
Hide file tree
Showing 14 changed files with 152 additions and 130 deletions.
8 changes: 8 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,9 @@ Language changes

* The syntax `(x...)` for constructing a tuple is deprecated; use `(x...,)` instead (#24452).

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

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

Expand Down Expand Up @@ -288,6 +291,9 @@ This section lists changes that do not have deprecation warnings.
Its return value has been removed. Use the `process_running` function
to determine if a process has already exited.

* `reverse(::AbstractString)` now unconditionally returns a `String`. Previously it
returned a `RevString`, which has been removed from Base ([#23612]).

Library improvements
--------------------

Expand Down Expand Up @@ -1525,6 +1531,7 @@ Command-line option changes
[#22572]: https://github.com/JuliaLang/julia/issues/22572
[#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 @@ -1580,6 +1587,7 @@ Command-line option changes
[#23529]: https://github.com/JuliaLang/julia/issues/23529
[#23530]: https://github.com/JuliaLang/julia/issues/23530
[#23570]: https://github.com/JuliaLang/julia/issues/23570
[#23612]: https://github.com/JuliaLang/julia/issues/23612
[#23628]: https://github.com/JuliaLang/julia/issues/23628
[#23665]: https://github.com/JuliaLang/julia/issues/23665
[#23690]: https://github.com/JuliaLang/julia/issues/23690
Expand Down
4 changes: 3 additions & 1 deletion base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2200,7 +2200,6 @@ end
@deprecate chol!(x::Number, uplo) chol(x) false
end


# issue #16307
@deprecate finalizer(o, f::Function) finalizer(f, o)
# This misses other callables but they are very rare in the wild
Expand All @@ -2211,6 +2210,9 @@ end
finalizer(f::Ptr{Void}, o::Ptr{Void}) = invoke(finalizer, Tuple{Ptr{Void}, Any}, f, o)
finalizer(f::Ptr{Void}, o::Function) = invoke(finalizer, Tuple{Ptr{Void}, Any}, f, o)

# Issue #22611
@deprecate_moved RevString "LegacyStrings"

# 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 @@ -88,7 +88,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 @@ -14,21 +14,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
74 changes: 74 additions & 0 deletions base/strings/basic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -646,3 +646,77 @@ next(r::Iterators.Reverse{<:AbstractString}, i) = (r.itr[i], prevind(r.itr, i))
start(r::Iterators.Reverse{<:EachStringIndex}) = endof(r.itr.s)
done(r::Iterators.Reverse{<:EachStringIndex}, i) = i < start(r.itr.s)
next(r::Iterators.Reverse{<:EachStringIndex}, i) = (i, prevind(r.itr.s, i))

"""
reverse(s::AbstractString) -> String
Reverse a string. The result is always a `String`, regardless of the input type.
Technically, this function reverses the codepoints in a string, and its
main utility is for reversed-order string processing, especially for reversed
regular-expression searches. See also [`reverseind`](@ref) to convert indices
in `s` to indices in `reverse(s)` and vice-versa, and [`graphemes`](@ref)
to operate on user-visible "characters" (graphemes) rather than codepoints.
# Examples
```jldoctest
julia> reverse("JuliaLang")
"gnaLailuJ"
julia> reverse("ax̂e") # combining characters can lead to surprising results
"êxa"
julia> join(reverse(collect(graphemes("ax̂e")))) # reverses graphemes
"ex̂a"
```
"""
reverse(s::AbstractString) = reverse(convert(String, s))

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

"""
reverseind(v, i)
Given an index `i` in [`reverse(v)`](@ref), return the corresponding index in `v` so that
`v[reverseind(v,i)] == reverse(v)[i]`. (This can be nontrivial in cases where `v` contains
non-ASCII characters.)
# Examples
```jldoctest
julia> r = reverse("Julia")
"ailuJ"
julia> for i in 1:length(r)
print(r[reverseind("Julia", i)])
end
Julia
```
"""
reverseind(s::AbstractString, i) = chr2ind(s, length(s) + 1 - ind2chr(reverse(s), i))

"""
repeat(s::AbstractString, r::Integer)
Repeat a string `r` times. This can equivalently be accomplished by calling [`s^r`](@ref ^).
# Examples
```jldoctest
julia> repeat("ha", 3)
"hahaha"
```
"""
repeat(s::AbstractString, r::Integer) = repeat(convert(String, s), r)

"""
^(s::Union{AbstractString,Char}, n::Integer)
Repeat a string or character `n` times.
The [`repeat`](@ref) function is an alias to this operator.
# Examples
```jldoctest
julia> "Test "^3
"Test Test Test "
```
"""
(^)(s::Union{AbstractString,Char}, r::Integer) = repeat(s, r)
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=endof(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 > 1
if k < 1
matched = false
break
end
c, k = next(rs,k)
d, j = next(t,j)
# Using `reverseind` with `prevind` in this way is like calling `nextind`
# on the reversed string
rk = reverseind(s, k)
c = s[rk]
k = prevind(s, rk)
rj = reverseind(t, j)
d = t[rj]
j = prevind(t, rj)
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
45 changes: 1 addition & 44 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 @@ -109,48 +109,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.
Technically, this function reverses the codepoints in a string, and its
main utility is for reversed-order string processing, especially for reversed
regular-expression searches. See also [`reverseind`](@ref) to convert indices
in `s` to indices in `reverse(s)` and vice-versa, and [`graphemes`](@ref)
to operate on user-visible "characters" (graphemes) rather than codepoints.
See also [`Iterators.reverse`](@ref) for reverse-order iteration without making a copy.
# Examples
```jldoctest
julia> reverse("JuliaLang")
"gnaLailuJ"
julia> reverse("ax̂e") # combining characters can lead to surprising results
"êxa"
julia> join(reverse(collect(graphemes("ax̂e")))) # reverses graphemes
"ex̂a"
```
"""
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 @@ -172,7 +130,6 @@ Julia
```
"""
reverseind(s::AbstractString, i) = chr2ind(s, length(s) + 1 - ind2chr(reverse(s), 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
12 changes: 4 additions & 8 deletions base/strings/util.jl
Original file line number Diff line number Diff line change
Expand Up @@ -190,14 +190,10 @@ 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
s[i] in chars || return SubString(s, 1, i)
i = prevind(s, i)
end
SubString(s, 1, 0)
end
Expand Down
Loading

0 comments on commit 0e7b347

Please sign in to comment.