Skip to content

Commit 64ae35b

Browse files
committed
Remove RevString
The `RevString` type for lazily reversed strings has been moved to the LegacyStrings package. Fixes #22611.
1 parent 83a89a1 commit 64ae35b

File tree

13 files changed

+81
-117
lines changed

13 files changed

+81
-117
lines changed

NEWS.md

+8
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,12 @@ Language changes
100100
* Prefix `&` for by-reference arguments to `ccall` has been deprecated in favor of
101101
`Ref` argument types ([#6080]).
102102

103+
* The `RevString` type for lazily reversed strings has been moved to the LegacyStrings
104+
package ([#22611]).
105+
106+
* `reverse` on `AbstractString`s has been deprecated in favor of converting to `String`
107+
before reversing ([#23612]).
108+
103109
Breaking changes
104110
----------------
105111

@@ -1311,6 +1317,7 @@ Command-line option changes
13111317
[#22532]: https://github.com/JuliaLang/julia/issues/22532
13121318
[#22588]: https://github.com/JuliaLang/julia/issues/22588
13131319
[#22605]: https://github.com/JuliaLang/julia/issues/22605
1320+
[#22611]: https://github.com/JuliaLang/julia/issues/22611
13141321
[#22666]: https://github.com/JuliaLang/julia/issues/22666
13151322
[#22696]: https://github.com/JuliaLang/julia/issues/22696
13161323
[#22703]: https://github.com/JuliaLang/julia/issues/22703
@@ -1340,3 +1347,4 @@ Command-line option changes
13401347
[#23233]: https://github.com/JuliaLang/julia/issues/23233
13411348
[#23342]: https://github.com/JuliaLang/julia/issues/23342
13421349
[#23404]: https://github.com/JuliaLang/julia/issues/23404
1350+
[#23612]: https://github.com/JuliaLang/julia/issues/23612

base/deprecated.jl

+6
Original file line numberDiff line numberDiff line change
@@ -1855,6 +1855,12 @@ end
18551855
nothing
18561856
end
18571857

1858+
# Issue #22611
1859+
@deprecate_moved RevString "LegacyStrings"
1860+
1861+
# PR 23612
1862+
@deprecate reverse(s::AbstractString) reverse(String(s))
1863+
18581864
# END 0.7 deprecations
18591865

18601866
# BEGIN 1.0 deprecations

base/exports.jl

-1
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,6 @@ export
9292
Rational,
9393
Regex,
9494
RegexMatch,
95-
RevString,
9695
RoundFromZero,
9796
RoundDown,
9897
RoundingMode,

base/precompile.jl

-3
Original file line numberDiff line numberDiff line change
@@ -581,9 +581,6 @@ precompile(Tuple{typeof(Base.LineEdit.complete_line), Base.LineEdit.PromptState,
581581
precompile(Tuple{typeof(Base.LineEdit.input_string_newlines_aftercursor), Base.LineEdit.PromptState})
582582
precompile(Tuple{typeof(Base.LineEdit.complete_line), Base.REPL.REPLCompletionProvider, Base.LineEdit.PromptState})
583583
precompile(Tuple{getfield(Base, Symbol("#kw##parse")), Array{Any, 1}, typeof(Base.parse), String})
584-
precompile(Tuple{typeof(Base.isvalid), Base.RevString{String}, Int64})
585-
precompile(Tuple{typeof(Base.nextind), Base.RevString{String}, Int64})
586-
precompile(Tuple{typeof(Base.search), Base.RevString{String}, Array{Char, 1}, Int64})
587584
precompile(Tuple{typeof(Base.rsearch), String, Array{Char, 1}, Int64})
588585
precompile(Tuple{getfield(Base.REPLCompletions, Symbol("#kw##find_start_brace")), Array{Any, 1}, typeof(Base.REPLCompletions.find_start_brace), String})
589586
precompile(Tuple{typeof(Core.Inference.isbits), Tuple{Void, Void, Void}})

base/repl/REPLCompletions.jl

+9-8
Original file line numberDiff line numberDiff line change
@@ -225,13 +225,13 @@ end
225225
# closed start brace from the end of the string.
226226
function find_start_brace(s::AbstractString; c_start='(', c_end=')')
227227
braces = 0
228-
r = RevString(s)
229-
i = start(r)
228+
i = endof(s)
230229
in_single_quotes = false
231230
in_double_quotes = false
232231
in_back_ticks = false
233-
while !done(r, i)
234-
c, i = next(r, i)
232+
while i > 0
233+
c = s[i]
234+
nexti = prevind(s, i)
235235
if !in_single_quotes && !in_double_quotes && !in_back_ticks
236236
if c == c_start
237237
braces += 1
@@ -245,18 +245,19 @@ function find_start_brace(s::AbstractString; c_start='(', c_end=')')
245245
in_back_ticks = true
246246
end
247247
else
248-
if !in_back_ticks && !in_double_quotes && c == '\'' && !done(r, i) && next(r, i)[1]!='\\'
248+
if !in_back_ticks && !in_double_quotes && c == '\'' && i > 0 && s[nexti] != '\\'
249249
in_single_quotes = !in_single_quotes
250-
elseif !in_back_ticks && !in_single_quotes && c == '"' && !done(r, i) && next(r, i)[1]!='\\'
250+
elseif !in_back_ticks && !in_single_quotes && c == '"' && i > 0 && s[nexti] != '\\'
251251
in_double_quotes = !in_double_quotes
252-
elseif !in_single_quotes && !in_double_quotes && c == '`' && !done(r, i) && next(r, i)[1]!='\\'
252+
elseif !in_single_quotes && !in_double_quotes && c == '`' && i > 0 && s[nexti] != '\\'
253253
in_back_ticks = !in_back_ticks
254254
end
255255
end
256256
braces == 1 && break
257+
i = nexti
257258
end
258259
braces != 1 && return 0:-1, -1
259-
method_name_end = reverseind(r, i)
260+
method_name_end = i - 1
260261
startind = nextind(s, rsearch(s, non_identifier_chars, method_name_end))
261262
return (startind:endof(s), method_name_end)
262263
end

base/shell.jl

+8-9
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,20 @@ function shell_parse(str::AbstractString, interpolate::Bool=true;
1212
special::AbstractString="")
1313
s = lstrip(str)
1414
# strips the end but respects the space when the string ends with "\\ "
15-
r = RevString(s)
16-
i = start(r)
17-
c_old = nothing
18-
while !done(r,i)
19-
c, j = next(r,i)
15+
i = endof(s)
16+
c_old = '\0' # initialized to a null byte for type stability
17+
while i > 0
18+
c = s[i]
2019
if c == '\\' && c_old == ' '
21-
i -= 1
20+
i += 1
2221
break
23-
elseif !(c in _default_delims)
22+
elseif !in(c, _default_delims)
2423
break
2524
end
26-
i = j
25+
i = prevind(s, i)
2726
c_old = c
2827
end
29-
s = s[1:end-i+1]
28+
s = s[1:i]
3029

3130
last_parse = 0:-1
3231
isempty(s) && return interpolate ? (Expr(:tuple,:()),last_parse) : ([],last_parse)

base/strings/search.jl

+28-28
Original file line numberDiff line numberDiff line change
@@ -194,12 +194,6 @@ end
194194
search(s::AbstractString, t::AbstractString, i::Integer=start(s)) = _search(s, t, i)
195195
search(s::ByteArray, t::ByteArray, i::Integer=start(s)) = _search(s, t, i)
196196

197-
function rsearch(s::AbstractString, c::Chars)
198-
j = search(RevString(s), c)
199-
j == 0 && return 0
200-
endof(s)-j+1
201-
end
202-
203197
"""
204198
rsearch(s::AbstractString, chars::Chars, [start::Integer])
205199
@@ -212,44 +206,50 @@ julia> rsearch("aaabbb","b")
212206
6:6
213207
```
214208
"""
215-
function rsearch(s::AbstractString, c::Chars, i::Integer)
216-
e = endof(s)
217-
j = search(RevString(s), c, e-i+1)
218-
j == 0 && return 0
219-
e-j+1
209+
function rsearch(s::AbstractString, c::Chars, i::Integer=start(s))
210+
@boundscheck checkbounds(s, i)
211+
isempty(c) && return i
212+
j = i
213+
while j > 0
214+
d = s[j]
215+
d in c && return j
216+
j = prevind(s, j)
217+
end
218+
return 0
220219
end
221220

222221
function _rsearchindex(s, t, i)
223222
if isempty(t)
224-
return 1 <= i <= nextind(s,endof(s)) ? i :
225-
throw(BoundsError(s, i))
223+
@boundscheck checkbounds(s, i)
224+
return i
226225
end
227-
t = RevString(t)
228-
rs = RevString(s)
229226
l = endof(s)
230-
t1, j2 = next(t,start(t))
227+
t1, j2 = last(t), endof(t)
231228
while true
232-
i = rsearch(s,t1,i)
233-
if i == 0 return 0 end
234-
c, ii = next(rs,l-i+1)
235-
j = j2; k = ii
229+
i = rsearch(s, t1, i)
230+
i == 0 && return 0
231+
c = s[i]
232+
ii = prevind(s, i)
233+
j, k = j2, ii
236234
matched = true
237-
while !done(t,j)
238-
if done(rs,k)
235+
while j > 0
236+
if k < 1
239237
matched = false
240238
break
241239
end
242-
c, k = next(rs,k)
243-
d, j = next(t,j)
240+
c, k = let rs_k = reverseind(s, k)
241+
s[rs_k], prevind(s, rs_k)
242+
end
243+
d, j = let rt_j = reverseind(t, j)
244+
t[rt_j], prevind(t, rt_j)
245+
end
244246
if c != d
245247
matched = false
246248
break
247249
end
248250
end
249-
if matched
250-
return nextind(s,l-k+1)
251-
end
252-
i = l-ii+1
251+
matched && return nextind(s, k)
252+
i = ii
253253
end
254254
end
255255

base/strings/types.jl

+1-31
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# This file is a part of Julia. License is MIT: https://julialang.org/license
22

3-
# SubString and RevString types
3+
# SubString type
44

55
## substrings reference original strings ##
66

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

100-
## reversed strings without data movement ##
101-
102-
struct RevString{T<:AbstractString} <: AbstractString
103-
string::T
104-
end
105-
106-
endof(s::RevString) = endof(s.string)
107-
length(s::RevString) = length(s.string)
108-
sizeof(s::RevString) = sizeof(s.string)
109-
110-
function next(s::RevString, i::Int)
111-
n = endof(s); j = n-i+1
112-
(s.string[j], n-prevind(s.string,j)+1)
113-
end
114-
115-
"""
116-
reverse(s::AbstractString) -> AbstractString
117-
118-
Reverses a string.
119-
120-
# Examples
121-
```jldoctest
122-
julia> reverse("JuliaLang")
123-
"gnaLailuJ"
124-
```
125-
"""
126-
reverse(s::AbstractString) = RevString(s)
127-
reverse(s::RevString) = s.string
128-
129100
## reverse an index i so that reverse(s)[i] == s[reverseind(s,i)]
130101

131102
"""
@@ -148,7 +119,6 @@ Julia
148119
"""
149120
reverseind(s::AbstractString, i) = chr2ind(s, length(s) + 1 - ind2chr(reverse(s), i))
150121
reverseind(s::Union{DirectIndexString,SubString{DirectIndexString}}, i::Integer) = length(s) + 1 - i
151-
reverseind(s::RevString, i::Integer) = endof(s) - i + 1
152122
reverseind(s::SubString{String}, i::Integer) =
153123
reverseind(s.string, nextind(s.string, endof(s.string))-s.offset-s.endof+i-1) - s.offset
154124

base/strings/util.jl

+5-8
Original file line numberDiff line numberDiff line change
@@ -173,14 +173,11 @@ julia> rstrip(a)
173173
```
174174
"""
175175
function rstrip(s::AbstractString, chars::Chars=_default_delims)
176-
r = RevString(s)
177-
i = start(r)
178-
while !done(r,i)
179-
c, j = next(r,i)
180-
if !(c in chars)
181-
return SubString(s, 1, endof(s)-i+1)
182-
end
183-
i = j
176+
i = endof(s)
177+
while i > 0
178+
c = s[i]
179+
c in chars || return SubString(s, 1, i)
180+
i = prevind(s, i)
184181
end
185182
SubString(s, 1, 0)
186183
end

contrib/Julia_Notepad++.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
<Keywords name="Folders in comment, middle"></Keywords>
2626
<Keywords name="Folders in comment, close"></Keywords>
2727
<Keywords name="Keywords1">true false C_NULL Inf NaN Inf32 NaN32 nothing</Keywords>
28-
<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>
28+
<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>
2929
<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>
3030
<Keywords name="Keywords4">close enumerate error info open print println read write warn</Keywords>
3131
<Keywords name="Keywords5">print println</Keywords>

contrib/julia.xml

-1
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,6 @@
156156
<item> RegexMatch </item>
157157
<item> RegexMatchIterator </item>
158158
<item> RepString </item>
159-
<item> RevString </item>
160159
<item> Reverse </item>
161160
<item> Schur </item>
162161
<item> Set </item>

doc/src/manual/interacting-with-julia.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ When the cursor is at the beginning of the line, the prompt can be changed to a
6767
julia> ? # upon typing ?, the prompt changes (in place) to: help?>
6868
6969
help?> string
70-
search: string String stringmime Cstring Cwstring RevString randstring bytestring SubString
70+
search: string String stringmime Cstring Cwstring randstring bytestring SubString
7171
7272
string(xs...)
7373

test/strings/types.jl

+14-26
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# This file is a part of Julia. License is MIT: https://julialang.org/license
22

3-
## SubString, RevString and Cstring tests ##
3+
## SubString and Cstring tests ##
44

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

164164
## Reverse strings ##
165165

166-
let rs = RevString("foobar")
167-
@test length(rs) == 6
168-
@test sizeof(rs) == 6
169-
@test isascii(rs)
170-
end
171-
172-
# issue #4586
173-
@test rsplit(RevString("ailuj"),'l') == ["ju","ia"]
174-
@test parse(Float64,RevString("64")) === 46.0
175-
176166
# reverseind
177167
for T in (String, GenericString)
178168
for prefix in ("", "abcd", "\U0001d6a4\U0001d4c1", "\U0001d6a4\U0001d4c1c", " \U0001d6a4\U0001d4c1")
179169
for suffix in ("", "abcde", "\U0001d4c1β\U0001d6a4", "\U0001d4c1β\U0001d6a4c", " \U0001d4c1β\U0001d6a4")
180170
for c in ('X', 'δ', '\U0001d6a5')
181-
s = convert(T, string(prefix, c, suffix))
182-
r = reverse(s)
183-
ri = search(r, c)
184-
@test r == RevString(s)
185-
@test c == s[reverseind(s, ri)] == r[ri]
186-
s = RevString(s)
187-
r = reverse(s)
188-
ri = search(r, c)
189-
@test c == s[reverseind(s, ri)] == r[ri]
190-
s = convert(T, string(prefix, prefix, c, suffix, suffix))
191-
pre = convert(T, prefix)
192-
sb = SubString(s, nextind(pre, endof(pre)), endof(convert(T, string(prefix, prefix, c, suffix))))
193-
r = reverse(sb)
194-
ri = search(r, c)
195-
@test c == sb[reverseind(sb, ri)] == r[ri]
171+
let s = convert(T, string(prefix, c, suffix))
172+
r = reverse(String(s))
173+
ri = search(r, c)
174+
@test c == s[reverseind(s, ri)] == r[ri]
175+
end
176+
let s = convert(T, string(prefix, prefix, c, suffix, suffix))
177+
pre = convert(T, prefix)
178+
sb = SubString(s, nextind(pre, endof(pre)), endof(convert(T, string(prefix, prefix, c, suffix))))
179+
r = reverse(String(sb))
180+
ri = search(r, c)
181+
sbs = String(sb)
182+
@test c == sbs[reverseind(sbs, ri)] == r[ri]
183+
end
196184
end
197185
end
198186
end

0 commit comments

Comments
 (0)