local find = string.find
local len = string.len
local pattern_simplifier = require("Module:string/pattern simplifier")
local select = select
local sub = string.sub
local ufind = mw.ustring.find
local ulen = mw.ustring.len
local usub = mw.ustring.sub
local function add_captures(text, n, ...)
-- Insert any captures from the splitting pattern.
local offset, capture = n - 1, ...
while capture do
n = n + 1
text[n] = capture
capture = select(n - offset, ...)
end
return n
end
local function iterate(str, str_len, text, n, start, _sub, loc1, loc2, ...)
if not (loc1 and start <= str_len) then
-- If no match, or there is but we're past the end of the string
-- (which happens when the match is the empty string), then add
-- the final chunk and return.
n = n + 1
text[n] = _sub(str, start)
return
elseif loc2 < start then
-- Special case: If we don't advance by any characters, then advance
-- by one character; this avoids an infinite loop, and makes splitting
-- by an empty string work the way mw.text.split() does. If we reach
-- the end of the string this way, return immediately, so we don't
-- get a final empty string.
n = n + 1
text[n] = _sub(str, start, start)
if start == str_len then
return add_captures(text, n, ...)
end
start = start + 1
else
-- Add chunk up to the current match.
n = n + 1
text[n] = _sub(str, start, loc1 - 1)
start = loc2 + 1
end
return add_captures(text, n, ...), start
end
return function (str, pattern)
local text, n, start, simple, str_len, _sub, _find = {}, 0, 1, pattern_simplifier(pattern)
if simple then
str_len, _sub, _find, pattern = len(str), sub, find, simple
else
str_len, _sub, _find = ulen(str), usub, ufind
end
repeat
n, start = iterate(str, str_len, text, n, start, _sub, _find(str, pattern, start))
until not start
return text
end