Modul:mpiksubstrind

Dari Wiktionary bahasa Indonesia, kamus bebas
Loncat ke navigasi Loncat ke pencarian

Dokumentasi untuk modul ini dapat dibuat di Modul:mpiksubstrind/doc

--[===[

MODULE "MPIKSUBSTRIND" (pick substring by index)

"eo.wiktionary.org/wiki/Modulo:mpiksubstrind" <!--2019-Jun-07-->
"id.wiktionary.org/wiki/Modul:mpiksubstrind"

Purpose: picks a comma-separated substring from a compound string, this
         helps to pick a string from a cell of a two-dimensional table

Utilo: elprenas perkome apartigitan subsignocxenon el kunigita signocxeno, tio
       helpas elpreni signocxenon el cxelo de dudimensia tabelo

Manfaat: ...

Syfte: haemtar en substraeng ...

Used by templates / Uzata far sxablonoj /
Digunakan oleh templat / Anvaent av mallar:
- sxakterminologio

Used by modules / Uzata far moduloj /
Digunakan oleh modul / Anvaent av moduler:
- mkomtbllin ... mpiktblmon ... mkomtblmon ...

Incoming: - 2 obligatory anonymous parameters
            - string (length must be 1...10'000 chars, with comma-separated
              substrings, empty substrings do evaluate as error if the
              search reaches such a string)
            - index of the substring (ZERO-based, must be integer 0...63,
              1 or 2 digits, too high index ie "not found" counts as error)
              or special value "-" to count substrings
          - 1 optional named parameter "err="
            - alternative output string to replace the "=" error
              message (1...64 char:s, default is "=") (this works even
              for errors coming from anonymous parameters)

Returned: - found substring if success or special string "=" if something
            goes wrong (when copying, possible leading and trailing
            whitespace is being removed, while inner whitespace is
            preserved but reduced and converted to exactly one space,
            everything ASCII <=32 is considered as whitespace),
            alternatively a 2-digit decimal number "01" ... "64"
            revealing the amount of substrings

This module is unbreakable (when called with correct module name
and function name). Every imaginable input will output either a useful
result or the string "=".

Cxi tiu modulo estas nerompebla (kiam vokita kun gxustaj nomo de modulo
kaj nomo de funkcio). Cxiu imagebla enigo eldonas aux utilan
rezulton aux signocxenon "=".

Usage examples with results / Ekzemploj de uzo
kun rezultoj / Contoh penggunaan dengan hasil:

: ---------------------------------------

* "{{#invoke:mpiksubstrong}}" (no function)
* (expected result) -> Lua error / Skripteraro

* "{{#invoke:mpiksubstrind|fek}}" (wrong function)
* (expected result) -> Lua error / Skripteraro

* "{{#invoke:mpiksubstrind|ek}}" (no params)
* (expected result) -> "="

* "{{#invoke:mpiksubstrind|ek|}}" (one empty param)
* (expected result) -> "="

* "{{#invoke:mpiksubstrind|ek||}}" (two empty params)
* (expected result) -> "="

* "{{#invoke:mpiksubstrind|ek|||}}" (three empty params)
* (expected result) -> "="

* "{{#invoke:mpiksubstrind|ek|X}}" (only one param)
* (expected result) -> "="

* "{{#invoke:mpiksubstrind|ek|X|}}" (one valid param and one empty param)
* (expected result) -> "="

: ---------------------------------------

* "{{#invoke:mpiksubstrind|ek|X|999}}" (invalid index "999")
* (expected result) -> "="

* "{{#invoke:mpiksubstrind|ek||XX|}}" (invalid params)
* (expected result) -> "="

* "{{#invoke:mpiksubstrind|ek|XX|XX|}}" (invalid params)
* (expected result) -> "="

* "{{#invoke:mpiksubstrind|ek||0}}" (invalid params)
* (expected result) -> "="

* "{{#invoke:mpiksubstrind|ek|X|0}}" (valid minimal case)
* (expected result) -> "X"

* "{{#invoke:mpiksubstrind|ek|X           |0}}"
* (expected result) -> "X"

* "{{#invoke:mpiksubstrind|ek|nul,unu,du,tri,kvar,kvin|4}}"
* (expected result) -> "kvar"

* "{{#invoke:mpiksubstrind|ek|nul,unu,du,tri,kvar,kvin|5}}"
* (expected result) -> "kvin"

: ---------------------------------------

* (index valid but out of range)
* "{{#invoke:mpiksubstrind|ek|nul,unu,du,tri,kvar,kvin|6}}"
* (expected result) -> "="

* "{{#invoke:mpiksubstrind|ek| nul  ,unu,du , tri,kvar,  kvin  |5}}"
* (expected result) -> "kvin"

* "{{#invoke:mpiksubstrind|ek|err=damne}}" (no params, "err=" param)
* (expected result) -> "damne"

* "{{#invoke:mpiksubstrind|ek||0|err=damne}}" (invalid params, "err=" param)
* (expected result) -> "damne"

* (index valid but out of range, "err=" param)
* "{{#invoke:mpiksubstrind|ek|nul,unu,du,tri,kvar,kvin|6|err=damne}}"
* (expected result) -> "damne"

* (index valid but out of range, invalid empty "err=" param)
* "{{#invoke:mpiksubstrind|ek|nul,unu,du,tri,kvar,kvin|6|err=}}"
* (expected result) -> "="

: ---------------------------------------

"{{#invoke:mpiksubstrind|ek|  nul,unu, du
,
tri   ,kvar,kvin  |4}}"

(expected result) -> "kvar"

: ---------------------------------------

"{{#invoke:mpiksubstrind|ek|nul,unu,du,tri,kvar,kv  i
n|5}}"

(expected result) -> "kv i n"

: ---------------------------------------

* "{{#invoke:mpiksubstrind|ek|nul,unu,du,tri,kvar, |5}}"
* (expected result) -> "="

* "{{#invoke:mpiksubstrind|ek|nul,unu,du,tri,kvar,|5}}"
* (expected result) -> "="

* "{{#invoke:mpiksubstrind|ek|nul,unu,du,tri,kvar,,|5}}"
* (expected result) -> "="

* "{{#invoke:mpiksubstrind|ek|nul,unu,du,tri,,kvar,kvin|3}}"
* (expected result) -> "tri"

* "{{#invoke:mpiksubstrind|ek|nul,unu,du,tri,,kvar,kvin|4}}"
* (expected result) -> "="

* "{{#invoke:mpiksubstrind|ek|nul,unu,du,tri,,kvar,kvin|5}}"
* (expected result) -> "="

* "{{#invoke:mpiksubstrind|ek|nul,unu,du,tri,  ,kvar,kvin|5}}"
* (expected result) -> "="

* "{{#invoke:mpiksubstrind|ek|nul,unu,du,tri,unu,kvin|4}}"
* (expected result) -> "unu"

: ---------------------------------------

* "{{#invoke:mpiksubstrind|ek|nul,unu,du,tri,unu,kvin|-}}"
* (expected result) -> "06"

* "{{#invoke:mpiksubstrind|ek|nul,unu,du,tri,unu,kvin,|-}}"
* (expected result) -> "="

* "{{#invoke:mpiksubstrind|ek|,nul,unu,du,tri,unu,kvin|-}}"
* (expected result) -> "="

* "{{#invoke:mpiksubstrind|ek| |-}}"
* (expected result) -> "="

* "{{#invoke:mpiksubstrind|ek|nul,unu,du,tri,kvar,kvin|0}}"
* (expected result) -> "nul"

* "{{#invoke:mpiksubstrind|ek|nul,unu,du,tri,kvar,kvin|00}}"
* (expected result) -> "nul"

* "{{#invoke:mpiksubstrind|ek|nul,unu,du,tri,kvar,kvin|000}}"
* (expected result) -> "="

* "{{#invoke:mpiksubstrind|ek|nul,unu,du,tri,kvar,kvin|4.99}}"
* (expected result) -> "="

: ---------------------------------------

* (invalid index "-1")
* "{{#invoke:mpiksubstrind|ek|nul,unu,du,tri,kvar,kvin|-1}}"
* (expected result) -> "="

: ---------------------------------------

"{{#invoke:mpiksubstrind|ek|a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,
a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,
a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,
a,b,x,y,z,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t|63}}"

(expected result) -> "y"

: ---------------------------------------

"{{#invoke:mpiksubstrind|ek|a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,
a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,
a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,
a,b,x,y|-}}"

(expected result) -> "64"

: ---------------------------------------

"{{#invoke:mpiksubstrind|ek|a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,
a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,
a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,
a,b,x,y,z|-}}"

(expected result) -> "="

: ---------------------------------------

"{{#invoke:mpiksubstrind|ek|a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,
a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,
a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,
a,b,x,y,z,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t|64}}"

(expected result) -> "="

: ---------------------------------------

Note that output from this module when called from a template will be
subject to partial wiki parsing and full HTML parsing. This will
result in among other effects whitespace reduction. It is not
possible to call a module between "<pre>". In order to test this
module more thoroughly the output can be fed into another module
that analyzes the string and diplays ASCII codes or similar.

]===]

local piksubstrind = {}

------------------------------------------------------------------------

---- ORDINARY LOCAL LOW LEVEL FUNCTIONS ----

------------------------------------------------------------------------

local function lfdec1digit (num1digit) -- convert 1 decimal digit to integer
  num1digit = num1digit - 48 -- may become invalid
  if ((num1digit<0) or (num1digit>9)) then
    num1digit = 255
  end--if
  return num1digit
end--function lfdec1digit

local function lfstr12dig2int (strmasuk) -- conv 1 or 2 decimal digits to int
  local numleen = 0
  local numaa = 255 -- preset to "error"
  local numbb = 0
  numleen = string.len (strmasuk)
  if ((numleen==1) or (numleen==2)) then
    numaa = string.byte (strmasuk,1,1)
    numaa = lfdec1digit (numaa) -- 255 if invalid, ZERO would be valid
  end--if
  if ((numaa~=255) and (numleen==2)) then
    numbb = string.byte (strmasuk,2,2)
    numbb = lfdec1digit (numbb) -- 255 if invalid, ZERO would be valid
    if (numbb==255) then
      numaa = 255 -- 255 is invalid, note that ZERO would be valid
    else
      numaa = numaa * 10 + numbb -- valid integer number 0...99 now
    end--if
  end--if
  return numaa
end--function lfstr12dig2int

local function lfint2str2dig (nummasuk) -- convert integer to 2 decimal digits
  local numlow = 0
  local numhaj = 0
  local strdi2gi = ''
  numhaj = math.floor (nummasuk/10)
  numlow = nummasuk % 10
  strdi2gi = string.char (numhaj+48) .. string.char (numlow+48)
  return strdi2gi
end--function lfint2str2dig

------------------------------------------------------------------------

---- MAIN EXPORTED FUNCTION ----

------------------------------------------------------------------------

function piksubstrind.ek (arxframent)

  -- special type "args"

  local arxourown = 0  -- metaized "args" from our own "frame" (NOT caller's)

  -- general str

  local strarg = ""      -- the long input string from arxourown[1]
  local strtmp = ""      -- temp
  local strret = ""      -- output string
  local strerrequ = "="  -- default or alterna string to replace "=" on error

  -- general num

  local numsin = 0     -- index of the string
  local numlong = 0    -- temp for parameter evaluation, length of parameter
  local numcunt = 0    -- counts up
  local numlength = 0  -- length of the input string from arxourown[1]
  local numoct = 0     -- code of a single char
  local numipos = 0    -- iteration index, counts octet chars, ONE-based

  -- general boo

  local boocount = false  -- count substrings instead of picking
  local booqqfnd = false  -- multipurpose "yes found" and "do pick" flag
  local boospc = false    -- flag for whitespace reduction feature
  local boouch = false    -- flag for found useful char when skipping string
  local booeof = false    -- flag set if end of string reached valid result

  ---- SEIZE 2 OBLIGATORY ARGUMENTS FROM THE CALLER ----

  -- there is no "booerr" here, if we do not get our required stuff
  -- both delivered and valid then we end with numlength==0

  arxourown = arxframent.args -- "args" from our own "frame"

  if ((arxourown[1]) and (arxourown[2])) then
    strarg = arxourown[1] -- the long input string with comma-separated substr
    numlength = string.len (strarg) -- octet length of the input string
    if (numlength>10000) then
      numlength = 0 -- this means "error" -- 10 K is max length
    end--if
    strtmp = arxourown[2] -- ZERO-based indx of substr (1 or 2 digits), or "-"
    if (strtmp=="-") then
      boocount = true -- count substrings instead of picking
    else
      numsin = lfstr12dig2int (strtmp) -- 0...99 or 255
      if (numsin>63) then
        numlength = 0 -- this means "error" -- 63 is max value
      end--if
    end--if (strtmp=="-") else
  end--if

  ---- SEIZE NAMED PARAMETER EVEN IF WE ALREADY SUCK ----

  -- try to pick named parameter "err=" even if we have "numlength==0"

  if (type(arxourown["err"])=="string") then
    strtmp = arxourown["err"] -- 1...64 char:s alterna string to replace "="
    numlong = string.len (strtmp) -- temp
    if ((numlong<1) or (numlong>64)) then
      numlength = 0 -- this means "error" -- 64 is max length
    else
      strerrequ = strtmp -- was preset to "="
    end--if
  end--if (type(arxourown["err"])=="string") then

  ---- DO THE JOB ----

  -- "numsin" counts down the substrings (not if
  --          counting is requested via "boocount==true")

  -- "numcunt" counts up

  -- "numipos" counts up positions in the incoming string

  -- "booeof" is used only if counting is requested via "boocount==true"

  if (numlength>0) then
    while (true) do -- iterate through substr:s in order to skip or count them
      if (boocount) then
        if (booeof) then -- nothing to count anymore
          break -- exit the outer loop
        end--if
      else
        if (numsin==0) then -- nothing to skip anymore
          booqqfnd = true -- do try to pick a substring below
          break -- exit the outer loop
        end--if
        numsin = numsin - 1
      end--if (boocount) else
      booqqfnd = false
      boouch = false
      while (true) do -- iterate through whspace & chars mix looking for comma
        if (numipos>=numlength) then
          if (boouch and boocount) then
            booqqfnd = true -- field was not empty and counts and result valid
            booeof = true
          end--if
          break -- exit the inner loop, NOT found, give up or keep count
        end--if
        numipos = numipos + 1 -- ONE-based
        numoct = string.byte (strarg,numipos,numipos) ;
        if ((numoct>32) and (numoct~=44)) then
          boouch = true ; -- found a valid char (empty field is an error)
        end--if
        if (numoct==44) then
          if (boouch) then
            booqqfnd = true -- field was not empty
          end--if
          break ; -- exit the inner loop, found a comma, this is good or bad
        end--if
      end--while
      if (booqqfnd==false) then
        break ; -- exit the outer loop, NOT found or empty field, give up
      end--if
      numcunt = numcunt + 1
    end--while
    if (booeof) then
      booqqfnd = false -- do not try to copy anyhing below
      if ((numcunt>0) and (numcunt<65)) then -- valid integer 1...64
        strret = lfint2str2dig (numcunt) -- valid string "01" ... "64"
      else
        booeof = false -- no valid result
      end--if
    end--if
    if (booqqfnd) then
      booqqfnd = false
      while (true) do -- iterate through chars skipping whitespace
        if (numipos>=numlength) then
          break ; -- exit the loop, NOT found, give up
        end--if
        numipos = numipos + 1 ;
        numoct = string.byte (strarg,numipos,numipos) ;
        if (numoct>32) then
          if (numoct==44) then
            break ; -- exit the loop, found comma, give up according to rules
          end--if
          booqqfnd = true ;
          break ; -- exit the loop, found valid char, start copying now
        end--if
      end--while
    end--if
    if (booqqfnd) then
      while (true) do -- iterate through chars copying the found string
        if (numoct<=32) then
          boospc=true ; -- everything <=32 is considered as whitespace
        else
          if (boospc) then
            strret = strret .. " " -- output just ONE space
            boospc = false
          end--if
          strret = strret .. string.char (numoct)
        end--if
        if (numipos>=numlength) then
          break ; -- exit the loop, done
        end--if
        numipos = numipos + 1
        numoct = string.byte (strarg,numipos,numipos)
        if (numoct==44) then
          break ; -- exit the loop, done
        end--if
      end--while
    end--if
  end--if (numlength>0) then

  if ((booqqfnd==false) and (booeof==false)) then
    strret = strerrequ -- NOT found or error
  end--if

  ---- RETURN THE JUNK STRING ----

  return strret

end--function

  ---- RETURN THE JUNK LUA TABLE ----

return piksubstrind