Skip to content

Commit 380950a

Browse files
authored
feat: support contains and occursin method (#37)
- Added codeunit and codeunit(s, i) methods for accessing code units - Implemented isvalid and thisind for proper UTF-8 character boundary detection
1 parent b3413bc commit 380950a

File tree

2 files changed

+34
-4
lines changed

2 files changed

+34
-4
lines changed

src/staticstring.jl

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# https://github.com/mkitti/StaticStrings.jl
22
# https://github.com/JuliaPy/PythonCall.jl/blob/main/src/Utils/Utils.jl
3+
using Base: between
34

45
struct StaticString{N, T} <: AbstractString
56
codeunits::NTuple{N, T}
@@ -60,10 +61,33 @@ function Base.String(x::StaticString{N, T}) where {N, T}
6061
return String(b .= x.codeunits)
6162
end
6263

63-
@inline Base.ncodeunits(::StaticString{N}) where N = N
64+
@inline Base.ncodeunits(::StaticString{N}) where {N} = N
65+
Base.codeunit(::StaticString{N, T}) where {N, T} = T
66+
Base.@propagate_inbounds Base.codeunit(s::StaticString, i::Int) = s.codeunits[i]
6467

65-
function StaticString(cu::Base.CodeUnits{T}) where T
68+
function StaticString(cu::Base.CodeUnits{T}) where {T}
6669
N = length(cu)
6770
return StaticString{N, T}(NTuple{N, T}(cu))
6871
end
69-
StaticString(s::AbstractString) = StaticString(codeunits(s))
72+
StaticString(s::AbstractString) = StaticString(codeunits(s))
73+
74+
Base.isvalid(s::StaticString, i::Int) = checkbounds(Bool, s, i) && thisind(s, i) == i
75+
Base.thisind(s::StaticString, i::Int) = _thisind_str(s, i)
76+
77+
@inline function _thisind_str(s, i::Int)
78+
i == 0 && return 0
79+
n = ncodeunits(s)
80+
i == n + 1 && return i
81+
@boundscheck between(i, 1, n) || throw(BoundsError(s, i))
82+
@inbounds b = codeunit(s, i)
83+
(b & 0xc0 == 0x80) & (i - 1 > 0) || return i
84+
@inbounds b = codeunit(s, i - 1)
85+
between(b, 0b11000000, 0b11110111) && return i - 1
86+
(b & 0xc0 == 0x80) & (i - 2 > 0) || return i
87+
@inbounds b = codeunit(s, i - 2)
88+
between(b, 0b11100000, 0b11110111) && return i - 2
89+
(b & 0xc0 == 0x80) & (i - 3 > 0) || return i
90+
@inbounds b = codeunit(s, i - 3)
91+
between(b, 0b11110000, 0b11110111) && return i - 3
92+
return i
93+
end

test/staticstring.jl

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using CommonDataFormat: StaticString
2+
using Test
23

34
@testset "StaticString" begin
45
s = "Hello, World!"
@@ -8,4 +9,9 @@ using CommonDataFormat: StaticString
89
@test ss == s
910
@test String(ss) == s
1011
@test !isempty(ss)
11-
end
12+
@test contains(ss, "World")
13+
@test occursin("World", ss)
14+
@test replace(ss, "World" => "Julia") == "Hello, Julia!"
15+
16+
@test codeunit(ss) == UInt8
17+
end

0 commit comments

Comments
 (0)