Skip to content

Commit

Permalink
thisind, 3-arg length/nextind/prevind, codeunit(s) (#573)
Browse files Browse the repository at this point in the history
  • Loading branch information
stevengj authored Jun 15, 2018
1 parent b374312 commit 5c1875a
Show file tree
Hide file tree
Showing 3 changed files with 160 additions and 0 deletions.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,11 @@ Currently, the `@compat` macro supports the following syntaxes:

* `codeunits(s)` returns an array-like view of the `UInt8` code units of
a string and `ncodeunits(s)` returns the number of code units ([#25241]).
`codeunit(s)` returns the type of the code units of `s` ([#24999]).

* `thisind(s, i)` returns the character index for codeunit `i` ([#24414]).

* Three-argument methods `prevind(s,i,n)`, `nextind(s,i,n)` ([#23805]), and `length(s,i,j)` ([#24999]); the latter two replace `chr2ind` and `ind2chr` in Julia 0.7, respectively.

* `printstyled` prints to a given stream optionally in color and/or bolded ([#25522]).

Expand Down Expand Up @@ -562,12 +567,14 @@ includes this fix. Find the minimum version from there.
[#23642]: https://github.com/JuliaLang/julia/issues/23642
[#23666]: https://github.com/JuliaLang/julia/issues/23666
[#23757]: https://github.com/JuliaLang/julia/issues/23757
[#23805]: https://github.com/JuliaLang/julia/issues/23805
[#23931]: https://github.com/JuliaLang/julia/issues/23931
[#24047]: https://github.com/JuliaLang/julia/issues/24047
[#24182]: https://github.com/JuliaLang/julia/issues/24182
[#24282]: https://github.com/JuliaLang/julia/issues/24282
[#24361]: https://github.com/JuliaLang/julia/issues/24361
[#24372]: https://github.com/JuliaLang/julia/issues/24372
[#24414]: https://github.com/JuliaLang/julia/issues/24414
[#24443]: https://github.com/JuliaLang/julia/issues/24443
[#24459]: https://github.com/JuliaLang/julia/issues/24459
[#24490]: https://github.com/JuliaLang/julia/issues/24490
Expand All @@ -582,6 +589,7 @@ includes this fix. Find the minimum version from there.
[#24808]: https://github.com/JuliaLang/julia/issues/24808
[#24831]: https://github.com/JuliaLang/julia/issues/24831
[#24874]: https://github.com/JuliaLang/julia/issues/24874
[#24999]: https://github.com/JuliaLang/julia/issues/24999
[#25012]: https://github.com/JuliaLang/julia/issues/25012
[#25021]: https://github.com/JuliaLang/julia/issues/25021
[#25056]: https://github.com/JuliaLang/julia/issues/25056
Expand Down
54 changes: 54 additions & 0 deletions src/Compat.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1925,6 +1925,60 @@ end
export @cfunction
end

if VERSION < v"0.7.0-DEV.2920" # julia#24999
Base.length(s::AbstractString, i::Integer, j::Integer) = length(s, Int(i), Int(j))
function Base.length(s::AbstractString, i::Int, j::Int)
@boundscheck begin
0 < i ncodeunits(s)+1 || throw(BoundsError(s, i))
0  j < ncodeunits(s)+1 || throw(BoundsError(s, j))
end
n = 0
for k = i:j
@inbounds n += isvalid(s, k)
end
return n
end
Base.codeunit(s::String) = UInt8
Base.codeunit(s::SubString) = codeunit(s.string)
end
if !isdefined(Base, :thisind) # #24414
thisind(s::AbstractString, i::Integer) = thisind(s, Int(i))
function thisind(s::AbstractString, i::Int)
z = ncodeunits(s) + 1
i == z && return i
@boundscheck 0 i z || throw(BoundsError(s, i))
@inbounds while 1 < i && !isvalid(s, i)
i -= 1
end
return i
end
export thisind
end
if VERSION < v"0.7.0-DEV.2019" # julia#23805
Base.prevind(s::AbstractString, i::Integer, n::Integer) = prevind(s, Int(i), Int(n))
Base.nextind(s::AbstractString, i::Integer, n::Integer) = nextind(s, Int(i), Int(n))
function Base.nextind(s::AbstractString, i::Int, n::Int)
n < 0 && throw(ArgumentError("n cannot be negative: $n"))
z = ncodeunits(s)
@boundscheck 0 i z || throw(BoundsError(s, i))
n == 0 && return thisind(s, i) == i ? i : throw(BoundsError(s, i))
while n > 0 && i < z
@inbounds n -= isvalid(s, i += 1)
end
return i + n
end
function Base.prevind(s::AbstractString, i::Int, n::Int)
n < 0 && throw(ArgumentError("n cannot be negative: $n"))
z = ncodeunits(s) + 1
@boundscheck 0 < i z || throw(BoundsError(s, i))
n == 0 && return thisind(s, i) == i ? i : throw(BoundsError(s, i))
while n > 0 && 1 < i
@inbounds n -= isvalid(s, i -= 1)
end
return i - n
end
end

if VERSION < v"0.7.0-DEV.5278"
something() = throw(ArgumentError("No value arguments present"))
something(x::Nothing, y...) = something(y...)
Expand Down
98 changes: 98 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1238,6 +1238,7 @@ end

@test codeunits("foo") == [0x66,0x6f,0x6f] == codeunits(SubString("fooαβγ",1,3))
@test ncodeunits("αβγ") == 6 == ncodeunits(SubString("fooαβγ",4,8))
@test codeunit("foo") == codeunit(SubString("fooαβγ",1,3)) == UInt8

# 0.7.0-DEV.3539
@test nameof(Compat.Sys) == :Sys
Expand Down Expand Up @@ -1768,6 +1769,103 @@ end
@test something(Some(2), 1) === 2
@test something(nothing, Some(1)) === 1

# julia#24999
let s = "∀α>β:α+"
@test [length(s,i,j) for i=1:ncodeunits(s)+1, j=0:ncodeunits(s)] ==
[0 1 1 1 2 2 3 4 4 5 6 6 7; 0 0 0 0 1 1 2 3 3 4 5 5 6; 0 0 0 0 1 1 2 3 3 4 5 5 6; 0 0 0 0 1 1 2 3 3 4 5 5 6; 0 0 0 0 0 0 1 2 2 3 4 4 5; 0 0 0 0 0 0 1 2 2 3 4 4 5; 0 0 0 0 0 0 0 1 1 2 3 3 4; 0 0 0 0 0 0 0 0 0 1 2 2 3; 0 0 0 0 0 0 0 0 0 1 2 2 3; 0 0 0 0 0 0 0 0 0 0 1 1 2; 0 0 0 0 0 0 0 0 0 0 0 0 1; 0 0 0 0 0 0 0 0 0 0 0 0 1; 0 0 0 0 0 0 0 0 0 0 0 0 0]
end
@test_throws BoundsError length("hello", 1, -1)
@test_throws BoundsError length("hellø", 1, -1)
@test_throws BoundsError length("hello", 1, 10)
@test_throws BoundsError length("hellø", 1, 10) == 9
@test_throws BoundsError prevind("hello", 0, 1)
@test_throws BoundsError prevind("hellø", 0, 1)
@test nextind("hello", 0, 10) == 10
# julia#24414
let strs = Any["∀α>β:α+1>β", SubString("123∀α>β:α+1>β123", 4, 18)]
for s in strs
@test_throws BoundsError thisind(s, -2)
@test_throws BoundsError thisind(s, -1)
@test thisind(s, 0) == 0
@test thisind(s, 1) == 1
@test thisind(s, 2) == 1
@test thisind(s, 3) == 1
@test thisind(s, 4) == 4
@test thisind(s, 5) == 4
@test thisind(s, 6) == 6
@test thisind(s, 15) == 15
@test thisind(s, 16) == 15
@test thisind(s, 17) == 17
@test_throws BoundsError thisind(s, 18)
@test_throws BoundsError thisind(s, 19)
end
end
let strs = Any["", SubString("123", 2, 1)]
for s in strs
@test_throws BoundsError thisind(s, -1)
@test thisind(s, 0) == 0
@test thisind(s, 1) == 1
@test_throws BoundsError thisind(s, 2)
end
end
# prevind and nextind, julia#23805
let s = "∀α>β:α+1>β"
@test_throws BoundsError prevind(s, 0, 0)
@test_throws BoundsError prevind(s, 0, 1)
@test prevind(s, 1, 1) == 0
@test prevind(s, 1, 0) == 1
@test prevind(s, 2, 1) == 1
@test prevind(s, 4, 1) == 1
@test prevind(s, 5, 1) == 4
@test prevind(s, 5, 2) == 1
@test prevind(s, 5, 3) == 0
@test prevind(s, 15, 1) == 14
@test prevind(s, 15, 2) == 13
@test prevind(s, 15, 3) == 12
@test prevind(s, 15, 4) == 10
@test prevind(s, 15, 10) == 0
@test prevind(s, 15, 9) == 1
@test prevind(s, 16, 1) == 15
@test prevind(s, 16, 2) == 14
@test prevind(s, 17, 1) == 15
@test prevind(s, 17, 2) == 14
@test_throws BoundsError prevind(s, 18, 0)
@test_throws BoundsError prevind(s, 18, 1)
@test_throws BoundsError nextind(s, -1, 0)
@test_throws BoundsError nextind(s, -1, 1)
@test nextind(s, 0, 2) == 4
@test nextind(s, 0, 20) == 26
@test nextind(s, 0, 10) == 15
@test nextind(s, 1, 1) == 4
@test nextind(s, 1, 2) == 6
@test nextind(s, 1, 9) == 15
@test nextind(s, 1, 10) == 17
@test nextind(s, 2, 1) == 4
@test nextind(s, 3, 1) == 4
@test nextind(s, 4, 1) == 6
@test nextind(s, 14, 1) == 15
@test nextind(s, 15, 1) == 17
@test nextind(s, 15, 2) == 18
@test nextind(s, 16, 1) == 17
@test nextind(s, 16, 2) == 18
@test nextind(s, 16, 3) == 19
@test_throws BoundsError nextind(s, 17, 0)
@test_throws BoundsError nextind(s, 17, 1)
for k in 0:ncodeunits(s)+1
n = p = k
for j in 1:40
if 1 p
p = prevind(s, p)
@test prevind(s, k, j) == p
end
if n  ncodeunits(s)
n = nextind(s, n)
@test nextind(s, k, j) == n
end
end
end
end

# 0.7.0-DEV.5171
let sep = Compat.Sys.iswindows() ? ';' : ':'
withenv("PATH" => string(Compat.Sys.BINDIR, sep, get(ENV, "PATH", ""))) do
Expand Down

0 comments on commit 5c1875a

Please sign in to comment.