2019-08-19 19:54:38 +02:00
|
|
|
# String with Length
|
|
|
|
# This allows to compute length once and only once
|
2019-08-20 20:15:05 +02:00
|
|
|
struct StringWithLength{T<:AbstractString} <: AbstractString
|
2019-08-19 19:54:38 +02:00
|
|
|
s::T
|
|
|
|
l::Int
|
|
|
|
end
|
|
|
|
string_with_length(s::AbstractString) = StringWithLength(s, length(s))
|
|
|
|
Base.length(s::StringWithLength) = s.l
|
2019-08-20 20:15:05 +02:00
|
|
|
Base.iterate(s::StringWithLength, i::Integer = firstindex(s.s)) = iterate(s.s, i)
|
2019-08-19 19:54:38 +02:00
|
|
|
Base.nextind(s::StringWithLength, i::Int, n::Int = 1) = nextind(s.s, i, n)
|
|
|
|
Base.ncodeunits(s::StringWithLength) = ncodeunits(s.s)
|
|
|
|
Base.isvalid(s::StringWithLength, i::Int) = isvalid(s.s, i)
|
2019-12-12 15:38:20 +01:00
|
|
|
|
2019-08-19 19:54:38 +02:00
|
|
|
function reorder(s1::AbstractString, s2::AbstractString)
|
|
|
|
s1 = string_with_length(s1)
|
|
|
|
s2 = string_with_length(s2)
|
2019-08-20 17:59:23 +02:00
|
|
|
if length(s1) <= length(s2)
|
|
|
|
return s1, s2
|
|
|
|
else
|
|
|
|
return s2, s1
|
2019-08-19 19:54:38 +02:00
|
|
|
end
|
2019-08-20 17:59:23 +02:00
|
|
|
end
|
2019-08-17 17:40:26 +02:00
|
|
|
|
2019-08-19 19:54:38 +02:00
|
|
|
|
2019-08-17 17:40:26 +02:00
|
|
|
## Find common prefixes (up to lim. -1 means Inf)
|
2019-08-19 19:12:55 +02:00
|
|
|
function remove_prefix(s1::AbstractString, s2::AbstractString, lim::Integer = -1)
|
2019-08-17 20:38:49 +02:00
|
|
|
l = 0
|
2019-08-17 17:40:26 +02:00
|
|
|
x1 = iterate(s1)
|
|
|
|
x2 = iterate(s2)
|
|
|
|
while (x1 !== nothing) & (x2 !== nothing) & (l < lim || lim < 0)
|
|
|
|
ch1, state1 = x1
|
|
|
|
ch2, state2 = x2
|
|
|
|
ch1 != ch2 && break
|
|
|
|
x1 = iterate(s1, state1)
|
|
|
|
x2 = iterate(s2, state2)
|
|
|
|
l += 1
|
|
|
|
end
|
|
|
|
return l, x1, x2
|
2019-12-13 02:01:47 +01:00
|
|
|
end
|