-- See Copyright Notice in the file LICENSE local luatest = require "luatest" local N = luatest.NT local unpack = unpack or table.unpack local function norm(a) return a==nil and N or a end local function fill (n, m) local t = {} for i = n, m, -1 do table.insert (t, i) end return t end local function set_named_subpatterns (lib, flg) return { Name = "Named Subpatterns", Func = function (subj, methodname, patt, name1, name2) local r = lib.new (patt) local _,_,caps = r[methodname] (r, subj) return norm(caps[name1]), norm(caps[name2]) end, --{} N.B. subject is always first element { {"abcd", "tfind", "(?P.)b.(?Pd)", "dog", "cat"}, {"a","d"} }, { {"abcd", "exec", "(?P.)b.(?Pd)", "dog", "cat"}, {"a","d"} }, } end local function set_f_find (lib, flg) local cp1251 = "ÀÁÂÃÄŨÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäå¸æçèéêëìíîïðñòóôõö÷øùúûüýþÿ" local loc = "Russian_Russia.1251" return { Name = "Function find", Func = lib.find, --{subj, patt, st,cf,ef,lo}, { results } { {"abcd", ".+", 5}, { N } }, -- failing st { {"abcd", ".*?"}, { 1,0 } }, -- non-greedy { {"abc", "aBC", N,flg.CASELESS}, { 1,3 } }, -- cf { {"abc", "aBC", N,"i" }, { 1,3 } }, -- cf { {"abc", "bc", N,flg.ANCHORED}, { N } }, -- cf { {"abc", "bc", N,N,flg.ANCHORED}, { N } }, -- ef --{ {cp1251, "[[:upper:]]+", N,N,N, loc}, { 1,33} }, -- locale --{ {cp1251, "[[:lower:]]+", N,N,N, loc}, {34,66} }, -- locale } end local function set_f_match (lib, flg) return { Name = "Function match", Func = lib.match, --{subj, patt, st,cf,ef,lo}, { results } { {"abcd", ".+", 5}, { N }}, -- failing st { {"abcd", ".*?"}, { "" }}, -- non-greedy { {"abc", "aBC", N,flg.CASELESS}, {"abc" }}, -- cf { {"abc", "aBC", N,"i" }, {"abc" }}, -- cf { {"abc", "bc", N,flg.ANCHORED}, { N }}, -- cf { {"abc", "bc", N,N,flg.ANCHORED}, { N }}, -- ef } end local function set_f_gmatch (lib, flg) -- gmatch (s, p, [cf], [ef]) local pCSV = "[^,]*" local F = false local function test_gmatch (subj, patt) local out, guard = {}, 10 for a, b in lib.gmatch (subj, patt) do table.insert (out, { norm(a), norm(b) }) guard = guard - 1 if guard == 0 then break end end return unpack (out) end return { Name = "Function gmatch", Func = test_gmatch, --{ subj patt results } { {"a\0c", "." }, {{"a",N},{"\0",N},{"c",N}} },--nuls in subj { {"", pCSV}, {{"",N}} }, { {"12", pCSV}, {{"12",N}} }, { {",", pCSV}, {{"", N},{"", N}} }, { {"12,,45", pCSV}, {{"12",N},{"",N},{"45",N}} }, { {",,12,45,,ab,", pCSV}, {{"",N},{"",N},{"12",N},{"45",N},{"",N},{"ab",N},{"",N}} }, { {"12345", "(.)(.)"}, {{"1","2"},{"3","4"}} }, { {"12345", "(.)(.?)"}, {{"1","2"},{"3","4"},{"5",""}} }, } end local function set_f_split (lib, flg) -- split (s, p, [cf], [ef]) local function test_split (subj, patt) local out, guard = {}, 10 for a, b, c in lib.split (subj, patt) do table.insert (out, { norm(a), norm(b), norm(c) }) guard = guard - 1 if guard == 0 then break end end return unpack (out) end return { Name = "Function split", Func = test_split, --{ subj patt results } { {"a,\0,c", ","}, {{"a",",",N},{"\0",",",N},{"c",N,N}, } },--nuls in subj { {"ab", "$"}, {{"ab","",N}, {"",N,N} } }, { {"ab", "^|$"}, {{"", "", N}, {"ab","",N}, {"",N,N} } }, { {"ab45ab","(?<=ab).*?"}, {{"ab","",N}, {"45ab","",N}, {"",N,N} } }, { {"ab", "\\b"}, {{"", "", N}, {"ab","",N}, {"",N,N} } }, { {"ab", ".*" }, {{"","ab",N}, {"",N,N} } }, { {"ab", ".*?" }, {{"","",N}, {"a","",N}, {"b","",N}, {"",N,N} } }, { {"ab;de", ";*" }, {{"","",N},{"a","",N},{"b",";",N},{"d","",N},{"e","",N},{"",N,N} }}, } end local function set_m_exec (lib, flg) return { Name = "Method exec", Method = "exec", --{patt,cf,lo}, {subj,st,ef} { results } { {".+"}, {"abcd",5}, { N } }, -- failing st { {".*?"}, {"abcd"}, {1,0,{}} }, -- non-greedy { {"aBC",flg.CASELESS}, {"abc"}, {1,3,{}} }, -- cf { {"aBC","i" }, {"abc"}, {1,3,{}} }, -- cf { {"bc",flg.ANCHORED}, {"abc"}, { N } }, -- cf { {"bc"}, {"abc",N, flg.ANCHORED}, { N } }, -- ef } end local function set_m_tfind (lib, flg) return { Name = "Method tfind", Method = "tfind", --{patt,cf,lo}, {subj,st,ef} { results } { {".+"}, {"abcd",5}, { N } }, -- failing st { {".*?"}, {"abcd"}, {1,0,{}} }, -- non-greedy { {"aBC",flg.CASELESS}, {"abc"}, {1,3,{}} }, -- cf { {"aBC","i" }, {"abc"}, {1,3,{}} }, -- cf { {"bc",flg.ANCHORED}, {"abc"}, { N } }, -- cf { {"bc"}, {"abc",N, flg.ANCHORED}, { N } }, -- ef } end local function set_m_dfa_exec (lib, flg) local ver = tonumber(lib.version():match("%d+%.%d+")) local NAP = ver < 8.34 and "" or "(*NO_AUTO_POSSESS)" local flag_partial = ver < 10.0 and flg.PARTIAL or flg.PARTIAL_SOFT return { Name = "Method dfa_exec", Method = "dfa_exec", --{patt,cf,lo}, {subj,st,ef,os,ws} { results } { {NAP..".+"}, {"abcd"}, {1,{4,3,2,1},4} }, -- [none] { {NAP..".+"}, {"abcd",2}, {2,{4,3,2}, 3} }, -- positive st { {NAP..".+"}, {"abcd",-2}, {3,{4,3}, 2} }, -- negative st { {".+"}, {"abcd",5}, {N } }, -- failing st { {NAP..".*"}, {"abcd"}, {1,{4,3,2,1,0},5}}, -- [none] { {".*?"}, {"abcd"}, {1,{4,3,2,1,0},5}}, -- non-greedy { {"aBC",flg.CASELESS}, {"abc"}, {1,{3},1} }, -- cf { {"aBC","i" }, {"abc"}, {1,{3},1} }, -- cf { {"bc"}, {"abc"}, {2,{3},1} }, -- [none] { {"bc",flg.ANCHORED}, {"abc"}, {N } }, -- cf { {"bc"}, {"abc",N, flg.ANCHORED}, {N } }, -- ef { { "(.)b.(d)"}, {"abcd"}, {1,{4},1} }, --[captures] { {"abc"}, {"ab"}, {N } }, { {"abc"}, {"ab",N,flag_partial}, {1,{2},flg.ERROR_PARTIAL} }, { {NAP..".+"}, {string.rep("a",50),N,N,50,50}, {1, fill(50,26), 0}},-- small ovecsize } end local function set_m_fullinfo (lib, flg) local r = lib.new("(foo)(bar)") local info = r:fullinfo() assert(info.CAPTURECOUNT == 2) end return function (libname) local lib = require (libname) local flags = lib.flags () local sets = { set_f_match (lib, flags), set_f_find (lib, flags), set_f_gmatch (lib, flags), set_f_split (lib, flags), set_m_exec (lib, flags), set_m_tfind (lib, flags), set_m_fullinfo (lib, flags), } if flags.MAJOR >= 4 then table.insert (sets, set_named_subpatterns (lib, flags)) end if flags.MAJOR >= 6 then table.insert (sets, set_m_dfa_exec (lib, flags)) end return sets end